@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
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import { claudeProviderId } from "@opengeni/config";
|
|
2
|
+
import {
|
|
3
|
+
CreateOrganizationProviderCustomModelRequest,
|
|
4
|
+
DeleteOrganizationProviderCustomModelRequest,
|
|
5
|
+
OrganizationModelProviderConnectionResponse,
|
|
6
|
+
OrganizationModelProviderKind,
|
|
7
|
+
OrganizationProviderCustomModel,
|
|
8
|
+
OrganizationProviderCustomModelsResponse,
|
|
9
|
+
RevokeOrganizationModelProviderConnectionRequest,
|
|
10
|
+
UpsertOrganizationModelProviderConnectionRequest,
|
|
11
|
+
} from "@opengeni/contracts";
|
|
12
|
+
import { requireEnvironmentEncryption, type ApiRouteDeps } from "@opengeni/core";
|
|
13
|
+
import {
|
|
14
|
+
createOrganizationModelProviderCustomModel,
|
|
15
|
+
encryptEnvironmentValue,
|
|
16
|
+
getOrganizationModelProviderConnection,
|
|
17
|
+
listOrganizationModelProviderCustomModels,
|
|
18
|
+
organizationModelProviderCredentialDigest,
|
|
19
|
+
OrganizationModelProviderConflictError,
|
|
20
|
+
OrganizationModelProviderLimitError,
|
|
21
|
+
retireOrganizationModelProviderCustomModel,
|
|
22
|
+
revokeOrganizationModelProviderConnection,
|
|
23
|
+
upsertOrganizationModelProviderConnection,
|
|
24
|
+
} from "@opengeni/db";
|
|
25
|
+
import type { Context, Hono } from "hono";
|
|
26
|
+
import { HTTPException } from "hono/http-exception";
|
|
27
|
+
import { z } from "zod";
|
|
28
|
+
|
|
29
|
+
import { requireOrganizationCodexHuman, requireSameOriginBrowserMutation } from "./codex";
|
|
30
|
+
|
|
31
|
+
const OrganizationId = z.string().uuid();
|
|
32
|
+
|
|
33
|
+
function parseOrganizationId(value: string): string {
|
|
34
|
+
const parsed = OrganizationId.safeParse(value);
|
|
35
|
+
if (!parsed.success) throw new HTTPException(404, { message: "organization not found" });
|
|
36
|
+
return parsed.data;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function jsonBody<T>(c: Context, schema: z.ZodType<T>, message: string): Promise<T> {
|
|
40
|
+
const parsed = schema.safeParse(await c.req.json().catch(() => null));
|
|
41
|
+
if (!parsed.success) throw new HTTPException(422, { message });
|
|
42
|
+
return parsed.data;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function providerKind(value: string) {
|
|
46
|
+
const parsed = OrganizationModelProviderKind.safeParse(value);
|
|
47
|
+
if (!parsed.success) throw new HTTPException(404, { message: "model provider not found" });
|
|
48
|
+
return parsed.data;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function connectionJson(connection: {
|
|
52
|
+
providerKind: "vercel_gateway" | "openrouter" | "anthropic" | "claude_subscription";
|
|
53
|
+
status: "active" | "revoked";
|
|
54
|
+
version: number;
|
|
55
|
+
createdAt: Date;
|
|
56
|
+
updatedAt: Date;
|
|
57
|
+
}) {
|
|
58
|
+
return OrganizationModelProviderConnectionResponse.parse({
|
|
59
|
+
...connection,
|
|
60
|
+
createdAt: connection.createdAt.toISOString(),
|
|
61
|
+
updatedAt: connection.updatedAt.toISOString(),
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function modelJson(model: {
|
|
66
|
+
id: string;
|
|
67
|
+
upstreamModelId: string;
|
|
68
|
+
label: string | null;
|
|
69
|
+
version: number;
|
|
70
|
+
createdAt: Date;
|
|
71
|
+
updatedAt: Date;
|
|
72
|
+
}) {
|
|
73
|
+
return OrganizationProviderCustomModel.parse({
|
|
74
|
+
...model,
|
|
75
|
+
createdAt: model.createdAt.toISOString(),
|
|
76
|
+
updatedAt: model.updatedAt.toISOString(),
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function conflict(error: unknown): never {
|
|
81
|
+
if (error instanceof OrganizationModelProviderConflictError) {
|
|
82
|
+
throw new HTTPException(409, { message: "organization model provider version conflict" });
|
|
83
|
+
}
|
|
84
|
+
if (error instanceof OrganizationModelProviderLimitError) {
|
|
85
|
+
throw new HTTPException(409, { message: "organization custom model limit reached" });
|
|
86
|
+
}
|
|
87
|
+
throw error;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function registerOrganizationModelProviderRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
91
|
+
app.use("/v1/organizations/:organizationId/model-providers/:providerKind", async (c, next) => {
|
|
92
|
+
if (
|
|
93
|
+
c.req.param("providerKind") === "claude_subscription" &&
|
|
94
|
+
!deps.settings.claudeSubscriptionEnabled
|
|
95
|
+
)
|
|
96
|
+
throw new HTTPException(404, { message: "Claude subscriptions are not enabled" });
|
|
97
|
+
await next();
|
|
98
|
+
});
|
|
99
|
+
app.use("/v1/organizations/:organizationId/model-providers/:providerKind/*", async (c, next) => {
|
|
100
|
+
if (
|
|
101
|
+
c.req.param("providerKind") === "claude_subscription" &&
|
|
102
|
+
!deps.settings.claudeSubscriptionEnabled
|
|
103
|
+
)
|
|
104
|
+
throw new HTTPException(404, { message: "Claude subscriptions are not enabled" });
|
|
105
|
+
await next();
|
|
106
|
+
});
|
|
107
|
+
app.get("/v1/organizations/:organizationId/model-providers/:providerKind", async (c) => {
|
|
108
|
+
c.header("cache-control", "private, no-store");
|
|
109
|
+
const organizationId = parseOrganizationId(c.req.param("organizationId"));
|
|
110
|
+
const human = await requireOrganizationCodexHuman(c, deps, organizationId);
|
|
111
|
+
if (c.req.param("providerKind") === "claude_subscription")
|
|
112
|
+
throw new HTTPException(410, { message: "Claude subscriptions use individual accounts." });
|
|
113
|
+
const connection = await getOrganizationModelProviderConnection(deps.db, {
|
|
114
|
+
organizationId,
|
|
115
|
+
actorSubjectId: human.subjectId,
|
|
116
|
+
providerKind: providerKind(c.req.param("providerKind")),
|
|
117
|
+
});
|
|
118
|
+
return connection ? c.json(connectionJson(connection)) : c.json(null);
|
|
119
|
+
});
|
|
120
|
+
const usagePath = "/v1/organizations/:organizationId/model-providers/:providerKind/usage";
|
|
121
|
+
async function usageScope(c: Context) {
|
|
122
|
+
c.header("cache-control", "private, no-store");
|
|
123
|
+
if (providerKind(c.req.param("providerKind")!) !== "claude_subscription")
|
|
124
|
+
throw new HTTPException(404, { message: "Usage not available for this provider" });
|
|
125
|
+
const organizationId = parseOrganizationId(c.req.param("organizationId")!);
|
|
126
|
+
const human = await requireOrganizationCodexHuman(c, deps, organizationId);
|
|
127
|
+
return {
|
|
128
|
+
accountId: organizationId,
|
|
129
|
+
workspaceId: null,
|
|
130
|
+
scope: "organization" as const,
|
|
131
|
+
actorSubjectId: human.subjectId,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
app.get(usagePath, async (c) => {
|
|
135
|
+
await usageScope(c);
|
|
136
|
+
throw new HTTPException(410, { message: "Check usage on the individual Claude account." });
|
|
137
|
+
});
|
|
138
|
+
app.post(`${usagePath}/refresh`, async (c) => {
|
|
139
|
+
requireSameOriginBrowserMutation(c, deps);
|
|
140
|
+
await usageScope(c);
|
|
141
|
+
throw new HTTPException(410, { message: "Check usage on the individual Claude account." });
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
app.put("/v1/organizations/:organizationId/model-providers/:providerKind", async (c) => {
|
|
145
|
+
c.header("cache-control", "private, no-store");
|
|
146
|
+
requireSameOriginBrowserMutation(c, deps);
|
|
147
|
+
const organizationId = parseOrganizationId(c.req.param("organizationId"));
|
|
148
|
+
const human = await requireOrganizationCodexHuman(c, deps, organizationId);
|
|
149
|
+
const payload = await jsonBody(
|
|
150
|
+
c,
|
|
151
|
+
UpsertOrganizationModelProviderConnectionRequest,
|
|
152
|
+
"invalid organization model provider connection",
|
|
153
|
+
);
|
|
154
|
+
const kind = providerKind(c.req.param("providerKind"));
|
|
155
|
+
if (kind === "claude_subscription")
|
|
156
|
+
throw new HTTPException(410, { message: "Claude subscriptions use individual accounts." });
|
|
157
|
+
if (kind === "anthropic" && !/^sk-ant-api[0-9]+-\S+$/.test(payload.apiKey))
|
|
158
|
+
throw new HTTPException(422, {
|
|
159
|
+
message: "Enter an Anthropic API key. Use Claude subscription for setup tokens.",
|
|
160
|
+
});
|
|
161
|
+
if (payload.claudeIdentity)
|
|
162
|
+
throw new HTTPException(422, {
|
|
163
|
+
message: "Claude identity is only valid for subscription connections.",
|
|
164
|
+
});
|
|
165
|
+
const credential = payload.apiKey;
|
|
166
|
+
try {
|
|
167
|
+
const connection = await upsertOrganizationModelProviderConnection(deps.db, {
|
|
168
|
+
organizationId,
|
|
169
|
+
actorSubjectId: human.subjectId,
|
|
170
|
+
providerKind: providerKind(c.req.param("providerKind")),
|
|
171
|
+
credentialEncrypted: encryptEnvironmentValue(
|
|
172
|
+
requireEnvironmentEncryption(deps.settings),
|
|
173
|
+
credential,
|
|
174
|
+
),
|
|
175
|
+
credentialDigest: organizationModelProviderCredentialDigest(credential),
|
|
176
|
+
operationId: payload.operationId,
|
|
177
|
+
...(payload.expectedVersion === undefined
|
|
178
|
+
? {}
|
|
179
|
+
: { expectedVersion: payload.expectedVersion }),
|
|
180
|
+
});
|
|
181
|
+
return c.json(connectionJson(connection));
|
|
182
|
+
} catch (error) {
|
|
183
|
+
conflict(error);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
app.delete("/v1/organizations/:organizationId/model-providers/:providerKind", async (c) => {
|
|
188
|
+
c.header("cache-control", "private, no-store");
|
|
189
|
+
requireSameOriginBrowserMutation(c, deps);
|
|
190
|
+
const organizationId = parseOrganizationId(c.req.param("organizationId"));
|
|
191
|
+
const human = await requireOrganizationCodexHuman(c, deps, organizationId);
|
|
192
|
+
const payload = await jsonBody(
|
|
193
|
+
c,
|
|
194
|
+
RevokeOrganizationModelProviderConnectionRequest,
|
|
195
|
+
"invalid organization model provider disconnect",
|
|
196
|
+
);
|
|
197
|
+
try {
|
|
198
|
+
if (c.req.param("providerKind") === "claude_subscription")
|
|
199
|
+
throw new HTTPException(410, { message: "Claude subscriptions use individual accounts." });
|
|
200
|
+
const connection = await revokeOrganizationModelProviderConnection(deps.db, {
|
|
201
|
+
organizationId,
|
|
202
|
+
actorSubjectId: human.subjectId,
|
|
203
|
+
providerKind: providerKind(c.req.param("providerKind")),
|
|
204
|
+
...payload,
|
|
205
|
+
});
|
|
206
|
+
return c.json(connectionJson(connection));
|
|
207
|
+
} catch (error) {
|
|
208
|
+
conflict(error);
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
app.get(
|
|
213
|
+
"/v1/organizations/:organizationId/model-providers/:providerKind/custom-models",
|
|
214
|
+
async (c) => {
|
|
215
|
+
c.header("cache-control", "private, no-store");
|
|
216
|
+
const organizationId = parseOrganizationId(c.req.param("organizationId"));
|
|
217
|
+
const human = await requireOrganizationCodexHuman(c, deps, organizationId);
|
|
218
|
+
const models = await listOrganizationModelProviderCustomModels(deps.db, {
|
|
219
|
+
organizationId,
|
|
220
|
+
actorSubjectId: human.subjectId,
|
|
221
|
+
providerKind: providerKind(c.req.param("providerKind")),
|
|
222
|
+
});
|
|
223
|
+
return c.json(
|
|
224
|
+
OrganizationProviderCustomModelsResponse.parse({ models: models.map(modelJson) }),
|
|
225
|
+
);
|
|
226
|
+
},
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
app.post(
|
|
230
|
+
"/v1/organizations/:organizationId/model-providers/:providerKind/custom-models",
|
|
231
|
+
async (c) => {
|
|
232
|
+
c.header("cache-control", "private, no-store");
|
|
233
|
+
requireSameOriginBrowserMutation(c, deps);
|
|
234
|
+
const organizationId = parseOrganizationId(c.req.param("organizationId"));
|
|
235
|
+
const human = await requireOrganizationCodexHuman(c, deps, organizationId);
|
|
236
|
+
const payload = await jsonBody(
|
|
237
|
+
c,
|
|
238
|
+
CreateOrganizationProviderCustomModelRequest,
|
|
239
|
+
"invalid organization custom model",
|
|
240
|
+
);
|
|
241
|
+
const kind = providerKind(c.req.param("providerKind"));
|
|
242
|
+
if (
|
|
243
|
+
(kind === "anthropic" || kind === "claude_subscription") &&
|
|
244
|
+
`${claudeProviderId(kind)}/${payload.upstreamModelId}`.length > 256
|
|
245
|
+
)
|
|
246
|
+
throw new HTTPException(422, { message: "Claude model ID is too long" });
|
|
247
|
+
try {
|
|
248
|
+
const model = await createOrganizationModelProviderCustomModel(deps.db, {
|
|
249
|
+
organizationId,
|
|
250
|
+
actorSubjectId: human.subjectId,
|
|
251
|
+
providerKind: providerKind(c.req.param("providerKind")),
|
|
252
|
+
operationId: payload.operationId,
|
|
253
|
+
upstreamModelId: payload.upstreamModelId,
|
|
254
|
+
...(payload.label === undefined ? {} : { label: payload.label }),
|
|
255
|
+
});
|
|
256
|
+
return c.json(modelJson(model), 201);
|
|
257
|
+
} catch (error) {
|
|
258
|
+
conflict(error);
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
app.delete(
|
|
264
|
+
"/v1/organizations/:organizationId/model-providers/:providerKind/custom-models/:customModelId",
|
|
265
|
+
async (c) => {
|
|
266
|
+
c.header("cache-control", "private, no-store");
|
|
267
|
+
requireSameOriginBrowserMutation(c, deps);
|
|
268
|
+
const organizationId = parseOrganizationId(c.req.param("organizationId"));
|
|
269
|
+
const human = await requireOrganizationCodexHuman(c, deps, organizationId);
|
|
270
|
+
const payload = await jsonBody(
|
|
271
|
+
c,
|
|
272
|
+
DeleteOrganizationProviderCustomModelRequest,
|
|
273
|
+
"invalid organization custom model deletion",
|
|
274
|
+
);
|
|
275
|
+
const customModelId = z.string().uuid().safeParse(c.req.param("customModelId"));
|
|
276
|
+
if (!customModelId.success) {
|
|
277
|
+
throw new HTTPException(422, { message: "invalid organization custom model id" });
|
|
278
|
+
}
|
|
279
|
+
try {
|
|
280
|
+
const model = await retireOrganizationModelProviderCustomModel(deps.db, {
|
|
281
|
+
organizationId,
|
|
282
|
+
actorSubjectId: human.subjectId,
|
|
283
|
+
providerKind: providerKind(c.req.param("providerKind")),
|
|
284
|
+
customModelId: customModelId.data,
|
|
285
|
+
...payload,
|
|
286
|
+
});
|
|
287
|
+
return c.json(modelJson(model));
|
|
288
|
+
} catch (error) {
|
|
289
|
+
conflict(error);
|
|
290
|
+
}
|
|
291
|
+
},
|
|
292
|
+
);
|
|
293
|
+
}
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AcceptOrganizationRecoveryCustodyRequest,
|
|
3
|
+
ConfigureOrganizationRecoveryPolicyRequest,
|
|
4
|
+
DisableOrganizationRecoveryPolicyRequest,
|
|
5
|
+
OrganizationRecoveryMutationResponse,
|
|
6
|
+
OrganizationRecoveryOperationCommandRequest,
|
|
7
|
+
OrganizationRecoveryOverview,
|
|
8
|
+
StartOrganizationRecoveryOperationRequest,
|
|
9
|
+
} from "@opengeni/contracts/organization-recovery";
|
|
10
|
+
import {
|
|
11
|
+
getManagedAuthRequestActorAdmissionStamp,
|
|
12
|
+
getManagedAuthRequestActorLeaseStamp,
|
|
13
|
+
requireCanonicalHumanRequestIdentity,
|
|
14
|
+
} from "@opengeni/core/canonical-human-identities";
|
|
15
|
+
import type { ApiRouteDeps } from "@opengeni/core";
|
|
16
|
+
import {
|
|
17
|
+
acceptOrganizationRecoveryCustody,
|
|
18
|
+
approveOrganizationRecoveryOperation,
|
|
19
|
+
cancelOrganizationRecoveryOperation,
|
|
20
|
+
configureOrganizationRecoveryPolicy,
|
|
21
|
+
disableOrganizationRecoveryPolicy,
|
|
22
|
+
executeOrganizationRecoveryOperation,
|
|
23
|
+
getOrganizationRecoveryOverview,
|
|
24
|
+
OrganizationRecoveryDeniedError,
|
|
25
|
+
OrganizationRecoveryOperationReuseError,
|
|
26
|
+
OrganizationRecoveryRevisionConflictError,
|
|
27
|
+
OrganizationRecoveryUnavailableError,
|
|
28
|
+
startOrganizationRecoveryOperation,
|
|
29
|
+
} from "@opengeni/db";
|
|
30
|
+
import type { Context, Hono } from "hono";
|
|
31
|
+
import { HTTPException } from "hono/http-exception";
|
|
32
|
+
import { z } from "zod";
|
|
33
|
+
import { ApiHttpError } from "../http/api-error";
|
|
34
|
+
|
|
35
|
+
const OrganizationId = z.string().uuid();
|
|
36
|
+
const RecoveryOperationId = z.string().uuid();
|
|
37
|
+
|
|
38
|
+
export type OrganizationRecoveryRouteServices = {
|
|
39
|
+
requireCanonicalHumanRequestIdentity: typeof requireCanonicalHumanRequestIdentity;
|
|
40
|
+
getManagedAuthRequestActorAdmissionStamp: typeof getManagedAuthRequestActorAdmissionStamp;
|
|
41
|
+
getManagedAuthRequestActorLeaseStamp: typeof getManagedAuthRequestActorLeaseStamp;
|
|
42
|
+
getOrganizationRecoveryOverview: typeof getOrganizationRecoveryOverview;
|
|
43
|
+
configureOrganizationRecoveryPolicy: typeof configureOrganizationRecoveryPolicy;
|
|
44
|
+
acceptOrganizationRecoveryCustody: typeof acceptOrganizationRecoveryCustody;
|
|
45
|
+
disableOrganizationRecoveryPolicy: typeof disableOrganizationRecoveryPolicy;
|
|
46
|
+
startOrganizationRecoveryOperation: typeof startOrganizationRecoveryOperation;
|
|
47
|
+
approveOrganizationRecoveryOperation: typeof approveOrganizationRecoveryOperation;
|
|
48
|
+
cancelOrganizationRecoveryOperation: typeof cancelOrganizationRecoveryOperation;
|
|
49
|
+
executeOrganizationRecoveryOperation: typeof executeOrganizationRecoveryOperation;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const productionServices: OrganizationRecoveryRouteServices = {
|
|
53
|
+
requireCanonicalHumanRequestIdentity,
|
|
54
|
+
getManagedAuthRequestActorAdmissionStamp,
|
|
55
|
+
getManagedAuthRequestActorLeaseStamp,
|
|
56
|
+
getOrganizationRecoveryOverview,
|
|
57
|
+
configureOrganizationRecoveryPolicy,
|
|
58
|
+
acceptOrganizationRecoveryCustody,
|
|
59
|
+
disableOrganizationRecoveryPolicy,
|
|
60
|
+
startOrganizationRecoveryOperation,
|
|
61
|
+
approveOrganizationRecoveryOperation,
|
|
62
|
+
cancelOrganizationRecoveryOperation,
|
|
63
|
+
executeOrganizationRecoveryOperation,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
async function requireRecoveryIdentity(
|
|
67
|
+
context: Context,
|
|
68
|
+
deps: ApiRouteDeps,
|
|
69
|
+
services: OrganizationRecoveryRouteServices,
|
|
70
|
+
) {
|
|
71
|
+
// Recovery is a browser-session ceremony. Never let ambient API, bearer,
|
|
72
|
+
// service, or machine authority become a competing recovery identity.
|
|
73
|
+
if (
|
|
74
|
+
deps.settings.productAccessMode !== "managed" ||
|
|
75
|
+
!deps.managedAuth ||
|
|
76
|
+
!context.req.header("cookie") ||
|
|
77
|
+
context.req.header("authorization")
|
|
78
|
+
) {
|
|
79
|
+
throw new HTTPException(401, {
|
|
80
|
+
message: "Managed human authentication required",
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
const identity = await services.requireCanonicalHumanRequestIdentity(context, {
|
|
84
|
+
db: deps.db,
|
|
85
|
+
managedAuth: deps.managedAuth,
|
|
86
|
+
managedAuthSessionAdapter: deps.managedAuthSessionAdapter,
|
|
87
|
+
managedAuthSessionSetMode: deps.settings.managedAuthSessionSetMode,
|
|
88
|
+
allowRecovery: false,
|
|
89
|
+
});
|
|
90
|
+
return { ...identity, actorSubjectId: `user:${identity.authUserId}` };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async function parseBody<S extends z.ZodType>(context: Context, schema: S): Promise<z.infer<S>> {
|
|
94
|
+
const parsed = schema.safeParse(await context.req.json().catch(() => null));
|
|
95
|
+
if (!parsed.success) {
|
|
96
|
+
throw new HTTPException(422, {
|
|
97
|
+
message: "Invalid organization recovery request",
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
return parsed.data;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function parseId(schema: z.ZodString, value: string, label: string): string {
|
|
104
|
+
const parsed = schema.safeParse(value);
|
|
105
|
+
if (!parsed.success) throw new HTTPException(422, { message: `Invalid ${label}` });
|
|
106
|
+
return parsed.data;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function organizationId(context: Context): string {
|
|
110
|
+
return parseId(OrganizationId, context.req.param("organizationId") ?? "", "organization id");
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function recoveryOperationId(context: Context): string {
|
|
114
|
+
return parseId(
|
|
115
|
+
RecoveryOperationId,
|
|
116
|
+
context.req.param("recoveryOperationId") ?? "",
|
|
117
|
+
"recovery operation id",
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function organizationRecoveryHttpError(error: unknown): Error {
|
|
122
|
+
if (error instanceof OrganizationRecoveryRevisionConflictError) {
|
|
123
|
+
return new ApiHttpError(409, {
|
|
124
|
+
code: "conflict",
|
|
125
|
+
message: "Recovery state changed; refresh before submitting a new action.",
|
|
126
|
+
retryable: false,
|
|
127
|
+
outcomeUnknown: false,
|
|
128
|
+
details: { code: error.code },
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
if (error instanceof OrganizationRecoveryOperationReuseError) {
|
|
132
|
+
return new ApiHttpError(409, {
|
|
133
|
+
code: "idempotency_conflict",
|
|
134
|
+
message: "Operation id was reused with different input.",
|
|
135
|
+
retryable: false,
|
|
136
|
+
outcomeUnknown: false,
|
|
137
|
+
details: { code: error.code },
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
if (error instanceof OrganizationRecoveryUnavailableError) {
|
|
141
|
+
return new ApiHttpError(409, {
|
|
142
|
+
code: "conflict",
|
|
143
|
+
message: "Organization recovery is unavailable.",
|
|
144
|
+
retryable: false,
|
|
145
|
+
outcomeUnknown: false,
|
|
146
|
+
details: { code: error.code },
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
if (error instanceof OrganizationRecoveryDeniedError) {
|
|
150
|
+
return new ApiHttpError(404, {
|
|
151
|
+
code: "not_found",
|
|
152
|
+
message: "Organization recovery not found.",
|
|
153
|
+
retryable: false,
|
|
154
|
+
outcomeUnknown: false,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
if (error instanceof Error) return error;
|
|
158
|
+
return new Error("Organization recovery failed");
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function requireActorFence(
|
|
162
|
+
context: Context,
|
|
163
|
+
deps: ApiRouteDeps,
|
|
164
|
+
services: OrganizationRecoveryRouteServices,
|
|
165
|
+
) {
|
|
166
|
+
const actorFence = services.getManagedAuthRequestActorLeaseStamp(context.req.raw);
|
|
167
|
+
if (deps.settings.managedAuthSessionSetMode !== "legacy" && !actorFence) {
|
|
168
|
+
throw new HTTPException(409, {
|
|
169
|
+
message: "Managed actor mutation fence is unavailable",
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
if (!actorFence) {
|
|
173
|
+
throw new HTTPException(409, {
|
|
174
|
+
message: "Organization recovery requires provider-neutral browser login slots",
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
return actorFence;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
async function mutationContext(
|
|
181
|
+
context: Context,
|
|
182
|
+
deps: ApiRouteDeps,
|
|
183
|
+
services: OrganizationRecoveryRouteServices,
|
|
184
|
+
) {
|
|
185
|
+
const identity = await requireRecoveryIdentity(context, deps, services);
|
|
186
|
+
return {
|
|
187
|
+
organizationId: organizationId(context),
|
|
188
|
+
actorSubjectId: identity.actorSubjectId,
|
|
189
|
+
actorAuthUserId: identity.authUserId,
|
|
190
|
+
actorAuthSessionId: identity.authSessionId,
|
|
191
|
+
actorFence: requireActorFence(context, deps, services),
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function mutationResponse(context: Context, value: unknown): Response {
|
|
196
|
+
return context.json(OrganizationRecoveryMutationResponse.parse(value));
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export function registerOrganizationRecoveryRoutes(
|
|
200
|
+
app: Hono,
|
|
201
|
+
deps: ApiRouteDeps,
|
|
202
|
+
services: OrganizationRecoveryRouteServices = productionServices,
|
|
203
|
+
): void {
|
|
204
|
+
const base = "/v1/organizations/:organizationId/recovery";
|
|
205
|
+
|
|
206
|
+
app.get(base, async (context) => {
|
|
207
|
+
const identity = await requireRecoveryIdentity(context, deps, services);
|
|
208
|
+
try {
|
|
209
|
+
return context.json(
|
|
210
|
+
OrganizationRecoveryOverview.parse(
|
|
211
|
+
await services.getOrganizationRecoveryOverview(deps.db, {
|
|
212
|
+
organizationId: organizationId(context),
|
|
213
|
+
actorSubjectId: identity.actorSubjectId,
|
|
214
|
+
actorAuthUserId: identity.authUserId,
|
|
215
|
+
actorAuthSessionId: identity.authSessionId,
|
|
216
|
+
actorFence: services.getManagedAuthRequestActorAdmissionStamp(context.req.raw) ?? null,
|
|
217
|
+
}),
|
|
218
|
+
),
|
|
219
|
+
);
|
|
220
|
+
} catch (error) {
|
|
221
|
+
throw organizationRecoveryHttpError(error);
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
app.put(`${base}/policy`, async (context) => {
|
|
226
|
+
const authority = await mutationContext(context, deps, services);
|
|
227
|
+
const payload = await parseBody(context, ConfigureOrganizationRecoveryPolicyRequest);
|
|
228
|
+
try {
|
|
229
|
+
return mutationResponse(
|
|
230
|
+
context,
|
|
231
|
+
await services.configureOrganizationRecoveryPolicy(deps.db, {
|
|
232
|
+
...authority,
|
|
233
|
+
operationId: payload.operationId,
|
|
234
|
+
expectedPolicyRevision: payload.expectedPolicyRevision,
|
|
235
|
+
custodianMembershipIds: payload.custodianMembershipIds,
|
|
236
|
+
}),
|
|
237
|
+
);
|
|
238
|
+
} catch (error) {
|
|
239
|
+
throw organizationRecoveryHttpError(error);
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
app.post(`${base}/policy/accept`, async (context) => {
|
|
244
|
+
const authority = await mutationContext(context, deps, services);
|
|
245
|
+
const payload = await parseBody(context, AcceptOrganizationRecoveryCustodyRequest);
|
|
246
|
+
try {
|
|
247
|
+
return mutationResponse(
|
|
248
|
+
context,
|
|
249
|
+
await services.acceptOrganizationRecoveryCustody(deps.db, {
|
|
250
|
+
...authority,
|
|
251
|
+
operationId: payload.operationId,
|
|
252
|
+
expectedPolicyRevision: payload.expectedPolicyRevision,
|
|
253
|
+
}),
|
|
254
|
+
);
|
|
255
|
+
} catch (error) {
|
|
256
|
+
throw organizationRecoveryHttpError(error);
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
app.post(`${base}/policy/disable`, async (context) => {
|
|
261
|
+
const authority = await mutationContext(context, deps, services);
|
|
262
|
+
const payload = await parseBody(context, DisableOrganizationRecoveryPolicyRequest);
|
|
263
|
+
try {
|
|
264
|
+
return mutationResponse(
|
|
265
|
+
context,
|
|
266
|
+
await services.disableOrganizationRecoveryPolicy(deps.db, {
|
|
267
|
+
...authority,
|
|
268
|
+
operationId: payload.operationId,
|
|
269
|
+
expectedPolicyRevision: payload.expectedPolicyRevision,
|
|
270
|
+
}),
|
|
271
|
+
);
|
|
272
|
+
} catch (error) {
|
|
273
|
+
throw organizationRecoveryHttpError(error);
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
app.post(`${base}/operations`, async (context) => {
|
|
278
|
+
const authority = await mutationContext(context, deps, services);
|
|
279
|
+
const payload = await parseBody(context, StartOrganizationRecoveryOperationRequest);
|
|
280
|
+
try {
|
|
281
|
+
return mutationResponse(
|
|
282
|
+
context,
|
|
283
|
+
await services.startOrganizationRecoveryOperation(deps.db, {
|
|
284
|
+
...authority,
|
|
285
|
+
operationId: payload.operationId,
|
|
286
|
+
expectedPolicyRevision: payload.expectedPolicyRevision,
|
|
287
|
+
targetMembershipId: payload.targetMembershipId,
|
|
288
|
+
}),
|
|
289
|
+
);
|
|
290
|
+
} catch (error) {
|
|
291
|
+
throw organizationRecoveryHttpError(error);
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
async function mutateOperation(
|
|
296
|
+
context: Context,
|
|
297
|
+
command: typeof approveOrganizationRecoveryOperation,
|
|
298
|
+
): Promise<Response> {
|
|
299
|
+
const authority = await mutationContext(context, deps, services);
|
|
300
|
+
const payload = await parseBody(context, OrganizationRecoveryOperationCommandRequest);
|
|
301
|
+
try {
|
|
302
|
+
return mutationResponse(
|
|
303
|
+
context,
|
|
304
|
+
await command(deps.db, {
|
|
305
|
+
...authority,
|
|
306
|
+
recoveryOperationId: recoveryOperationId(context),
|
|
307
|
+
operationId: payload.operationId,
|
|
308
|
+
expectedOperationRevision: payload.expectedOperationRevision,
|
|
309
|
+
}),
|
|
310
|
+
);
|
|
311
|
+
} catch (error) {
|
|
312
|
+
throw organizationRecoveryHttpError(error);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
app.post(`${base}/operations/:recoveryOperationId/approve`, async (context) =>
|
|
317
|
+
mutateOperation(context, services.approveOrganizationRecoveryOperation),
|
|
318
|
+
);
|
|
319
|
+
app.post(`${base}/operations/:recoveryOperationId/cancel`, async (context) =>
|
|
320
|
+
mutateOperation(context, services.cancelOrganizationRecoveryOperation),
|
|
321
|
+
);
|
|
322
|
+
app.post(`${base}/operations/:recoveryOperationId/execute`, async (context) =>
|
|
323
|
+
mutateOperation(context, services.executeOrganizationRecoveryOperation),
|
|
324
|
+
);
|
|
325
|
+
}
|