From ea6f03f478f410b1fb93e38422a14f4a9f10dc77 Mon Sep 17 00:00:00 2001 From: Theodore Li Date: Fri, 2 Oct 2026 16:10:46 -0700 Subject: [PATCH] fix(credentials): make Claude Platform API keys available in the provider catalog --- .../integrations/credential-display.test.ts | 2 +- .../credential-visibility.server.test.ts | 78 +++++++++++-------- .../src/integration-availability.ts | 7 +- 3 files changed, 53 insertions(+), 34 deletions(-) diff --git a/apps/sim/lib/integrations/credential-display.test.ts b/apps/sim/lib/integrations/credential-display.test.ts index a980857f7a0..b89865d2899 100644 --- a/apps/sim/lib/integrations/credential-display.test.ts +++ b/apps/sim/lib/integrations/credential-display.test.ts @@ -37,7 +37,7 @@ const EXPECTED_COVERAGE: Record = { 'attio-service-account': ['attio'], 'box-service-account': ['box'], 'calcom-service-account': ['cal-com'], - 'claude-platform-service-account': [], + 'claude-platform-service-account': ['claude-managed-agents'], 'clickup-service-account': ['clickup'], 'coda-service-account': ['coda'], 'github-app-installation': ['github'], diff --git a/apps/sim/lib/integrations/credential-visibility.server.test.ts b/apps/sim/lib/integrations/credential-visibility.server.test.ts index e478a4be9bd..566ce32c374 100644 --- a/apps/sim/lib/integrations/credential-visibility.server.test.ts +++ b/apps/sim/lib/integrations/credential-visibility.server.test.ts @@ -67,40 +67,56 @@ describe('integration credential visibility', () => { ]) }) - it('exposes Coda token credentials without OAuth while honoring integration policy and visibility', () => { - const catalog = resolveIntegrationAvailability({}) - expect(catalog.find((entry) => entry.type === 'coda')).toMatchObject({ - state: 'ready', - oauthAvailable: false, - serviceAccountAvailable: true, - }) - getIntegrationAvailabilityMock.mockReturnValue(catalog) - const service: OAuthServiceMetadata = { + it.each([ + { serviceId: 'coda', - providerId: 'coda', - serviceAccountProviderId: 'coda-service-account', - authType: 'service_account', + providerId: 'coda-service-account', + blockType: 'coda', name: 'Coda', - description: 'Coda token', - baseProvider: 'coda', - } - const identity = { providerId: 'coda-service-account', type: 'service_account' } as const - const visibility = (allowed: ReadonlySet | null, disabled: boolean) => - createIntegrationCredentialVisibility({ - allowedIntegrationTypes: allowed, - oauthServices: [service], - blockVisibility: { - revealed: new Set(), - previewTagged: new Set(), - disabled: new Set(disabled ? ['coda'] : []), - }, + }, + { + serviceId: 'claude-platform', + providerId: 'claude-platform-service-account', + blockType: 'managed_agent', + name: 'Claude Platform', + }, + ])( + 'exposes $name token credentials without OAuth while honoring integration policy and visibility', + ({ serviceId, providerId, blockType, name }) => { + const catalog = resolveIntegrationAvailability({}) + expect(catalog.find((entry) => entry.type === blockType)).toMatchObject({ + state: 'ready', + oauthAvailable: false, + serviceAccountAvailable: true, }) - expect(visibility(new Set(['coda']), false).isCredentialVisible(identity)).toBe(true) - expect(visibility(new Set(['slack_v2']), false).isCredentialVisible(identity)).toBe(false) - expect(visibility(null, true).isCredentialVisible(identity)).toBe(false) - getBlockMock.mockReturnValue({ type: 'coda', preview: true } as never) - expect(visibility(null, false).isCredentialVisible(identity)).toBe(false) - }) + getIntegrationAvailabilityMock.mockReturnValue(catalog) + const service: OAuthServiceMetadata = { + serviceId, + providerId: serviceId, + serviceAccountProviderId: providerId, + authType: 'service_account', + name, + description: `${name} token`, + baseProvider: serviceId, + } + const identity = { providerId, type: 'service_account' } as const + const visibility = (allowed: ReadonlySet | null, disabled: boolean) => + createIntegrationCredentialVisibility({ + allowedIntegrationTypes: allowed, + oauthServices: [service], + blockVisibility: { + revealed: new Set(), + previewTagged: new Set(), + disabled: new Set(disabled ? [blockType] : []), + }, + }) + expect(visibility(new Set([blockType]), false).isCredentialVisible(identity)).toBe(true) + expect(visibility(new Set(['slack_v2']), false).isCredentialVisible(identity)).toBe(false) + expect(visibility(null, true).isCredentialVisible(identity)).toBe(false) + getBlockMock.mockReturnValue({ type: blockType, preview: true } as never) + expect(visibility(null, false).isCredentialVisible(identity)).toBe(false) + } + ) it('applies the integration allowlist to OAuth and service-account credentials', () => { const visibility = createIntegrationCredentialVisibility({ diff --git a/packages/deployment-config/src/integration-availability.ts b/packages/deployment-config/src/integration-availability.ts index 0be1458546a..8dcc11a6f4d 100644 --- a/packages/deployment-config/src/integration-availability.ts +++ b/packages/deployment-config/src/integration-availability.ts @@ -29,8 +29,11 @@ const deploymentGatedIntegrationTypes = new Set( const integrationTypesByOAuthServiceId = new Map() /** Search authorization shares GitHub's integration policy while its workflow tools retain PAT auth. */ integrationTypesByOAuthServiceId.set('github-repositories', ['github_v2']) -/** Coda's stored API-token credential is available without a deployment OAuth client. */ -const tokenCredentialIntegrationTypes = new Map([['coda', 'coda']]) +/** Stored API-token credentials for api-key blocks are available without a deployment OAuth client. */ +const tokenCredentialIntegrationTypes = new Map([ + ['coda', 'coda'], + ['claude-platform', 'managed_agent'], +]) for (const [serviceId, integrationType] of tokenCredentialIntegrationTypes) { integrationTypesByOAuthServiceId.set(serviceId, [integrationType]) }