From 92d84480c006e3babd2e54476aaef4ffdf8a58b2 Mon Sep 17 00:00:00 2001 From: Theodore Li Date: Thu, 27 Aug 2026 11:02:26 -0700 Subject: [PATCH] fix(slack): remove stale preview gate references --- .../components/special-tags/special-tags.tsx | 6 +-- apps/sim/blocks/registry-lookup.test.ts | 46 +++++++++++-------- apps/sim/blocks/registry.ts | 9 ++-- .../sim/lib/copilot/integration-tools.test.ts | 4 +- 4 files changed, 36 insertions(+), 29 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/special-tags/special-tags.tsx b/apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/special-tags/special-tags.tsx index 2c4d0536e68..45531a39e92 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/special-tags/special-tags.tsx +++ b/apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/special-tags/special-tags.tsx @@ -2319,9 +2319,9 @@ function ServiceAccountConnectDisplay({ const connected = locallyConnected // Creating a credential mutates the workspace — hide it from read-only - // members, and honour the provider's own preview gate (custom Slack bots - // ride the slack_v2 flag) so chat can't surface what the integrations page - // deliberately hides. + // members, and honor the owning block's visibility (custom Slack bots follow + // slack_v2) so chat can't surface what the integrations page deliberately + // hides. if (!target || target.hidden || !canEdit || !workspaceId) return null const label = reconnectCredentialId diff --git a/apps/sim/blocks/registry-lookup.test.ts b/apps/sim/blocks/registry-lookup.test.ts index 060e3b1702f..b95cc3797b2 100644 --- a/apps/sim/blocks/registry-lookup.test.ts +++ b/apps/sim/blocks/registry-lookup.test.ts @@ -33,25 +33,33 @@ describe('getBlock prototype safety', () => { /** * The list and the detail read must agree about a type. * - * `slack_v2` is `preview`-gated while `slack` v1 deliberately stays in the - * toolbar so a workspace has a Slack block during the gate. Resolving the - * detail to the newest version and then hiding it answered `404` for a type - * `GET /api/v2/blocks` was publishing in the same breath. + * A preview successor can be hidden while its released base version remains in + * the toolbar. Resolving the detail to the newest version and then hiding it + * would answer `404` for a type `GET /api/v2/blocks` publishes in the same + * breath. Once the successor is released, both surfaces must resolve to it. */ describe('version resolution for a viewer', () => { - it.each(['slack', 'table'])( - 'resolves %s to a version the unrevealed viewer can actually see', - async (type) => { - const { getLatestBlockForViewer, getAllBlocks } = await import('@/blocks/registry') - - const detail = getLatestBlockForViewer(type) - const listed = getAllBlocks().find( - (block) => - !block.hideFromToolbar && (block.type === type || block.type.startsWith(`${type}_v`)) - ) - - expect(Boolean(detail)).toBe(Boolean(listed)) - if (detail && listed) expect(detail.type).toBe(listed.type) - } - ) + it('falls back to the released table block while table_v2 is unrevealed', async () => { + const { getLatestBlockForViewer, getAllBlocks } = await import('@/blocks/registry') + const detail = getLatestBlockForViewer('table') + const listed = getAllBlocks().find( + (block) => + !block.hideFromToolbar && (block.type === 'table' || block.type.startsWith('table_v')) + ) + + expect(detail?.type).toBe('table') + expect(listed?.type).toBe('table') + }) + + it('resolves Slack to the released slack_v2 block', async () => { + const { getLatestBlockForViewer, getAllBlocks } = await import('@/blocks/registry') + const detail = getLatestBlockForViewer('slack') + const listed = getAllBlocks().find( + (block) => + !block.hideFromToolbar && (block.type === 'slack' || block.type.startsWith('slack_v')) + ) + + expect(detail?.type).toBe('slack_v2') + expect(listed?.type).toBe('slack_v2') + }) }) diff --git a/apps/sim/blocks/registry.ts b/apps/sim/blocks/registry.ts index dfc104d7516..8c72b8f0989 100644 --- a/apps/sim/blocks/registry.ts +++ b/apps/sim/blocks/registry.ts @@ -142,11 +142,10 @@ export function getLatestBlockForViewer(type: string): BlockConfig | undefined { * * The detail read walks these rather than taking `getLatestBlock` and hiding * the result, because "newest" and "visible to this viewer" are different - * questions. `slack_v2` is `preview`-gated while `slack` v1 deliberately stays - * in the toolbar so the workspace has a Slack block at all — so resolving to - * the newest and then hiding it answers `404` for a type the list is - * simultaneously publishing. Walking down to the newest *visible* version is - * what makes the two agree. + * questions. For example, `table_v2` is `preview`-gated while `table` remains + * in the toolbar — so resolving to the newest and then hiding it answers `404` + * for a type the list is simultaneously publishing. Walking down to the newest + * *visible* version is what makes the two agree. */ function versionCandidates(type: string): BlockConfig[] { const normalized = normalizeType(type) diff --git a/apps/sim/lib/copilot/integration-tools.test.ts b/apps/sim/lib/copilot/integration-tools.test.ts index edc4c8555b2..e0b453d3923 100644 --- a/apps/sim/lib/copilot/integration-tools.test.ts +++ b/apps/sim/lib/copilot/integration-tools.test.ts @@ -9,8 +9,8 @@ vi.mock('@/blocks/registry-maps', () => ({ type: 'svc', tools: { access: ['svc_send_v2'] }, }, - // Preview successor sharing the released block's tools (the slack/slack_v2 - // paradigm) — both owners must remain available for projection. + // A preview successor sharing the released block's tools keeps both owners + // available for projection. svc_v2: { type: 'svc_v2', preview: true,