@opengeni/api-router 0.30.1 → 1.0.0
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/dist/access-grant-rls.d.ts +3 -0
- package/dist/admission-trace.d.ts +8 -0
- package/dist/api-websocket.d.ts +18 -0
- package/dist/app.d.ts +50 -2
- package/dist/app.js +12 -1
- package/dist/artifact-catalog-cursor.d.ts +27 -0
- package/dist/auth/managed-auth-attempt-context.d.ts +10 -0
- package/dist/auth/managed-auth-rate-limits.d.ts +167 -0
- package/dist/auth/managed-auth-session-adapter.d.ts +6 -0
- package/dist/auth/managed-auth.d.ts +102 -3
- package/dist/auth/managed-email.d.ts +29 -0
- package/dist/auth/managed-sign-in-notifications.d.ts +4 -0
- package/dist/auth/new-signups-gate.d.ts +23 -0
- package/dist/auth/organization-user-setup.d.ts +80 -0
- package/dist/auth/signup-funnel-metrics.d.ts +44 -0
- package/dist/browser-controller-authority.d.ts +1 -61
- package/dist/browser-ephemeral.d.ts +5 -0
- package/dist/browser-state-authority.d.ts +1 -27
- package/dist/chunk-6TZ5LG3O.js +123948 -0
- package/dist/chunk-6TZ5LG3O.js.map +1 -0
- package/dist/chunk-OGQDXVXY.js +18 -0
- package/dist/chunk-OGQDXVXY.js.map +1 -0
- package/dist/claude-subscription-account-conflicts.d.ts +1 -0
- package/dist/claude-subscription-account-usage.d.ts +39 -0
- package/dist/claude-subscription-oauth.d.ts +25 -0
- package/dist/claude-subscription-profile.d.ts +9 -0
- package/dist/claude-subscription-usage.d.ts +44 -0
- package/dist/claude-workspace-connection.d.ts +15 -0
- package/dist/codemode.d.ts +32 -1
- package/dist/company-brain-okf.d.ts +24 -0
- package/dist/connected-machine-computer-access.d.ts +11 -0
- package/dist/connection-ownership.d.ts +54 -0
- package/dist/controller-data-plane.d.ts +32 -0
- package/dist/editable-artifact-office-import.d.ts +7 -4
- package/dist/editable-artifact-source-session.d.ts +3 -0
- package/dist/editable-artifact-websocket.d.ts +10 -18
- package/dist/editable-artifact-workspace-files.d.ts +1 -1
- package/dist/fatal-process-boundary.d.ts +25 -0
- package/dist/github-access.d.ts +31 -2
- package/dist/http/acting-person.d.ts +24 -0
- package/dist/http/api-contract-compat.d.ts +19 -0
- package/dist/http/api-error.d.ts +27 -1
- package/dist/http/cors.d.ts +17 -0
- package/dist/http/deprecation.d.ts +42 -0
- package/dist/http/interaction-control-error.d.ts +13 -0
- package/dist/http/keyed-admission.d.ts +12 -0
- package/dist/http/local-browser-boundary.d.ts +72 -0
- package/dist/http/metrics-listener.d.ts +22 -0
- package/dist/http/path-identifier.d.ts +17 -0
- package/dist/http/registered-route-label.d.ts +16 -0
- package/dist/http/request-body.d.ts +27 -0
- package/dist/http/request-source.d.ts +52 -0
- package/dist/http/sse.d.ts +17 -6
- package/dist/http/unmatched-route.d.ts +18 -0
- package/dist/http/user-content.d.ts +36 -0
- package/dist/http/websocket-upgrade-dispatch.d.ts +18 -0
- package/dist/index.d.ts +10 -3
- package/dist/index.js +1129 -166
- package/dist/index.js.map +1 -1
- package/dist/integration-endpoint-test.d.ts +20 -0
- package/dist/integrations/api-integrations.d.ts +2 -2
- package/dist/integrations/atlassian.d.ts +29 -3
- package/dist/integrations/connect-authority.d.ts +1 -0
- package/dist/integrations/connect-callback-return.d.ts +6 -0
- package/dist/integrations/fiken.d.ts +16 -2
- package/dist/integrations/github-app-connect.d.ts +47 -0
- package/dist/integrations/github-installation-proof.d.ts +3 -0
- package/dist/integrations/github-lens-connect.d.ts +116 -0
- package/dist/integrations/github-skill-source.d.ts +1 -5
- package/dist/integrations/google-drive.d.ts +25 -0
- package/dist/integrations/integration-commit-authority.d.ts +13 -0
- package/dist/integrations/marketplace-plugin.d.ts +2691 -0
- package/dist/integrations/oauth-client.d.ts +178 -18
- package/dist/integrations/oauth-profiles.d.ts +222 -0
- package/dist/integrations/oauth-return-path.d.ts +1 -0
- package/dist/integrations/personal-github-repositories.d.ts +84 -0
- package/dist/integrations/personal-github.d.ts +42 -0
- package/dist/integrations/pr-review-provider.d.ts +22 -0
- package/dist/integrations/provider-oauth.d.ts +19 -1
- package/dist/integrations/slack-app-home.d.ts +24 -0
- package/dist/integrations/slack-bot.d.ts +367 -12
- package/dist/integrations/slack-file-upload-flow.d.ts +62 -0
- package/dist/integrations/slack-install.d.ts +20 -0
- package/dist/integrations/slack-interactions.d.ts +113 -10
- package/dist/integrations/slack-mrkdwn.d.ts +41 -0
- package/dist/integrations/slack-routing.d.ts +120 -0
- package/dist/integrations/slack-session-defaults.d.ts +58 -0
- package/dist/integrations/slack-task-file-upload.d.ts +36 -0
- package/dist/integrations/social-oauth.d.ts +7 -0
- package/dist/interaction-agent-access.d.ts +15 -0
- package/dist/interaction-frame-proxy.d.ts +68 -0
- package/dist/interaction-metrics.d.ts +2 -0
- package/dist/mcp/action-catalog-types.d.ts +9 -0
- package/dist/mcp/action-catalog.gen.d.ts +2 -0
- package/dist/mcp/capability-account-readiness.d.ts +7 -0
- package/dist/mcp/child-read-evidence.d.ts +9 -0
- package/dist/mcp/command-read.d.ts +24 -0
- package/dist/mcp/company-profile-agent-admin.d.ts +44 -0
- package/dist/mcp/contract-input.d.ts +11 -0
- package/dist/mcp/documents.d.ts +7 -5
- package/dist/mcp/files.d.ts +2 -2
- package/dist/mcp/first-party-tool-permissions.d.ts +650 -0
- package/dist/mcp/knowledge-entries.d.ts +5 -0
- package/dist/mcp/orchestration-failure-diagnostic.d.ts +43 -0
- package/dist/mcp/receipts.d.ts +9 -0
- package/dist/mcp/request-abort.d.ts +19 -0
- package/dist/mcp/scheduled-task-input.d.ts +1189 -0
- package/dist/mcp/scheduled-task-view.d.ts +22 -4
- package/dist/mcp/server.d.ts +255 -3
- package/dist/mcp/session-event-view.d.ts +94 -0
- package/dist/mcp/session-view.d.ts +66 -2
- package/dist/mcp/session-wait.d.ts +174 -0
- package/dist/mcp-oauth.d.ts +52 -0
- package/dist/model-catalog.d.ts +11 -31
- package/dist/observability.d.ts +3 -1
- package/dist/organization-mcp.d.ts +52 -0
- package/dist/organization-recovery-notifications.d.ts +41 -0
- package/dist/routes/analytics-consent.d.ts +26 -0
- package/dist/routes/api-integrations.d.ts +25 -0
- package/dist/routes/api-keys.d.ts +17 -0
- package/dist/routes/artifact-catalog.d.ts +6 -0
- package/dist/routes/automations.d.ts +19 -0
- package/dist/routes/billing.d.ts +49 -0
- package/dist/routes/browser-sessions.d.ts +71 -3
- package/dist/routes/claude-subscription-accounts.d.ts +3 -0
- package/dist/routes/claude-subscription-oauth.d.ts +3 -0
- package/dist/routes/client-errors.d.ts +146 -0
- package/dist/routes/codex.d.ts +76 -2
- package/dist/routes/company-brain.d.ts +3 -0
- package/dist/routes/company-profile.d.ts +2 -1
- package/dist/routes/computer-sessions.d.ts +14 -0
- package/dist/routes/connect.d.ts +5 -0
- package/dist/routes/editable-artifacts.d.ts +2 -0
- package/dist/routes/external-identity-links.d.ts +6 -0
- package/dist/routes/feedback.d.ts +3 -0
- package/dist/routes/files.d.ts +4 -0
- package/dist/routes/github-browser-pages.d.ts +12 -0
- package/dist/routes/github.d.ts +2 -0
- package/dist/routes/insights-response-cache.d.ts +10 -0
- package/dist/routes/insights-usage.d.ts +12 -0
- package/dist/routes/insights.d.ts +30 -1
- package/dist/routes/knowledge.d.ts +3 -0
- package/dist/routes/managed-auth-session-sets.d.ts +26 -0
- package/dist/routes/managed-onboarding.d.ts +29 -0
- package/dist/routes/managed-sign-in-methods.d.ts +6 -0
- package/dist/routes/model-connection-access.d.ts +3 -0
- package/dist/routes/organization-integration-policy.d.ts +3 -0
- package/dist/routes/organization-integrations.d.ts +6 -0
- package/dist/routes/organization-mcp-connections.d.ts +3 -0
- package/dist/routes/organization-model-providers.d.ts +3 -0
- package/dist/routes/organization-recovery.d.ts +19 -0
- package/dist/routes/organization-service-accounts.d.ts +3 -0
- package/dist/routes/organization-sessions.d.ts +26 -0
- package/dist/routes/personal-github-git-broker.d.ts +29 -0
- package/dist/routes/personal-github.d.ts +3 -0
- package/dist/routes/pr-review-github.d.ts +3 -0
- package/dist/routes/pr-review.d.ts +3 -0
- package/dist/routes/session-artifact-associations.d.ts +4 -0
- package/dist/routes/session-history-imports.d.ts +9 -0
- package/dist/routes/sessions.d.ts +44 -6
- package/dist/routes/skill-content.d.ts +4 -0
- package/dist/routes/skill-install-authority.d.ts +6 -0
- package/dist/routes/subscription-account-pools.d.ts +34 -0
- package/dist/routes/subscription-pool-access.d.ts +16 -0
- package/dist/routes/supergrok.d.ts +6 -1
- package/dist/routes/usage-allowances.d.ts +12 -0
- package/dist/routes/user-resource-authorities.d.ts +3 -0
- package/dist/routes/workspace-artifacts.d.ts +2 -1
- package/dist/routes/workspace-capture.d.ts +10 -2
- package/dist/routes/workspace-integrations.d.ts +35 -0
- package/dist/routes/workspace-learning.d.ts +3 -0
- package/dist/routes/workspace-model-providers.d.ts +4 -0
- package/dist/routes/workspaces.d.ts +29 -0
- package/dist/sandbox/auth-callout.d.ts +8 -0
- package/dist/sandbox/channel-a.d.ts +19 -1
- package/dist/sandbox/connection-authority.d.ts +3 -0
- package/dist/sandbox/enrollment.d.ts +9 -1
- package/dist/sandbox/machines.d.ts +5 -2
- package/dist/sandbox/metrics-ingestion.d.ts +28 -20
- package/dist/sandbox/rematerialize.d.ts +2 -0
- package/dist/sandbox/session-attach-variable-sets.d.ts +30 -0
- package/dist/sandbox/viewer.d.ts +26 -1
- package/dist/sandbox-file-artifacts.d.ts +50 -0
- package/dist/scheduled-task-deletion.d.ts +13 -0
- package/dist/session-create-observability.d.ts +5 -0
- package/dist/session-event-view-MPS2OZD3.js +292 -0
- package/dist/session-event-view-MPS2OZD3.js.map +1 -0
- package/dist/site-session-origin.d.ts +13 -0
- package/dist/site-uploads.d.ts +41 -0
- package/dist/slack-reaction-files.d.ts +1 -1
- package/dist/temporal-schedule-cleanup.d.ts +1 -0
- package/dist/temporal-schedule-sync.d.ts +26 -0
- package/dist/transcription/providers/xai-subscription.d.ts +1 -0
- package/dist/transcription/service.d.ts +2 -1
- package/dist/work-discovery-observability.d.ts +33 -0
- package/dist/workspace-artifact-content.d.ts +28 -0
- package/dist/workspace-artifact-provenance.d.ts +7 -0
- package/dist/workspace-delete-observability.d.ts +10 -0
- package/dist/workspace-deletion.d.ts +6 -0
- package/dist/workspace-state-projection.d.ts +3 -5
- package/dist/workspace-tool-gateway-observability.d.ts +17 -0
- package/dist/workspace-tool-gateway.d.ts +123 -0
- package/dist/workspace-webhook-dispatch.d.ts +26 -0
- package/package.json +23 -19
- package/src/access-grant-rls.ts +75 -0
- package/src/admission-trace.ts +14 -0
- package/src/api-websocket.ts +23 -0
- package/src/app.ts +1974 -256
- package/src/artifact-catalog-cursor.ts +60 -0
- package/src/auth/managed-auth-attempt-context.ts +70 -0
- package/src/auth/managed-auth-rate-limits.ts +252 -0
- package/src/auth/managed-auth-session-adapter.ts +222 -0
- package/src/auth/managed-auth.ts +536 -60
- package/src/auth/managed-email.ts +174 -0
- package/src/auth/managed-sign-in-notifications.ts +81 -0
- package/src/auth/new-signups-gate.ts +49 -0
- package/src/auth/organization-user-setup.ts +307 -0
- package/src/auth/signup-funnel-metrics.ts +164 -0
- package/src/browser-controller-authority.ts +1 -186
- package/src/browser-ephemeral.ts +39 -0
- package/src/browser-state-authority.ts +1 -236
- package/src/claude-subscription-account-conflicts.ts +12 -0
- package/src/claude-subscription-account-usage.ts +48 -0
- package/src/claude-subscription-oauth.ts +362 -0
- package/src/claude-subscription-profile.ts +73 -0
- package/src/claude-subscription-usage.ts +97 -0
- package/src/claude-workspace-connection.ts +82 -0
- package/src/codemode.ts +194 -30
- package/src/codex-realtime.ts +8 -2
- package/src/company-brain-okf.ts +340 -0
- package/src/connected-machine-computer-access.ts +33 -0
- package/src/connection-ownership.ts +199 -0
- package/src/controller-data-plane.ts +81 -0
- package/src/editable-artifact-native-kernel.ts +26 -15
- package/src/editable-artifact-office-import.ts +77 -9
- package/src/editable-artifact-production.ts +23 -7
- package/src/editable-artifact-source-session.ts +123 -0
- package/src/editable-artifact-websocket.ts +27 -21
- package/src/editable-artifact-workspace-files.ts +31 -6
- package/src/fatal-process-boundary.ts +246 -0
- package/src/gateway-realtime.ts +1 -1
- package/src/github-access.ts +147 -5
- package/src/http/acting-person.ts +71 -0
- package/src/http/api-contract-compat.ts +49 -0
- package/src/http/api-error.ts +115 -1
- package/src/http/auth.ts +48 -0
- package/src/http/cors.ts +67 -0
- package/src/http/deprecation.ts +118 -0
- package/src/http/interaction-control-error.ts +164 -0
- package/src/http/keyed-admission.ts +29 -0
- package/src/http/local-browser-boundary.ts +343 -0
- package/src/http/metrics-listener.ts +57 -0
- package/src/http/path-identifier.ts +54 -0
- package/src/http/registered-route-label.ts +34 -0
- package/src/http/request-body.ts +127 -0
- package/src/http/request-source.ts +178 -0
- package/src/http/sse.ts +486 -132
- package/src/http/unmatched-route.ts +60 -0
- package/src/http/user-content.ts +158 -0
- package/src/http/websocket-upgrade-dispatch.ts +29 -0
- package/src/index.ts +157 -52
- package/src/integration-endpoint-test.ts +291 -0
- package/src/integrations/api-integrations.ts +98 -11
- package/src/integrations/atlassian.ts +474 -136
- package/src/integrations/connect-authority.ts +2 -0
- package/src/integrations/connect-callback-return.ts +86 -0
- package/src/integrations/fiken.ts +354 -64
- package/src/integrations/github-app-connect.ts +435 -0
- package/src/integrations/github-installation-proof.ts +60 -0
- package/src/integrations/github-lens-connect.ts +76 -0
- package/src/integrations/github-skill-source.ts +2 -142
- package/src/integrations/google-drive.ts +820 -222
- package/src/integrations/integration-commit-authority.ts +69 -0
- package/src/integrations/marketplace-plugin.ts +48 -0
- package/src/integrations/oauth-client.ts +1356 -459
- package/src/integrations/oauth-profiles.ts +537 -0
- package/src/integrations/oauth-return-path.ts +18 -0
- package/src/integrations/personal-github-repositories.ts +674 -0
- package/src/integrations/personal-github.ts +825 -0
- package/src/integrations/pr-review-provider.ts +246 -0
- package/src/integrations/provider-oauth.ts +250 -22
- package/src/integrations/slack-app-home.ts +300 -0
- package/src/integrations/slack-bot.ts +963 -239
- package/src/integrations/slack-file-upload-flow.ts +147 -0
- package/src/integrations/slack-install.ts +83 -0
- package/src/integrations/slack-interactions.ts +3170 -474
- package/src/integrations/slack-mrkdwn.ts +193 -0
- package/src/integrations/slack-routing.ts +337 -0
- package/src/integrations/slack-session-defaults.ts +224 -0
- package/src/integrations/slack-task-file-upload.ts +323 -0
- package/src/integrations/social-oauth.ts +213 -15
- package/src/interaction-agent-access.ts +48 -0
- package/src/interaction-frame-proxy.ts +409 -0
- package/src/interaction-metrics.ts +30 -0
- package/src/mcp/action-catalog-types.ts +9 -0
- package/src/mcp/action-catalog.gen.ts +6696 -0
- package/src/mcp/capability-account-readiness.ts +17 -0
- package/src/mcp/child-read-evidence.ts +19 -0
- package/src/mcp/command-read.ts +109 -0
- package/src/mcp/company-profile-agent-admin.ts +198 -0
- package/src/mcp/contract-input.ts +141 -0
- package/src/mcp/documents.ts +65 -377
- package/src/mcp/editable-artifacts.ts +12 -6
- package/src/mcp/files.ts +80 -38
- package/src/mcp/first-party-tool-permissions.ts +305 -0
- package/src/mcp/knowledge-entries.ts +322 -0
- package/src/mcp/orchestration-failure-diagnostic.ts +43 -0
- package/src/mcp/receipts.ts +34 -0
- package/src/mcp/request-abort.ts +44 -0
- package/src/mcp/scheduled-task-input.ts +76 -0
- package/src/mcp/scheduled-task-view.ts +44 -3
- package/src/mcp/server.ts +3030 -1267
- package/src/mcp/session-event-view.ts +383 -0
- package/src/mcp/session-view.ts +84 -3
- package/src/mcp/session-wait.ts +665 -0
- package/src/mcp-oauth.ts +1123 -0
- package/src/model-catalog.ts +91 -333
- package/src/observability.ts +15 -1
- package/src/organization-mcp.ts +397 -0
- package/src/organization-recovery-notifications.ts +103 -0
- package/src/routes/analytics-consent.ts +123 -0
- package/src/routes/api-integrations.ts +364 -74
- package/src/routes/api-keys.ts +336 -10
- package/src/routes/artifact-catalog.ts +279 -0
- package/src/routes/automations.ts +768 -0
- package/src/routes/billing.ts +461 -46
- package/src/routes/browser-sessions.ts +839 -131
- package/src/routes/canonical-human-identities.ts +90 -14
- package/src/routes/capabilities.ts +107 -6
- package/src/routes/channels.ts +20 -3
- package/src/routes/claude-subscription-accounts.ts +334 -0
- package/src/routes/claude-subscription-oauth.ts +142 -0
- package/src/routes/client-errors.ts +362 -0
- package/src/routes/codex.ts +833 -116
- package/src/routes/company-brain.ts +322 -0
- package/src/routes/company-profile.ts +65 -1
- package/src/routes/computer-sessions.ts +557 -106
- package/src/routes/connect.ts +1938 -0
- package/src/routes/connections.ts +1040 -349
- package/src/routes/documents.ts +488 -287
- package/src/routes/editable-artifacts.ts +79 -9
- package/src/routes/enrollments.ts +135 -39
- package/src/routes/environments.ts +154 -58
- package/src/routes/external-identity-links.ts +201 -0
- package/src/routes/feedback.ts +113 -0
- package/src/routes/files.ts +337 -39
- package/src/routes/github-browser-pages.ts +162 -0
- package/src/routes/github.ts +446 -144
- package/src/routes/insights-response-cache.ts +83 -0
- package/src/routes/insights-usage.ts +345 -0
- package/src/routes/insights.ts +153 -19
- package/src/routes/install.ts +133 -38
- package/src/routes/integration-facets.ts +107 -33
- package/src/routes/interaction-resources.ts +30 -3
- package/src/routes/knowledge.ts +488 -0
- package/src/routes/machines.ts +313 -15
- package/src/routes/managed-auth-session-sets.ts +1218 -0
- package/src/routes/managed-onboarding.ts +337 -0
- package/src/routes/managed-sign-in-methods.ts +433 -0
- package/src/routes/memory-slack-publications.ts +3 -2
- package/src/routes/model-connection-access.ts +208 -0
- package/src/routes/organization-integration-policy.ts +116 -0
- package/src/routes/organization-integrations.ts +326 -0
- package/src/routes/organization-mcp-connections.ts +178 -0
- package/src/routes/organization-memberships.ts +1019 -27
- package/src/routes/organization-model-providers.ts +293 -0
- package/src/routes/organization-recovery.ts +325 -0
- package/src/routes/organization-service-accounts.ts +128 -0
- package/src/routes/organization-sessions.ts +350 -0
- package/src/routes/personal-github-git-broker.ts +785 -0
- package/src/routes/personal-github.ts +370 -0
- package/src/routes/plugins.ts +251 -22
- package/src/routes/pr-review-github.ts +881 -0
- package/src/routes/pr-review.ts +622 -0
- package/src/routes/preference-registry.ts +12 -93
- package/src/routes/rigs.ts +167 -50
- package/src/routes/scheduled-tasks.ts +346 -41
- package/src/routes/session-artifact-associations.ts +87 -0
- package/src/routes/session-history-imports.ts +280 -0
- package/src/routes/sessions.ts +2306 -264
- package/src/routes/skill-content.ts +297 -0
- package/src/routes/skill-install-authority.ts +64 -0
- package/src/routes/skills.ts +62 -9
- package/src/routes/social.ts +46 -18
- package/src/routes/subscription-account-pools.ts +436 -0
- package/src/routes/subscription-pool-access.ts +126 -0
- package/src/routes/supergrok.ts +219 -303
- package/src/routes/transcription-recordings.ts +38 -3
- package/src/routes/transcriptions.ts +4 -0
- package/src/routes/usage-allowances.ts +378 -0
- package/src/routes/user-resource-authorities.ts +138 -0
- package/src/routes/video-generation.ts +14 -10
- package/src/routes/workspace-artifacts.ts +275 -69
- package/src/routes/workspace-capture.ts +21 -0
- package/src/routes/workspace-integrations.ts +576 -0
- package/src/routes/workspace-learning.ts +159 -0
- package/src/routes/workspace-model-providers.ts +148 -0
- package/src/routes/workspace-state.ts +38 -25
- package/src/routes/workspaces.ts +1004 -127
- package/src/sandbox/auth-callout.ts +96 -19
- package/src/sandbox/channel-a.ts +323 -24
- package/src/sandbox/connection-authority.ts +3 -0
- package/src/sandbox/enrollment.ts +81 -6
- package/src/sandbox/machines.ts +218 -76
- package/src/sandbox/metrics-ingestion.ts +411 -62
- package/src/sandbox/rematerialize.ts +121 -19
- package/src/sandbox/session-attach-variable-sets.ts +131 -0
- package/src/sandbox/viewer.ts +280 -25
- package/src/sandbox-file-artifacts.ts +413 -0
- package/src/scheduled-task-deletion.ts +138 -0
- package/src/session-create-observability.ts +46 -0
- package/src/session-realtime-context.ts +6 -3
- package/src/site-session-origin.ts +48 -0
- package/src/site-uploads.ts +224 -0
- package/src/slack-reaction-files.ts +16 -5
- package/src/temporal-schedule-cleanup.ts +13 -0
- package/src/temporal-schedule-sync.ts +74 -0
- package/src/transcription/providers/codex-subscription.ts +2 -0
- package/src/transcription/providers/openai.ts +1 -0
- package/src/transcription/providers/xai-subscription.ts +49 -3
- package/src/transcription/segmenter.ts +8 -2
- package/src/transcription/service.ts +43 -6
- package/src/work-discovery-observability.ts +121 -0
- package/src/workspace-artifact-content.ts +144 -0
- package/src/workspace-artifact-provenance.ts +104 -0
- package/src/workspace-delete-observability.ts +75 -0
- package/src/workspace-deletion.ts +73 -0
- package/src/workspace-state-projection.ts +18 -148
- package/src/workspace-tool-gateway-observability.ts +100 -0
- package/src/workspace-tool-gateway.ts +870 -0
- package/src/workspace-webhook-dispatch.ts +190 -0
- package/src/xai-subscription-auth.ts +9 -2
- package/dist/chunk-2PQMSRCB.js +0 -49759
- package/dist/chunk-2PQMSRCB.js.map +0 -1
- package/dist/routes/packs.d.ts +0 -3
- package/src/routes/packs.ts +0 -729
|
@@ -1,10 +1,17 @@
|
|
|
1
|
+
import { withOrganizationIntegrationAcquisition } from "@opengeni/db/organization-integration-policy";
|
|
2
|
+
import { claimOAuthAcquisition, finishOAuthAcquisition } from "./oauth-client";
|
|
3
|
+
import { safeReturnPath } from "./oauth-return-path";
|
|
1
4
|
import type { ApiRouteDeps } from "@opengeni/core";
|
|
2
5
|
import type { Settings } from "@opengeni/config";
|
|
6
|
+
import { createHash } from "node:crypto";
|
|
7
|
+
import { ExternalActorContinuation } from "@opengeni/contracts/external-identities";
|
|
8
|
+
import { requireConnectOwnerAuthority } from "@opengeni/core";
|
|
3
9
|
import {
|
|
4
10
|
FIKEN_CREDENTIAL_LABEL,
|
|
5
11
|
FIKEN_CREDENTIAL_ROLE,
|
|
6
12
|
FIKEN_PROVIDER_DOMAIN,
|
|
7
13
|
FikenOAuthStartResponse,
|
|
14
|
+
FikenInstallRequest,
|
|
8
15
|
type AccessGrant,
|
|
9
16
|
type ConnectionMetadata,
|
|
10
17
|
type FikenCompanySummary,
|
|
@@ -13,7 +20,6 @@ import {
|
|
|
13
20
|
} from "@opengeni/contracts";
|
|
14
21
|
import {
|
|
15
22
|
fikenConnectionMetadata,
|
|
16
|
-
hasPermission,
|
|
17
23
|
isFikenConnection,
|
|
18
24
|
preferredFikenConnection,
|
|
19
25
|
requireEnvironmentEncryption,
|
|
@@ -24,9 +30,12 @@ import {
|
|
|
24
30
|
consumeIntegrationOAuthStateNonce,
|
|
25
31
|
createConnection,
|
|
26
32
|
encryptEnvironmentValue,
|
|
33
|
+
decryptEnvironmentValue,
|
|
34
|
+
getConnectAttempt,
|
|
35
|
+
finishConnectOperation,
|
|
27
36
|
getConnectionMetadata,
|
|
28
|
-
getWorkspaceGrant,
|
|
29
37
|
listConnectionsMetadata,
|
|
38
|
+
loadConnectionCredentialForBroker,
|
|
30
39
|
recordAuditEvent,
|
|
31
40
|
setConnectionStatus,
|
|
32
41
|
updateConnection,
|
|
@@ -37,8 +46,10 @@ import { readResponseJsonBounded, type FetchLike } from "@opengeni/network";
|
|
|
37
46
|
import { HTTPException } from "hono/http-exception";
|
|
38
47
|
import {
|
|
39
48
|
integrationBaseUrl,
|
|
49
|
+
oauthStateFailureReturn,
|
|
40
50
|
oauthStateTtlMs,
|
|
41
51
|
requireIntegrationsStateSecret,
|
|
52
|
+
workspaceIntegrationsPath,
|
|
42
53
|
} from "./oauth-client";
|
|
43
54
|
|
|
44
55
|
const FIKEN_API_BASE = "https://api.fiken.no/api/v2";
|
|
@@ -54,6 +65,87 @@ const MAX_DRAFT_LINES = 100;
|
|
|
54
65
|
// Fiken company slugs as issued by Fiken: lowercase alphanumerics and dashes.
|
|
55
66
|
const COMPANY_SLUG_PATTERN = /^[a-z0-9][a-z0-9-]{0,127}$/;
|
|
56
67
|
|
|
68
|
+
/** Shared native/embedded token adapter. Provider verification happens before
|
|
69
|
+
* persistence; the caller reauthorizes inside its durable commit transaction.
|
|
70
|
+
* That caller must acquire the organization policy fence for `fiken` BEFORE
|
|
71
|
+
* owner/tenancy locks and invoke the returned writer with that exact tx. */
|
|
72
|
+
export async function prepareFikenTokenInstall(
|
|
73
|
+
deps: ApiRouteDeps,
|
|
74
|
+
grant: Pick<AccessGrant, "accountId" | "workspaceId" | "subjectId">,
|
|
75
|
+
raw: unknown,
|
|
76
|
+
expectedVersion?: number,
|
|
77
|
+
): Promise<(tx: Database) => Promise<ConnectionMetadata>> {
|
|
78
|
+
const payload = FikenInstallRequest.parse(raw);
|
|
79
|
+
await withOrganizationIntegrationAcquisition(deps.db, grant, ["fiken"], async () => {});
|
|
80
|
+
const key = requireEnvironmentEncryption(deps.settings);
|
|
81
|
+
const existing = payload.connectionId
|
|
82
|
+
? await getConnectionMetadata(deps.db, grant.workspaceId, payload.connectionId, null)
|
|
83
|
+
: null;
|
|
84
|
+
if (payload.connectionId && !existing)
|
|
85
|
+
throw new HTTPException(404, { message: "connection not found" });
|
|
86
|
+
if (existing && !isFikenConnection(existing))
|
|
87
|
+
throw new HTTPException(422, { message: "connectionId is not a Fiken connection" });
|
|
88
|
+
if (expectedVersion !== undefined && existing?.version !== expectedVersion)
|
|
89
|
+
throw new HTTPException(409, { message: "The selected Fiken account changed" });
|
|
90
|
+
const verified = await verifyFikenApiToken(payload.apiToken, deps.fikenFetch ?? fetch);
|
|
91
|
+
const defaultCompanySlug = resolveFikenDefaultCompanySlug({
|
|
92
|
+
requested: payload.defaultCompanySlug ?? null,
|
|
93
|
+
previous: existing
|
|
94
|
+
? (fikenConnectionMetadata(existing.metadata)?.defaultCompanySlug ?? null)
|
|
95
|
+
: null,
|
|
96
|
+
companies: verified.companies,
|
|
97
|
+
});
|
|
98
|
+
if (payload.defaultCompanySlug && defaultCompanySlug !== payload.defaultCompanySlug)
|
|
99
|
+
throw new HTTPException(422, {
|
|
100
|
+
message: "The selected company is not accessible with this token",
|
|
101
|
+
});
|
|
102
|
+
const metadata = {
|
|
103
|
+
credentialRole: FIKEN_CREDENTIAL_ROLE,
|
|
104
|
+
credentialLabel: FIKEN_CREDENTIAL_LABEL,
|
|
105
|
+
companies: verified.companies,
|
|
106
|
+
defaultCompanySlug,
|
|
107
|
+
verifiedAt: new Date().toISOString(),
|
|
108
|
+
};
|
|
109
|
+
const credentialEncrypted = encryptEnvironmentValue(
|
|
110
|
+
key,
|
|
111
|
+
JSON.stringify(fikenCredentialBundle(payload.apiToken)),
|
|
112
|
+
);
|
|
113
|
+
return async (tx) => {
|
|
114
|
+
if (existing) {
|
|
115
|
+
const updated = await updateConnection(tx, {
|
|
116
|
+
workspaceId: grant.workspaceId,
|
|
117
|
+
connectionId: existing.id,
|
|
118
|
+
visibleToSubjectId: null,
|
|
119
|
+
expectedVersion: existing.version,
|
|
120
|
+
kind: "api_key",
|
|
121
|
+
status: "active",
|
|
122
|
+
credentialEncrypted,
|
|
123
|
+
grantedScopes: [],
|
|
124
|
+
expiresAt: null,
|
|
125
|
+
metadata,
|
|
126
|
+
updatedBySubjectId: grant.subjectId,
|
|
127
|
+
});
|
|
128
|
+
if (!updated)
|
|
129
|
+
throw new HTTPException(409, {
|
|
130
|
+
message: "The Fiken connection changed; reload before retrying",
|
|
131
|
+
});
|
|
132
|
+
return updated;
|
|
133
|
+
}
|
|
134
|
+
return createConnection(tx, {
|
|
135
|
+
accountId: grant.accountId,
|
|
136
|
+
workspaceId: grant.workspaceId,
|
|
137
|
+
subjectId: null,
|
|
138
|
+
providerDomain: FIKEN_PROVIDER_DOMAIN,
|
|
139
|
+
kind: "api_key",
|
|
140
|
+
credentialEncrypted,
|
|
141
|
+
grantedScopes: [],
|
|
142
|
+
expiresAt: null,
|
|
143
|
+
metadata,
|
|
144
|
+
createdBySubjectId: grant.subjectId,
|
|
145
|
+
});
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
57
149
|
export type FikenOperation =
|
|
58
150
|
| "companies.list"
|
|
59
151
|
| "contacts.list"
|
|
@@ -102,6 +194,8 @@ type FikenContext = {
|
|
|
102
194
|
sessionId: string | null;
|
|
103
195
|
};
|
|
104
196
|
|
|
197
|
+
type FikenProviderAuthorization = () => Promise<boolean | void>;
|
|
198
|
+
|
|
105
199
|
/**
|
|
106
200
|
* Fiken allows only a single concurrent API request per credential; concurrent
|
|
107
201
|
* requests can 429 and repeated violations can get the token banned. Serialize
|
|
@@ -281,6 +375,7 @@ export type FikenListInput = {
|
|
|
281
375
|
|
|
282
376
|
export class FikenClient {
|
|
283
377
|
private readonly resolveCredential: ReturnType<typeof buildConnectionTokenResolver>;
|
|
378
|
+
private expectedConnectionVersion: number;
|
|
284
379
|
|
|
285
380
|
constructor(
|
|
286
381
|
private readonly db: Database,
|
|
@@ -289,11 +384,22 @@ export class FikenClient {
|
|
|
289
384
|
private readonly metadata: FikenConnectionMetadata,
|
|
290
385
|
private readonly context: FikenContext,
|
|
291
386
|
private readonly fetchImpl: FetchLike = fetch,
|
|
387
|
+
private readonly authorizeProviderRequest?: FikenProviderAuthorization,
|
|
292
388
|
) {
|
|
389
|
+
this.expectedConnectionVersion = connection.version;
|
|
293
390
|
// OAuth-kind connections refresh through the generic broker; route that
|
|
294
|
-
// token-endpoint transport through the same injectable Fiken fetch.
|
|
391
|
+
// token-endpoint transport through the same injectable Fiken fetch. Keep
|
|
392
|
+
// the optional authorization immediately before actual refresh I/O.
|
|
393
|
+
const refreshFetch: FetchLike = this.authorizeProviderRequest
|
|
394
|
+
? async (input, init) => {
|
|
395
|
+
if ((await this.authorizeProviderRequest?.()) === false) {
|
|
396
|
+
throw new Error("the Fiken credential refresh is no longer authorized");
|
|
397
|
+
}
|
|
398
|
+
return await this.fetchImpl(input, init);
|
|
399
|
+
}
|
|
400
|
+
: fetchImpl;
|
|
295
401
|
this.resolveCredential = buildConnectionTokenResolver(db, settings, undefined, {
|
|
296
|
-
refreshTransport: { fetchImpl },
|
|
402
|
+
refreshTransport: { fetchImpl: refreshFetch },
|
|
297
403
|
});
|
|
298
404
|
}
|
|
299
405
|
|
|
@@ -619,17 +725,27 @@ export class FikenClient {
|
|
|
619
725
|
for (const [key, value] of Object.entries(input.query ?? {})) {
|
|
620
726
|
url.searchParams.set(key, value);
|
|
621
727
|
}
|
|
622
|
-
// Credential resolution (DB read + possible broker refresh) happens
|
|
623
|
-
// outside the serialization chain: only the provider HTTP call itself
|
|
624
|
-
// must obey Fiken's single-concurrent-request rule.
|
|
625
|
-
const headers = await this.headersFor(operation, url.toString());
|
|
626
728
|
const result = await serializedPerConnection(this.connection.id, async () => {
|
|
729
|
+
const authority = await this.currentAuthority(this.expectedConnectionVersion);
|
|
730
|
+
const credential = await this.credentialFor(operation, url.toString());
|
|
731
|
+
await this.currentAuthority(credential.connectionVersion, authority.authorityGeneration);
|
|
732
|
+
// The adapter callback is a fallible preflight. The canonical
|
|
733
|
+
// credential callback below records the physical-use fact, so it must
|
|
734
|
+
// be the final await before the target fetch.
|
|
735
|
+
if (this.authorizeProviderRequest && (await this.authorizeProviderRequest()) === false) {
|
|
736
|
+
throw new Error("the Fiken provider request is no longer authorized");
|
|
737
|
+
}
|
|
738
|
+
await this.currentAuthority(credential.connectionVersion, authority.authorityGeneration);
|
|
739
|
+
if (credential.authorizeProviderRequest && !(await credential.authorizeProviderRequest())) {
|
|
740
|
+
throw new Error("the Fiken provider request is no longer authorized");
|
|
741
|
+
}
|
|
742
|
+
this.expectedConnectionVersion = credential.connectionVersion;
|
|
627
743
|
let response: Response;
|
|
628
744
|
try {
|
|
629
745
|
response = await this.fetchImpl(url, {
|
|
630
746
|
method,
|
|
631
747
|
headers: {
|
|
632
|
-
...headers,
|
|
748
|
+
...credential.headers,
|
|
633
749
|
accept: "application/json",
|
|
634
750
|
...(input.body !== undefined ? { "content-type": "application/json" } : {}),
|
|
635
751
|
},
|
|
@@ -642,7 +758,7 @@ export class FikenClient {
|
|
|
642
758
|
} catch {
|
|
643
759
|
throw new FikenProviderError("transport_error");
|
|
644
760
|
}
|
|
645
|
-
return await this.readResponse(operation, response);
|
|
761
|
+
return await this.readResponse(operation, response, credential.connectionVersion);
|
|
646
762
|
});
|
|
647
763
|
await this.recordAudit(operation, "succeeded");
|
|
648
764
|
return result;
|
|
@@ -655,15 +771,14 @@ export class FikenClient {
|
|
|
655
771
|
private async readResponse(
|
|
656
772
|
operation: FikenOperation,
|
|
657
773
|
response: Response,
|
|
774
|
+
credentialVersion: number,
|
|
658
775
|
): Promise<{ payload: unknown; page: FikenPage | null; locationId: number | null }> {
|
|
659
776
|
if (response.status === 401) {
|
|
660
777
|
await response.body?.cancel().catch(() => undefined);
|
|
661
|
-
//
|
|
662
|
-
//
|
|
663
|
-
//
|
|
664
|
-
|
|
665
|
-
// instead of using the resolution-time snapshot.
|
|
666
|
-
await this.markNeedsReauth().catch(() => undefined);
|
|
778
|
+
// Only the exact active credential generation sent on this request may
|
|
779
|
+
// transition. A late 401 must not poison a reconnect or revocation that
|
|
780
|
+
// became current while the provider response was in flight.
|
|
781
|
+
await this.markNeedsReauth(credentialVersion).catch(() => undefined);
|
|
667
782
|
throw new FikenProviderError("credential_rejected", 401);
|
|
668
783
|
}
|
|
669
784
|
if (response.status === 429) {
|
|
@@ -699,27 +814,67 @@ export class FikenClient {
|
|
|
699
814
|
return { payload, page: pageFromHeaders(response.headers), locationId };
|
|
700
815
|
}
|
|
701
816
|
|
|
702
|
-
private async markNeedsReauth(): Promise<void> {
|
|
817
|
+
private async markNeedsReauth(credentialVersion: number): Promise<void> {
|
|
703
818
|
const current = await getConnectionMetadata(
|
|
704
819
|
this.db,
|
|
705
820
|
this.context.workspaceId,
|
|
706
821
|
this.connection.id,
|
|
707
822
|
null,
|
|
708
823
|
);
|
|
709
|
-
if (
|
|
824
|
+
if (
|
|
825
|
+
!current ||
|
|
826
|
+
current.status !== "active" ||
|
|
827
|
+
current.version !== credentialVersion ||
|
|
828
|
+
!isFikenConnection(current)
|
|
829
|
+
) {
|
|
830
|
+
return;
|
|
831
|
+
}
|
|
710
832
|
await setConnectionStatus(
|
|
711
833
|
this.db,
|
|
712
834
|
this.context.workspaceId,
|
|
713
835
|
"needs_reauth",
|
|
714
836
|
"Fiken rejected the credential",
|
|
715
|
-
{ id: current.id, version:
|
|
837
|
+
{ id: current.id, version: credentialVersion, subjectId: null },
|
|
716
838
|
);
|
|
717
839
|
}
|
|
718
840
|
|
|
719
|
-
private async
|
|
841
|
+
private async currentAuthority(
|
|
842
|
+
expectedVersion: number,
|
|
843
|
+
expectedAuthorityGeneration?: number,
|
|
844
|
+
): Promise<{ version: number; authorityGeneration: number }> {
|
|
845
|
+
const current = await loadConnectionCredentialForBroker(this.db, this.settings, {
|
|
846
|
+
workspaceId: this.context.workspaceId,
|
|
847
|
+
connectionId: this.connection.id,
|
|
848
|
+
providerDomain: FIKEN_PROVIDER_DOMAIN,
|
|
849
|
+
kind: this.connection.kind === "oauth2" ? "oauth2" : "api_key",
|
|
850
|
+
subjectId: null,
|
|
851
|
+
...(expectedAuthorityGeneration !== undefined ? { expectedAuthorityGeneration } : {}),
|
|
852
|
+
});
|
|
853
|
+
if (
|
|
854
|
+
!current ||
|
|
855
|
+
current.accountId !== this.context.accountId ||
|
|
856
|
+
current.workspaceId !== this.context.workspaceId ||
|
|
857
|
+
current.subjectId !== null ||
|
|
858
|
+
current.providerDomain !== FIKEN_PROVIDER_DOMAIN ||
|
|
859
|
+
current.kind !== this.connection.kind ||
|
|
860
|
+
current.status !== "active" ||
|
|
861
|
+
current.version !== expectedVersion ||
|
|
862
|
+
current.authorityGeneration === undefined ||
|
|
863
|
+
!fikenConnectionMetadata(current.metadata)
|
|
864
|
+
) {
|
|
865
|
+
throw new Error("the Fiken connection authority changed");
|
|
866
|
+
}
|
|
867
|
+
return { version: current.version, authorityGeneration: current.authorityGeneration };
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
private async credentialFor(
|
|
720
871
|
operation: FikenOperation,
|
|
721
872
|
destinationUrl: string,
|
|
722
|
-
): Promise<
|
|
873
|
+
): Promise<{
|
|
874
|
+
headers: Record<string, string>;
|
|
875
|
+
connectionVersion: number;
|
|
876
|
+
authorizeProviderRequest?: () => Promise<boolean>;
|
|
877
|
+
}> {
|
|
723
878
|
const result = await this.resolveCredential({
|
|
724
879
|
workspaceId: this.context.workspaceId,
|
|
725
880
|
serverId: "opengeni-fiken",
|
|
@@ -732,10 +887,20 @@ export class FikenClient {
|
|
|
732
887
|
},
|
|
733
888
|
destinationUrl,
|
|
734
889
|
});
|
|
735
|
-
if (
|
|
890
|
+
if (
|
|
891
|
+
result.status !== "ok" ||
|
|
892
|
+
result.connectionId !== this.connection.id ||
|
|
893
|
+
result.connectionVersion === undefined
|
|
894
|
+
) {
|
|
736
895
|
throw new Error("the Fiken connection needs to be reconnected");
|
|
737
896
|
}
|
|
738
|
-
return
|
|
897
|
+
return {
|
|
898
|
+
headers: result.headers,
|
|
899
|
+
connectionVersion: result.connectionVersion,
|
|
900
|
+
...(result.authorizeProviderRequest
|
|
901
|
+
? { authorizeProviderRequest: result.authorizeProviderRequest }
|
|
902
|
+
: {}),
|
|
903
|
+
};
|
|
739
904
|
}
|
|
740
905
|
|
|
741
906
|
private receipt(operation: FikenOperation, operationId?: string) {
|
|
@@ -771,7 +936,12 @@ export class FikenClient {
|
|
|
771
936
|
}
|
|
772
937
|
|
|
773
938
|
export function createFikenClient(
|
|
774
|
-
deps: {
|
|
939
|
+
deps: {
|
|
940
|
+
db: Database;
|
|
941
|
+
settings: Settings;
|
|
942
|
+
fikenFetch?: typeof fetch;
|
|
943
|
+
authorizeProviderRequest?: FikenProviderAuthorization;
|
|
944
|
+
},
|
|
775
945
|
resolved: Awaited<ReturnType<typeof resolveFikenConnectionForTool>>,
|
|
776
946
|
): FikenClient {
|
|
777
947
|
return new FikenClient(
|
|
@@ -781,6 +951,7 @@ export function createFikenClient(
|
|
|
781
951
|
resolved.metadata,
|
|
782
952
|
resolved.context,
|
|
783
953
|
deps.fikenFetch,
|
|
954
|
+
deps.authorizeProviderRequest,
|
|
784
955
|
);
|
|
785
956
|
}
|
|
786
957
|
|
|
@@ -898,6 +1069,8 @@ export class FikenOAuthCallbackError extends Error {
|
|
|
898
1069
|
}
|
|
899
1070
|
|
|
900
1071
|
type FikenOAuthState = {
|
|
1072
|
+
externalContinuation?: ExternalActorContinuation;
|
|
1073
|
+
connectAttemptId?: string;
|
|
901
1074
|
accountId: string;
|
|
902
1075
|
workspaceId: string;
|
|
903
1076
|
subjectId: string;
|
|
@@ -931,8 +1104,11 @@ export async function startFikenOAuth(
|
|
|
931
1104
|
subjectId: string;
|
|
932
1105
|
requestUrl: string;
|
|
933
1106
|
payload: FikenOAuthStartRequest;
|
|
1107
|
+
externalContinuation?: ExternalActorContinuation;
|
|
1108
|
+
connectAttemptId?: string;
|
|
934
1109
|
},
|
|
935
1110
|
): Promise<FikenOAuthStartResponse> {
|
|
1111
|
+
await withOrganizationIntegrationAcquisition(deps.db, input, ["fiken"], async () => {});
|
|
936
1112
|
const fiken = requireFikenOAuthSettings(deps.settings);
|
|
937
1113
|
const existing = input.payload.connectionId
|
|
938
1114
|
? await getConnectionMetadata(deps.db, input.workspaceId, input.payload.connectionId, null)
|
|
@@ -948,7 +1124,18 @@ export async function startFikenOAuth(
|
|
|
948
1124
|
accountId: input.accountId,
|
|
949
1125
|
workspaceId: input.workspaceId,
|
|
950
1126
|
subjectId: input.subjectId,
|
|
951
|
-
returnPath:
|
|
1127
|
+
returnPath: safeReturnPath(
|
|
1128
|
+
input.payload.returnPath ?? workspaceIntegrationsPath(input.workspaceId),
|
|
1129
|
+
),
|
|
1130
|
+
...(input.connectAttemptId ? { connectAttemptId: input.connectAttemptId } : {}),
|
|
1131
|
+
...(input.externalContinuation
|
|
1132
|
+
? {
|
|
1133
|
+
encryptedExternalContinuation: encryptEnvironmentValue(
|
|
1134
|
+
requireEnvironmentEncryption(deps.settings),
|
|
1135
|
+
JSON.stringify(ExternalActorContinuation.parse(input.externalContinuation)),
|
|
1136
|
+
),
|
|
1137
|
+
}
|
|
1138
|
+
: {}),
|
|
952
1139
|
...(existing ? { connectionId: existing.id, connectionVersion: existing.version } : {}),
|
|
953
1140
|
});
|
|
954
1141
|
const authorizationUrl = new URL(FIKEN_AUTHORIZE_URL);
|
|
@@ -970,12 +1157,38 @@ export async function completeFikenOAuthCallback(
|
|
|
970
1157
|
error?: string | undefined;
|
|
971
1158
|
requestUrl: string;
|
|
972
1159
|
},
|
|
973
|
-
): Promise<{ redirectTo: string }> {
|
|
1160
|
+
): Promise<{ redirectTo: string; exactReturn?: boolean }> {
|
|
974
1161
|
const baseUrl = integrationBaseUrl(deps.settings.publicBaseUrl, input.requestUrl);
|
|
975
1162
|
const returnBaseUrl = deps.settings.webBaseUrl?.replace(/\/+$/, "") ?? baseUrl;
|
|
976
1163
|
let state: FikenOAuthState | null = null;
|
|
1164
|
+
let exactReturnUrl: string | undefined;
|
|
1165
|
+
let operation: { attemptId: string; operationId: string; inputDigest: string } | undefined;
|
|
977
1166
|
try {
|
|
978
1167
|
state = readFikenOAuthState(input.state, deps.settings);
|
|
1168
|
+
if (state.connectAttemptId) {
|
|
1169
|
+
const stored = await getConnectAttempt(deps.db, state, state.connectAttemptId);
|
|
1170
|
+
if (stored.attempt.providerId !== "fiken-oauth" || stored.attempt.ownership !== "workspace")
|
|
1171
|
+
throw new FikenOAuthCallbackError("invalid_state");
|
|
1172
|
+
exactReturnUrl = stored.returnUrl;
|
|
1173
|
+
operation = {
|
|
1174
|
+
attemptId: state.connectAttemptId,
|
|
1175
|
+
operationId: `oauth:${state.nonce}`,
|
|
1176
|
+
inputDigest: createHash("sha256").update(input.state!).digest("hex"),
|
|
1177
|
+
};
|
|
1178
|
+
const claim = await claimOAuthAcquisition(
|
|
1179
|
+
deps.db,
|
|
1180
|
+
state,
|
|
1181
|
+
{
|
|
1182
|
+
...operation,
|
|
1183
|
+
expectedRevision: stored.attempt.revision,
|
|
1184
|
+
authorize: (tx, _attempt, origin) =>
|
|
1185
|
+
requireConnectOwnerAuthority(tx, state!, "connections:write", origin),
|
|
1186
|
+
},
|
|
1187
|
+
"fiken",
|
|
1188
|
+
Boolean(input.code && !input.error),
|
|
1189
|
+
);
|
|
1190
|
+
if (claim.status === "replayed") return { redirectTo: exactReturnUrl, exactReturn: true };
|
|
1191
|
+
}
|
|
979
1192
|
await requireFikenCallbackGrant(deps.db, state);
|
|
980
1193
|
const consumed = await consumeIntegrationOAuthStateNonce(deps.db, {
|
|
981
1194
|
accountId: state.accountId,
|
|
@@ -988,6 +1201,27 @@ export async function completeFikenOAuthCallback(
|
|
|
988
1201
|
if (!consumed) {
|
|
989
1202
|
throw new FikenOAuthCallbackError("state_replayed");
|
|
990
1203
|
}
|
|
1204
|
+
// A proven pre-exchange rejection is terminal, not an uncertain provider
|
|
1205
|
+
// effect. Persist its receipt so repeated browser callbacks cannot retry it.
|
|
1206
|
+
if (operation && (input.error || !input.code)) {
|
|
1207
|
+
await finishConnectOperation(deps.db, state, {
|
|
1208
|
+
...operation,
|
|
1209
|
+
authorize: (tx, _attempt, origin) =>
|
|
1210
|
+
requireConnectOwnerAuthority(tx, state!, "connections:write", origin),
|
|
1211
|
+
commit: async (_tx, current) => ({
|
|
1212
|
+
...current,
|
|
1213
|
+
revision: current.revision + 1,
|
|
1214
|
+
state: input.error === "access_denied" ? "cancelled" : "failed",
|
|
1215
|
+
nextAction: { type: "none" },
|
|
1216
|
+
error: {
|
|
1217
|
+
code: input.error ? "provider_denied" : "missing_code",
|
|
1218
|
+
message: "Authorization was not completed. Start a new connection attempt.",
|
|
1219
|
+
retryable: false,
|
|
1220
|
+
},
|
|
1221
|
+
}),
|
|
1222
|
+
});
|
|
1223
|
+
return { redirectTo: exactReturnUrl!, exactReturn: true };
|
|
1224
|
+
}
|
|
991
1225
|
if (input.error) {
|
|
992
1226
|
throw new FikenOAuthCallbackError(
|
|
993
1227
|
input.error === "access_denied" ? "provider_denied" : "provider_error",
|
|
@@ -996,6 +1230,7 @@ export async function completeFikenOAuthCallback(
|
|
|
996
1230
|
if (!input.code) {
|
|
997
1231
|
throw new FikenOAuthCallbackError("missing_code");
|
|
998
1232
|
}
|
|
1233
|
+
await withOrganizationIntegrationAcquisition(deps.db, state, ["fiken"], async () => {});
|
|
999
1234
|
const fiken = requireFikenOAuthSettings(deps.settings);
|
|
1000
1235
|
const key = requireEnvironmentEncryption(deps.settings);
|
|
1001
1236
|
const fetchImpl = deps.fikenFetch ?? fetch;
|
|
@@ -1052,34 +1287,76 @@ export async function completeFikenOAuthCallback(
|
|
|
1052
1287
|
defaultCompanySlug,
|
|
1053
1288
|
verifiedAt: new Date().toISOString(),
|
|
1054
1289
|
};
|
|
1055
|
-
const
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1290
|
+
const persist = (tx: Database) =>
|
|
1291
|
+
existing
|
|
1292
|
+
? updateConnection(tx, {
|
|
1293
|
+
workspaceId: state!.workspaceId,
|
|
1294
|
+
connectionId: existing.id,
|
|
1295
|
+
visibleToSubjectId: null,
|
|
1296
|
+
expectedVersion: existing.version,
|
|
1297
|
+
kind: "oauth2",
|
|
1298
|
+
status: "active",
|
|
1299
|
+
credentialEncrypted,
|
|
1300
|
+
expiresAt: token.expiresAt,
|
|
1301
|
+
metadata,
|
|
1302
|
+
updatedBySubjectId: state!.subjectId,
|
|
1303
|
+
})
|
|
1304
|
+
: createConnection(tx, {
|
|
1305
|
+
accountId: state!.accountId,
|
|
1306
|
+
workspaceId: state!.workspaceId,
|
|
1307
|
+
// Workspace-owned by design, like the pasted-token install: the
|
|
1308
|
+
// first-party fiken tools resolve only workspace connections until
|
|
1309
|
+
// the delegation-snapshot lane exists for personal ownership.
|
|
1310
|
+
subjectId: null,
|
|
1311
|
+
providerDomain: FIKEN_PROVIDER_DOMAIN,
|
|
1312
|
+
kind: "oauth2",
|
|
1313
|
+
credentialEncrypted,
|
|
1314
|
+
grantedScopes: [],
|
|
1315
|
+
expiresAt: token.expiresAt,
|
|
1316
|
+
metadata,
|
|
1317
|
+
createdBySubjectId: state!.subjectId,
|
|
1318
|
+
});
|
|
1319
|
+
if (operation) {
|
|
1320
|
+
await finishOAuthAcquisition(
|
|
1321
|
+
deps.db,
|
|
1322
|
+
state,
|
|
1323
|
+
{
|
|
1324
|
+
...operation,
|
|
1325
|
+
authorize: (tx, _attempt, origin) =>
|
|
1326
|
+
requireConnectOwnerAuthority(tx, state!, "connections:write", origin),
|
|
1327
|
+
commit: async (tx, current) => {
|
|
1328
|
+
const connection = await persist(tx);
|
|
1329
|
+
if (!connection) throw new FikenOAuthCallbackError("connection_conflict");
|
|
1330
|
+
return {
|
|
1331
|
+
...current,
|
|
1332
|
+
revision: current.revision + 1,
|
|
1333
|
+
state: "complete",
|
|
1334
|
+
credentialsCommitted: true,
|
|
1335
|
+
nextAction: { type: "none" },
|
|
1336
|
+
account: {
|
|
1337
|
+
id: connection.id,
|
|
1338
|
+
version: connection.version,
|
|
1339
|
+
providerId: "fiken-oauth",
|
|
1340
|
+
label: "Fiken",
|
|
1341
|
+
ownership: "workspace",
|
|
1342
|
+
status: "connected",
|
|
1343
|
+
},
|
|
1344
|
+
};
|
|
1345
|
+
},
|
|
1346
|
+
},
|
|
1347
|
+
"fiken",
|
|
1348
|
+
);
|
|
1349
|
+
return { redirectTo: exactReturnUrl!, exactReturn: true };
|
|
1350
|
+
}
|
|
1351
|
+
const connection = await withOrganizationIntegrationAcquisition(
|
|
1352
|
+
deps.db,
|
|
1353
|
+
state,
|
|
1354
|
+
["fiken"],
|
|
1355
|
+
async (tx) => {
|
|
1356
|
+
await requireFikenCallbackGrant(tx, state!);
|
|
1357
|
+
return persist(tx);
|
|
1358
|
+
},
|
|
1359
|
+
);
|
|
1083
1360
|
if (!connection) {
|
|
1084
1361
|
throw new FikenOAuthCallbackError("connection_conflict");
|
|
1085
1362
|
}
|
|
@@ -1087,12 +1364,17 @@ export async function completeFikenOAuthCallback(
|
|
|
1087
1364
|
redirectTo: fikenReturnUrl(returnBaseUrl, state.returnPath, "connected", connection.id),
|
|
1088
1365
|
};
|
|
1089
1366
|
} catch (error) {
|
|
1367
|
+
if (exactReturnUrl) return { redirectTo: exactReturnUrl, exactReturn: true };
|
|
1368
|
+
// Reading the state is the first step, so no state means the link itself
|
|
1369
|
+
// was unusable: say whether it expired instead of suggesting a token.
|
|
1370
|
+
const failure = state ? null : oauthStateFailureReturn(deps.settings, input.state);
|
|
1090
1371
|
return {
|
|
1091
1372
|
redirectTo: fikenReturnUrl(
|
|
1092
1373
|
returnBaseUrl,
|
|
1093
|
-
state?.returnPath ??
|
|
1374
|
+
state?.returnPath ?? failure!.returnPath,
|
|
1094
1375
|
"error",
|
|
1095
|
-
|
|
1376
|
+
failure?.reason ??
|
|
1377
|
+
(error instanceof FikenOAuthCallbackError ? error.reason : "callback_failed"),
|
|
1096
1378
|
),
|
|
1097
1379
|
};
|
|
1098
1380
|
}
|
|
@@ -1190,6 +1472,21 @@ function readFikenOAuthState(raw: string | undefined, settings: Settings): Fiken
|
|
|
1190
1472
|
workspaceId: required(payload.workspaceId),
|
|
1191
1473
|
subjectId: required(payload.subjectId),
|
|
1192
1474
|
returnPath: required(payload.returnPath),
|
|
1475
|
+
...(typeof payload.connectAttemptId === "string"
|
|
1476
|
+
? { connectAttemptId: required(payload.connectAttemptId) }
|
|
1477
|
+
: {}),
|
|
1478
|
+
...(typeof payload.encryptedExternalContinuation === "string"
|
|
1479
|
+
? {
|
|
1480
|
+
externalContinuation: ExternalActorContinuation.parse(
|
|
1481
|
+
JSON.parse(
|
|
1482
|
+
decryptEnvironmentValue(
|
|
1483
|
+
requireEnvironmentEncryption(settings),
|
|
1484
|
+
payload.encryptedExternalContinuation,
|
|
1485
|
+
),
|
|
1486
|
+
),
|
|
1487
|
+
),
|
|
1488
|
+
}
|
|
1489
|
+
: {}),
|
|
1193
1490
|
...(typeof payload.connectionId === "string" ? { connectionId: payload.connectionId } : {}),
|
|
1194
1491
|
...(typeof payload.connectionVersion === "number"
|
|
1195
1492
|
? { connectionVersion: payload.connectionVersion }
|
|
@@ -1200,14 +1497,7 @@ function readFikenOAuthState(raw: string | undefined, settings: Settings): Fiken
|
|
|
1200
1497
|
}
|
|
1201
1498
|
|
|
1202
1499
|
async function requireFikenCallbackGrant(db: Database, state: FikenOAuthState): Promise<void> {
|
|
1203
|
-
|
|
1204
|
-
if (
|
|
1205
|
-
!grant ||
|
|
1206
|
-
grant.accountId !== state.accountId ||
|
|
1207
|
-
!hasPermission(grant.permissions, "connections:write")
|
|
1208
|
-
) {
|
|
1209
|
-
throw new FikenOAuthCallbackError("permission_lost");
|
|
1210
|
-
}
|
|
1500
|
+
await requireConnectOwnerAuthority(db, state);
|
|
1211
1501
|
}
|
|
1212
1502
|
|
|
1213
1503
|
function fikenReturnUrl(
|