@opengeni/api-router 0.30.3 → 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-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 +1091 -162
- 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 +24 -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 +107 -9
- 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 +59 -2
- 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/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 +1967 -252
- 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 +28 -3
- 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 +717 -225
- 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 +3167 -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 -43
- 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 +780 -112
- 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 +1039 -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 +267 -33
- 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-WCXHI3FF.js +0 -49920
- package/dist/chunk-WCXHI3FF.js.map +0 -1
- package/dist/routes/packs.d.ts +0 -3
- package/src/routes/packs.ts +0 -729
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
listOrganizationXaiSubscriptions,
|
|
3
|
+
updateOrganizationXaiSubscription,
|
|
4
|
+
updateOrganizationXaiRotation,
|
|
5
|
+
listXaiSubscriptionAccountsMetadata,
|
|
6
|
+
getXaiRotationSettings,
|
|
7
|
+
ensureXaiRotationSettings,
|
|
8
|
+
getXaiSubscriptionAccountAuthoritySnapshot,
|
|
9
|
+
resolveXaiProviderAccountAuthoritySnapshotForAcceptance,
|
|
10
|
+
setActiveXaiCredential,
|
|
11
|
+
updateXaiRotationSettings,
|
|
12
|
+
updateXaiAllocatorEligibility,
|
|
13
|
+
renameXaiSubscriptionAccount,
|
|
14
|
+
disconnectXaiSubscriptionCredentialAndRepick,
|
|
15
|
+
wakeXaiCapacityWaiters,
|
|
16
|
+
XaiSubscriptionAccountMetadata,
|
|
17
|
+
} from "@opengeni/db";
|
|
18
|
+
import { requireAccessGrant, type ApiRouteDeps } from "@opengeni/core";
|
|
19
|
+
import type { Context, Hono } from "hono";
|
|
20
|
+
import { HTTPException } from "hono/http-exception";
|
|
21
|
+
import * as z from "zod/v4";
|
|
22
|
+
import { requireOrganizationCodexHuman } from "./codex";
|
|
23
|
+
import {
|
|
24
|
+
requirePrivateSubscriptionHuman,
|
|
25
|
+
requireSameOriginBrowserMutation,
|
|
26
|
+
requireSubscriptionScopeMutation,
|
|
27
|
+
} from "./subscription-pool-access";
|
|
28
|
+
const allocatorBody = z.object({
|
|
29
|
+
enabled: z.boolean(),
|
|
30
|
+
expectedVersion: z.number().int().positive(),
|
|
31
|
+
});
|
|
32
|
+
const settingsBody = z.object({ rotationEnabled: z.boolean() });
|
|
33
|
+
const renameBody = z.object({ label: z.string().trim().max(200).nullable() });
|
|
34
|
+
|
|
35
|
+
type PoolRepository = {
|
|
36
|
+
listOrganizationSubscriptions: typeof listOrganizationXaiSubscriptions;
|
|
37
|
+
updateOrganizationSubscription: typeof updateOrganizationXaiSubscription;
|
|
38
|
+
updateOrganizationSubscriptionRotation: typeof updateOrganizationXaiRotation;
|
|
39
|
+
listSubscriptionAccountsMetadata: typeof listXaiSubscriptionAccountsMetadata;
|
|
40
|
+
getSubscriptionRotationSettings: typeof getXaiRotationSettings;
|
|
41
|
+
ensureSubscriptionRotationSettings: typeof ensureXaiRotationSettings;
|
|
42
|
+
getSubscriptionAccountAuthoritySnapshot: typeof getXaiSubscriptionAccountAuthoritySnapshot;
|
|
43
|
+
resolveSubscriptionProviderAccountAuthoritySnapshotForAcceptance: typeof resolveXaiProviderAccountAuthoritySnapshotForAcceptance;
|
|
44
|
+
setActiveSubscriptionCredential: typeof setActiveXaiCredential;
|
|
45
|
+
updateSubscriptionRotationSettings: typeof updateXaiRotationSettings;
|
|
46
|
+
updateSubscriptionAllocatorEligibility: typeof updateXaiAllocatorEligibility;
|
|
47
|
+
renameSubscriptionAccount: typeof renameXaiSubscriptionAccount;
|
|
48
|
+
disconnectSubscriptionCredentialAndRepick: typeof disconnectXaiSubscriptionCredentialAndRepick;
|
|
49
|
+
wakeSubscriptionCapacityWaiters: typeof wakeXaiCapacityWaiters;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/** Account CRUD uses one authority, allocator and wake contract for every pool. */
|
|
53
|
+
export function registerSubscriptionAccountPoolRoutes(
|
|
54
|
+
app: Hono,
|
|
55
|
+
deps: ApiRouteDeps,
|
|
56
|
+
options: {
|
|
57
|
+
provider: "xai" | "claude";
|
|
58
|
+
route: "supergrok" | "claude";
|
|
59
|
+
displayName: "SuperGrok" | "Claude";
|
|
60
|
+
enabled: () => boolean;
|
|
61
|
+
repository: PoolRepository;
|
|
62
|
+
accountJson: (
|
|
63
|
+
account: XaiSubscriptionAccountMetadata,
|
|
64
|
+
activeId: string | null,
|
|
65
|
+
) => Record<string, unknown>;
|
|
66
|
+
projectAccounts?: (
|
|
67
|
+
accounts: XaiSubscriptionAccountMetadata[],
|
|
68
|
+
activeId: string | null,
|
|
69
|
+
authority: { accountId: string; workspaceId: string | null; subjectId: string },
|
|
70
|
+
) => Promise<Record<string, unknown>[]>;
|
|
71
|
+
},
|
|
72
|
+
) {
|
|
73
|
+
const { db } = deps;
|
|
74
|
+
const {
|
|
75
|
+
listOrganizationSubscriptions,
|
|
76
|
+
updateOrganizationSubscription,
|
|
77
|
+
updateOrganizationSubscriptionRotation,
|
|
78
|
+
listSubscriptionAccountsMetadata,
|
|
79
|
+
getSubscriptionRotationSettings,
|
|
80
|
+
ensureSubscriptionRotationSettings,
|
|
81
|
+
getSubscriptionAccountAuthoritySnapshot,
|
|
82
|
+
resolveSubscriptionProviderAccountAuthoritySnapshotForAcceptance,
|
|
83
|
+
setActiveSubscriptionCredential,
|
|
84
|
+
updateSubscriptionRotationSettings,
|
|
85
|
+
updateSubscriptionAllocatorEligibility,
|
|
86
|
+
renameSubscriptionAccount,
|
|
87
|
+
disconnectSubscriptionCredentialAndRepick,
|
|
88
|
+
wakeSubscriptionCapacityWaiters,
|
|
89
|
+
} = options.repository;
|
|
90
|
+
const workspacePath = `/v1/workspaces/:workspaceId/${options.route}`;
|
|
91
|
+
const organizationPath = `/v1/organizations/:organizationId/${options.route}`;
|
|
92
|
+
const requireEnabled = () => {
|
|
93
|
+
if (!options.enabled())
|
|
94
|
+
throw new HTTPException(404, {
|
|
95
|
+
message: options.displayName + " subscriptions are not enabled",
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
const organizationActor = async (c: Context, mutation = false) => {
|
|
99
|
+
requireEnabled();
|
|
100
|
+
if (mutation) requireSameOriginBrowserMutation(c, deps);
|
|
101
|
+
const organizationId = c.req.param("organizationId")!;
|
|
102
|
+
const human = await requireOrganizationCodexHuman(c, deps, organizationId);
|
|
103
|
+
return { organizationId, actorSubjectId: human.subjectId };
|
|
104
|
+
};
|
|
105
|
+
const resolveReadAuthority = async (c: Context, _deps: ApiRouteDeps, workspaceId: string) => {
|
|
106
|
+
const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:read");
|
|
107
|
+
const snapshot = await resolveSubscriptionProviderAccountAuthoritySnapshotForAcceptance(db, {
|
|
108
|
+
workspaceId,
|
|
109
|
+
subjectId: grant.subjectId,
|
|
110
|
+
});
|
|
111
|
+
if (snapshot.scope === "user") {
|
|
112
|
+
const human = await requirePrivateSubscriptionHuman(
|
|
113
|
+
c,
|
|
114
|
+
deps,
|
|
115
|
+
workspaceId,
|
|
116
|
+
options.displayName,
|
|
117
|
+
);
|
|
118
|
+
if (human.subjectId !== grant.subjectId)
|
|
119
|
+
throw new HTTPException(403, { message: "managed browser identity mismatch" });
|
|
120
|
+
}
|
|
121
|
+
return { accountId: grant.accountId, subjectId: grant.subjectId, snapshot };
|
|
122
|
+
};
|
|
123
|
+
const authorityForAccountMutation = async (
|
|
124
|
+
c: Context,
|
|
125
|
+
_deps: ApiRouteDeps,
|
|
126
|
+
workspaceId: string,
|
|
127
|
+
credentialId: string,
|
|
128
|
+
) => {
|
|
129
|
+
const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:read");
|
|
130
|
+
const snapshot = await getSubscriptionAccountAuthoritySnapshot(db, {
|
|
131
|
+
workspaceId,
|
|
132
|
+
subjectId: grant.subjectId,
|
|
133
|
+
credentialId,
|
|
134
|
+
});
|
|
135
|
+
if (!snapshot)
|
|
136
|
+
throw new HTTPException(404, { message: options.displayName + " account not found" });
|
|
137
|
+
const authority = await requireSubscriptionScopeMutation(
|
|
138
|
+
c,
|
|
139
|
+
deps,
|
|
140
|
+
workspaceId,
|
|
141
|
+
snapshot.scope,
|
|
142
|
+
options.displayName,
|
|
143
|
+
);
|
|
144
|
+
return { ...authority, snapshot };
|
|
145
|
+
};
|
|
146
|
+
app.get(`${organizationPath}/accounts`, async (c) => {
|
|
147
|
+
const actor = await organizationActor(c);
|
|
148
|
+
const { accounts, rotation } = await listOrganizationSubscriptions(db, actor);
|
|
149
|
+
const activeAccountId = rotation?.activeCredentialId ?? null;
|
|
150
|
+
return c.json({
|
|
151
|
+
accounts: options.projectAccounts
|
|
152
|
+
? await options.projectAccounts(accounts, activeAccountId, {
|
|
153
|
+
accountId: actor.organizationId,
|
|
154
|
+
workspaceId: null,
|
|
155
|
+
subjectId: actor.actorSubjectId,
|
|
156
|
+
})
|
|
157
|
+
: accounts.map((account) => options.accountJson(account, activeAccountId)),
|
|
158
|
+
activeAccountId,
|
|
159
|
+
source: "organization",
|
|
160
|
+
organizationId: actor.organizationId,
|
|
161
|
+
settings: {
|
|
162
|
+
rotationEnabled: rotation?.rotationEnabled ?? false,
|
|
163
|
+
rotationStrategy: "sharded",
|
|
164
|
+
activeCredentialId: activeAccountId,
|
|
165
|
+
},
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
app.patch(`${organizationPath}/settings`, async (c) => {
|
|
169
|
+
const actor = await organizationActor(c, true);
|
|
170
|
+
const parsed = settingsBody.safeParse(await c.req.json().catch(() => null));
|
|
171
|
+
if (!parsed.success) throw new HTTPException(400, { message: "rotationEnabled is required" });
|
|
172
|
+
const rotation = await updateOrganizationSubscriptionRotation(db, { ...actor, ...parsed.data });
|
|
173
|
+
return c.json({
|
|
174
|
+
rotationEnabled: rotation.rotationEnabled,
|
|
175
|
+
rotationStrategy: "sharded",
|
|
176
|
+
activeCredentialId: rotation.activeCredentialId,
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
const updateOrganizationAccount = async (
|
|
180
|
+
c: Context,
|
|
181
|
+
changes: Omit<
|
|
182
|
+
Parameters<typeof updateOrganizationSubscription>[1],
|
|
183
|
+
"organizationId" | "actorSubjectId" | "credentialId"
|
|
184
|
+
>,
|
|
185
|
+
) => {
|
|
186
|
+
const actor = await organizationActor(c, true);
|
|
187
|
+
try {
|
|
188
|
+
const result = await updateOrganizationSubscription(db, {
|
|
189
|
+
...actor,
|
|
190
|
+
credentialId: c.req.param("accountId")!,
|
|
191
|
+
...changes,
|
|
192
|
+
});
|
|
193
|
+
if (!result)
|
|
194
|
+
throw new HTTPException(404, { message: `${options.displayName} account not found` });
|
|
195
|
+
return c.json(result);
|
|
196
|
+
} catch (error) {
|
|
197
|
+
if (error instanceof HTTPException) throw error;
|
|
198
|
+
throw new HTTPException(409, {
|
|
199
|
+
message:
|
|
200
|
+
error instanceof Error
|
|
201
|
+
? error.message
|
|
202
|
+
: `${options.displayName} subscription could not be updated`,
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
app.post(`${organizationPath}/accounts/:accountId/activate`, (c) =>
|
|
207
|
+
updateOrganizationAccount(c, { activate: true }),
|
|
208
|
+
);
|
|
209
|
+
app.delete(`${organizationPath}/accounts/:accountId`, (c) =>
|
|
210
|
+
updateOrganizationAccount(c, { disconnect: true }),
|
|
211
|
+
);
|
|
212
|
+
app.patch(`${organizationPath}/accounts/:accountId`, async (c) => {
|
|
213
|
+
const parsed = renameBody.safeParse(await c.req.json().catch(() => null));
|
|
214
|
+
if (!parsed.success) throw new HTTPException(400, { message: "label is invalid" });
|
|
215
|
+
return updateOrganizationAccount(c, { label: parsed.data.label || null });
|
|
216
|
+
});
|
|
217
|
+
app.patch(`${organizationPath}/accounts/:accountId/allocator`, async (c) => {
|
|
218
|
+
const parsed = allocatorBody.safeParse(await c.req.json().catch(() => null));
|
|
219
|
+
if (!parsed.success)
|
|
220
|
+
throw new HTTPException(400, { message: "enabled and expectedVersion are required" });
|
|
221
|
+
return updateOrganizationAccount(c, {
|
|
222
|
+
allocatorEnabled: parsed.data.enabled,
|
|
223
|
+
expectedAllocatorVersion: parsed.data.expectedVersion,
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
app.get(`${workspacePath}/accounts`, async (c) => {
|
|
228
|
+
requireEnabled();
|
|
229
|
+
const workspaceId = c.req.param("workspaceId")!;
|
|
230
|
+
const authority = await resolveReadAuthority(c, deps, workspaceId);
|
|
231
|
+
const [accounts, settings] = await Promise.all([
|
|
232
|
+
listSubscriptionAccountsMetadata(deps.db, {
|
|
233
|
+
workspaceId,
|
|
234
|
+
subjectId: authority.subjectId,
|
|
235
|
+
}),
|
|
236
|
+
getSubscriptionRotationSettings(deps.db, {
|
|
237
|
+
workspaceId,
|
|
238
|
+
subjectId: authority.subjectId,
|
|
239
|
+
authoritySnapshot: authority.snapshot,
|
|
240
|
+
}),
|
|
241
|
+
]);
|
|
242
|
+
const activeCredentialId = settings?.activeCredentialId ?? null;
|
|
243
|
+
return c.json({
|
|
244
|
+
source: authority.snapshot.scope,
|
|
245
|
+
organizationId: authority.accountId,
|
|
246
|
+
accounts: options.projectAccounts
|
|
247
|
+
? await options.projectAccounts(
|
|
248
|
+
accounts.filter((account) =>
|
|
249
|
+
authority.snapshot.scope === "organization"
|
|
250
|
+
? account.scope === "organization"
|
|
251
|
+
: account.scope !== "organization",
|
|
252
|
+
),
|
|
253
|
+
activeCredentialId,
|
|
254
|
+
{ accountId: authority.accountId, workspaceId, subjectId: authority.subjectId },
|
|
255
|
+
)
|
|
256
|
+
: accounts
|
|
257
|
+
.filter((account) =>
|
|
258
|
+
authority.snapshot.scope === "organization"
|
|
259
|
+
? account.scope === "organization"
|
|
260
|
+
: account.scope !== "organization",
|
|
261
|
+
)
|
|
262
|
+
.map((account) => options.accountJson(account, activeCredentialId)),
|
|
263
|
+
activeAccountId: activeCredentialId,
|
|
264
|
+
settings: {
|
|
265
|
+
rotationEnabled: settings?.rotationEnabled ?? true,
|
|
266
|
+
rotationStrategy: "sharded" as const,
|
|
267
|
+
activeCredentialId,
|
|
268
|
+
},
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
app.post(`${workspacePath}/accounts/:accountId/activate`, async (c) => {
|
|
273
|
+
requireEnabled();
|
|
274
|
+
const workspaceId = c.req.param("workspaceId")!;
|
|
275
|
+
const credentialId = c.req.param("accountId")!;
|
|
276
|
+
const authority = await authorityForAccountMutation(c, deps, workspaceId, credentialId);
|
|
277
|
+
const activated = await setActiveSubscriptionCredential(deps.db, {
|
|
278
|
+
accountId: authority.accountId,
|
|
279
|
+
workspaceId,
|
|
280
|
+
subjectId: authority.subjectId,
|
|
281
|
+
authoritySnapshot: authority.snapshot,
|
|
282
|
+
credentialId,
|
|
283
|
+
});
|
|
284
|
+
if (!activated)
|
|
285
|
+
throw new HTTPException(409, {
|
|
286
|
+
message: `${options.displayName} account requires reconnect`,
|
|
287
|
+
});
|
|
288
|
+
await wakeSubscriptionCapacityWaiters(deps.db, {
|
|
289
|
+
workspaceId,
|
|
290
|
+
subjectId: authority.subjectId,
|
|
291
|
+
authoritySnapshot: authority.snapshot,
|
|
292
|
+
reason: `${options.provider}_active_credential_changed`,
|
|
293
|
+
});
|
|
294
|
+
return c.json({ activated: true, accountId: credentialId });
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
app.patch(`${workspacePath}/settings`, async (c) => {
|
|
298
|
+
requireEnabled();
|
|
299
|
+
const workspaceId = c.req.param("workspaceId")!;
|
|
300
|
+
const parsed = settingsBody.safeParse(await c.req.json().catch(() => null));
|
|
301
|
+
if (!parsed.success) throw new HTTPException(400, { message: "rotationEnabled is required" });
|
|
302
|
+
const readAuthority = await resolveReadAuthority(c, deps, workspaceId);
|
|
303
|
+
const authority = await requireSubscriptionScopeMutation(
|
|
304
|
+
c,
|
|
305
|
+
deps,
|
|
306
|
+
workspaceId,
|
|
307
|
+
readAuthority.snapshot.scope,
|
|
308
|
+
options.displayName,
|
|
309
|
+
);
|
|
310
|
+
const current = await ensureSubscriptionRotationSettings(deps.db, {
|
|
311
|
+
accountId: authority.accountId,
|
|
312
|
+
workspaceId,
|
|
313
|
+
subjectId: authority.subjectId,
|
|
314
|
+
authoritySnapshot: readAuthority.snapshot,
|
|
315
|
+
});
|
|
316
|
+
const updated = await updateSubscriptionRotationSettings(deps.db, {
|
|
317
|
+
workspaceId,
|
|
318
|
+
subjectId: authority.subjectId,
|
|
319
|
+
authoritySnapshot: readAuthority.snapshot,
|
|
320
|
+
expectedVersion: current.version,
|
|
321
|
+
rotationEnabled: parsed.data.rotationEnabled,
|
|
322
|
+
}).catch(() => null);
|
|
323
|
+
if (!updated)
|
|
324
|
+
throw new HTTPException(409, { message: `${options.displayName} settings changed` });
|
|
325
|
+
await wakeSubscriptionCapacityWaiters(deps.db, {
|
|
326
|
+
workspaceId,
|
|
327
|
+
subjectId: authority.subjectId,
|
|
328
|
+
authoritySnapshot: readAuthority.snapshot,
|
|
329
|
+
reason: `${options.provider}_rotation_settings_changed`,
|
|
330
|
+
});
|
|
331
|
+
return c.json({
|
|
332
|
+
rotationEnabled: updated.rotationEnabled,
|
|
333
|
+
rotationStrategy: "sharded" as const,
|
|
334
|
+
activeCredentialId: updated.activeCredentialId,
|
|
335
|
+
});
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
app.patch(`${workspacePath}/accounts/:accountId/allocator`, async (c) => {
|
|
339
|
+
requireEnabled();
|
|
340
|
+
const workspaceId = c.req.param("workspaceId")!;
|
|
341
|
+
const credentialId = c.req.param("accountId")!;
|
|
342
|
+
const authority = await authorityForAccountMutation(c, deps, workspaceId, credentialId);
|
|
343
|
+
const parsed = allocatorBody.safeParse(await c.req.json().catch(() => null));
|
|
344
|
+
if (!parsed.success) {
|
|
345
|
+
throw new HTTPException(400, {
|
|
346
|
+
message: "enabled and expectedVersion are required",
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
const result = await updateSubscriptionAllocatorEligibility(deps.db, {
|
|
350
|
+
workspaceId,
|
|
351
|
+
subjectId: authority.subjectId,
|
|
352
|
+
credentialId,
|
|
353
|
+
enabled: parsed.data.enabled,
|
|
354
|
+
expectedVersion: parsed.data.expectedVersion,
|
|
355
|
+
});
|
|
356
|
+
if (result.kind === "not_found") {
|
|
357
|
+
throw new HTTPException(404, {
|
|
358
|
+
message: `${options.displayName} account not found`,
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
const response = {
|
|
362
|
+
allocatorEnabled: result.allocatorEnabled,
|
|
363
|
+
allocatorVersion: result.allocatorVersion,
|
|
364
|
+
allocatorUpdatedAt: result.allocatorUpdatedAt?.toISOString() ?? null,
|
|
365
|
+
changed: result.kind === "updated",
|
|
366
|
+
};
|
|
367
|
+
if (result.kind === "updated") {
|
|
368
|
+
await wakeSubscriptionCapacityWaiters(deps.db, {
|
|
369
|
+
workspaceId,
|
|
370
|
+
subjectId: authority.subjectId,
|
|
371
|
+
authoritySnapshot: authority.snapshot,
|
|
372
|
+
reason: `${options.provider}_allocator_eligibility_changed`,
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
return result.kind === "conflict" ? c.json(response, 409) : c.json(response);
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
app.patch(`${workspacePath}/accounts/:accountId`, async (c) => {
|
|
379
|
+
requireEnabled();
|
|
380
|
+
const workspaceId = c.req.param("workspaceId")!;
|
|
381
|
+
const credentialId = c.req.param("accountId")!;
|
|
382
|
+
const authority = await authorityForAccountMutation(c, deps, workspaceId, credentialId);
|
|
383
|
+
const parsed = renameBody.safeParse(await c.req.json().catch(() => null));
|
|
384
|
+
if (!parsed.success) throw new HTTPException(400, { message: "label is invalid" });
|
|
385
|
+
const account = await renameSubscriptionAccount(deps.db, {
|
|
386
|
+
workspaceId,
|
|
387
|
+
subjectId: authority.subjectId,
|
|
388
|
+
credentialId,
|
|
389
|
+
label: parsed.data.label || null,
|
|
390
|
+
});
|
|
391
|
+
if (!account)
|
|
392
|
+
throw new HTTPException(404, {
|
|
393
|
+
message: `${options.displayName} account not found`,
|
|
394
|
+
});
|
|
395
|
+
const settings = await getSubscriptionRotationSettings(deps.db, {
|
|
396
|
+
workspaceId,
|
|
397
|
+
subjectId: authority.subjectId,
|
|
398
|
+
authoritySnapshot: authority.snapshot,
|
|
399
|
+
});
|
|
400
|
+
return c.json(options.accountJson(account, settings?.activeCredentialId ?? null));
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
app.delete(`${workspacePath}/accounts/:accountId`, async (c) => {
|
|
404
|
+
requireEnabled();
|
|
405
|
+
const workspaceId = c.req.param("workspaceId")!;
|
|
406
|
+
const credentialId = c.req.param("accountId")!;
|
|
407
|
+
const authority = await authorityForAccountMutation(c, deps, workspaceId, credentialId);
|
|
408
|
+
if (authority.snapshot.scope === "user") {
|
|
409
|
+
await wakeSubscriptionCapacityWaiters(deps.db, {
|
|
410
|
+
workspaceId,
|
|
411
|
+
subjectId: authority.subjectId,
|
|
412
|
+
authoritySnapshot: authority.snapshot,
|
|
413
|
+
reason: `${options.provider}_credential_disconnecting`,
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
const result = await disconnectSubscriptionCredentialAndRepick(deps.db, {
|
|
417
|
+
accountId: authority.accountId,
|
|
418
|
+
workspaceId,
|
|
419
|
+
subjectId: authority.subjectId,
|
|
420
|
+
credentialId,
|
|
421
|
+
authoritySnapshot: authority.snapshot,
|
|
422
|
+
});
|
|
423
|
+
if (result.disconnected && authority.snapshot.scope === "workspace") {
|
|
424
|
+
await wakeSubscriptionCapacityWaiters(deps.db, {
|
|
425
|
+
workspaceId,
|
|
426
|
+
subjectId: authority.subjectId,
|
|
427
|
+
authoritySnapshot: { version: 1, scope: "workspace" },
|
|
428
|
+
reason: `${options.provider}_credential_disconnected`,
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
return c.json({
|
|
432
|
+
disconnected: result.disconnected,
|
|
433
|
+
newActiveId: result.newActiveCredentialId,
|
|
434
|
+
});
|
|
435
|
+
});
|
|
436
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { getWorkspaceGrant } from "@opengeni/db";
|
|
2
|
+
import {
|
|
3
|
+
getManagedSession,
|
|
4
|
+
requireAccessGrant,
|
|
5
|
+
requireAccessGrantAuthorization,
|
|
6
|
+
externalActorContinuationForAuthorization,
|
|
7
|
+
type ApiRouteDeps,
|
|
8
|
+
} from "@opengeni/core";
|
|
9
|
+
import type { Context } from "hono";
|
|
10
|
+
import { HTTPException } from "hono/http-exception";
|
|
11
|
+
import { agentActingAsPersonBeforeGrantCheck, isAgentActingAsPerson } from "../http/acting-person";
|
|
12
|
+
type ManagedCookieHuman = { subjectId: string };
|
|
13
|
+
export async function managedCookieHuman(
|
|
14
|
+
c: Context,
|
|
15
|
+
deps: ApiRouteDeps,
|
|
16
|
+
): Promise<ManagedCookieHuman | null> {
|
|
17
|
+
if (
|
|
18
|
+
deps.settings.productAccessMode !== "managed" ||
|
|
19
|
+
!deps.managedAuth ||
|
|
20
|
+
!c.req.header("cookie") ||
|
|
21
|
+
c.req.header("authorization")
|
|
22
|
+
) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
const session = await getManagedSession(c, deps.managedAuth, {
|
|
26
|
+
db: deps.db,
|
|
27
|
+
sessionAdapter: deps.managedAuthSessionAdapter,
|
|
28
|
+
sessionSetMode: deps.settings.managedAuthSessionSetMode,
|
|
29
|
+
});
|
|
30
|
+
return session?.user?.id ? { subjectId: `user:${session.user.id}` } : null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function requireSameOriginBrowserMutation(c: Context, deps: ApiRouteDeps): void {
|
|
34
|
+
// Built in process for an agent acting as a person: no browser credentials
|
|
35
|
+
// ride along, so there is no cross-site request to guard against.
|
|
36
|
+
if (isAgentActingAsPerson(c)) return;
|
|
37
|
+
const contentType = c.req.header("content-type")?.split(";", 1)[0]?.trim().toLowerCase();
|
|
38
|
+
if (contentType !== "application/json") {
|
|
39
|
+
throw new HTTPException(403, { message: "JSON browser request required" });
|
|
40
|
+
}
|
|
41
|
+
if (!deps.settings.publicBaseUrl) {
|
|
42
|
+
throw new HTTPException(503, {
|
|
43
|
+
message: "managed browser origin is not configured",
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
const expectedOrigin = new URL(deps.settings.publicBaseUrl).origin;
|
|
47
|
+
if (c.req.header("origin") !== expectedOrigin) {
|
|
48
|
+
throw new HTTPException(403, {
|
|
49
|
+
message: "same-origin browser request required",
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
if (c.req.header("sec-fetch-site")?.toLowerCase() !== "same-origin") {
|
|
53
|
+
throw new HTTPException(403, {
|
|
54
|
+
message: "same-origin fetch metadata required",
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export async function requirePrivateSubscriptionHuman(
|
|
60
|
+
c: Context,
|
|
61
|
+
deps: ApiRouteDeps,
|
|
62
|
+
workspaceId: string,
|
|
63
|
+
displayName: string,
|
|
64
|
+
): Promise<{ accountId: string; subjectId: string }> {
|
|
65
|
+
if (c.req.header("authorization")) {
|
|
66
|
+
const authorization = await requireAccessGrantAuthorization(
|
|
67
|
+
c,
|
|
68
|
+
deps,
|
|
69
|
+
workspaceId,
|
|
70
|
+
"connections:write",
|
|
71
|
+
);
|
|
72
|
+
const external = externalActorContinuationForAuthorization(authorization);
|
|
73
|
+
if (
|
|
74
|
+
external &&
|
|
75
|
+
authorization.contextIntegrity &&
|
|
76
|
+
external.actor.effectiveSubjectId === authorization.grant.subjectId
|
|
77
|
+
) {
|
|
78
|
+
// The shared user-pool domain requires an ordinary workspace
|
|
79
|
+
// membership, not just the synthetic Personal-workspace owner grant.
|
|
80
|
+
if (!(await getWorkspaceGrant(deps.db, authorization.grant.subjectId, workspaceId)))
|
|
81
|
+
throw new HTTPException(409, {
|
|
82
|
+
message: `Private ${displayName} accounts require membership in an ordinary workspace`,
|
|
83
|
+
});
|
|
84
|
+
return { accountId: authorization.grant.accountId, subjectId: authorization.grant.subjectId };
|
|
85
|
+
}
|
|
86
|
+
throw new HTTPException(403, {
|
|
87
|
+
message: `Private ${displayName} accounts require a verified owning user`,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
const human = (await managedCookieHuman(c, deps)) ?? agentActingAsPersonBeforeGrantCheck(c);
|
|
91
|
+
if (!human) {
|
|
92
|
+
throw new HTTPException(401, {
|
|
93
|
+
message: "managed browser session required",
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
const grant = await requireAccessGrant(c, deps, workspaceId, "connections:write");
|
|
97
|
+
if (grant.subjectId !== human.subjectId) {
|
|
98
|
+
throw new HTTPException(403, {
|
|
99
|
+
message: "managed browser identity mismatch",
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
if (!(await getWorkspaceGrant(deps.db, grant.subjectId, workspaceId)))
|
|
103
|
+
throw new HTTPException(409, {
|
|
104
|
+
message: `Private ${displayName} accounts require membership in an ordinary workspace`,
|
|
105
|
+
});
|
|
106
|
+
return { accountId: grant.accountId, subjectId: grant.subjectId };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export async function requireSubscriptionScopeMutation(
|
|
110
|
+
c: Context,
|
|
111
|
+
deps: ApiRouteDeps,
|
|
112
|
+
workspaceId: string,
|
|
113
|
+
scope: "workspace" | "user" | "organization",
|
|
114
|
+
displayName: string,
|
|
115
|
+
): Promise<{ accountId: string; subjectId: string }> {
|
|
116
|
+
if (scope === "organization")
|
|
117
|
+
throw new HTTPException(409, { message: "Manage this subscription in organization settings" });
|
|
118
|
+
if (scope === "user") {
|
|
119
|
+
// Server-side external-user assertions do not use browser cookies. Ordinary
|
|
120
|
+
// bearers remain rejected by requirePrivateHuman; native CSRF is unchanged.
|
|
121
|
+
if (!c.req.header("authorization")) requireSameOriginBrowserMutation(c, deps);
|
|
122
|
+
return await requirePrivateSubscriptionHuman(c, deps, workspaceId, displayName);
|
|
123
|
+
}
|
|
124
|
+
const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:admin");
|
|
125
|
+
return { accountId: grant.accountId, subjectId: grant.subjectId };
|
|
126
|
+
}
|