@tangle-network/agent-integrations 0.33.0 → 0.33.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -7
- package/dist/catalog.d.ts +2 -2
- package/dist/catalog.js +9 -7
- package/dist/{chunk-7T5YTVER.js → chunk-53NQJZAT.js} +8 -318
- package/dist/chunk-53NQJZAT.js.map +1 -0
- package/dist/chunk-7P2LN4VT.js +318 -0
- package/dist/chunk-7P2LN4VT.js.map +1 -0
- package/dist/{chunk-XO2RSS6Y.js → chunk-C4CGT5JE.js} +52 -669
- package/dist/chunk-C4CGT5JE.js.map +1 -0
- package/dist/{chunk-YPZORI3G.js → chunk-CR35IEKW.js} +2 -2
- package/dist/{chunk-43VQSANC.js → chunk-D57YS6XC.js} +2 -2
- package/dist/{chunk-6N23S4JY.js → chunk-DT3H3NIW.js} +532 -5
- package/dist/chunk-DT3H3NIW.js.map +1 -0
- package/dist/{chunk-RF3RH374.js → chunk-O553GSCX.js} +2 -2
- package/dist/chunk-PZ5AY32C.js +10 -0
- package/dist/{chunk-NQ7OPDUM.js → chunk-ZDK7Y4QG.js} +12 -1
- package/dist/chunk-ZDK7Y4QG.js.map +1 -0
- package/dist/connect/index.d.ts +2 -2
- package/dist/connect/index.js +3 -2
- package/dist/connectors/adapters/index.d.ts +2 -2
- package/dist/connectors/adapters/index.js +3 -2
- package/dist/connectors/index.d.ts +2 -2
- package/dist/connectors/index.js +3 -2
- package/dist/{consumer-CzJgntej.d.ts → consumer-yV4NtH2h.d.ts} +1 -1
- package/dist/consumer.d.ts +3 -3
- package/dist/consumer.js +3 -2
- package/dist/{core-types-D5Dc65Ud.d.ts → core-types-CjWifQOf.d.ts} +2 -2
- package/dist/coverage-catalog.d.ts +26 -0
- package/dist/coverage-catalog.js +12 -0
- package/dist/coverage-catalog.js.map +1 -0
- package/dist/index.d.ts +74 -58
- package/dist/index.js +16 -47
- package/dist/middleware/index.d.ts +2 -2
- package/dist/middleware/index.js +3 -2
- package/dist/registry.d.ts +2 -2
- package/dist/registry.js +9 -7
- package/dist/runtime.d.ts +2 -2
- package/dist/runtime.js +9 -7
- package/dist/specs.d.ts +2 -2
- package/dist/specs.js +3 -1
- package/dist/stripe/index.js +1 -0
- package/dist/stripe/index.js.map +1 -1
- package/dist/{tangle-id-DA_qj-O_.d.ts → tangle-id-hDDWP-2f.d.ts} +1 -1
- package/dist/{types-XdpvaIzW.d.ts → types-Bxg-wJkW.d.ts} +12 -3
- package/dist/webhooks/index.js +1 -0
- package/dist/webhooks/index.js.map +1 -1
- package/docs/adapter-triage.md +9 -42
- package/docs/external-product-integration.md +3 -4
- package/docs/integration-execution-audit.md +134 -70
- package/docs/integration-execution-matrix.json +3062 -1823
- package/package.json +14 -25
- package/dist/bin/tangle-catalog-runtime.d.ts +0 -1
- package/dist/bin/tangle-catalog-runtime.js +0 -82
- package/dist/bin/tangle-catalog-runtime.js.map +0 -1
- package/dist/chunk-6N23S4JY.js.map +0 -1
- package/dist/chunk-7T5YTVER.js.map +0 -1
- package/dist/chunk-NQ7OPDUM.js.map +0 -1
- package/dist/chunk-XO2RSS6Y.js.map +0 -1
- package/dist/tangle-catalog-runtime-2HddXxoM.d.ts +0 -242
- package/dist/tangle-catalog-runtime.d.ts +0 -3
- package/dist/tangle-catalog-runtime.js +0 -32
- /package/dist/{chunk-YPZORI3G.js.map → chunk-CR35IEKW.js.map} +0 -0
- /package/dist/{chunk-43VQSANC.js.map → chunk-D57YS6XC.js.map} +0 -0
- /package/dist/{chunk-RF3RH374.js.map → chunk-O553GSCX.js.map} +0 -0
- /package/dist/{tangle-catalog-runtime.js.map → chunk-PZ5AY32C.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/specs/types.ts","../src/specs/families.ts","../src/coverage-catalog.ts","../src/specs/overrides.ts","../src/specs/registry.ts","../src/specs/renderers.ts","../src/specs/validation.ts"],"sourcesContent":["import type {\n IntegrationActionRisk,\n IntegrationConnector,\n IntegrationConnectorAction,\n IntegrationConnectorCategory,\n IntegrationConnectorTrigger,\n IntegrationDataClass,\n} from '../index.js'\n\nexport type IntegrationAuthMode = 'oauth2' | 'api_key' | 'hmac' | 'none' | 'custom'\n\nexport type IntegrationSpecStatus = 'catalog' | 'executable' | 'deprecated'\n\nexport type IntegrationFamilyId =\n | 'google'\n | 'microsoft-graph'\n | 'atlassian'\n | 'salesforce'\n | 'hubspot'\n | 'slack'\n | 'notion'\n | 'standard-oauth2'\n | 'api-key'\n | 'hmac'\n | 'none'\n\nexport type NormalizedPermission =\n | `${string}.read`\n | `${string}.write`\n | `${string}.delete`\n | `${string}.admin`\n\nexport interface IntegrationSpec {\n kind: string\n title: string\n category: IntegrationConnectorCategory\n status: IntegrationSpecStatus\n family: IntegrationFamilyId\n auth: IntegrationAuthSpec\n permissions: PermissionDescriptor[]\n actions: IntegrationConnectorAction[]\n triggers?: IntegrationConnectorTrigger[]\n setup: IntegrationSetupSpec\n lifecycle?: IntegrationLifecycleSpec\n plannerHints?: IntegrationPlannerHints\n metadata?: Record<string, unknown>\n}\n\nexport type IntegrationAuthSpec =\n | OAuth2AuthSpec\n | ApiKeyAuthSpec\n | HmacAuthSpec\n | NoneAuthSpec\n | CustomAuthSpec\n\nexport interface OAuth2AuthSpec {\n mode: 'oauth2'\n authorizationUrl: string\n tokenUrl: string\n clientIdEnv?: string\n clientSecretEnv?: string\n scopes: ScopeDescriptor[]\n extraAuthParams?: Record<string, string>\n redirectUriTemplate: string\n pkce?: 'required' | 'supported' | 'unsupported'\n}\n\nexport interface ApiKeyAuthSpec {\n mode: 'api_key'\n credential: CredentialFieldSpec\n placement?: 'bearer' | 'header' | 'query' | 'basic'\n}\n\nexport interface HmacAuthSpec {\n mode: 'hmac'\n credential: CredentialFieldSpec\n signatureHeader?: string\n}\n\nexport interface NoneAuthSpec {\n mode: 'none'\n}\n\nexport interface CustomAuthSpec {\n mode: 'custom'\n description: string\n}\n\nexport interface ScopeDescriptor {\n normalized: NormalizedPermission\n providerScope: string\n title: string\n reason: string\n risk: IntegrationActionRisk\n dataClass: IntegrationDataClass\n}\n\nexport interface PermissionDescriptor {\n normalized: NormalizedPermission\n providerScopes: string[]\n title: string\n risk: IntegrationActionRisk\n dataClass: IntegrationDataClass\n reason: string\n}\n\nexport interface CredentialFieldSpec {\n label: string\n description: string\n env?: string\n example?: string\n regex?: string\n secret: boolean\n}\n\nexport interface ConsoleStep {\n id: string\n title: string\n detail: string\n copyValue?: string\n}\n\nexport interface Quirk {\n id: string\n severity: 'info' | 'warning' | 'critical'\n message: string\n}\n\nexport interface PostSetupCheck {\n id: string\n title: string\n detail: string\n}\n\nexport interface HealthcheckSpec {\n id: string\n level: 'client_config' | 'connection' | 'webhook' | 'static'\n method?: 'GET' | 'POST'\n url?: string\n expectedStatus?: number[]\n description: string\n}\n\nexport interface IntegrationSetupSpec {\n consoleUrl?: string\n consoleSteps: ConsoleStep[]\n credentialFields: CredentialFieldSpec[]\n redirectUriTemplate?: string\n knownQuirks?: Quirk[]\n postSetup?: PostSetupCheck[]\n healthcheck?: HealthcheckSpec\n}\n\nexport interface IntegrationLifecycleSpec {\n supportsRefresh: boolean\n supportsRevoke: boolean\n supportsIncrementalAuth: boolean\n recommendedHealthcheckIntervalHours?: number\n freshnessSloMinutes?: number\n}\n\nexport interface IntegrationPlannerHints {\n useFor: string[]\n avoidFor?: string[]\n dataFreshness: 'realtime' | 'near_realtime' | 'eventual' | 'manual'\n writeRisk: 'low' | 'medium' | 'high'\n}\n\nexport interface IntegrationFamilySpec {\n id: IntegrationFamilyId\n title: string\n authMode: IntegrationAuthMode\n consoleUrl?: string\n authorizationUrl?: string\n tokenUrl?: string\n redirectUriTemplate?: string\n credentialFields: CredentialFieldSpec[]\n consoleSteps: ConsoleStep[]\n knownQuirks?: Quirk[]\n lifecycle: IntegrationLifecycleSpec\n}\n\nexport interface IntegrationSpecValidationIssue {\n path: string\n message: string\n}\n\nexport interface IntegrationSpecValidationResult {\n ok: boolean\n issues: IntegrationSpecValidationIssue[]\n}\n\nexport interface RenderSpecOptions {\n host: string\n callbackPath?: string\n}\n\nexport interface RenderedConsoleStep extends ConsoleStep {\n detail: string\n copyValue?: string\n}\n\nexport interface CredentialValidationInput {\n field: CredentialFieldSpec\n value: string\n}\n\nexport interface CredentialValidationResult {\n ok: boolean\n field: string\n message?: string\n}\n\nexport interface HealthcheckPlan {\n kind: string\n healthcheck: HealthcheckSpec\n requires: Array<'client_id' | 'client_secret' | 'api_key' | 'hmac_secret' | 'connection_credentials'>\n message: string\n}\n\nexport function specAuthToConnectorAuth(auth: IntegrationAuthSpec): IntegrationConnector['auth'] {\n if (auth.mode === 'api_key') return 'api_key'\n if (auth.mode === 'oauth2') return 'oauth2'\n if (auth.mode === 'none') return 'none'\n return 'custom'\n}\n","import type { IntegrationFamilyId, IntegrationFamilySpec } from './types.js'\n\nexport const INTEGRATION_FAMILIES: Record<IntegrationFamilyId, IntegrationFamilySpec> = {\n google: {\n id: 'google',\n title: 'Google OAuth',\n authMode: 'oauth2',\n consoleUrl: 'https://console.cloud.google.com/apis/credentials',\n authorizationUrl: 'https://accounts.google.com/o/oauth2/v2/auth',\n tokenUrl: 'https://oauth2.googleapis.com/token',\n redirectUriTemplate: 'https://{host}/api/integrations/oauth/google/callback',\n credentialFields: [\n { label: 'Client ID', env: 'GOOGLE_OAUTH_CLIENT_ID', description: 'Google OAuth client ID.', example: '1234567890-abc.apps.googleusercontent.com', regex: '^[0-9]+-[a-zA-Z0-9_-]+\\\\.apps\\\\.googleusercontent\\\\.com$', secret: false },\n { label: 'Client Secret', env: 'GOOGLE_OAUTH_CLIENT_SECRET', description: 'Google OAuth client secret.', example: 'GOCSPX-...', secret: true },\n ],\n consoleSteps: [\n { id: 'project', title: 'Select project', detail: 'Open Google Cloud Console and select the project that owns the OAuth client.' },\n { id: 'consent', title: 'Configure consent screen', detail: 'Configure OAuth consent, app name, support email, and publishing status appropriate for the deployment.' },\n { id: 'client', title: 'Create web client', detail: 'Create an OAuth client of type Web application.' },\n { id: 'redirect', title: 'Add redirect URI', detail: 'Add {redirectUri} as an authorized redirect URI.', copyValue: '{redirectUri}' },\n { id: 'scopes', title: 'Add scopes', detail: 'Add the provider scopes listed in this spec.' },\n ],\n knownQuirks: [\n { id: 'offline-access', severity: 'warning', message: 'Use access_type=offline and prompt=consent when refresh tokens are required.' },\n { id: 'verification', severity: 'warning', message: 'Sensitive or restricted scopes may require Google verification before broad external use.' },\n ],\n lifecycle: { supportsRefresh: true, supportsRevoke: true, supportsIncrementalAuth: true, recommendedHealthcheckIntervalHours: 24 },\n },\n 'microsoft-graph': {\n id: 'microsoft-graph',\n title: 'Microsoft Graph OAuth',\n authMode: 'oauth2',\n consoleUrl: 'https://entra.microsoft.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade',\n authorizationUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',\n tokenUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/token',\n redirectUriTemplate: 'https://{host}/api/integrations/oauth/microsoft/callback',\n credentialFields: [\n { label: 'Client ID', env: 'MS_OAUTH_CLIENT_ID', description: 'Microsoft Entra application client ID.', example: '00000000-0000-0000-0000-000000000000', regex: '^[0-9a-fA-F-]{36}$', secret: false },\n { label: 'Client Secret', env: 'MS_OAUTH_CLIENT_SECRET', description: 'Microsoft Entra client secret value.', secret: true },\n ],\n consoleSteps: [\n { id: 'app', title: 'Register app', detail: 'Create or open an app registration in Microsoft Entra.' },\n { id: 'redirect', title: 'Add redirect URI', detail: 'Add {redirectUri} as a Web redirect URI.', copyValue: '{redirectUri}' },\n { id: 'secret', title: 'Create secret', detail: 'Create a client secret and store the secret value, not the secret ID.' },\n { id: 'permissions', title: 'Add Graph permissions', detail: 'Add the delegated Graph scopes listed in this spec and grant admin consent where required.' },\n ],\n knownQuirks: [\n { id: 'tenant-common', severity: 'info', message: 'The common tenant supports multi-tenant OAuth; single-tenant deployments should override the tenant segment.' },\n { id: 'admin-consent', severity: 'warning', message: 'Some Graph scopes require tenant admin consent.' },\n ],\n lifecycle: { supportsRefresh: true, supportsRevoke: true, supportsIncrementalAuth: true, recommendedHealthcheckIntervalHours: 24 },\n },\n atlassian: {\n id: 'atlassian',\n title: 'Atlassian OAuth',\n authMode: 'oauth2',\n consoleUrl: 'https://developer.atlassian.com/console/myapps/',\n authorizationUrl: 'https://auth.atlassian.com/authorize',\n tokenUrl: 'https://auth.atlassian.com/oauth/token',\n redirectUriTemplate: 'https://{host}/api/integrations/oauth/atlassian/callback',\n credentialFields: [\n { label: 'Client ID', description: 'Atlassian OAuth client ID.', secret: false },\n { label: 'Client Secret', description: 'Atlassian OAuth client secret.', secret: true },\n ],\n consoleSteps: [\n { id: 'app', title: 'Create OAuth app', detail: 'Create an OAuth 2.0 app in the Atlassian developer console.' },\n { id: 'redirect', title: 'Add callback URL', detail: 'Add {redirectUri} as the callback URL.', copyValue: '{redirectUri}' },\n { id: 'apis', title: 'Enable APIs', detail: 'Enable the Jira or Confluence APIs required by this connector.' },\n ],\n lifecycle: { supportsRefresh: true, supportsRevoke: false, supportsIncrementalAuth: false, recommendedHealthcheckIntervalHours: 24 },\n },\n salesforce: {\n id: 'salesforce',\n title: 'Salesforce OAuth',\n authMode: 'oauth2',\n consoleUrl: 'https://login.salesforce.com',\n authorizationUrl: 'https://login.salesforce.com/services/oauth2/authorize',\n tokenUrl: 'https://login.salesforce.com/services/oauth2/token',\n redirectUriTemplate: 'https://{host}/api/integrations/oauth/salesforce/callback',\n credentialFields: [\n { label: 'Client ID', env: 'SALESFORCE_OAUTH_CLIENT_ID', description: 'Salesforce connected app consumer key.', secret: false },\n { label: 'Client Secret', env: 'SALESFORCE_OAUTH_CLIENT_SECRET', description: 'Salesforce connected app consumer secret.', secret: true },\n ],\n consoleSteps: [\n { id: 'connected-app', title: 'Create connected app', detail: 'Create a Salesforce connected app with OAuth enabled.' },\n { id: 'callback', title: 'Add callback URL', detail: 'Add {redirectUri} as the callback URL.', copyValue: '{redirectUri}' },\n { id: 'scopes', title: 'Select scopes', detail: 'Add api and refresh_token/offline_access, plus any connector-specific scopes.' },\n ],\n knownQuirks: [\n { id: 'instance-url', severity: 'critical', message: 'Runtime calls must use the instance_url returned by the token response.' },\n ],\n lifecycle: { supportsRefresh: true, supportsRevoke: true, supportsIncrementalAuth: false, recommendedHealthcheckIntervalHours: 24 },\n },\n hubspot: {\n id: 'hubspot',\n title: 'HubSpot OAuth',\n authMode: 'oauth2',\n consoleUrl: 'https://developers.hubspot.com/',\n authorizationUrl: 'https://app.hubspot.com/oauth/authorize',\n tokenUrl: 'https://api.hubapi.com/oauth/v1/token',\n redirectUriTemplate: 'https://{host}/api/integrations/oauth/hubspot/callback',\n credentialFields: [\n { label: 'Client ID', env: 'HUBSPOT_OAUTH_CLIENT_ID', description: 'HubSpot app client ID.', secret: false },\n { label: 'Client Secret', env: 'HUBSPOT_OAUTH_CLIENT_SECRET', description: 'HubSpot app client secret.', secret: true },\n ],\n consoleSteps: [\n { id: 'app', title: 'Create private/public app', detail: 'Create a HubSpot app and configure OAuth.' },\n { id: 'redirect', title: 'Add redirect URL', detail: 'Add {redirectUri} to the app redirect URLs.', copyValue: '{redirectUri}' },\n { id: 'scopes', title: 'Add CRM scopes', detail: 'Add the CRM object scopes listed in this spec.' },\n ],\n lifecycle: { supportsRefresh: true, supportsRevoke: true, supportsIncrementalAuth: false, recommendedHealthcheckIntervalHours: 24 },\n },\n slack: {\n id: 'slack',\n title: 'Slack OAuth',\n authMode: 'oauth2',\n consoleUrl: 'https://api.slack.com/apps',\n authorizationUrl: 'https://slack.com/oauth/v2/authorize',\n tokenUrl: 'https://slack.com/api/oauth.v2.access',\n redirectUriTemplate: 'https://{host}/api/integrations/oauth/slack/callback',\n credentialFields: [\n { label: 'Client ID', env: 'SLACK_OAUTH_CLIENT_ID', description: 'Slack app client ID.', secret: false },\n { label: 'Client Secret', env: 'SLACK_OAUTH_CLIENT_SECRET', description: 'Slack app client secret.', secret: true },\n ],\n consoleSteps: [\n { id: 'app', title: 'Create Slack app', detail: 'Create or open a Slack app.' },\n { id: 'redirect', title: 'Add redirect URL', detail: 'Add {redirectUri} under OAuth & Permissions.', copyValue: '{redirectUri}' },\n { id: 'scopes', title: 'Add bot scopes', detail: 'Add the bot token scopes listed in this spec and reinstall the app.' },\n ],\n knownQuirks: [\n { id: 'bot-token', severity: 'info', message: 'Slack usually returns a bot access token; refresh tokens require token rotation.' },\n ],\n lifecycle: { supportsRefresh: false, supportsRevoke: true, supportsIncrementalAuth: false, recommendedHealthcheckIntervalHours: 24 },\n },\n notion: {\n id: 'notion',\n title: 'Notion OAuth',\n authMode: 'oauth2',\n consoleUrl: 'https://www.notion.so/my-integrations',\n authorizationUrl: 'https://api.notion.com/v1/oauth/authorize',\n tokenUrl: 'https://api.notion.com/v1/oauth/token',\n redirectUriTemplate: 'https://{host}/api/integrations/oauth/notion/callback',\n credentialFields: [\n { label: 'Client ID', env: 'NOTION_OAUTH_CLIENT_ID', description: 'Notion integration OAuth client ID.', secret: false },\n { label: 'Client Secret', env: 'NOTION_OAUTH_CLIENT_SECRET', description: 'Notion integration OAuth client secret.', secret: true },\n ],\n consoleSteps: [\n { id: 'integration', title: 'Create integration', detail: 'Create a Notion public integration.' },\n { id: 'redirect', title: 'Add redirect URI', detail: 'Add {redirectUri} as the redirect URI.', copyValue: '{redirectUri}' },\n { id: 'capabilities', title: 'Select capabilities', detail: 'Enable read/update/insert capabilities matching this connector.' },\n ],\n lifecycle: { supportsRefresh: true, supportsRevoke: true, supportsIncrementalAuth: false, recommendedHealthcheckIntervalHours: 24 },\n },\n 'standard-oauth2': {\n id: 'standard-oauth2',\n title: 'Standard OAuth 2.0',\n authMode: 'oauth2',\n redirectUriTemplate: 'https://{host}/api/integrations/oauth/{kind}/callback',\n credentialFields: [\n { label: 'Client ID', description: 'OAuth client ID.', secret: false },\n { label: 'Client Secret', description: 'OAuth client secret.', secret: true },\n ],\n consoleSteps: [\n { id: 'app', title: 'Create OAuth app', detail: 'Create an OAuth app in the provider console.' },\n { id: 'redirect', title: 'Add redirect URI', detail: 'Add {redirectUri} as an allowed redirect URI.', copyValue: '{redirectUri}' },\n { id: 'scopes', title: 'Add scopes', detail: 'Add the scopes listed in this spec.' },\n ],\n lifecycle: { supportsRefresh: true, supportsRevoke: false, supportsIncrementalAuth: false, recommendedHealthcheckIntervalHours: 24 },\n },\n 'api-key': {\n id: 'api-key',\n title: 'API key',\n authMode: 'api_key',\n credentialFields: [\n { label: 'API Key', description: 'Provider API key or token.', example: 'sk_...', secret: true },\n ],\n consoleSteps: [\n { id: 'token', title: 'Create token', detail: 'Create an API key/token in the provider console with the minimum required permissions.' },\n ],\n lifecycle: { supportsRefresh: false, supportsRevoke: true, supportsIncrementalAuth: false, recommendedHealthcheckIntervalHours: 24 },\n },\n hmac: {\n id: 'hmac',\n title: 'HMAC secret',\n authMode: 'hmac',\n credentialFields: [\n { label: 'Signing Secret', description: 'Webhook signing secret.', secret: true },\n ],\n consoleSteps: [\n { id: 'secret', title: 'Configure signing secret', detail: 'Configure the shared signing secret in the sender and receiver.' },\n ],\n lifecycle: { supportsRefresh: false, supportsRevoke: true, supportsIncrementalAuth: false, recommendedHealthcheckIntervalHours: 24 },\n },\n none: {\n id: 'none',\n title: 'No authentication',\n authMode: 'none',\n credentialFields: [],\n consoleSteps: [\n { id: 'configure', title: 'Configure endpoint', detail: 'No provider credentials are required.' },\n ],\n lifecycle: { supportsRefresh: false, supportsRevoke: false, supportsIncrementalAuth: false },\n },\n}\n\nexport function getIntegrationFamily(id: IntegrationFamilyId): IntegrationFamilySpec {\n return INTEGRATION_FAMILIES[id]\n}\n","import type {\n IntegrationConnector,\n IntegrationConnectorAction,\n IntegrationConnectorCategory,\n IntegrationConnectorTrigger,\n IntegrationProviderKind,\n} from './index.js'\n\nexport type IntegrationCoveragePriority = 'tier_0' | 'tier_1' | 'tier_2' | 'long_tail'\n\nexport interface IntegrationCoverageSpec {\n id: string\n title: string\n category: IntegrationConnectorCategory\n auth: IntegrationConnector['auth']\n priority: IntegrationCoveragePriority\n providerKinds: IntegrationProviderKind[]\n domains: string[]\n actionPack: IntegrationActionPack\n scopes?: string[]\n}\n\nexport type IntegrationActionPack =\n | 'email'\n | 'calendar'\n | 'chat'\n | 'crm'\n | 'storage'\n | 'docs'\n | 'database'\n | 'project'\n | 'support'\n | 'marketing'\n | 'sales'\n | 'commerce'\n | 'finance'\n | 'hr'\n | 'dev'\n | 'ai'\n | 'analytics'\n | 'workflow'\n | 'webhook'\n\ntype SpecTuple = [\n id: string,\n title: string,\n category: IntegrationConnectorCategory,\n actionPack: IntegrationActionPack,\n priority: IntegrationCoveragePriority,\n domains: string,\n auth?: IntegrationConnector['auth'],\n]\n\nconst DEFAULT_PROVIDER_KINDS: IntegrationProviderKind[] = ['first_party', 'nango', 'pipedream', 'tangle_catalog', 'custom']\n\nconst COVERAGE_SPECS: SpecTuple[] = [\n ['gmail', 'Gmail', 'email', 'email', 'tier_0', 'email,google,workspace,inbox'],\n ['outlook-mail', 'Outlook Mail', 'email', 'email', 'tier_0', 'email,microsoft,office,inbox'],\n ['google-calendar', 'Google Calendar', 'calendar', 'calendar', 'tier_0', 'calendar,google,workspace,scheduling'],\n ['outlook-calendar', 'Outlook Calendar', 'calendar', 'calendar', 'tier_0', 'calendar,microsoft,office,scheduling'],\n ['slack', 'Slack', 'chat', 'chat', 'tier_0', 'chat,collaboration,internal-comms'],\n ['microsoft-teams', 'Microsoft Teams', 'chat', 'chat', 'tier_0', 'chat,microsoft,collaboration'],\n ['google-drive', 'Google Drive', 'storage', 'storage', 'tier_0', 'files,google,workspace,storage'],\n ['onedrive', 'OneDrive', 'storage', 'storage', 'tier_0', 'files,microsoft,office,storage'],\n ['dropbox', 'Dropbox', 'storage', 'storage', 'tier_1', 'files,storage'],\n ['box', 'Box', 'storage', 'storage', 'tier_1', 'files,enterprise,storage'],\n ['google-docs', 'Google Docs', 'docs', 'docs', 'tier_0', 'docs,google,workspace'],\n ['google-sheets', 'Google Sheets', 'database', 'database', 'tier_0', 'sheets,spreadsheet,google,database'],\n ['microsoft-excel', 'Microsoft Excel', 'database', 'database', 'tier_0', 'sheets,spreadsheet,microsoft,database'],\n ['notion', 'Notion', 'docs', 'docs', 'tier_0', 'docs,wiki,knowledge'],\n ['airtable', 'Airtable', 'database', 'database', 'tier_0', 'database,spreadsheet,ops'],\n ['coda', 'Coda', 'docs', 'docs', 'tier_1', 'docs,wiki,ops'],\n ['confluence', 'Confluence', 'docs', 'docs', 'tier_1', 'docs,wiki,atlassian'],\n ['sharepoint', 'SharePoint', 'storage', 'storage', 'tier_1', 'files,microsoft,enterprise'],\n ['hubspot', 'HubSpot', 'crm', 'crm', 'tier_0', 'crm,sales,marketing'],\n ['salesforce', 'Salesforce', 'crm', 'crm', 'tier_0', 'crm,sales,enterprise'],\n ['pipedrive', 'Pipedrive', 'crm', 'crm', 'tier_1', 'crm,sales'],\n ['zoho-crm', 'Zoho CRM', 'crm', 'crm', 'tier_1', 'crm,sales'],\n ['close', 'Close', 'crm', 'crm', 'tier_1', 'crm,sales'],\n ['attio', 'Attio', 'crm', 'crm', 'tier_1', 'crm,sales,startups'],\n ['linear', 'Linear', 'workflow', 'project', 'tier_0', 'project,engineering,tickets'],\n ['jira', 'Jira', 'workflow', 'project', 'tier_0', 'project,engineering,tickets,atlassian'],\n ['github', 'GitHub', 'workflow', 'dev', 'tier_0', 'code,dev,issues,git'],\n ['gitlab', 'GitLab', 'workflow', 'dev', 'tier_1', 'code,dev,issues,git'],\n ['bitbucket', 'Bitbucket', 'workflow', 'dev', 'tier_2', 'code,dev,git,atlassian'],\n ['asana', 'Asana', 'workflow', 'project', 'tier_1', 'project,tasks'],\n ['trello', 'Trello', 'workflow', 'project', 'tier_1', 'project,tasks,atlassian'],\n ['monday', 'monday.com', 'workflow', 'project', 'tier_1', 'project,tasks,ops'],\n ['clickup', 'ClickUp', 'workflow', 'project', 'tier_1', 'project,tasks,ops'],\n ['basecamp', 'Basecamp', 'workflow', 'project', 'tier_2', 'project,tasks'],\n ['zendesk', 'Zendesk', 'crm', 'support', 'tier_0', 'support,tickets,customer-success'],\n ['intercom', 'Intercom', 'crm', 'support', 'tier_0', 'support,chat,customer-success'],\n ['freshdesk', 'Freshdesk', 'crm', 'support', 'tier_1', 'support,tickets'],\n ['helpscout', 'Help Scout', 'crm', 'support', 'tier_1', 'support,tickets'],\n ['front', 'Front', 'email', 'support', 'tier_1', 'support,email,shared-inbox'],\n ['gorgias', 'Gorgias', 'crm', 'support', 'tier_1', 'support,ecommerce'],\n ['stripe', 'Stripe', 'workflow', 'finance', 'tier_0', 'payments,billing,finance'],\n ['quickbooks', 'QuickBooks', 'workflow', 'finance', 'tier_0', 'accounting,finance'],\n ['xero', 'Xero', 'workflow', 'finance', 'tier_1', 'accounting,finance'],\n ['netsuite', 'NetSuite', 'workflow', 'finance', 'tier_1', 'erp,finance,enterprise'],\n ['sage', 'Sage', 'workflow', 'finance', 'tier_2', 'accounting,finance'],\n ['plaid', 'Plaid', 'workflow', 'finance', 'tier_1', 'banking,finance'],\n ['shopify', 'Shopify', 'workflow', 'commerce', 'tier_0', 'ecommerce,orders,commerce'],\n ['woocommerce', 'WooCommerce', 'workflow', 'commerce', 'tier_1', 'ecommerce,orders,wordpress'],\n ['bigcommerce', 'BigCommerce', 'workflow', 'commerce', 'tier_1', 'ecommerce,orders'],\n ['amazon-seller-central', 'Amazon Seller Central', 'workflow', 'commerce', 'tier_1', 'marketplace,ecommerce'],\n ['ebay', 'eBay', 'workflow', 'commerce', 'tier_2', 'marketplace,ecommerce'],\n ['etsy', 'Etsy', 'workflow', 'commerce', 'tier_2', 'marketplace,ecommerce'],\n ['mailchimp', 'Mailchimp', 'workflow', 'marketing', 'tier_0', 'email-marketing,marketing'],\n ['klaviyo', 'Klaviyo', 'workflow', 'marketing', 'tier_0', 'email-marketing,ecommerce,marketing'],\n ['marketo', 'Marketo', 'workflow', 'marketing', 'tier_1', 'marketing,enterprise'],\n ['braze', 'Braze', 'workflow', 'marketing', 'tier_1', 'marketing,lifecycle'],\n ['customer-io', 'Customer.io', 'workflow', 'marketing', 'tier_1', 'marketing,lifecycle'],\n ['sendgrid', 'SendGrid', 'email', 'email', 'tier_1', 'email,transactional'],\n ['postmark', 'Postmark', 'email', 'email', 'tier_1', 'email,transactional'],\n ['twilio', 'Twilio', 'chat', 'chat', 'tier_0', 'sms,voice,communications'],\n ['phony', 'ph0ny', 'chat', 'chat', 'tier_1', 'voice,telephony,communications', 'api_key'],\n ['discord', 'Discord', 'chat', 'chat', 'tier_1', 'chat,community'],\n ['telegram', 'Telegram', 'chat', 'chat', 'tier_1', 'chat,community'],\n ['whatsapp-business', 'WhatsApp Business', 'chat', 'chat', 'tier_1', 'chat,meta,customer-comms'],\n ['facebook-pages', 'Facebook Pages', 'workflow', 'marketing', 'tier_1', 'social,meta,marketing'],\n ['instagram-business', 'Instagram Business', 'workflow', 'marketing', 'tier_1', 'social,meta,marketing'],\n ['linkedin', 'LinkedIn', 'workflow', 'sales', 'tier_1', 'social,sales,gtm'],\n ['x-twitter', 'X / Twitter', 'workflow', 'marketing', 'tier_1', 'social,marketing'],\n ['youtube', 'YouTube', 'storage', 'storage', 'tier_1', 'video,content'],\n ['tiktok', 'TikTok', 'workflow', 'marketing', 'tier_2', 'social,video,marketing'],\n ['google-analytics', 'Google Analytics', 'database', 'analytics', 'tier_0', 'analytics,web,marketing'],\n ['mixpanel', 'Mixpanel', 'database', 'analytics', 'tier_1', 'analytics,product'],\n ['amplitude', 'Amplitude', 'database', 'analytics', 'tier_1', 'analytics,product'],\n ['segment', 'Segment', 'database', 'analytics', 'tier_1', 'analytics,cdp'],\n ['snowflake', 'Snowflake', 'database', 'database', 'tier_0', 'warehouse,data'],\n ['bigquery', 'BigQuery', 'database', 'database', 'tier_0', 'warehouse,google,data'],\n ['redshift', 'Redshift', 'database', 'database', 'tier_1', 'warehouse,aws,data'],\n ['postgres', 'Postgres', 'database', 'database', 'tier_0', 'database,sql'],\n ['mysql', 'MySQL', 'database', 'database', 'tier_1', 'database,sql'],\n ['mongodb', 'MongoDB', 'database', 'database', 'tier_1', 'database,nosql'],\n ['supabase', 'Supabase', 'database', 'database', 'tier_1', 'database,postgres'],\n ['firebase', 'Firebase', 'database', 'database', 'tier_1', 'database,google,app'],\n ['redis', 'Redis', 'database', 'database', 'tier_2', 'database,cache'],\n ['aws-s3', 'Amazon S3', 'storage', 'storage', 'tier_0', 'files,aws,storage'],\n ['aws-lambda', 'AWS Lambda', 'workflow', 'dev', 'tier_1', 'aws,serverless,dev'],\n ['aws-cloudwatch', 'AWS CloudWatch', 'database', 'analytics', 'tier_1', 'aws,logs,observability'],\n ['google-cloud-storage', 'Google Cloud Storage', 'storage', 'storage', 'tier_1', 'files,gcp,storage'],\n ['azure-blob-storage', 'Azure Blob Storage', 'storage', 'storage', 'tier_1', 'files,azure,storage'],\n ['vercel', 'Vercel', 'workflow', 'dev', 'tier_1', 'deployments,dev'],\n ['netlify', 'Netlify', 'workflow', 'dev', 'tier_2', 'deployments,dev'],\n ['cloudflare', 'Cloudflare', 'workflow', 'dev', 'tier_1', 'edge,dev,dns'],\n ['sentry', 'Sentry', 'workflow', 'dev', 'tier_1', 'errors,observability,dev'],\n ['datadog', 'Datadog', 'database', 'analytics', 'tier_1', 'observability,logs,metrics'],\n ['new-relic', 'New Relic', 'database', 'analytics', 'tier_2', 'observability,logs,metrics'],\n ['pagerduty', 'PagerDuty', 'workflow', 'project', 'tier_1', 'incident,on-call'],\n ['opsgenie', 'Opsgenie', 'workflow', 'project', 'tier_2', 'incident,on-call,atlassian'],\n ['okta', 'Okta', 'internal', 'workflow', 'tier_1', 'identity,security'],\n ['auth0', 'Auth0', 'internal', 'workflow', 'tier_1', 'identity,security'],\n ['workday', 'Workday', 'workflow', 'hr', 'tier_1', 'hr,finance,enterprise'],\n ['bamboohr', 'BambooHR', 'workflow', 'hr', 'tier_1', 'hr,people'],\n ['greenhouse', 'Greenhouse', 'workflow', 'hr', 'tier_1', 'recruiting,hr'],\n ['lever', 'Lever', 'workflow', 'hr', 'tier_1', 'recruiting,hr'],\n ['gusto', 'Gusto', 'workflow', 'hr', 'tier_1', 'payroll,hr'],\n ['rippling', 'Rippling', 'workflow', 'hr', 'tier_1', 'hr,it,identity'],\n ['docusign', 'DocuSign', 'docs', 'docs', 'tier_1', 'contracts,signature,legal'],\n ['pandadoc', 'PandaDoc', 'docs', 'docs', 'tier_1', 'contracts,signature,sales'],\n ['hellosign', 'Dropbox Sign', 'docs', 'docs', 'tier_2', 'contracts,signature'],\n ['clio', 'Clio', 'workflow', 'project', 'tier_1', 'legal,practice-management'],\n ['ironclad', 'Ironclad', 'docs', 'docs', 'tier_1', 'legal,contracts'],\n ['lexisnexis', 'LexisNexis', 'docs', 'docs', 'tier_2', 'legal,research'],\n ['calendly', 'Calendly', 'calendar', 'calendar', 'tier_0', 'scheduling,calendar'],\n ['cal-com', 'Cal.com', 'calendar', 'calendar', 'tier_1', 'scheduling,calendar'],\n ['zoom', 'Zoom', 'calendar', 'calendar', 'tier_0', 'meetings,video,calendar'],\n ['google-meet', 'Google Meet', 'calendar', 'calendar', 'tier_1', 'meetings,google,video'],\n ['microsoft-graph', 'Microsoft Graph', 'internal', 'workflow', 'tier_0', 'microsoft,enterprise,identity'],\n ['openai', 'OpenAI', 'workflow', 'ai', 'tier_0', 'ai,llm'],\n ['anthropic', 'Anthropic', 'workflow', 'ai', 'tier_1', 'ai,llm'],\n ['gemini', 'Google Gemini', 'workflow', 'ai', 'tier_1', 'ai,llm,google'],\n ['huggingface', 'Hugging Face', 'workflow', 'ai', 'tier_1', 'ai,models'],\n ['pinecone', 'Pinecone', 'database', 'database', 'tier_1', 'vector,database,ai'],\n ['weaviate', 'Weaviate', 'database', 'database', 'tier_1', 'vector,database,ai'],\n ['qdrant', 'Qdrant', 'database', 'database', 'tier_1', 'vector,database,ai'],\n ['zapier', 'Zapier', 'workflow', 'workflow', 'tier_1', 'automation,workflow'],\n ['make', 'Make', 'workflow', 'workflow', 'tier_1', 'automation,workflow'],\n ['nango', 'Nango', 'workflow', 'workflow', 'tier_1', 'integration-platform,oauth'],\n ['pipedream', 'Pipedream', 'workflow', 'workflow', 'tier_1', 'integration-platform,workflow'],\n ['open-automation-catalog', 'Open Automation Catalog', 'workflow', 'workflow', 'tier_1', 'automation,workflow,open-source'],\n ['webhook', 'Generic Webhook', 'webhook', 'webhook', 'tier_0', 'webhook,http,events', 'none'],\n ['http', 'HTTP Request', 'workflow', 'webhook', 'tier_0', 'http,api,webhook', 'none'],\n ['rss', 'RSS', 'webhook', 'webhook', 'tier_1', 'feeds,content', 'none'],\n ['zapier-transfer', 'Zapier Transfer', 'workflow', 'workflow', 'long_tail', 'automation,migration'],\n ['typeform', 'Typeform', 'workflow', 'marketing', 'tier_1', 'forms,marketing'],\n ['google-forms', 'Google Forms', 'workflow', 'marketing', 'tier_1', 'forms,google'],\n ['jotform', 'Jotform', 'workflow', 'marketing', 'tier_2', 'forms'],\n ['webflow', 'Webflow', 'workflow', 'marketing', 'tier_1', 'cms,website'],\n ['wordpress', 'WordPress', 'workflow', 'marketing', 'tier_1', 'cms,website'],\n ['contentful', 'Contentful', 'docs', 'docs', 'tier_1', 'cms,content'],\n ['sanity', 'Sanity', 'docs', 'docs', 'tier_1', 'cms,content'],\n ['figma', 'Figma', 'docs', 'docs', 'tier_0', 'design,creative'],\n ['canva', 'Canva', 'docs', 'docs', 'tier_1', 'design,creative'],\n ['adobe-creative-cloud', 'Adobe Creative Cloud', 'storage', 'storage', 'tier_1', 'design,creative,files'],\n ['miro', 'Miro', 'docs', 'docs', 'tier_1', 'whiteboard,collaboration'],\n ['figjam', 'FigJam', 'docs', 'docs', 'tier_2', 'whiteboard,design'],\n]\n\nexport function listIntegrationCoverageSpecs(): IntegrationCoverageSpec[] {\n return COVERAGE_SPECS.map(([id, title, category, actionPack, priority, domains, auth = 'oauth2']) => ({\n id,\n title,\n category,\n actionPack,\n priority,\n auth,\n providerKinds: providerKindsFor(auth),\n domains: domains.split(',').map((domain) => domain.trim()).filter(Boolean),\n scopes: scopesFor(id, actionPack),\n }))\n}\n\nexport function buildIntegrationCoverageConnectors(options: {\n providerId?: string\n priorities?: IntegrationCoveragePriority[]\n categories?: IntegrationConnectorCategory[]\n actionPacks?: IntegrationActionPack[]\n} = {}): IntegrationConnector[] {\n const providerId = options.providerId ?? 'coverage'\n return listIntegrationCoverageSpecs()\n .filter((spec) => !options.priorities || options.priorities.includes(spec.priority))\n .filter((spec) => !options.categories || options.categories.includes(spec.category))\n .filter((spec) => !options.actionPacks || options.actionPacks.includes(spec.actionPack))\n .map((spec) => specToConnector(spec, providerId))\n}\n\nexport function integrationCoverageChecklistMarkdown(): string {\n const specs = listIntegrationCoverageSpecs()\n const lines = [\n '# Agent Integrations Coverage Checklist',\n '',\n 'Generated from `listIntegrationCoverageSpecs()`. Catalog presence means the product can plan/request/connect the integration; native adapters and runtime backends execute behind the same provider contract.',\n '',\n '## Summary',\n '',\n `- Total cataloged integrations: ${specs.length}`,\n `- Tier 0: ${specs.filter((spec) => spec.priority === 'tier_0').length}`,\n `- Tier 1: ${specs.filter((spec) => spec.priority === 'tier_1').length}`,\n `- Tier 2: ${specs.filter((spec) => spec.priority === 'tier_2').length}`,\n `- Long tail: ${specs.filter((spec) => spec.priority === 'long_tail').length}`,\n '',\n '## Checklist',\n '',\n ]\n for (const spec of specs) {\n lines.push(`- [ ] ${spec.priority} / ${spec.category} / ${spec.title} (${spec.id}) - ${spec.domains.join(', ')}`)\n }\n return `${lines.join('\\n')}\\n`\n}\n\nfunction specToConnector(spec: IntegrationCoverageSpec, providerId: string): IntegrationConnector {\n const actions = actionPack(spec.actionPack, spec.scopes ?? [])\n return {\n id: spec.id,\n providerId,\n title: spec.title,\n category: spec.category,\n auth: spec.auth,\n scopes: spec.scopes ?? [],\n actions,\n triggers: triggersFor(spec.actionPack, spec.scopes ?? []),\n metadata: {\n source: 'coverage-catalog',\n priority: spec.priority,\n domains: spec.domains,\n providerKinds: spec.providerKinds,\n executable: false,\n },\n }\n}\n\nfunction actionPack(pack: IntegrationActionPack, scopes: string[]): IntegrationConnectorAction[] {\n const readScope = scopes.find((scope) => scope.endsWith('.read')) ?? scopes[0]\n const writeScope = scopes.find((scope) => scope.endsWith('.write')) ?? scopes[1] ?? readScope\n const scope = (value?: string) => value ? [value] : []\n const read = (id: string, title: string, description: string): IntegrationConnectorAction => ({\n id,\n title,\n description,\n risk: 'read',\n requiredScopes: scope(readScope),\n dataClass: dataClassFor(pack),\n inputSchema: objectSchema(),\n })\n const write = (id: string, title: string, description: string): IntegrationConnectorAction => ({\n id,\n title,\n description,\n risk: 'write',\n requiredScopes: scope(writeScope),\n dataClass: dataClassFor(pack),\n approvalRequired: true,\n inputSchema: objectSchema(),\n })\n const destructive = (id: string, title: string, description: string): IntegrationConnectorAction => ({\n id,\n title,\n description,\n risk: 'destructive',\n requiredScopes: scope(writeScope),\n dataClass: dataClassFor(pack),\n approvalRequired: true,\n inputSchema: objectSchema(),\n })\n switch (pack) {\n case 'email': return [read('messages.search', 'Search messages', 'Search messages and threads.'), read('messages.read', 'Read message', 'Read a message by id.'), write('drafts.create', 'Create draft', 'Create an email draft.'), write('messages.send', 'Send message', 'Send or reply to an email message.')]\n case 'calendar': return [read('events.search', 'Search events', 'Search calendar events.'), read('availability.read', 'Read availability', 'Read availability windows.'), write('events.create', 'Create event', 'Create a calendar event.'), write('events.update', 'Update event', 'Update a calendar event.'), destructive('events.cancel', 'Cancel event', 'Cancel a calendar event.')]\n case 'chat': return [read('messages.search', 'Search messages', 'Search channel or direct messages.'), read('channels.list', 'List channels', 'List channels or rooms.'), write('messages.post', 'Send message', 'Send a message to a channel or direct message.'), write('threads.reply', 'Reply in thread', 'Reply to a thread or conversation.')]\n case 'crm': return [read('records.search', 'Search records', 'Search contacts, companies, and deals.'), read('records.read', 'Read record', 'Read a CRM record.'), write('records.upsert', 'Upsert record', 'Create or update a CRM record.'), write('notes.create', 'Create note', 'Add a note or activity.')]\n case 'storage': return [read('files.search', 'Search files', 'Search files and folders.'), read('files.read', 'Read file', 'Read file metadata or content.'), write('files.upload', 'Upload file', 'Upload a file.'), write('files.update', 'Update file', 'Update file metadata or content.')]\n case 'docs': return [read('documents.search', 'Search documents', 'Search documents or pages.'), read('documents.read', 'Read document', 'Read a document.'), write('documents.create', 'Create document', 'Create a document or page.'), write('documents.update', 'Update document', 'Update a document or page.')]\n case 'database': return [read('records.query', 'Query records', 'Query rows, records, or objects.'), read('records.read', 'Read record', 'Read one row, record, or object.'), write('records.upsert', 'Upsert record', 'Create or update a row, record, or object.'), destructive('records.delete', 'Delete record', 'Delete a row, record, or object.')]\n case 'project': return [read('tasks.search', 'Search tasks', 'Search tasks, tickets, or issues.'), read('tasks.read', 'Read task', 'Read a task, ticket, or issue.'), write('tasks.create', 'Create task', 'Create a task, ticket, or issue.'), write('tasks.update', 'Update task', 'Update a task, ticket, or issue.')]\n case 'support': return [read('tickets.search', 'Search tickets', 'Search support tickets or conversations.'), read('customers.read', 'Read customer', 'Read a customer profile.'), write('tickets.reply', 'Reply to ticket', 'Reply to a support ticket.'), write('tickets.update', 'Update ticket', 'Update ticket status, tags, or assignee.')]\n case 'marketing': return [read('contacts.search', 'Search contacts', 'Search marketing contacts or audiences.'), read('campaigns.read', 'Read campaign', 'Read campaign metadata and performance.'), write('contacts.upsert', 'Upsert contact', 'Create or update a contact.'), write('campaigns.create', 'Create campaign', 'Create a campaign draft.')]\n case 'sales': return [read('prospects.search', 'Search prospects', 'Search prospects, leads, or accounts.'), read('activities.read', 'Read activities', 'Read sales activity history.'), write('prospects.upsert', 'Upsert prospect', 'Create or update a prospect.'), write('sequence.enqueue', 'Enroll in sequence', 'Enroll a prospect in a sales sequence.')]\n case 'commerce': return [read('orders.search', 'Search orders', 'Search orders.'), read('customers.read', 'Read customer', 'Read customer and purchase history.'), write('orders.update', 'Update order', 'Update order metadata or fulfillment state.'), write('products.update', 'Update product', 'Update product metadata.')]\n case 'finance': return [read('transactions.search', 'Search transactions', 'Search transactions, invoices, or payments.'), read('accounts.read', 'Read account', 'Read account or customer financial record.'), write('invoices.create', 'Create invoice', 'Create an invoice or payment object.'), write('records.sync', 'Sync record', 'Sync a finance or accounting record.')]\n case 'hr': return [read('people.search', 'Search people', 'Search employees, candidates, or contractors.'), read('people.read', 'Read person', 'Read a person profile.'), write('people.update', 'Update person', 'Update a person profile.'), write('events.create', 'Create HR event', 'Create a recruiting or HR event.')]\n case 'dev': return [read('resources.search', 'Search resources', 'Search issues, repos, deployments, logs, or incidents.'), read('resources.read', 'Read resource', 'Read a developer resource.'), write('resources.create', 'Create resource', 'Create an issue, deployment, incident, or config.'), write('resources.update', 'Update resource', 'Update a developer resource.')]\n case 'ai': return [read('models.list', 'List models', 'List available models or endpoints.'), write('responses.create', 'Create response', 'Create an AI response or job.'), write('embeddings.create', 'Create embeddings', 'Create embeddings or vector jobs.'), read('usage.read', 'Read usage', 'Read usage metadata.')]\n case 'analytics': return [read('reports.query', 'Query reports', 'Query analytics reports.'), read('events.search', 'Search events', 'Search analytics events.'), write('events.track', 'Track event', 'Track an analytics event.'), write('audiences.sync', 'Sync audience', 'Sync an audience or cohort.')]\n case 'workflow': return [read('runs.search', 'Search runs', 'Search workflow runs or jobs.'), read('templates.list', 'List templates', 'List workflow templates.'), write('runs.start', 'Start run', 'Start a workflow run.'), write('webhooks.dispatch', 'Dispatch webhook', 'Dispatch a workflow webhook.')]\n case 'webhook': return [write('requests.send', 'Send request', 'Send an HTTP request or webhook event.'), read('events.search', 'Search events', 'Search received webhook events.'), write('subscriptions.create', 'Create subscription', 'Create a webhook subscription.'), destructive('subscriptions.delete', 'Delete subscription', 'Delete a webhook subscription.')]\n }\n}\n\nfunction triggersFor(pack: IntegrationActionPack, scopes: string[]): IntegrationConnectorTrigger[] | undefined {\n const readScope = scopes.find((scope) => scope.endsWith('.read')) ?? scopes[0]\n const requiredScopes = readScope ? [readScope] : []\n if (pack === 'email') return [{ id: 'message.received', title: 'Message received', requiredScopes, dataClass: 'private' }]\n if (pack === 'calendar') return [{ id: 'event.changed', title: 'Event changed', requiredScopes, dataClass: 'private' }]\n if (pack === 'chat') return [{ id: 'message.posted', title: 'Message posted', requiredScopes, dataClass: 'private' }]\n if (pack === 'crm') return [{ id: 'record.changed', title: 'Record changed', requiredScopes, dataClass: 'private' }]\n if (pack === 'support') return [{ id: 'ticket.changed', title: 'Ticket changed', requiredScopes, dataClass: 'private' }]\n if (pack === 'commerce') return [{ id: 'order.changed', title: 'Order changed', requiredScopes, dataClass: 'sensitive' }]\n if (pack === 'finance') return [{ id: 'transaction.changed', title: 'Transaction changed', requiredScopes, dataClass: 'sensitive' }]\n if (pack === 'workflow' || pack === 'webhook') return [{ id: 'event.received', title: 'Event received', requiredScopes, dataClass: 'internal' }]\n return undefined\n}\n\nfunction scopesFor(id: string, pack: IntegrationActionPack): string[] {\n if (pack === 'webhook') return []\n return [`${id}.read`, `${id}.write`]\n}\n\nfunction providerKindsFor(auth: IntegrationConnector['auth']): IntegrationProviderKind[] {\n if (auth === 'none') return ['first_party', 'pipedream', 'tangle_catalog', 'custom']\n return DEFAULT_PROVIDER_KINDS\n}\n\nfunction dataClassFor(pack: IntegrationActionPack): 'public' | 'internal' | 'private' | 'sensitive' {\n if (pack === 'finance' || pack === 'commerce' || pack === 'hr') return 'sensitive'\n if (pack === 'workflow' || pack === 'webhook' || pack === 'dev' || pack === 'analytics') return 'internal'\n return 'private'\n}\n\nfunction objectSchema(): unknown {\n return { type: 'object', additionalProperties: true, properties: {} }\n}\n","/**\n * Per-kind overrides on top of family defaults.\n *\n * The family layer (`families.ts`) carries the auth-shape defaults — generic\n * \"API Key\" or \"Client ID + Client Secret\" credential fields, generic console\n * steps. Most kinds are happy with that. But some have provider-specific\n * shape that the family can't capture: Twilio's auth is two-part (Account\n * SID + Auth Token); Stripe's preferred path is restricted keys with specific\n * granted permissions; SendGrid demands a verified sender domain in the\n * console before keys work.\n *\n * `INTEGRATION_OVERRIDES` is the seam for that. The registry merges the\n * override on top of the family defaults at spec-build time. Override\n * fields are purely additive — set what you want to customize, leave the\n * rest absent and the family defaults apply.\n *\n * Adding a new override:\n * 1. Author the override entry below.\n * 2. The next spec build picks it up automatically; no other registry\n * change needed. Coverage catalog stays compact.\n *\n * Why a separate map and not inline on `IntegrationCoverageSpec`: the\n * coverage catalog is a flat tuple list optimized for fast iteration over\n * 142 specs. Bloating the tuple with optional override fields hurts\n * readability of the catalog AND scatters provider knowledge across two\n * data shapes. Keeping overrides in their own keyed map means contributors\n * looking for \"how does Stripe credential setup work\" find it in one place.\n */\n\nimport type {\n ConsoleStep,\n CredentialFieldSpec,\n HealthcheckSpec,\n PostSetupCheck,\n Quirk,\n} from './types.js'\n\nexport interface IntegrationOverride {\n /** Replaces `setup.consoleUrl` from the family default. */\n consoleUrl?: string\n /** Replaces `setup.consoleSteps`. Specify the full list — overrides do\n * not deep-merge step arrays because step ordering is meaningful. */\n consoleSteps?: ConsoleStep[]\n /** Replaces `setup.credentialFields`. Use to add a second field (e.g.\n * Twilio Account SID + Auth Token), tighten validation regex, or\n * enrich field descriptions with provider-specific guidance. */\n credentialFields?: CredentialFieldSpec[]\n /** Appended to `setup.knownQuirks`. */\n knownQuirks?: Quirk[]\n /** Replaces `setup.postSetup`. */\n postSetup?: PostSetupCheck[]\n /** Replaces the healthcheck the registry would otherwise infer. */\n healthcheck?: HealthcheckSpec\n}\n\nexport const INTEGRATION_OVERRIDES: Record<string, IntegrationOverride> = {\n // ── Stripe pack ────────────────────────────────────────────────────\n // Stripe issues two key types: secret keys (sk_*) and restricted keys\n // (rk_*). For voice-agent workloads, restricted keys are the right call\n // — least-privilege scoped to the specific resources the agent can\n // touch. The hint nudges operators toward that path.\n 'stripe-pack': {\n consoleUrl: 'https://dashboard.stripe.com/apikeys',\n credentialFields: [\n {\n label: 'Stripe secret key',\n description:\n 'Restricted key recommended. Dashboard → Developers → API keys → Create restricted key. ' +\n 'Grant write access on Customers, Invoices, and Checkout Sessions.',\n example: 'sk_live_… or rk_live_… (use sk_test_… / rk_test_… for staging)',\n regex: '^(sk|rk)_(live|test)_[A-Za-z0-9]+$',\n secret: true,\n },\n ],\n consoleSteps: [\n {\n id: 'open-keys',\n title: 'Open Stripe API keys',\n detail: 'Visit https://dashboard.stripe.com/apikeys',\n copyValue: 'https://dashboard.stripe.com/apikeys',\n },\n {\n id: 'create-restricted',\n title: 'Create a restricted key',\n detail:\n 'Click \"Create restricted key\". Name it something descriptive ' +\n '(e.g. \"ph0ny voice agent — prod\"). Grant WRITE on Customers, ' +\n 'Invoices, and Checkout Sessions. Leave everything else NONE.',\n },\n {\n id: 'paste',\n title: 'Paste the key',\n detail:\n 'Copy the key Stripe shows once (rk_live_… or sk_live_…). ' +\n 'Paste it into ph0ny. The key is sealed before persistence.',\n },\n ],\n },\n\n // ── Twilio SMS ─────────────────────────────────────────────────────\n // Twilio's REST API uses Basic auth with two parts: Account SID\n // (public-ish, AC…) + Auth Token (secret). The default api-key family\n // only exposes one field, which doesn't fit. Providing both fields\n // explicitly lets the consumer's UI render two inputs.\n 'twilio-sms': {\n consoleUrl: 'https://console.twilio.com/',\n credentialFields: [\n {\n label: 'Account SID',\n description: 'Your Twilio Account SID. Console → Account → API keys & tokens.',\n example: 'AC… (34 hex chars)',\n regex: '^AC[a-f0-9]{32}$',\n secret: false,\n },\n {\n label: 'Auth Token',\n description:\n 'Your Twilio Auth Token (or Standard API Key secret). ' +\n 'Use a non-primary auth token in production so rotating it ' +\n \"won't break other Twilio integrations.\",\n secret: true,\n },\n ],\n consoleSteps: [\n {\n id: 'open',\n title: 'Open Twilio console',\n detail: 'Visit https://console.twilio.com/',\n copyValue: 'https://console.twilio.com/',\n },\n {\n id: 'find',\n title: 'Find your Account SID + Auth Token',\n detail:\n 'Account info is on the dashboard home. For better security, ' +\n 'create a Standard API Key (Account → API keys & tokens → Create ' +\n 'API Key) and use the SID + Secret pair instead of the primary ' +\n 'auth token.',\n },\n {\n id: 'paste',\n title: 'Paste both values',\n detail: 'Account SID is non-secret; Auth Token is sealed before persistence.',\n },\n ],\n knownQuirks: [\n {\n id: 'subaccount-tokens',\n severity: 'info',\n message:\n 'If you use Twilio subaccounts, paste the SID/Token of the ' +\n 'subaccount that owns the phone numbers your agent calls — not ' +\n 'the master account.',\n },\n ],\n },\n\n // ── ph0ny ──────────────────────────────────────────────────────────\n // ph0ny issues a single Bearer API key per developer. The key is a\n // `plabs_` prefix followed by 32 url-safe nanoid chars. It is shown once\n // at creation (POST /v1/keys in the developer portal); only its hash is\n // stored server-side, so it cannot be retrieved later — rotate to replace.\n phony: {\n consoleUrl: 'https://api.ph0ny.com',\n credentialFields: [\n {\n label: 'ph0ny API key',\n description:\n 'Bearer key issued by ph0ny. Create one in the developer portal ' +\n '(POST /v1/keys). Sent as `Authorization: Bearer <key>`.',\n example: 'plabs_V1StGXR8Z5jdHi6BmyTAbCdEfGhIjKlm',\n regex: '^plabs_[A-Za-z0-9_-]{32}$',\n secret: true,\n },\n ],\n consoleSteps: [\n {\n id: 'open-portal',\n title: 'Open the ph0ny developer portal',\n detail: 'Visit https://api.ph0ny.com and sign in to the developer portal.',\n copyValue: 'https://api.ph0ny.com',\n },\n {\n id: 'create-key',\n title: 'Create an API key',\n detail:\n 'In the portal, create a new API key (POST /v1/keys). Give it a ' +\n 'descriptive name (e.g. \"tangle agent — prod\"). ph0ny returns the ' +\n 'full key exactly once.',\n },\n {\n id: 'paste',\n title: 'Paste the key',\n detail:\n 'Copy the plabs_… key ph0ny shows and paste it here. The key is ' +\n 'sealed before persistence.',\n },\n ],\n knownQuirks: [\n {\n id: 'key-shown-once',\n severity: 'warning',\n message:\n 'ph0ny stores only a hash of the key — the full plabs_… value is ' +\n 'shown exactly once at creation and cannot be retrieved later. Save ' +\n 'it immediately; if lost, rotate to issue a replacement.',\n },\n {\n id: 'rotate-endpoint',\n severity: 'info',\n message:\n 'Rotate a key with POST /v1/keys/:id/rotate. The old key is revoked ' +\n 'and a new plabs_… key is returned once — update this connection ' +\n 'with the new value.',\n },\n ],\n },\n}\n\n/** Public read — undefined when no override exists for the kind. */\nexport function getIntegrationOverride(kind: string): IntegrationOverride | undefined {\n return INTEGRATION_OVERRIDES[kind]\n}\n","import {\n buildIntegrationCoverageConnectors,\n listIntegrationCoverageSpecs,\n type IntegrationCoverageSpec,\n} from '../coverage-catalog.js'\nimport type {\n IntegrationConnector,\n IntegrationConnectorAction,\n IntegrationConnectorTrigger,\n IntegrationDataClass,\n} from '../index.js'\nimport { INTEGRATION_FAMILIES, getIntegrationFamily } from './families.js'\nimport { getIntegrationOverride } from './overrides.js'\nimport type {\n ApiKeyAuthSpec,\n HealthcheckSpec,\n HmacAuthSpec,\n IntegrationAuthSpec,\n IntegrationFamilyId,\n IntegrationPlannerHints,\n IntegrationSpec,\n IntegrationSpecStatus,\n NoneAuthSpec,\n NormalizedPermission,\n OAuth2AuthSpec,\n PermissionDescriptor,\n ScopeDescriptor,\n} from './types.js'\n\nconst EXECUTABLE_KINDS = new Set([\n 'google-calendar',\n 'google-sheets',\n 'outlook-calendar',\n 'microsoft-calendar',\n 'slack',\n 'hubspot',\n 'notion',\n 'notion-database',\n 'salesforce',\n 'github',\n 'gitlab',\n 'airtable',\n 'asana',\n 'stripe',\n 'stripe-pack',\n 'twilio',\n 'twilio-sms',\n 'phony',\n 'webhook',\n])\n\nconst KIND_ALIASES: Record<string, string> = {\n 'outlook-calendar': 'microsoft-calendar',\n notion: 'notion-database',\n stripe: 'stripe-pack',\n twilio: 'twilio-sms',\n}\n\nexport function listIntegrationSpecs(): IntegrationSpec[] {\n const connectors = new Map(buildIntegrationCoverageConnectors({ providerId: 'spec' }).map((c) => [c.id, c]))\n return listIntegrationCoverageSpecs().map((coverage) => {\n const connector = connectors.get(coverage.id)\n if (!connector) throw new Error(`missing coverage connector for ${coverage.id}`)\n return specFromCoverage(coverage, connector)\n })\n}\n\nexport function getIntegrationSpec(kind: string): IntegrationSpec | undefined {\n const canonical = KIND_ALIASES[kind] ?? kind\n return listIntegrationSpecs().find((spec) => spec.kind === canonical || KIND_ALIASES[spec.kind] === canonical)\n}\n\n/** Auth-driving descriptor the hub uses to start a connect flow per provider\n * instead of hard-coding scopes/auth kind. Derived from the spec catalog\n * ({@link getIntegrationSpec}); undefined when the kind is not in the\n * catalog. */\nexport interface ConnectorAuthSpec {\n kind: string\n authKind: 'oauth2' | 'api_key' | 'none' | 'custom'\n /** Provider scopes to request in the authorization grant. Empty for\n * api_key / none / custom. */\n requestedScopes: string[]\n /** OAuth-only: authorization + token endpoints and PKCE posture. Present\n * only when authKind === 'oauth2'. */\n authorizationUrl?: string\n tokenUrl?: string\n pkce?: 'required' | 'supported' | 'unsupported'\n redirectUriTemplate?: string\n clientIdEnv?: string\n clientSecretEnv?: string\n extraAuthParams?: Record<string, string>\n}\n\nexport function resolveConnectorAuthSpec(kind: string): ConnectorAuthSpec | undefined {\n const spec = getIntegrationSpec(kind)\n if (!spec) return undefined\n const auth = spec.auth\n if (auth.mode === 'oauth2') {\n return {\n kind: spec.kind,\n authKind: 'oauth2',\n requestedScopes: auth.scopes.map((scope) => scope.providerScope).filter(Boolean),\n authorizationUrl: auth.authorizationUrl,\n tokenUrl: auth.tokenUrl,\n pkce: auth.pkce,\n redirectUriTemplate: auth.redirectUriTemplate,\n clientIdEnv: auth.clientIdEnv,\n clientSecretEnv: auth.clientSecretEnv,\n extraAuthParams: auth.extraAuthParams,\n }\n }\n if (auth.mode === 'api_key') {\n return { kind: spec.kind, authKind: 'api_key', requestedScopes: [] }\n }\n if (auth.mode === 'none') {\n return { kind: spec.kind, authKind: 'none', requestedScopes: [] }\n }\n return { kind: spec.kind, authKind: 'custom', requestedScopes: [] }\n}\n\nexport function listExecutableIntegrationSpecs(): IntegrationSpec[] {\n return listIntegrationSpecs().filter((spec) => spec.status === 'executable')\n}\n\nexport function integrationSpecToConnector(spec: IntegrationSpec, providerId = 'spec'): IntegrationConnector {\n return {\n id: spec.kind,\n providerId,\n title: spec.title,\n category: spec.category,\n auth: spec.auth.mode === 'api_key' ? 'api_key' : spec.auth.mode === 'oauth2' ? 'oauth2' : spec.auth.mode === 'none' ? 'none' : 'custom',\n scopes: spec.permissions.flatMap((permission) => permission.providerScopes),\n actions: spec.actions,\n triggers: spec.triggers,\n metadata: {\n ...(spec.metadata ?? {}),\n source: 'integration-spec',\n status: spec.status,\n family: spec.family,\n plannerHints: spec.plannerHints,\n },\n }\n}\n\nfunction specFromCoverage(coverage: IntegrationCoverageSpec, connector: IntegrationConnector): IntegrationSpec {\n const kind = KIND_ALIASES[coverage.id] ?? coverage.id\n const family = familyFor(coverage)\n const familySpec = getIntegrationFamily(family)\n const permissions = permissionsFor(coverage, connector.actions)\n const auth = authFor(coverage, family, permissions)\n const status = statusFor(kind)\n // Per-kind overrides layer in here — see specs/overrides.ts. The override\n // is consulted under the canonical kind AND the original coverage id so\n // alias-collapsed kinds (e.g. notion → notion-database) can carry an\n // override under either name.\n const override =\n getIntegrationOverride(kind) ?? getIntegrationOverride(coverage.id)\n // Family quirks + override quirks are concatenated; everything else is\n // a replace (override fields take precedence when present).\n const knownQuirks = override?.knownQuirks\n ? [...(familySpec.knownQuirks ?? []), ...override.knownQuirks]\n : familySpec.knownQuirks\n return {\n kind,\n title: connector.title,\n category: connector.category,\n status,\n family,\n auth,\n permissions,\n actions: connector.actions,\n triggers: connector.triggers,\n setup: {\n consoleUrl: override?.consoleUrl ?? familySpec.consoleUrl,\n consoleSteps: override?.consoleSteps ?? familySpec.consoleSteps,\n credentialFields: override?.credentialFields ?? credentialFieldsFor(auth),\n redirectUriTemplate: auth.mode === 'oauth2' ? auth.redirectUriTemplate : familySpec.redirectUriTemplate,\n knownQuirks,\n postSetup: override?.postSetup,\n healthcheck: override?.healthcheck ?? healthcheckFor(kind, status, auth),\n },\n lifecycle: familySpec.lifecycle,\n plannerHints: plannerHintsFor(coverage, connector.actions),\n metadata: { priority: coverage.priority, domains: coverage.domains },\n }\n}\n\nfunction familyFor(spec: IntegrationCoverageSpec): IntegrationFamilyId {\n if (hmacKinds.has(spec.id)) return 'hmac'\n if (spec.auth === 'none') return 'none'\n if (spec.id.startsWith('google-') || spec.domains.includes('google')) return 'google'\n if (spec.id.startsWith('microsoft-') || ['outlook-mail', 'outlook-calendar', 'onedrive', 'sharepoint'].includes(spec.id)) return 'microsoft-graph'\n if (['jira', 'confluence', 'trello', 'bitbucket'].includes(spec.id)) return 'atlassian'\n if (spec.id === 'salesforce') return 'salesforce'\n if (spec.id === 'hubspot') return 'hubspot'\n if (spec.id === 'slack') return 'slack'\n if (spec.id === 'notion') return 'notion'\n if (apiKeyKinds.has(spec.id)) return 'api-key'\n return 'standard-oauth2'\n}\n\nconst apiKeyKinds = new Set(['github', 'gitlab', 'airtable', 'asana', 'stripe', 'twilio', 'sendgrid', 'postmark', 'phony'])\nconst hmacKinds = new Set(['webhook'])\n\nfunction authFor(\n spec: IntegrationCoverageSpec,\n family: IntegrationFamilyId,\n permissions: PermissionDescriptor[],\n): IntegrationAuthSpec {\n const f = INTEGRATION_FAMILIES[family]\n if (family === 'none') return { mode: 'none' } satisfies NoneAuthSpec\n if (family === 'hmac') {\n return { mode: 'hmac', credential: f.credentialFields[0]!, signatureHeader: `${spec.id}-signature` } satisfies HmacAuthSpec\n }\n if (family === 'api-key') {\n return { mode: 'api_key', credential: apiKeyFieldFor(spec.id), placement: apiKeyPlacementFor(spec.id) } satisfies ApiKeyAuthSpec\n }\n const scopes = permissions.flatMap((permission) =>\n permission.providerScopes.map((providerScope): ScopeDescriptor => ({\n normalized: permission.normalized,\n providerScope,\n title: permission.title,\n reason: permission.reason,\n risk: permission.risk,\n dataClass: permission.dataClass,\n })),\n )\n return {\n mode: 'oauth2',\n authorizationUrl: f.authorizationUrl ?? `https://example.invalid/${spec.id}/authorize`,\n tokenUrl: f.tokenUrl ?? `https://example.invalid/${spec.id}/token`,\n clientIdEnv: f.credentialFields.find((field) => !field.secret)?.env,\n clientSecretEnv: f.credentialFields.find((field) => field.secret)?.env,\n scopes,\n extraAuthParams: extraAuthParamsFor(family),\n redirectUriTemplate: (f.redirectUriTemplate ?? 'https://{host}/api/integrations/oauth/{kind}/callback').replace('{kind}', spec.id),\n pkce: family === 'google' || family === 'microsoft-graph' ? 'supported' : 'unsupported',\n } satisfies OAuth2AuthSpec\n}\n\nfunction credentialFieldsFor(auth: IntegrationAuthSpec) {\n if (auth.mode === 'api_key' || auth.mode === 'hmac') return [auth.credential]\n if (auth.mode === 'oauth2') {\n return [\n { label: 'Client ID', env: auth.clientIdEnv, description: 'OAuth client ID.', secret: false },\n { label: 'Client Secret', env: auth.clientSecretEnv, description: 'OAuth client secret.', secret: true },\n ]\n }\n return []\n}\n\nfunction permissionsFor(spec: IntegrationCoverageSpec, actions: IntegrationConnectorAction[]): PermissionDescriptor[] {\n const dataClass = dataClassFor(actions)\n const readScope = providerScopeFor(spec, 'read')\n const writeScope = providerScopeFor(spec, 'write')\n const permissions: PermissionDescriptor[] = [\n {\n normalized: `${spec.actionPack}.read` as NormalizedPermission,\n providerScopes: readScope ? [readScope] : [],\n title: `${spec.title} read`,\n risk: 'read',\n dataClass,\n reason: `Read ${spec.title} data for user-authorized agent workflows.`,\n },\n ]\n if (actions.some((a) => a.risk !== 'read')) {\n permissions.push({\n normalized: `${spec.actionPack}.write` as NormalizedPermission,\n providerScopes: writeScope ? [writeScope] : [],\n title: `${spec.title} write`,\n risk: 'write',\n dataClass,\n reason: `Create or update ${spec.title} resources after policy approval.`,\n })\n }\n return permissions\n}\n\nfunction providerScopeFor(spec: IntegrationCoverageSpec, mode: 'read' | 'write'): string {\n const explicit = explicitScopes[spec.id]?.[mode]\n if (explicit) return explicit\n if (spec.auth === 'none') return ''\n return `${spec.id}.${mode}`\n}\n\nconst explicitScopes: Record<string, Partial<Record<'read' | 'write', string>>> = {\n gmail: { read: 'https://www.googleapis.com/auth/gmail.readonly', write: 'https://www.googleapis.com/auth/gmail.modify' },\n 'google-calendar': { read: 'https://www.googleapis.com/auth/calendar.readonly', write: 'https://www.googleapis.com/auth/calendar' },\n 'google-sheets': { read: 'https://www.googleapis.com/auth/spreadsheets.readonly', write: 'https://www.googleapis.com/auth/spreadsheets' },\n 'google-drive': { read: 'https://www.googleapis.com/auth/drive.readonly', write: 'https://www.googleapis.com/auth/drive.file' },\n 'google-docs': { read: 'https://www.googleapis.com/auth/documents.readonly', write: 'https://www.googleapis.com/auth/documents' },\n 'outlook-mail': { read: 'Mail.Read', write: 'Mail.Send' },\n 'outlook-calendar': { read: 'Calendars.Read', write: 'Calendars.ReadWrite' },\n 'microsoft-teams': { read: 'ChannelMessage.Read.All', write: 'ChannelMessage.Send' },\n onedrive: { read: 'Files.Read', write: 'Files.ReadWrite' },\n sharepoint: { read: 'Sites.Read.All', write: 'Sites.ReadWrite.All' },\n slack: { read: 'channels:read', write: 'chat:write' },\n hubspot: { read: 'crm.objects.contacts.read', write: 'crm.objects.contacts.write' },\n salesforce: { read: 'api', write: 'api' },\n notion: { read: '', write: '' },\n github: { read: 'repo:read', write: 'repo' },\n gitlab: { read: 'read_api', write: 'api' },\n airtable: { read: 'data.records:read', write: 'data.records:write' },\n asana: { read: 'default', write: 'default' },\n stripe: { read: 'read_only', write: 'standard' },\n twilio: { read: 'api_key', write: 'api_key' },\n}\n\nfunction plannerHintsFor(spec: IntegrationCoverageSpec, actions: IntegrationConnectorAction[]): IntegrationPlannerHints {\n return {\n useFor: spec.domains.map((domain) => domain.replace(/-/g, ' ')),\n dataFreshness: ['calendar', 'chat', 'commerce', 'finance', 'support'].includes(spec.actionPack) ? 'near_realtime' : 'eventual',\n writeRisk: actions.some((a) => a.risk === 'destructive') ? 'high' : actions.some((a) => a.risk === 'write') ? 'medium' : 'low',\n }\n}\n\nfunction healthcheckFor(kind: string, status: IntegrationSpecStatus, auth: IntegrationAuthSpec): HealthcheckSpec {\n if (status !== 'executable') {\n return { id: `${kind}.static`, level: 'static', description: 'Catalog-only integration; no executable connector healthcheck is available yet.' }\n }\n if (auth.mode === 'oauth2') {\n return { id: `${kind}.connection`, level: 'connection', description: 'Validate a user connection by calling the connector test endpoint.' }\n }\n if (auth.mode === 'api_key') {\n return { id: `${kind}.connection`, level: 'connection', description: 'Validate API credentials by calling the connector test endpoint.' }\n }\n if (auth.mode === 'hmac') {\n return { id: `${kind}.webhook`, level: 'webhook', description: 'Validate webhook signing configuration with a signed test payload.' }\n }\n return { id: `${kind}.static`, level: 'static', description: 'No credentials are required.' }\n}\n\nfunction statusFor(kind: string): IntegrationSpecStatus {\n return EXECUTABLE_KINDS.has(kind) ? 'executable' : 'catalog'\n}\n\nfunction dataClassFor(actions: IntegrationConnectorAction[]): IntegrationDataClass {\n if (actions.some((a) => a.dataClass === 'secret')) return 'secret'\n if (actions.some((a) => a.dataClass === 'sensitive')) return 'sensitive'\n if (actions.some((a) => a.dataClass === 'private')) return 'private'\n if (actions.some((a) => a.dataClass === 'internal')) return 'internal'\n return 'public'\n}\n\nfunction apiKeyFieldFor(kind: string) {\n return {\n label: `${kind} API key`,\n description: `API key or token for ${kind}.`,\n example: kind === 'stripe' ? 'sk_live_...' : undefined,\n secret: true,\n }\n}\n\nfunction apiKeyPlacementFor(kind: string): ApiKeyAuthSpec['placement'] {\n if (kind === 'gitlab') return 'header'\n return 'bearer'\n}\n\nfunction extraAuthParamsFor(family: IntegrationFamilyId): Record<string, string> | undefined {\n if (family === 'google') return { access_type: 'offline', prompt: 'consent', include_granted_scopes: 'true' }\n if (family === 'notion') return { owner: 'user' }\n return undefined\n}\n","import type {\n ConsoleStep,\n HealthcheckPlan,\n IntegrationSpec,\n RenderSpecOptions,\n RenderedConsoleStep,\n} from './types.js'\n\nexport function renderConsoleSteps(spec: IntegrationSpec, options: RenderSpecOptions): RenderedConsoleStep[] {\n const redirectUri = renderRedirectUri(spec, options)\n return spec.setup.consoleSteps.map((step) => ({\n ...step,\n detail: renderTemplate(step.detail, spec, options, redirectUri),\n copyValue: step.copyValue ? renderTemplate(step.copyValue, spec, options, redirectUri) : undefined,\n }))\n}\n\nexport function renderRunbookMarkdown(spec: IntegrationSpec, options: RenderSpecOptions): string {\n const steps = renderConsoleSteps(spec, options)\n const lines = [\n `# ${spec.title} Integration Setup`,\n '',\n `- Kind: \\`${spec.kind}\\``,\n `- Status: \\`${spec.status}\\``,\n `- Auth: \\`${spec.auth.mode}\\``,\n `- Family: \\`${spec.family}\\``,\n ]\n if (spec.setup.consoleUrl) lines.push(`- Console: ${spec.setup.consoleUrl}`)\n if (spec.setup.redirectUriTemplate) lines.push(`- Redirect URI: \\`${renderRedirectUri(spec, options)}\\``)\n lines.push('', '## Credentials', '')\n for (const field of spec.setup.credentialFields) {\n lines.push(`- ${field.secret ? '[secret] ' : ''}${field.label}${field.env ? ` (\\`${field.env}\\`)` : ''}: ${field.description}`)\n }\n lines.push('', '## Permissions', '')\n for (const permission of spec.permissions) {\n lines.push(`- \\`${permission.normalized}\\`: ${permission.providerScopes.length ? permission.providerScopes.map((scope) => `\\`${scope}\\``).join(', ') : 'no provider scope'} - ${permission.reason}`)\n }\n lines.push('', '## Console Steps', '')\n for (const [i, step] of steps.entries()) {\n lines.push(`${i + 1}. ${step.title}: ${step.detail}`)\n }\n if (spec.setup.knownQuirks?.length) {\n lines.push('', '## Known Quirks', '')\n for (const quirk of spec.setup.knownQuirks) lines.push(`- ${quirk.severity}: ${quirk.message}`)\n }\n return `${lines.join('\\n')}\\n`\n}\n\nexport function renderAgentToolDescription(spec: IntegrationSpec): string {\n const hints = spec.plannerHints\n const useFor = hints?.useFor?.length ? `Use for ${hints.useFor.join(', ')}.` : `Use for ${spec.title} workflows.`\n const risk = hints ? `Freshness: ${hints.dataFreshness}. Write risk: ${hints.writeRisk}.` : ''\n return `${spec.title} (${spec.kind}). ${useFor} ${risk}`.trim()\n}\n\nexport function buildHealthcheckPlan(spec: IntegrationSpec): HealthcheckPlan {\n const healthcheck = spec.setup.healthcheck ?? { id: `${spec.kind}.static`, level: 'static', description: 'No healthcheck defined.' as const }\n const requires: HealthcheckPlan['requires'] = []\n if (healthcheck.level === 'connection') requires.push('connection_credentials')\n if (healthcheck.level === 'client_config' && spec.auth.mode === 'oauth2') requires.push('client_id', 'client_secret')\n if (spec.auth.mode === 'api_key') requires.push('api_key')\n if (spec.auth.mode === 'hmac') requires.push('hmac_secret')\n return {\n kind: spec.kind,\n healthcheck,\n requires,\n message: healthcheck.description,\n }\n}\n\nfunction renderTemplate(template: string, spec: IntegrationSpec, options: RenderSpecOptions, redirectUri?: string): string {\n return template\n .replaceAll('{host}', options.host)\n .replaceAll('{kind}', spec.kind)\n .replaceAll('{redirectUri}', redirectUri ?? renderRedirectUri(spec, options))\n}\n\nfunction renderRedirectUri(spec: IntegrationSpec, options: RenderSpecOptions): string {\n return (options.callbackPath ?? spec.setup.redirectUriTemplate ?? '')\n .replaceAll('{host}', options.host)\n .replaceAll('{kind}', spec.kind)\n}\n\nexport function consoleStepsToText(steps: ConsoleStep[]): string {\n return steps.map((step, index) => `${index + 1}. ${step.title}: ${step.detail}`).join('\\n')\n}\n","import type {\n CredentialFieldSpec,\n CredentialValidationResult,\n IntegrationSpec,\n IntegrationSpecValidationIssue,\n IntegrationSpecValidationResult,\n} from './types.js'\n\nexport function validateIntegrationSpec(spec: IntegrationSpec): IntegrationSpecValidationResult {\n const issues: IntegrationSpecValidationIssue[] = []\n if (!spec.kind.trim()) issues.push({ path: 'kind', message: 'kind is required' })\n if (!spec.title.trim()) issues.push({ path: 'title', message: 'title is required' })\n if (!spec.actions.length) issues.push({ path: 'actions', message: 'at least one action is required' })\n if (!spec.permissions.length) issues.push({ path: 'permissions', message: 'at least one permission is required' })\n if (spec.auth.mode === 'oauth2') {\n if (!spec.auth.authorizationUrl) issues.push({ path: 'auth.authorizationUrl', message: 'authorizationUrl is required' })\n if (!spec.auth.tokenUrl) issues.push({ path: 'auth.tokenUrl', message: 'tokenUrl is required' })\n if (!spec.auth.redirectUriTemplate) issues.push({ path: 'auth.redirectUriTemplate', message: 'redirectUriTemplate is required' })\n }\n const actionIds = new Set<string>()\n for (const [index, action] of spec.actions.entries()) {\n if (actionIds.has(action.id)) issues.push({ path: `actions[${index}].id`, message: `duplicate action id ${action.id}` })\n actionIds.add(action.id)\n }\n return { ok: issues.length === 0, issues }\n}\n\nexport function assertValidIntegrationSpec(spec: IntegrationSpec): void {\n const result = validateIntegrationSpec(spec)\n if (!result.ok) {\n throw new Error(`Invalid integration spec ${spec.kind}: ${result.issues.map((i) => `${i.path}: ${i.message}`).join('; ')}`)\n }\n}\n\nexport function validateCredentialFormat(field: CredentialFieldSpec, value: string): CredentialValidationResult {\n if (!value.trim()) return { ok: false, field: field.label, message: `${field.label} is required` }\n if (field.regex && !new RegExp(field.regex).test(value)) {\n return { ok: false, field: field.label, message: `${field.label} does not match expected format` }\n }\n return { ok: true, field: field.label }\n}\n\nexport function validateCredentialSet(spec: IntegrationSpec, values: Record<string, string>): CredentialValidationResult[] {\n return spec.setup.credentialFields.map((field) => {\n const key = field.env ?? field.label\n return validateCredentialFormat(field, values[key] ?? '')\n })\n}\n"],"mappings":"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","names":["actionPack","scope","dataClassFor"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/connectors/types.ts","../src/connectors/adapters/tangle-id.ts"],"sourcesContent":["/**\n * Connector primitives — the contract a concrete first-party integration\n * (Google Calendar, HubSpot, Stripe, ...) implements. Lower level than the\n * hub-side `IntegrationProvider` interface from `../index.ts`: a single\n * `IntegrationProvider` typically wraps several connectors (e.g., a\n * \"first-party\" provider that lists all your shipped connectors as a\n * single catalog).\n *\n * Layering:\n *\n * IntegrationHub — vendor-neutral facade (../index.ts)\n * ↓\n * IntegrationProvider — one per gateway or first-party provider\n * ↓\n * ConnectorAdapter (this file) — one per integration (Google Calendar, ...)\n * ↓\n * upstream HTTP API — vendor SDK / fetch / OAuth\n *\n * Three load-bearing decisions encoded here:\n *\n * 1. Capabilities are typed (`read` vs `mutation`). Every mutation MUST\n * declare a CAS strategy. Conflict resolution is the SDK's job, not the\n * connector's. `validateConnectorManifest()` rejects unsafe manifests\n * before a connector is registered.\n *\n * 2. ConsistencyModel pins what the rest of the system can assume:\n * authoritative → the source IS the truth (Calendar, payments)\n * cache → we mirror with TTL and may serve stale (price list)\n * advisory → informational only (FAQ doc)\n * Agent planners can (and should) refuse to promise outcomes based on\n * `cache`/`advisory` data without a live `authoritative` confirmation.\n *\n * 3. Capabilities surface to the calling agent's tool registry by\n * transformation, not by hand-wiring. Adding a connector automatically\n * expands the agent's toolbelt for that specific user without touching\n * the prompt or runner.\n */\n\n/** Minimal JSON-schema shape used for capability arg validation. We\n * intentionally don't pull `@types/json-schema` — most consumers already\n * declare parameters as `Record<string, unknown>` and the\n * shape is whatever the LLM SDK's structured-output expects. Keep the\n * contract loose at the boundary; tighten via runtime zod where needed. */\nexport type CapabilityParameterSchema = Record<string, unknown>\n\n/** What the rest of the system is allowed to assume about freshness. */\nexport type ConsistencyModel = 'authoritative' | 'cache' | 'advisory'\n\n/** Capability classes. `read` is safe to retry; `mutation` must go through\n * MutationGuard (CAS + idempotency). `subscribe` is reserved for future\n * push-driven sources (webhook callbacks) and is not yet wired. */\nexport type CapabilityClass = 'read' | 'mutation' | 'subscribe'\n\n/** Compare-and-swap strategy a mutation uses to detect conflicts. */\nexport type CASStrategy =\n /** Upstream returns an etag/sequence on read, accepts If-Match on write\n * (Google Calendar, GitHub, GDocs revision_id). The connector returns\n * 412 / Precondition Failed on conflict; the SDK maps to ResourceContention. */\n | 'etag-if-match'\n /** Upstream guarantees exactly-once-per-key (Stripe, idempotent webhooks).\n * The SDK passes the idempotency key through; no etag check. */\n | 'native-idempotency'\n /** No upstream concurrency control. Connector MUST do read-then-write\n * and verify nothing changed in-between (best-effort). Suitable only\n * for low-contention single-user resources; rejected for any\n * consistencyModel='authoritative' write that may race. */\n | 'optimistic-read-verify'\n /** Source is not contended (e.g. logging, telemetry). Mutations are\n * fire-and-forget. Marks the capability as not eligible for\n * authoritative writes. */\n | 'none'\n\nexport interface CapabilityRead {\n name: string\n class: 'read'\n description: string\n /** JSON-schema for the tool args the agent passes when invoking. */\n parameters: CapabilityParameterSchema\n /** Optional: declare which scopes (per the connector manifest) this\n * capability requires. The capability is hidden from the agent's\n * tool registry if the user's grant didn't include them. */\n requiredScopes?: string[]\n}\n\nexport interface CapabilityMutation {\n name: string\n class: 'mutation'\n description: string\n parameters: CapabilityParameterSchema\n /** Mandatory: how does the connector guarantee at-most-once + conflict-detect? */\n cas: CASStrategy\n /** True for capabilities that affect resources outside the calling user\n * (e.g. booking against a shared calendar, charging a card). The agent's\n * planner treats these specially: requires explicit caller confirmation\n * before the call. */\n externalEffect: boolean\n requiredScopes?: string[]\n}\n\nexport type Capability = CapabilityRead | CapabilityMutation\n\n/** OAuth2 scope catalog the user has granted us, plus arbitrary metadata\n * the connector pinned at connect-time (calendar id, sheet id, webhook\n * url, …). `metadata` MUST NOT contain secrets — those go in the\n * encrypted credentials envelope. */\nexport interface DataSourceMetadata {\n scopes: string[]\n [key: string]: unknown\n}\n\n/** A connected, authenticated, ready-to-call data source for a project.\n * Persistence shape mirrors the product's connection/source row but normalized — the\n * encrypted credentials envelope is decrypted at hand-out time and held\n * in memory only for the duration of the call. */\nexport interface ResolvedDataSource {\n id: string\n projectId: string\n publishedAgentId: string | null\n kind: string\n label: string\n consistencyModel: ConsistencyModel\n scopes: string[]\n metadata: Record<string, unknown>\n /** Unwrapped credentials handed to the connector at call-time. Never\n * persisted in this shape; never logged. */\n credentials: ConnectorCredentials\n status: 'active' | 'revoked' | 'error'\n}\n\n/** Discriminated union of credential shapes. Connectors that need new\n * shapes extend this union — `kind` is sealed via the tagged pattern so\n * TypeScript catches an exhaustiveness gap at compile time. */\nexport type ConnectorCredentials =\n | { kind: 'oauth2'; accessToken: string; refreshToken?: string; expiresAt?: number }\n | { kind: 'api-key'; apiKey: string }\n | { kind: 'custom'; values: Record<string, unknown> }\n | { kind: 'hmac'; secret: string }\n | { kind: 'none' }\n\n/** Result of a read capability invocation. */\nexport interface CapabilityReadResult {\n /** Free-form payload — the connector's data shape. The agent receives\n * this as the tool result; planners consume it via JSON-shape contract\n * declared in the capability's `parameters` (output schema). */\n data: unknown\n /** Optional etag/sequence the caller can reuse for a subsequent CAS\n * mutation. */\n etag?: string\n /** When this read happened (UTC ms since epoch). */\n fetchedAt: number\n}\n\n/** Result of a mutation capability invocation. Either committed (with the\n * resulting etag/sequence so the caller can chain mutations), or\n * contended (the upstream rejected with a state mismatch — the agent\n * should re-read and retry, or surface alternatives to the caller). */\nexport type CapabilityMutationResult =\n | {\n status: 'committed'\n data: unknown\n etagAfter?: string\n committedAt: number\n /** True iff this commit was returned from the idempotency store\n * rather than executed against upstream. The caller can use this\n * to suppress confirmation messages on retry. */\n idempotentReplay: boolean\n }\n | {\n status: 'conflict'\n /** Best-effort alternative options the upstream surfaced (e.g.,\n * next-available calendar slots after a booking conflict). */\n alternatives: unknown[]\n /** The current authoritative state, if the connector could re-read\n * cheaply. */\n currentState?: unknown\n message: string\n }\n | {\n status: 'rate-limited'\n /** Wall-clock ms the caller should wait before retrying. The SDK\n * computes this from the bucket's refill schedule so the agent\n * doesn't have to guess. */\n retryAfterMs: number\n message: string\n }\n\n/** Inputs the SDK passes into the connector's executeRead / executeMutation. */\nexport interface ConnectorInvocation {\n source: ResolvedDataSource\n capabilityName: string\n args: Record<string, unknown>\n /** Idempotency key the caller (or the SDK's defaulting policy) supplied.\n * Always present at the connector boundary — the SDK manufactures one\n * if the agent didn't pass one. */\n idempotencyKey: string\n /** Optional caller-supplied etag the connector should send as If-Match. */\n expectedEtag?: string\n /** Product/session id (if any) for forensic logging. */\n callSessionId?: string\n /** Fired by the adapter when it rotates the credentials mid-call (e.g. an\n * OAuth access token refreshed on expiry). The host re-encrypts +\n * persists the rotated envelope so the next expiry does not force a\n * reconnect. Adapters MUST invoke this with the FULL rotated envelope,\n * not a partial — the previous refresh token is preserved by the caller's\n * refresh logic, not inferred here. */\n onCredentialsRotated?: (credentials: ConnectorCredentials) => void\n}\n\n/** A single inbound event extracted from a push payload. The webhook\n * receiver persists one `InboundEvent` row per entry the connector returns. */\nexport interface InboundEvent {\n eventType: string\n providerEventId?: string\n payload: Record<string, unknown>\n}\n\n/** Adapter response from an inbound-webhook dispatch. The receiver persists\n * every `events[]` entry, then either honors the connector's `response`\n * override (Slack `url_verification` echo, provider-specific 2xx body) or\n * defaults to `{status: 200, body: {received: true, count: events.length}}`. */\nexport interface EventHandlerResult {\n events: InboundEvent[]\n /** Optional: how to respond to the provider. Stripe wants 200 within\n * 30s; Slack wants the challenge param echoed. */\n response?: { status: number; body: unknown; headers?: Record<string, string> }\n}\n\n/**\n * Connector adapter — one per integration kind. Stateless. The SDK holds\n * the persistence + crypto + mutation-guard concerns; the adapter only\n * knows how to talk to its upstream.\n */\nexport interface ConnectorAdapter {\n /** Manifest entry the registry uses to render UI + validate args. */\n manifest: ConnectorManifest\n /** Read invocation. Required when manifest.capabilities contains reads.\n * Should return whatever shape the capability declared\n * in its parameters output schema. */\n executeRead?(inv: ConnectorInvocation): Promise<CapabilityReadResult>\n /** Mutation invocation. Required when manifest.capabilities contains mutations.\n * Throws ResourceContention on a CAS miss; throws\n * any other Error for upstream failures. The MutationGuard wraps this\n * with idempotency-key short-circuit + audit logging — adapters do\n * NOT manage their own dedup. */\n executeMutation?(inv: ConnectorInvocation): Promise<CapabilityMutationResult>\n /** Inbound webhook signature verifier. Called BEFORE handleInboundEvent.\n * MUST use constant-time comparison (`crypto.timingSafeEqual`) for any\n * HMAC check. The receiver returns 401 on `valid=false` without invoking\n * handleInboundEvent. Optional: connectors that don't accept push events\n * omit this method and the receiver returns 405 for the kind. */\n verifySignature?(input: {\n rawBody: string\n headers: Record<string, string | string[] | undefined>\n source: ResolvedDataSource\n }): { valid: boolean; reason?: string }\n /** Inbound webhook dispatch. Called AFTER verifySignature passes. The\n * adapter parses the provider payload and emits zero-or-more\n * `InboundEvent` rows; the receiver persists them as one row each (modulo\n * the (dataSourceId, providerEventId) dedup unique). The optional\n * `response` overrides the receiver's default 200 (Slack `url_verification`\n * needs to echo the challenge in the body to pass Slack's app-config check). */\n handleInboundEvent?(input: {\n source: ResolvedDataSource\n rawBody: string\n headers: Record<string, string | string[] | undefined>\n }): Promise<EventHandlerResult>\n /** OAuth callback handler — exchanges the auth code for tokens, returns\n * the credentials envelope + scopes + metadata. Only present for\n * oauth2-style adapters. */\n exchangeOAuth?(input: {\n code: string\n state: string\n codeVerifier: string\n redirectUri: string\n }): Promise<{\n credentials: ConnectorCredentials\n scopes: string[]\n metadata: Record<string, unknown>\n }>\n /** Refresh access token. Only required for oauth2 adapters with\n * short-lived access tokens. */\n refreshToken?(input: ConnectorCredentials): Promise<ConnectorCredentials>\n /** Health check — invoked when the user clicks \"Test connection\" in the\n * UI. Should perform the cheapest possible read that proves the grant\n * is still valid. Returns `{ok: false, reason}` rather than throwing\n * for the common case (token expired, scope missing). */\n test(source: ResolvedDataSource): Promise<{ ok: true } | { ok: false; reason: string }>\n}\n\n/** Static manifest a connector module exports. Drives the UI catalog,\n * scope display, capability discovery for the agent's tool registry. */\nexport interface ConnectorManifest {\n /** Stable kind id used as the foreign key in DataSource.kind. */\n kind: string\n /** Human label shown in the UI catalog. */\n displayName: string\n /** One-paragraph description shown next to the connect button. */\n description: string\n /** Auth shape this connector requires. */\n auth: AuthSpec\n /** Capability catalog — the agent's tool registry derives ToolDefinition\n * entries from this list at request time. */\n capabilities: Capability[]\n /** ConsistencyModel default for this kind — overridable per DataSource\n * if a particular instance is special (e.g., a user marks a sheet as\n * `cache` because they refresh it nightly). */\n defaultConsistencyModel: ConsistencyModel\n /** Connector category for UI grouping. */\n category:\n | 'calendar'\n | 'spreadsheet'\n | 'crm'\n | 'doc'\n | 'webhook'\n | 'storage'\n | 'comms'\n | 'commerce'\n | 'database'\n | 'other'\n /** Optional icon URL or named icon. */\n icon?: string\n /** Optional per-kind rate-limit budget. The SDK enforces it inside\n * `executeGuardedMutation` and the read path of `/invoke`. Omit to\n * leave the connector unrestricted. */\n rateLimit?: RateLimitSpec\n}\n\n/** Token-bucket budget the SDK enforces against the connector's upstream.\n * We meter on OUR side rather than letting the upstream reject so a\n * chatty agent can't burn quota that's shared across customers (almost\n * every OAuth client is). */\nexport interface RateLimitSpec {\n /** Max requests per window. */\n requests: number\n /** Window in ms. */\n windowMs: number\n /** Whether to apply across all DataSources sharing the same OAuth\n * client (true; default), or per-DataSource (false). The former\n * matches how upstreams meter (per-app), so almost always pick true. */\n scope?: 'oauth-client' | 'data-source'\n}\n\nexport type AuthSpec =\n | {\n kind: 'oauth2'\n /** Authorization endpoint URL. */\n authorizationUrl: string\n /** Token endpoint URL. */\n tokenUrl: string\n /** Scopes requested in the authorization grant. The user UI shows\n * these so the customer knows what's being shared. */\n scopes: string[]\n /** Whether the connector supports incremental authorization (Google\n * does; many don't). */\n incremental?: boolean\n /** Env-var name holding the OAuth client_id. */\n clientIdEnv: string\n /** Env-var name holding the OAuth client_secret. */\n clientSecretEnv: string\n /** Optional extra params attached to the authorization URL (e.g.,\n * Google's `access_type=offline&prompt=consent` to obtain refresh\n * tokens). */\n extraAuthParams?: Record<string, string>\n }\n | {\n kind: 'api-key'\n /** UI hint shown when collecting the key. */\n hint: string\n }\n | { kind: 'hmac' }\n | { kind: 'none' }\n\n/** Thrown by `executeMutation` when upstream rejects on CAS — caught and\n * rewrapped by MutationGuard. */\nexport class ResourceContention extends Error {\n override readonly name = 'ResourceContention'\n constructor(\n message: string,\n public readonly alternatives: unknown[] = [],\n public readonly currentState?: unknown,\n ) {\n super(message)\n }\n}\n\n/** Thrown when the connector finds the user's grant has been revoked or\n * the access token is no longer valid AND refresh failed. Surfaces to\n * the UI as \"Reconnect required\". */\nexport class CredentialsExpired extends Error {\n override readonly name = 'CredentialsExpired'\n constructor(message: string, public readonly dataSourceId: string) {\n super(message)\n }\n}\n\nexport interface ConnectorManifestValidationIssue {\n path: string\n message: string\n}\n\nexport interface ConnectorManifestValidationResult {\n ok: boolean\n issues: ConnectorManifestValidationIssue[]\n}\n\n/** Validate the static connector manifest before a provider registers it.\n * This catches the expensive mistakes early: duplicate capability names,\n * mutation capabilities without CAS, authoritative fire-and-forget writes,\n * and invalid rate-limit specs. */\nexport function validateConnectorManifest(manifest: ConnectorManifest): ConnectorManifestValidationResult {\n const issues: ConnectorManifestValidationIssue[] = []\n if (!manifest.kind.trim()) issues.push({ path: 'kind', message: 'kind is required' })\n if (!manifest.displayName.trim()) issues.push({ path: 'displayName', message: 'displayName is required' })\n const seen = new Set<string>()\n for (const [index, capability] of manifest.capabilities.entries()) {\n const path = `capabilities[${index}]`\n if (!capability.name.trim()) issues.push({ path: `${path}.name`, message: 'capability name is required' })\n if (seen.has(capability.name)) issues.push({ path: `${path}.name`, message: `duplicate capability name: ${capability.name}` })\n seen.add(capability.name)\n if (capability.class === 'mutation') {\n if (!capability.cas) issues.push({ path: `${path}.cas`, message: 'mutation capability must declare a CAS strategy' })\n if (manifest.defaultConsistencyModel === 'authoritative' && capability.cas === 'none') {\n issues.push({ path: `${path}.cas`, message: 'authoritative mutations cannot use cas=\"none\"' })\n }\n }\n }\n if (manifest.rateLimit) {\n if (!Number.isFinite(manifest.rateLimit.requests) || manifest.rateLimit.requests <= 0) {\n issues.push({ path: 'rateLimit.requests', message: 'rateLimit.requests must be positive' })\n }\n if (!Number.isFinite(manifest.rateLimit.windowMs) || manifest.rateLimit.windowMs <= 0) {\n issues.push({ path: 'rateLimit.windowMs', message: 'rateLimit.windowMs must be positive' })\n }\n }\n return { ok: issues.length === 0, issues }\n}\n\nexport function assertValidConnectorManifest(manifest: ConnectorManifest): void {\n const result = validateConnectorManifest(manifest)\n if (!result.ok) {\n throw new Error(`Invalid connector manifest ${manifest.kind || '<unknown>'}: ${result.issues.map((issue) => `${issue.path}: ${issue.message}`).join('; ')}`)\n }\n}\n","/**\n * @stable Tangle Identity — `id.tangle.tools` connector + verifier.\n *\n * This is the *identity* substrate every Tangle product (legal, tax, gtm,\n * creative, agent-builder, sandbox, evals, …) sits on. The shape mirrors\n * what `tcloud` and the sandbox `PlatformClient` already implement against\n * the platform repo at `agent-dev-container-collab-m1/products/platform`,\n * so consumers can switch from a hand-rolled fetch loop to this adapter\n * without changing the wire protocol.\n *\n * What it covers, end-to-end:\n *\n * verify_token({ token })\n * → { kind: 'api_key' | 'session', valid, userId?, workspaceId?, scopes, expiresAt? }\n * Verifies a single credential. Two token shapes are recognized:\n * - `sk-tan-*` API keys — POST /v1/keys/verify with the service token.\n * Returns `userId`, `keyId`, `product`, granted scopes (`allowedModels`\n * + product flag), and budget metadata.\n * - Better Auth session cookies / Bearer session tokens — GET\n * /api/auth/get-session with the credential forwarded as-is.\n * Returns the user row.\n * Wrong-issuer / tampered / expired all surface as `{ valid: false }`\n * with a stable `reason`. Never throws on bad-token; only throws when\n * id.tangle.tools itself is unreachable or returns a 5xx (lets callers\n * fail closed without confusing token failures with platform failures).\n *\n * get_user({ userId })\n * → { id, email, name?, image? }\n * Read-only profile lookup. Service-token authenticated. Used by\n * `requireTangleAuth` middleware to hydrate the request context when\n * a downstream wants the user's email without re-verifying.\n *\n * list_workspaces({ userId })\n * → { workspaces: [{ id, name, role, isPersonal }] }\n * A workspace = a Tangle team. Personal workspace is rendered with\n * `isPersonal: true` (own id === userId on the platform schema).\n * Mirrors `GET /v1/teams` on the platform side.\n *\n * switch_workspace({ workspaceId })\n * → { ok: true, workspaceId, scopes }\n * Stateless on this adapter — the caller persists the workspaceId in\n * its own session. The connector returns the workspace's effective\n * scope set so the caller can immediately filter capability discovery\n * against the new workspace's grant matrix.\n *\n * revoke_session({ token })\n * → { ok: true }\n * For session tokens: POST /api/auth/sign-out. For API keys: DELETE\n * /v1/keys/{id}. The adapter detects the kind from the prefix.\n *\n * Auth:\n * - **Service token** (`Bearer svc_*`) is required for `verify_token` of\n * `sk-tan-*` keys, `get_user`, `list_workspaces`, and `revoke_session`\n * of API keys.\n * - **Session cookie / Bearer session** is forwarded as-is for session\n * verification and session revocation.\n *\n * The adapter is stateless. Caller resolves `serviceToken` + `baseUrl` from\n * env (`TANGLE_PLATFORM_URL`, `TANGLE_SERVICE_TOKEN`) and passes them at\n * construction. The adapter never reads from `process.env` itself — this\n * keeps it CF Worker compatible (no Node-only env semantics) and lets\n * tests inject a fake fetch + service token in one place.\n */\n\nimport {\n type CapabilityMutationResult,\n type CapabilityReadResult,\n type ConnectorAdapter,\n type ConnectorInvocation,\n CredentialsExpired,\n} from '../types.js'\n\n/** Default platform URL (matches `DEFAULT_PLATFORM_URL` in tcloud). */\nexport const DEFAULT_TANGLE_PLATFORM_URL = 'https://id.tangle.tools'\n\n/** Hard timeout for every outbound platform call. Matches sandbox's\n * `PLATFORM_FETCH_TIMEOUT_MS` so a slow id.tangle.tools doesn't tie up\n * the consumer's request handler. */\nconst PLATFORM_FETCH_TIMEOUT_MS = 5_000\n\n/** API-key prefix the platform issues. Used to disambiguate token kind\n * without a round-trip. */\nexport const TANGLE_API_KEY_PREFIX = 'sk-tan-'\n\n/** Service-token prefix. Mirrored from the platform's middleware so we\n * can refuse to forward service tokens through the user-session path. */\nexport const TANGLE_SERVICE_TOKEN_PREFIX = 'svc_'\n\nexport interface TangleIdentityOptions {\n /** Base URL of the id.tangle.tools deployment (no trailing slash). */\n baseUrl?: string\n /**\n * Service token (`svc_*`) used for S2S calls (verify, provision, etc.).\n * Required for API-key verification and the user/workspace read paths.\n * Omit only for session-only flows on a deployment that exposes those\n * routes unauthenticated (rare; never in production).\n */\n serviceToken?: string\n /** Service identity claimed in the `X-Service-Name` header. */\n serviceName?: string\n /** Injected fetch — defaults to global. Tests pass a vi mock. */\n fetchImpl?: typeof fetch\n /** Per-call timeout override (default {@link PLATFORM_FETCH_TIMEOUT_MS}). */\n timeoutMs?: number\n}\n\n/** Stable result of a token verification. `valid: false` is returned for\n * every recognizable bad-token shape (expired, tampered, wrong issuer,\n * unknown kind); only true platform unreachability throws. */\nexport type TangleTokenVerifyResult =\n | {\n valid: true\n kind: 'api_key' | 'session'\n userId: string\n /** Active workspace at the moment of issue, if the credential is\n * workspace-scoped (team-owned API key). Personal credentials\n * return the user's personal workspace (== `userId`). */\n workspaceId: string\n scopes: string[]\n /** Wall-clock ms epoch when the credential expires. Undefined for\n * non-expiring credentials (most session cookies are sliding). */\n expiresAt?: number\n /** Stable id of the credential row, when known (key.id for API\n * keys, session.id for sessions). Useful for revoke + audit. */\n credentialId?: string\n /** Product the credential is scoped to, when known. */\n product?: string\n /** Owner shape — `user` for personal credentials, `team` for\n * team-owned API keys. Always matches the workspace's owner type. */\n ownerType: 'user' | 'team'\n }\n | {\n valid: false\n /** Stable reason code: `tampered`, `expired`, `revoked`,\n * `wrong_issuer`, `unknown_kind`, `service_token_refused`. */\n reason: TangleTokenVerifyFailure\n }\n\nexport type TangleTokenVerifyFailure =\n | 'tampered'\n | 'expired'\n | 'revoked'\n | 'wrong_issuer'\n | 'unknown_kind'\n | 'service_token_refused'\n | 'malformed'\n\nexport interface TangleUserSummary {\n id: string\n email?: string\n name?: string | null\n image?: string | null\n}\n\nexport interface TangleWorkspaceSummary {\n id: string\n name: string\n role: 'owner' | 'admin' | 'member'\n isPersonal: boolean\n /** Effective scope set for the calling user inside this workspace.\n * Sourced from the team's plan + per-product policy on the platform. */\n scopes: string[]\n}\n\n/** Thrown when id.tangle.tools is unreachable or returns 5xx. NOT thrown\n * for bad-token responses — those round-trip as `{ valid: false }`. */\nexport class TangleIdentityUnreachableError extends Error {\n override readonly name = 'TangleIdentityUnreachableError'\n readonly status?: number\n constructor(message: string, opts?: { status?: number; cause?: unknown }) {\n super(message, opts)\n this.status = opts?.status\n }\n}\n\n/** Build a `ConnectorAdapter` exposing id.tangle.tools as a first-party\n * integration. The adapter participates in the standard discovery /\n * capability gating loop, so a product can list identity ops alongside\n * Gmail / Stripe / etc. in the same tool registry. */\nexport function tangleIdentity(opts: TangleIdentityOptions = {}): ConnectorAdapter {\n const client = createTangleIdentityClient(opts)\n const adapter: ConnectorAdapter = {\n manifest: {\n kind: 'tangle-id',\n displayName: 'Tangle Identity',\n description:\n 'Verify Tangle session cookies and API keys issued by id.tangle.tools, resolve user + workspace identity, and gate capability discovery against the calling workspace scopes.',\n auth: { kind: 'api-key', hint: 'Tangle platform service token (svc_*).' },\n category: 'other',\n defaultConsistencyModel: 'authoritative',\n // 50 req/s per service token matches the platform's documented\n // S2S budget. We meter on our side so a chatty product doesn't\n // burn the shared service-token quota and block the rest.\n rateLimit: { requests: 50, windowMs: 1_000, scope: 'oauth-client' },\n capabilities: [\n {\n name: 'verify_token',\n class: 'read',\n description:\n 'Verify a session cookie or sk-tan-* API key. Returns { valid, userId, workspaceId, scopes, expiresAt } or { valid: false, reason }.',\n parameters: {\n type: 'object',\n properties: {\n token: { type: 'string', minLength: 1 },\n },\n required: ['token'],\n },\n },\n {\n name: 'get_user',\n class: 'read',\n description: 'Read the user profile (id, email, name, image) for a verified userId.',\n parameters: {\n type: 'object',\n properties: { userId: { type: 'string', minLength: 1 } },\n required: ['userId'],\n },\n },\n {\n name: 'list_workspaces',\n class: 'read',\n description: 'List workspaces (teams + the personal workspace) the user belongs to, with role + effective scopes.',\n parameters: {\n type: 'object',\n properties: { userId: { type: 'string', minLength: 1 } },\n required: ['userId'],\n },\n },\n {\n name: 'switch_workspace',\n class: 'mutation',\n description:\n 'Resolve a workspace by id and return its effective scope set. Stateless on this adapter — caller persists the workspaceId in its own session store.',\n parameters: {\n type: 'object',\n properties: {\n userId: { type: 'string', minLength: 1 },\n workspaceId: { type: 'string', minLength: 1 },\n },\n required: ['userId', 'workspaceId'],\n },\n cas: 'native-idempotency',\n externalEffect: false,\n },\n {\n name: 'revoke_session',\n class: 'mutation',\n description: 'Revoke a session token or API key. Idempotent.',\n parameters: {\n type: 'object',\n properties: { token: { type: 'string', minLength: 1 } },\n required: ['token'],\n },\n cas: 'native-idempotency',\n externalEffect: true,\n },\n {\n name: 'workspaces.create',\n class: 'mutation',\n description:\n 'Create a new workspace (team) owned by the calling user. Idempotent by display name + owner — re-issuing with the same name returns the existing workspace.',\n parameters: {\n type: 'object',\n properties: {\n userId: { type: 'string', minLength: 1 },\n name: { type: 'string', minLength: 1 },\n slug: { type: 'string', minLength: 1 },\n },\n required: ['userId', 'name'],\n },\n cas: 'native-idempotency',\n externalEffect: true,\n },\n {\n name: 'workspaces.delete',\n class: 'mutation',\n description:\n 'Delete a workspace. Refuses to delete a user personal workspace. Idempotent: 404 is treated as a no-op.',\n parameters: {\n type: 'object',\n properties: { workspaceId: { type: 'string', minLength: 1 } },\n required: ['workspaceId'],\n },\n cas: 'native-idempotency',\n externalEffect: true,\n },\n {\n name: 'members.invite',\n class: 'mutation',\n description:\n 'Invite a member to a workspace by email. Idempotent: re-inviting the same email returns the existing invitation.',\n parameters: {\n type: 'object',\n properties: {\n workspaceId: { type: 'string', minLength: 1 },\n email: { type: 'string', minLength: 3 },\n role: { type: 'string', enum: ['owner', 'admin', 'member'] },\n },\n required: ['workspaceId', 'email'],\n },\n cas: 'native-idempotency',\n externalEffect: true,\n },\n {\n name: 'members.remove',\n class: 'mutation',\n description:\n 'Remove a member from a workspace by userId. Idempotent: 404 is treated as a no-op.',\n parameters: {\n type: 'object',\n properties: {\n workspaceId: { type: 'string', minLength: 1 },\n userId: { type: 'string', minLength: 1 },\n },\n required: ['workspaceId', 'userId'],\n },\n cas: 'native-idempotency',\n externalEffect: true,\n },\n ],\n },\n\n async executeRead(inv: ConnectorInvocation): Promise<CapabilityReadResult> {\n if (inv.capabilityName === 'verify_token') {\n const token = readStringArg(inv.args, 'token')\n const result = await client.verifyToken(token)\n return { data: result, fetchedAt: Date.now() }\n }\n if (inv.capabilityName === 'get_user') {\n const userId = readStringArg(inv.args, 'userId')\n const user = await client.getUser(userId)\n return { data: user, fetchedAt: Date.now() }\n }\n if (inv.capabilityName === 'list_workspaces') {\n const userId = readStringArg(inv.args, 'userId')\n const workspaces = await client.listWorkspaces(userId)\n return { data: { workspaces }, fetchedAt: Date.now() }\n }\n throw new Error(`tangle-id: unknown read capability ${inv.capabilityName}`)\n },\n\n async executeMutation(inv: ConnectorInvocation): Promise<CapabilityMutationResult> {\n if (inv.capabilityName === 'switch_workspace') {\n const userId = readStringArg(inv.args, 'userId')\n const workspaceId = readStringArg(inv.args, 'workspaceId')\n const result = await client.switchWorkspace(userId, workspaceId)\n return {\n status: 'committed',\n data: result,\n committedAt: Date.now(),\n idempotentReplay: false,\n }\n }\n if (inv.capabilityName === 'revoke_session') {\n const token = readStringArg(inv.args, 'token')\n await client.revokeSession(token)\n return {\n status: 'committed',\n data: { ok: true },\n committedAt: Date.now(),\n idempotentReplay: false,\n }\n }\n if (inv.capabilityName === 'workspaces.create') {\n const userId = readStringArg(inv.args, 'userId')\n const name = readStringArg(inv.args, 'name')\n const slug = readOptionalStringArg(inv.args, 'slug')\n const workspace = await client.createWorkspace(userId, { name, slug })\n return {\n status: 'committed',\n data: workspace,\n committedAt: Date.now(),\n idempotentReplay: false,\n }\n }\n if (inv.capabilityName === 'workspaces.delete') {\n const workspaceId = readStringArg(inv.args, 'workspaceId')\n await client.deleteWorkspace(workspaceId)\n return {\n status: 'committed',\n data: { ok: true, workspaceId },\n committedAt: Date.now(),\n idempotentReplay: false,\n }\n }\n if (inv.capabilityName === 'members.invite') {\n const workspaceId = readStringArg(inv.args, 'workspaceId')\n const email = readStringArg(inv.args, 'email')\n const role = readOptionalRole(inv.args, 'role')\n const invitation = await client.inviteMember(workspaceId, email, role)\n return {\n status: 'committed',\n data: invitation,\n committedAt: Date.now(),\n idempotentReplay: false,\n }\n }\n if (inv.capabilityName === 'members.remove') {\n const workspaceId = readStringArg(inv.args, 'workspaceId')\n const userId = readStringArg(inv.args, 'userId')\n await client.removeMember(workspaceId, userId)\n return {\n status: 'committed',\n data: { ok: true, workspaceId, userId },\n committedAt: Date.now(),\n idempotentReplay: false,\n }\n }\n throw new Error(`tangle-id: unknown mutation capability ${inv.capabilityName}`)\n },\n\n async test(source) {\n try {\n // Cheapest probe: hit the platform's /health endpoint. Doesn't\n // burn the service-token quota and proves the deployment is up.\n const ok = await client.ping()\n if (!ok) return { ok: false, reason: 'id.tangle.tools /health returned non-200' }\n return { ok: true }\n } catch (err) {\n if (err instanceof CredentialsExpired) {\n return { ok: false, reason: 'service token rejected — rotate TANGLE_SERVICE_TOKEN' }\n }\n return { ok: false, reason: err instanceof Error ? err.message : String(err) }\n }\n },\n }\n return adapter\n}\n\n/** Low-level HTTP client used by the adapter. Exported so consumers\n * (middleware, connect routes, custom apps) can hit id.tangle.tools\n * without going through the connector pipeline. */\nexport interface TangleIdentityClient {\n verifyToken(token: string): Promise<TangleTokenVerifyResult>\n getUser(userId: string): Promise<TangleUserSummary>\n listWorkspaces(userId: string): Promise<TangleWorkspaceSummary[]>\n switchWorkspace(\n userId: string,\n workspaceId: string,\n ): Promise<{ ok: true; workspaceId: string; scopes: string[] }>\n revokeSession(token: string): Promise<void>\n /** Create a new workspace owned by `userId`. The platform's\n * `POST /v1/teams` returns the persisted row. Idempotent on\n * `(ownerId, name)` upstream; conflicts are unwrapped to the\n * existing row, not surfaced as errors. */\n createWorkspace(\n userId: string,\n spec: { name: string; slug?: string },\n ): Promise<TangleWorkspaceSummary>\n /** Delete a workspace. Refuses to delete the user's personal\n * workspace (the platform-side `/v1/teams/{id}` returns 409). */\n deleteWorkspace(workspaceId: string): Promise<void>\n /** Invite a member to a workspace by email. Idempotent: re-issuing\n * the same invite returns the existing pending invitation row. */\n inviteMember(\n workspaceId: string,\n email: string,\n role?: TangleWorkspaceSummary['role'],\n ): Promise<TangleInvitationSummary>\n /** Remove a member from a workspace by `userId`. 404 is a no-op. */\n removeMember(workspaceId: string, userId: string): Promise<void>\n ping(): Promise<boolean>\n}\n\nexport interface TangleInvitationSummary {\n id: string\n workspaceId: string\n email: string\n role: TangleWorkspaceSummary['role']\n status: 'pending' | 'accepted' | 'revoked'\n}\n\nexport function createTangleIdentityClient(opts: TangleIdentityOptions = {}): TangleIdentityClient {\n const baseUrl = (opts.baseUrl ?? DEFAULT_TANGLE_PLATFORM_URL).replace(/\\/+$/, '')\n const serviceToken = opts.serviceToken\n const serviceName = opts.serviceName ?? 'integrations'\n const fetchImpl = opts.fetchImpl ?? fetch\n const timeoutMs = opts.timeoutMs ?? PLATFORM_FETCH_TIMEOUT_MS\n\n function s2sHeaders(): Record<string, string> {\n if (!serviceToken) {\n throw new TangleIdentityUnreachableError(\n 'tangle-id: serviceToken is required for service-to-service calls (verify, get_user, list_workspaces, revoke)',\n )\n }\n return {\n 'content-type': 'application/json',\n authorization: `Bearer ${serviceToken}`,\n 'x-service-name': serviceName,\n }\n }\n\n async function jsonFetch(path: string, init: RequestInit): Promise<Response> {\n let res: Response\n try {\n res = await fetchImpl(`${baseUrl}${path}`, {\n ...init,\n signal: init.signal ?? AbortSignal.timeout(timeoutMs),\n })\n } catch (err) {\n throw new TangleIdentityUnreachableError(\n `tangle-id: request to ${path} failed`,\n { cause: err },\n )\n }\n return res\n }\n\n async function readErrorDetail(res: Response): Promise<string> {\n try {\n const text = await res.text()\n return text.trim().slice(0, 200)\n } catch {\n return ''\n }\n }\n\n async function verifyApiKey(token: string): Promise<TangleTokenVerifyResult> {\n const res = await jsonFetch('/v1/keys/verify', {\n method: 'POST',\n headers: s2sHeaders(),\n body: JSON.stringify({ key: token }),\n })\n if (res.status === 401) {\n // Service token rejected — distinct from \"token is bad\". The\n // platform middleware refuses our svc_* credential. Surface that\n // as `service_token_refused` so the caller can rotate.\n return { valid: false, reason: 'service_token_refused' }\n }\n if (!res.ok) {\n throw new TangleIdentityUnreachableError(\n `tangle-id: /v1/keys/verify returned ${res.status}: ${await readErrorDetail(res)}`,\n { status: res.status },\n )\n }\n const body = (await res.json().catch(() => null)) as\n | {\n valid?: boolean\n userId?: string\n ownerId?: string\n ownerType?: 'user' | 'team'\n keyId?: string\n product?: string\n allowedModels?: unknown\n expiresAt?: string\n }\n | null\n if (!body || typeof body.valid !== 'boolean') {\n return { valid: false, reason: 'malformed' }\n }\n if (!body.valid || !body.userId) {\n return { valid: false, reason: 'revoked' }\n }\n const scopes = Array.isArray(body.allowedModels)\n ? body.allowedModels.filter((value): value is string => typeof value === 'string')\n : []\n if (body.product) scopes.push(`product:${body.product}`)\n const expiresAt =\n typeof body.expiresAt === 'string' && body.expiresAt\n ? Date.parse(body.expiresAt)\n : undefined\n return {\n valid: true,\n kind: 'api_key',\n userId: body.userId,\n workspaceId: body.ownerType === 'team' && body.ownerId ? body.ownerId : body.userId,\n ownerType: body.ownerType ?? 'user',\n scopes,\n ...(Number.isFinite(expiresAt) ? { expiresAt: expiresAt as number } : {}),\n ...(body.keyId ? { credentialId: body.keyId } : {}),\n ...(body.product ? { product: body.product } : {}),\n }\n }\n\n async function verifySession(token: string): Promise<TangleTokenVerifyResult> {\n // Better Auth's get-session endpoint accepts either:\n // - Cookie header `better-auth.session_token=<jwt>` (browser flow)\n // - Bearer token (mobile / CLI flow), which Better Auth's bearer\n // plugin extracts and resolves to a session row.\n // We always send Bearer; the platform's auth handler treats absent\n // cookie + present Bearer identically.\n const res = await jsonFetch('/api/auth/get-session', {\n method: 'GET',\n headers: {\n accept: 'application/json',\n authorization: `Bearer ${token}`,\n },\n })\n if (res.status === 401 || res.status === 403) {\n return { valid: false, reason: 'expired' }\n }\n if (!res.ok) {\n throw new TangleIdentityUnreachableError(\n `tangle-id: /api/auth/get-session returned ${res.status}: ${await readErrorDetail(res)}`,\n { status: res.status },\n )\n }\n const body = (await res.json().catch(() => null)) as\n | {\n user?: { id?: string; email?: string }\n session?: { id?: string; expiresAt?: string; activeTeamId?: string | null }\n }\n | null\n if (!body || !body.user || typeof body.user.id !== 'string') {\n return { valid: false, reason: 'expired' }\n }\n const expiresAtRaw = body.session?.expiresAt\n const expiresAt = expiresAtRaw ? Date.parse(expiresAtRaw) : NaN\n return {\n valid: true,\n kind: 'session',\n userId: body.user.id,\n workspaceId: body.session?.activeTeamId || body.user.id,\n ownerType: body.session?.activeTeamId ? 'team' : 'user',\n scopes: [],\n ...(Number.isFinite(expiresAt) ? { expiresAt } : {}),\n ...(body.session?.id ? { credentialId: body.session.id } : {}),\n }\n }\n\n return {\n async verifyToken(token: string): Promise<TangleTokenVerifyResult> {\n if (!token || typeof token !== 'string') {\n return { valid: false, reason: 'malformed' }\n }\n if (token.startsWith(TANGLE_SERVICE_TOKEN_PREFIX)) {\n // Service tokens MUST NOT be accepted as user identity. The\n // platform middleware sets `authMethod: 'service_token'` and\n // refuses every user-bound route on that path; mirror the\n // refusal here so a misconfigured product can't accidentally\n // treat an svc_* as the calling user.\n return { valid: false, reason: 'service_token_refused' }\n }\n if (token.startsWith(TANGLE_API_KEY_PREFIX)) {\n return verifyApiKey(token)\n }\n // Anything else — treat as a session bearer (Better Auth-emitted\n // JWTs are opaque to us). Wrong-issuer / random-string lands\n // on the 401 path inside `verifySession` and round-trips as\n // `expired`. We do not pre-validate JWT signatures — only the\n // platform holds the signing secret.\n return verifySession(token)\n },\n\n async getUser(userId: string): Promise<TangleUserSummary> {\n if (!userId) {\n throw new TangleIdentityUnreachableError('tangle-id: getUser requires a non-empty userId')\n }\n const res = await jsonFetch(`/v1/users/${encodeURIComponent(userId)}`, {\n method: 'GET',\n headers: s2sHeaders(),\n })\n if (res.status === 404) {\n throw new TangleIdentityUnreachableError(`tangle-id: user ${userId} not found`, { status: 404 })\n }\n if (!res.ok) {\n throw new TangleIdentityUnreachableError(\n `tangle-id: /v1/users/${userId} returned ${res.status}: ${await readErrorDetail(res)}`,\n { status: res.status },\n )\n }\n const body = (await res.json().catch(() => null)) as\n | { success?: boolean; data?: { id?: string; email?: string; name?: string | null; image?: string | null } }\n | null\n const data = body?.data\n if (!data || typeof data.id !== 'string') {\n throw new TangleIdentityUnreachableError('tangle-id: /v1/users response had an invalid shape')\n }\n return {\n id: data.id,\n ...(typeof data.email === 'string' ? { email: data.email } : {}),\n ...(data.name !== undefined ? { name: data.name } : {}),\n ...(data.image !== undefined ? { image: data.image } : {}),\n }\n },\n\n async listWorkspaces(userId: string): Promise<TangleWorkspaceSummary[]> {\n const res = await jsonFetch('/v1/teams', {\n method: 'GET',\n headers: { ...s2sHeaders(), 'x-platform-user-id': userId },\n })\n if (!res.ok) {\n throw new TangleIdentityUnreachableError(\n `tangle-id: /v1/teams returned ${res.status}: ${await readErrorDetail(res)}`,\n { status: res.status },\n )\n }\n const body = (await res.json().catch(() => null)) as\n | {\n success?: boolean\n data?: Array<{\n id?: string\n name?: string\n role?: string\n isPersonal?: boolean\n scopes?: unknown\n }>\n }\n | null\n const rows = Array.isArray(body?.data) ? body!.data : []\n const workspaces: TangleWorkspaceSummary[] = []\n for (const row of rows) {\n if (!row || typeof row.id !== 'string' || typeof row.name !== 'string') continue\n const role: TangleWorkspaceSummary['role'] =\n row.role === 'owner' || row.role === 'admin' ? row.role : 'member'\n const scopes = Array.isArray(row.scopes)\n ? row.scopes.filter((value): value is string => typeof value === 'string')\n : []\n workspaces.push({\n id: row.id,\n name: row.name,\n role,\n isPersonal: Boolean(row.isPersonal) || row.id === userId,\n scopes,\n })\n }\n return workspaces\n },\n\n async switchWorkspace(userId, workspaceId) {\n const workspaces = await this.listWorkspaces(userId)\n const match = workspaces.find((w) => w.id === workspaceId)\n if (!match) {\n throw new TangleIdentityUnreachableError(\n `tangle-id: workspace ${workspaceId} not found for user ${userId}`,\n { status: 404 },\n )\n }\n return { ok: true, workspaceId: match.id, scopes: match.scopes }\n },\n\n async revokeSession(token: string): Promise<void> {\n if (!token) return\n if (token.startsWith(TANGLE_SERVICE_TOKEN_PREFIX)) {\n throw new TangleIdentityUnreachableError(\n 'tangle-id: refusing to revoke a service token — rotate it instead',\n )\n }\n if (token.startsWith(TANGLE_API_KEY_PREFIX)) {\n // We don't know the key id until we verify; do that first so\n // revoke is keyed by id (the only thing the platform's DELETE\n // /v1/keys/{id} accepts). Bad-key responses are no-ops.\n const v = await verifyApiKey(token)\n if (!v.valid || !v.credentialId) return\n const res = await jsonFetch(`/v1/keys/${encodeURIComponent(v.credentialId)}`, {\n method: 'DELETE',\n headers: s2sHeaders(),\n })\n if (res.status === 404) return\n if (!res.ok) {\n throw new TangleIdentityUnreachableError(\n `tangle-id: DELETE /v1/keys/${v.credentialId} returned ${res.status}: ${await readErrorDetail(res)}`,\n { status: res.status },\n )\n }\n return\n }\n // Session token — Better Auth's sign-out endpoint accepts the\n // session via Bearer + Cookie. We forward the credential as-is.\n const res = await jsonFetch('/api/auth/sign-out', {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n authorization: `Bearer ${token}`,\n },\n body: '{}',\n })\n // Better Auth returns 200 on a fresh sign-out and 200/401 on a\n // stale one; either way the session is no longer usable.\n if (res.status >= 500) {\n throw new TangleIdentityUnreachableError(\n `tangle-id: /api/auth/sign-out returned ${res.status}: ${await readErrorDetail(res)}`,\n { status: res.status },\n )\n }\n },\n\n async createWorkspace(userId, spec) {\n if (!userId) {\n throw new TangleIdentityUnreachableError(\n 'tangle-id: createWorkspace requires a non-empty userId',\n )\n }\n const res = await jsonFetch('/v1/teams', {\n method: 'POST',\n headers: { ...s2sHeaders(), 'x-platform-user-id': userId },\n body: JSON.stringify({\n name: spec.name,\n ...(spec.slug ? { slug: spec.slug } : {}),\n }),\n })\n if (res.status === 401) {\n throw new CredentialsExpired(\n 'tangle-id: service token rejected on POST /v1/teams',\n 'tangle-id',\n )\n }\n if (!res.ok) {\n throw new TangleIdentityUnreachableError(\n `tangle-id: POST /v1/teams returned ${res.status}: ${await readErrorDetail(res)}`,\n { status: res.status },\n )\n }\n const body = (await res.json().catch(() => null)) as\n | {\n success?: boolean\n data?: { id?: string; name?: string; role?: string; isPersonal?: boolean; scopes?: unknown }\n }\n | null\n const data = body?.data\n if (!data || typeof data.id !== 'string' || typeof data.name !== 'string') {\n throw new TangleIdentityUnreachableError(\n 'tangle-id: POST /v1/teams response had an invalid shape',\n )\n }\n const role: TangleWorkspaceSummary['role'] =\n data.role === 'owner' || data.role === 'admin' ? data.role : 'owner'\n const scopes = Array.isArray(data.scopes)\n ? data.scopes.filter((value): value is string => typeof value === 'string')\n : []\n return {\n id: data.id,\n name: data.name,\n role,\n isPersonal: Boolean(data.isPersonal) || data.id === userId,\n scopes,\n }\n },\n\n async deleteWorkspace(workspaceId) {\n if (!workspaceId) {\n throw new TangleIdentityUnreachableError(\n 'tangle-id: deleteWorkspace requires a non-empty workspaceId',\n )\n }\n const res = await jsonFetch(`/v1/teams/${encodeURIComponent(workspaceId)}`, {\n method: 'DELETE',\n headers: s2sHeaders(),\n })\n if (res.status === 401) {\n throw new CredentialsExpired(\n 'tangle-id: service token rejected on DELETE /v1/teams',\n 'tangle-id',\n )\n }\n if (res.status === 404) return\n if (!res.ok) {\n throw new TangleIdentityUnreachableError(\n `tangle-id: DELETE /v1/teams/${workspaceId} returned ${res.status}: ${await readErrorDetail(res)}`,\n { status: res.status },\n )\n }\n },\n\n async inviteMember(workspaceId, email, role) {\n if (!workspaceId) {\n throw new TangleIdentityUnreachableError(\n 'tangle-id: inviteMember requires a non-empty workspaceId',\n )\n }\n if (!email) {\n throw new TangleIdentityUnreachableError(\n 'tangle-id: inviteMember requires a non-empty email',\n )\n }\n const res = await jsonFetch(\n `/v1/teams/${encodeURIComponent(workspaceId)}/invitations`,\n {\n method: 'POST',\n headers: s2sHeaders(),\n body: JSON.stringify({\n email,\n ...(role ? { role } : {}),\n }),\n },\n )\n if (res.status === 401) {\n throw new CredentialsExpired(\n 'tangle-id: service token rejected on POST invitation',\n 'tangle-id',\n )\n }\n if (!res.ok) {\n throw new TangleIdentityUnreachableError(\n `tangle-id: POST /v1/teams/${workspaceId}/invitations returned ${res.status}: ${await readErrorDetail(res)}`,\n { status: res.status },\n )\n }\n const body = (await res.json().catch(() => null)) as\n | {\n success?: boolean\n data?: {\n id?: string\n workspaceId?: string\n teamId?: string\n email?: string\n role?: string\n status?: string\n }\n }\n | null\n const data = body?.data\n if (!data || typeof data.id !== 'string') {\n throw new TangleIdentityUnreachableError(\n 'tangle-id: POST invitation response had an invalid shape',\n )\n }\n const resolvedRole: TangleWorkspaceSummary['role'] =\n data.role === 'owner' || data.role === 'admin' ? data.role : 'member'\n const status: TangleInvitationSummary['status'] =\n data.status === 'accepted' || data.status === 'revoked' ? data.status : 'pending'\n return {\n id: data.id,\n workspaceId: data.workspaceId ?? data.teamId ?? workspaceId,\n email: data.email ?? email,\n role: resolvedRole,\n status,\n }\n },\n\n async removeMember(workspaceId, userId) {\n if (!workspaceId || !userId) {\n throw new TangleIdentityUnreachableError(\n 'tangle-id: removeMember requires non-empty workspaceId and userId',\n )\n }\n const res = await jsonFetch(\n `/v1/teams/${encodeURIComponent(workspaceId)}/members/${encodeURIComponent(userId)}`,\n {\n method: 'DELETE',\n headers: s2sHeaders(),\n },\n )\n if (res.status === 401) {\n throw new CredentialsExpired(\n 'tangle-id: service token rejected on DELETE member',\n 'tangle-id',\n )\n }\n if (res.status === 404) return\n if (!res.ok) {\n throw new TangleIdentityUnreachableError(\n `tangle-id: DELETE /v1/teams/${workspaceId}/members/${userId} returned ${res.status}: ${await readErrorDetail(res)}`,\n { status: res.status },\n )\n }\n },\n\n async ping(): Promise<boolean> {\n const res = await jsonFetch('/health', { method: 'GET' })\n return res.ok\n },\n }\n}\n\nfunction readStringArg(args: Record<string, unknown>, key: string): string {\n const value = args[key]\n if (typeof value !== 'string' || !value) {\n throw new Error(`tangle-id: missing required argument \"${key}\"`)\n }\n return value\n}\n\nfunction readOptionalStringArg(args: Record<string, unknown>, key: string): string | undefined {\n const value = args[key]\n if (value === undefined || value === null) return undefined\n if (typeof value !== 'string' || !value) return undefined\n return value\n}\n\nfunction readOptionalRole(\n args: Record<string, unknown>,\n key: string,\n): TangleWorkspaceSummary['role'] | undefined {\n const value = args[key]\n if (value === 'owner' || value === 'admin' || value === 'member') return value\n return undefined\n}\n"],"mappings":"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","names":["res"]}
|