From 56e851855fa1141b9a1992c1ade33548f4638584 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Mon, 24 Aug 2026 12:32:45 -0700 Subject: [PATCH 1/4] refactor(auth): drop the isProduction prop nothing on the signin path reads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same shape as the `isWorkflowRunning` removal: declared, required, threaded through every layer, and never read at the end of the chain. `SocialLoginButtons` declares `isProduction: boolean` as a REQUIRED prop and never reads it, so every caller had to produce and forward a value that was discarded. Neither `login-form` nor `signup-form` reads it either — each only declares it, destructures it, and passes it down. `signup-form` forwards it twice, through its own inner `SignupFormContent` hop. With the chain gone, `getOAuthProviderStatus` has no consumer for the `isProduction: isProd` it returned: the pages destructured it only to forward it, and `/api/auth/providers` already takes just the three availability flags. So the return value and its `isProd` import go too. `isProduction` stays alive where it is genuinely used — `verify-content.tsx` branches on it and hands it to `useVerification`, and imports `isProd` directly rather than through this helper. That path is untouched. Found by the rule enabled in #7037: it was the only `.tsx` unused-parameter warning in `apps/sim`. (cherry picked from commit 331c2ed2eda3a7cefb90a1b1c2ea99c030c7041a) --- apps/sim/app/(auth)/components/oauth-provider-checker.tsx | 3 +-- apps/sim/app/(auth)/components/social-login-buttons.tsx | 2 -- apps/sim/app/(auth)/login/login-form.tsx | 3 --- apps/sim/app/(auth)/login/page.tsx | 4 +--- apps/sim/app/(auth)/signup/page.tsx | 4 +--- apps/sim/app/(auth)/signup/signup-form.tsx | 5 ----- 6 files changed, 3 insertions(+), 18 deletions(-) diff --git a/apps/sim/app/(auth)/components/oauth-provider-checker.tsx b/apps/sim/app/(auth)/components/oauth-provider-checker.tsx index ee2f4ede8a3..a8ba38dcfb4 100644 --- a/apps/sim/app/(auth)/components/oauth-provider-checker.tsx +++ b/apps/sim/app/(auth)/components/oauth-provider-checker.tsx @@ -3,7 +3,6 @@ import { isGithubAuthDisabled, isGoogleAuthDisabled, isMicrosoftAuthDisabled, - isProd, } from '@/lib/core/config/env-flags' export async function getOAuthProviderStatus() { @@ -16,5 +15,5 @@ export async function getOAuthProviderStatus() { const microsoftAvailable = !!(env.MICROSOFT_CLIENT_ID && env.MICROSOFT_CLIENT_SECRET) && !isMicrosoftAuthDisabled - return { githubAvailable, googleAvailable, microsoftAvailable, isProduction: isProd } + return { githubAvailable, googleAvailable, microsoftAvailable } } diff --git a/apps/sim/app/(auth)/components/social-login-buttons.tsx b/apps/sim/app/(auth)/components/social-login-buttons.tsx index c2156e7dd3f..c200d86bd11 100644 --- a/apps/sim/app/(auth)/components/social-login-buttons.tsx +++ b/apps/sim/app/(auth)/components/social-login-buttons.tsx @@ -15,7 +15,6 @@ interface SocialLoginButtonsProps { googleAvailable: boolean microsoftAvailable: boolean callbackURL?: string - isProduction: boolean children?: ReactNode } @@ -24,7 +23,6 @@ export function SocialLoginButtons({ googleAvailable, microsoftAvailable, callbackURL = '/workspace', - isProduction, children, }: SocialLoginButtonsProps) { const [isGithubLoading, setIsGithubLoading] = useState(false) diff --git a/apps/sim/app/(auth)/login/login-form.tsx b/apps/sim/app/(auth)/login/login-form.tsx index d3c7d8bd6ed..cfe0b1403b8 100644 --- a/apps/sim/app/(auth)/login/login-form.tsx +++ b/apps/sim/app/(auth)/login/login-form.tsx @@ -87,13 +87,11 @@ export default function LoginPage({ githubAvailable, googleAvailable, microsoftAvailable, - isProduction, registrationDisabled, }: { githubAvailable: boolean googleAvailable: boolean microsoftAvailable: boolean - isProduction: boolean /** DISABLE_REGISTRATION. Hides the signup cross-link, which `/signup` blocks. */ registrationDisabled: boolean }) { @@ -430,7 +428,6 @@ export default function LoginPage({ googleAvailable={googleAvailable} githubAvailable={githubAvailable} microsoftAvailable={microsoftAvailable} - isProduction={isProduction} callbackURL={callbackUrl} > {ssoEnabled && !hasOnlySSO && ( diff --git a/apps/sim/app/(auth)/login/page.tsx b/apps/sim/app/(auth)/login/page.tsx index 3b0c3f6a96a..726727b1435 100644 --- a/apps/sim/app/(auth)/login/page.tsx +++ b/apps/sim/app/(auth)/login/page.tsx @@ -12,8 +12,7 @@ export const metadata: Metadata = { export const dynamic = 'force-dynamic' export default async function LoginPage() { - const { githubAvailable, googleAvailable, microsoftAvailable, isProduction } = - await getOAuthProviderStatus() + const { githubAvailable, googleAvailable, microsoftAvailable } = await getOAuthProviderStatus() return ( }> @@ -21,7 +20,6 @@ export default async function LoginPage() { githubAvailable={githubAvailable} googleAvailable={googleAvailable} microsoftAvailable={microsoftAvailable} - isProduction={isProduction} registrationDisabled={isRegistrationDisabled} /> diff --git a/apps/sim/app/(auth)/signup/page.tsx b/apps/sim/app/(auth)/signup/page.tsx index d43dc7c0475..496f779b7fb 100644 --- a/apps/sim/app/(auth)/signup/page.tsx +++ b/apps/sim/app/(auth)/signup/page.tsx @@ -36,15 +36,13 @@ export default async function SignupPage({ ) } - const { githubAvailable, googleAvailable, microsoftAvailable, isProduction } = - await getOAuthProviderStatus() + const { githubAvailable, googleAvailable, microsoftAvailable } = await getOAuthProviderStatus() return ( diff --git a/apps/sim/app/(auth)/signup/signup-form.tsx b/apps/sim/app/(auth)/signup/signup-form.tsx index ad0d5213b97..94c4b74dfee 100644 --- a/apps/sim/app/(auth)/signup/signup-form.tsx +++ b/apps/sim/app/(auth)/signup/signup-form.tsx @@ -91,7 +91,6 @@ interface SignupFormProps { githubAvailable: boolean googleAvailable: boolean microsoftAvailable: boolean - isProduction: boolean emailSignupEnabled: boolean /** Server-derived: verification is enabled AND a mail provider is configured. */ emailVerificationEnabled: boolean @@ -101,7 +100,6 @@ function SignupFormContent({ githubAvailable, googleAvailable, microsoftAvailable, - isProduction, emailSignupEnabled, emailVerificationEnabled, }: SignupFormProps) { @@ -484,7 +482,6 @@ function SignupFormContent({ googleAvailable={googleAvailable} microsoftAvailable={microsoftAvailable} callbackURL={redirectUrl || '/workspace'} - isProduction={isProduction} > {ssoEnabled && !hasOnlySSO && ( @@ -507,7 +504,6 @@ export default function SignupPage({ githubAvailable, googleAvailable, microsoftAvailable, - isProduction, emailSignupEnabled, emailVerificationEnabled, }: SignupFormProps) { @@ -519,7 +515,6 @@ export default function SignupPage({ githubAvailable={githubAvailable} googleAvailable={googleAvailable} microsoftAvailable={microsoftAvailable} - isProduction={isProduction} emailSignupEnabled={emailSignupEnabled} emailVerificationEnabled={emailVerificationEnabled} /> From e14c80e14c193178c2758185dec477003e797be7 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Mon, 24 Aug 2026 12:37:32 -0700 Subject: [PATCH 2/4] refactor: drop two more props declared, threaded, and never read MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same shape as the two already in this PR, found by sweeping the rest of the unused-parameter list for params callers actively compute and pass. `FieldItem.level` is the worse of the two. It is a required `level: number` that the component never reads, and `FieldTreeNodes` exists to thread it: declared, destructured, handed to `FieldItem`, and incremented on every recursion (`level={level + 1}`) from a `level={0}` seed. So a depth counter was carried through an arbitrarily deep tree to feed a component that ignores it. Indentation comes from the nested wrapper divs (`ml-1.5 pl-2.5`, `ml-3 pl-2.5`), not from the counter — removing it changes no rendering. `useMentionMenu`'s `onContextSelect` is a required prop carrying the TSDoc "Callback when a context is selected". The hook never invokes it, so that contract is unimplemented and a future caller would reasonably rely on it. Only the dead hand-off goes there. `addContextNotified` stays: the caller invokes it directly at five sites, and the ref sinks behind it keep its identity stable for those. Context selection has always worked because the caller does the work itself, not because the hook calls back. (cherry picked from commit 110ba76df37055946b456afa5622d6d8f2c1e588) --- .../user-input/components/prompt-editor/use-prompt-editor.ts | 1 - .../copilot/components/user-input/hooks/use-mention-menu.ts | 3 --- .../connection-blocks/components/field-item/field-item.tsx | 2 -- .../components/connection-blocks/connection-blocks.tsx | 5 ----- 4 files changed, 11 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/prompt-editor/use-prompt-editor.ts b/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/prompt-editor/use-prompt-editor.ts index f86f69f24a2..41ddd83e4e8 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/prompt-editor/use-prompt-editor.ts +++ b/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/prompt-editor/use-prompt-editor.ts @@ -218,7 +218,6 @@ export function usePromptEditor({ const mentionMenu = useMentionMenu({ message: value, selectedContexts: contextManagement.selectedContexts, - onContextSelect: addContextNotified, onMessageChange: commitValue, }) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/hooks/use-mention-menu.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/hooks/use-mention-menu.ts index 3e9a390f5ac..ac69a0d6e58 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/hooks/use-mention-menu.ts +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/hooks/use-mention-menu.ts @@ -7,8 +7,6 @@ interface UseMentionMenuProps { message: string /** Currently selected contexts */ selectedContexts: ChatContext[] - /** Callback when a context is selected */ - onContextSelect: (context: ChatContext) => void /** Callback when message changes */ onMessageChange: (message: string) => void } @@ -23,7 +21,6 @@ interface UseMentionMenuProps { export function useMentionMenu({ message, selectedContexts, - onContextSelect, onMessageChange, }: UseMentionMenuProps) { // Refs diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/connection-blocks/components/field-item/field-item.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/connection-blocks/components/field-item/field-item.tsx index 3e5c792bced..40b6623f0eb 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/connection-blocks/components/field-item/field-item.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/connection-blocks/components/field-item/field-item.tsx @@ -24,7 +24,6 @@ interface FieldItemProps { connection: ConnectedBlock field: SchemaField path: string - level: number hasChildren?: boolean isExpanded?: boolean onToggleExpand?: (path: string) => void @@ -37,7 +36,6 @@ export function FieldItem({ connection, field, path, - level, hasChildren, isExpanded, onToggleExpand, diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/connection-blocks/connection-blocks.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/connection-blocks/connection-blocks.tsx index 5d39c1b100e..98c6493a0b8 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/connection-blocks/connection-blocks.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/connection-blocks/connection-blocks.tsx @@ -27,7 +27,6 @@ interface ConnectionBlocksProps { interface FieldTreeNodesProps { fields: SchemaField[] parentPath: string - level: number connection: ConnectedBlock isFieldExpanded: (connectionId: string, fieldPath: string) => boolean onToggleFieldExpansion: (connectionId: string, fieldPath: string) => void @@ -36,7 +35,6 @@ interface FieldTreeNodesProps { function FieldTreeNodes({ fields, parentPath, - level, connection, isFieldExpanded, onToggleFieldExpansion, @@ -52,7 +50,6 @@ function FieldTreeNodes({ connection={connection} field={field} path={fieldPath} - level={level} hasChildren={hasChildren} isExpanded={expanded} onToggleExpand={(p) => onToggleFieldExpansion(connection.id, p)} @@ -63,7 +60,6 @@ function FieldTreeNodes({ Date: Mon, 24 Aug 2026 13:06:20 -0700 Subject: [PATCH 3/4] refactor: drop two more dead prop chains in the sub-block editor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `GroupedCheckboxList` declares `title` (required) and `maxHeight` and reads neither. It renders its own hardcoded copy instead — `Select PII Types to Detect` for the header and `PII types` for the field label — so a block author who sets `title` on a `grouped-checkbox-list` subBlock gets silence, and the `maxHeight = 400` default implies a scroll ceiling that is never applied. Both props go, along with the two values `sub-block.tsx` was passing. `flatTagList` was threaded through the recursive tag renderers to a dead end: declared on `NestedTagRendererProps`, inherited by `FolderContentsProps`, destructured in both, forwarded once more, and read by neither. Its real consumer is `flatTagIndexMap`, built from it at the top level and documented "Map from tag string to index for O(1) lookups" — so the array was being carried alongside its own index through arbitrary nesting depth. The top-level memo and its length checks stay; only the descent goes. Note the component's copy is PII-specific while its name and props present as generic. Renaming it is a separate call, not made here. Both removals were caught mid-flight by `tsc`: my line patterns also matched a live `flatTagList` on `KeyboardNavigationHandler` and a live `title` on `Switch`, which is exactly why the type-check runs before the commit and not after. (cherry picked from commit 5db44f347b1474374a8303b005ff70ac942a3c4a) --- .../grouped-checkbox-list/grouped-checkbox-list.tsx | 4 ---- .../sub-block/components/tag-dropdown/tag-dropdown.tsx | 7 +------ .../components/editor/components/sub-block/sub-block.tsx | 2 -- 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/grouped-checkbox-list/grouped-checkbox-list.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/grouped-checkbox-list/grouped-checkbox-list.tsx index ff14d9ef4b2..ec74704c42b 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/grouped-checkbox-list/grouped-checkbox-list.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/grouped-checkbox-list/grouped-checkbox-list.tsx @@ -35,23 +35,19 @@ function SelectedCountDisplay({ noneSelected, allSelected, count }: SelectedCoun interface GroupedCheckboxListProps { blockId: string subBlockId: string - title: string options: { label: string; id: string; group?: string }[] isPreview?: boolean subBlockValues: Record disabled?: boolean - maxHeight?: number } export function GroupedCheckboxList({ blockId, subBlockId, - title, options, isPreview = false, subBlockValues, disabled = false, - maxHeight = 400, }: GroupedCheckboxListProps) { const activeSearchTarget = useActiveSearchTarget() const [open, setOpen] = useState(false) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tag-dropdown/tag-dropdown.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tag-dropdown/tag-dropdown.tsx index cec7d6e9c2b..97321b5b4a4 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tag-dropdown/tag-dropdown.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tag-dropdown/tag-dropdown.tsx @@ -376,7 +376,6 @@ const buildNestedTagTree = (tags: string[], blockName: string): NestedTag[] => { interface NestedTagRendererProps { nestedTag: NestedTag group: NestedBlockTagGroup - flatTagList: Array<{ tag: string; group?: BlockTagGroup }> /** Map from tag string to index for O(1) lookups */ flatTagIndexMap: Map selectedIndex: number @@ -403,7 +402,6 @@ interface FolderContentsProps extends NestedTagRendererProps { */ const FolderContentsInner: React.FC = ({ group, - flatTagList, flatTagIndexMap, selectedIndex, setSelectedIndex, @@ -565,7 +563,6 @@ const FolderContents: React.FC> = (props) => const NestedTagRenderer: React.FC = ({ nestedTag, group, - flatTagList, flatTagIndexMap, selectedIndex, setSelectedIndex, @@ -612,7 +609,6 @@ const NestedTagRenderer: React.FC = ({ = ({ { @@ -1720,7 +1716,6 @@ export const TagDropdown: React.FC = ({ key={`${group.blockId}-${nestedTag.key}`} nestedTag={nestedTag} group={group} - flatTagList={flatTagList} flatTagIndexMap={flatTagIndexMap} selectedIndex={selectedIndex} setSelectedIndex={setSelectedIndex} diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/sub-block.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/sub-block.tsx index 22fb31478c0..9833b32824e 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/sub-block.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/sub-block.tsx @@ -844,12 +844,10 @@ function SubBlockComponent({ ) From e12c716b4a49916c84e0746202b862173eaa6277 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Mon, 24 Aug 2026 13:07:31 -0700 Subject: [PATCH 4/4] refactor(custom-blocks): drop the workspaceId three mutation hooks never use MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `usePublishCustomBlock`, `useUpdateCustomBlock` and `useDeleteCustomBlock` each take `workspaceId?: string` and never read it. `custom-block-detail.tsx` passes it to all three. The parameter looks like it was meant to narrow the invalidation to `customBlockKeys.list(workspaceId)`, but `lists()` is the level CLAUDE.md's targeted-invalidation rule actually prescribes, and it is a correct superset. So the invalidation is right as written and the parameter is simply vestigial — removing it is the honest fix, and narrowing the key would be a separate call with its own risk of under-invalidating. Worth recording that these three were reported to me as having zero callers and therefore being dead exports. They are not: the search that produced that claim omitted `apps/sim/ee`, where all three are used. (cherry picked from commit 2d0854a5879269c9f182710665643fd5e4753470) --- .../sim/ee/custom-blocks/components/custom-block-detail.tsx | 6 +++--- apps/sim/hooks/queries/custom-blocks.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/sim/ee/custom-blocks/components/custom-block-detail.tsx b/apps/sim/ee/custom-blocks/components/custom-block-detail.tsx index 59cd4a0bd1d..6ee3c467b1e 100644 --- a/apps/sim/ee/custom-blocks/components/custom-block-detail.tsx +++ b/apps/sim/ee/custom-blocks/components/custom-block-detail.tsx @@ -85,9 +85,9 @@ export function CustomBlockDetail({ blockId, workspaceId, onBack }: CustomBlockD [blocks, blockId] ) - const publish = usePublishCustomBlock(workspaceId) - const update = useUpdateCustomBlock(workspaceId) - const remove = useDeleteCustomBlock(workspaceId) + const publish = usePublishCustomBlock() + const update = useUpdateCustomBlock() + const remove = useDeleteCustomBlock() // Needed in both modes: the source picker (create) and the manage gate (edit). const { data: workspaces = [] } = useWorkspacesQuery() diff --git a/apps/sim/hooks/queries/custom-blocks.ts b/apps/sim/hooks/queries/custom-blocks.ts index 55a127fc68f..ff9f8228754 100644 --- a/apps/sim/hooks/queries/custom-blocks.ts +++ b/apps/sim/hooks/queries/custom-blocks.ts @@ -75,7 +75,7 @@ export function useCustomBlockUsageCounts(blockId?: string, options?: { enabled? }) } -export function usePublishCustomBlock(workspaceId?: string) { +export function usePublishCustomBlock() { const queryClient = useQueryClient() return useMutation({ mutationFn: (body: PublishCustomBlockBody) => requestJson(publishCustomBlockContract, { body }), @@ -85,7 +85,7 @@ export function usePublishCustomBlock(workspaceId?: string) { }) } -export function useUpdateCustomBlock(workspaceId?: string) { +export function useUpdateCustomBlock() { const queryClient = useQueryClient() return useMutation({ mutationFn: ({ id, ...body }: UpdateCustomBlockBody & { id: string }) => @@ -96,7 +96,7 @@ export function useUpdateCustomBlock(workspaceId?: string) { }) } -export function useDeleteCustomBlock(workspaceId?: string) { +export function useDeleteCustomBlock() { const queryClient = useQueryClient() return useMutation({ mutationFn: (id: string) => requestJson(deleteCustomBlockContract, { params: { id } }),