@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
package/src/github-access.ts
CHANGED
|
@@ -1,15 +1,63 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import {
|
|
2
|
+
defaultRepositoryMountPath,
|
|
3
|
+
type GitHubAppRepositoryBranchPage,
|
|
4
|
+
type GitHubBindingStatus,
|
|
5
|
+
type GitHubInstallationBinding,
|
|
6
|
+
type GitHubRepository,
|
|
7
|
+
type RepositoryResourceRef,
|
|
5
8
|
} from "@opengeni/contracts";
|
|
6
9
|
import {
|
|
10
|
+
GitHubRepositoryBranchesResponse as GitHubRepositoryBranchesResponseSchema,
|
|
11
|
+
type GitHubRepositoryBranchesResponse,
|
|
12
|
+
type ListGitHubRepositoryBranchesQuery,
|
|
13
|
+
} from "@opengeni/contracts/github-repository-contracts";
|
|
14
|
+
import {
|
|
15
|
+
areGitHubRepositoriesAllowedForWorkspace,
|
|
7
16
|
hasAuditableGitHubInstallationAuthority,
|
|
8
17
|
listGitHubInstallationAccessForWorkspace,
|
|
9
18
|
} from "@opengeni/db";
|
|
10
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
GitHubAppApiError,
|
|
21
|
+
listGitHubAppInstallationSummaries,
|
|
22
|
+
listGitHubAppRepositories,
|
|
23
|
+
listGitHubAppRepositoryBranches,
|
|
24
|
+
} from "@opengeni/github";
|
|
11
25
|
import type { ApiRouteDeps } from "@opengeni/core";
|
|
12
26
|
|
|
27
|
+
export type GitHubRepositoryBranchAuthorityErrorCode = "changed" | "not_authorized";
|
|
28
|
+
|
|
29
|
+
export class GitHubRepositoryBranchAuthorityError extends Error {
|
|
30
|
+
constructor(readonly code: GitHubRepositoryBranchAuthorityErrorCode) {
|
|
31
|
+
super(code);
|
|
32
|
+
this.name = "GitHubRepositoryBranchAuthorityError";
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type WorkspaceGitHubRepositoryBranchServices = {
|
|
37
|
+
listInstallationAccess: typeof listGitHubInstallationAccessForWorkspace;
|
|
38
|
+
areRepositoriesAllowed: typeof areGitHubRepositoriesAllowedForWorkspace;
|
|
39
|
+
listProviderBranches: (
|
|
40
|
+
deps: ApiRouteDeps,
|
|
41
|
+
input: {
|
|
42
|
+
installationId: number;
|
|
43
|
+
repositoryId: number;
|
|
44
|
+
page: number;
|
|
45
|
+
limit: number;
|
|
46
|
+
},
|
|
47
|
+
) => Promise<GitHubAppRepositoryBranchPage | null>;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const workspaceGitHubRepositoryBranchServices: WorkspaceGitHubRepositoryBranchServices = {
|
|
51
|
+
listInstallationAccess: listGitHubInstallationAccessForWorkspace,
|
|
52
|
+
areRepositoriesAllowed: areGitHubRepositoriesAllowedForWorkspace,
|
|
53
|
+
listProviderBranches: async (deps, input) =>
|
|
54
|
+
deps.githubAppApi?.listRepositoryBranches
|
|
55
|
+
? await deps.githubAppApi.listRepositoryBranches(input)
|
|
56
|
+
: deps.githubAppApi
|
|
57
|
+
? null
|
|
58
|
+
: await listGitHubAppRepositoryBranches(deps.settings, input),
|
|
59
|
+
};
|
|
60
|
+
|
|
13
61
|
export async function listWorkspaceGitHubInstallationBindings(
|
|
14
62
|
deps: ApiRouteDeps,
|
|
15
63
|
workspaceId: string,
|
|
@@ -153,3 +201,97 @@ export async function listWorkspaceGitHubRepositories(
|
|
|
153
201
|
return installation.repositoryIds.includes(repository.id);
|
|
154
202
|
});
|
|
155
203
|
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* The exact session repository resource for one workspace GitHub App
|
|
207
|
+
* repository: its default branch, a canonical clone URI, and the installation
|
|
208
|
+
* identity that platform-brokered Git auth and create-time validation check.
|
|
209
|
+
*/
|
|
210
|
+
export function githubRepositoryResourceRef(repository: GitHubRepository): RepositoryResourceRef {
|
|
211
|
+
const uri = normalizedRepositoryUri(repository.cloneUrl);
|
|
212
|
+
return {
|
|
213
|
+
kind: "repository",
|
|
214
|
+
uri,
|
|
215
|
+
ref: repository.defaultBranch,
|
|
216
|
+
provider: "github",
|
|
217
|
+
mountPath: defaultRepositoryMountPath(uri, "github"),
|
|
218
|
+
githubInstallationId: repository.installationId,
|
|
219
|
+
githubRepositoryId: repository.id,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function normalizedRepositoryUri(value: string): string {
|
|
224
|
+
const url = new URL(value);
|
|
225
|
+
const path = url.pathname.replace(/^\/+|\/+$/g, "").replace(/\.git$/, "");
|
|
226
|
+
return `https://${url.host.toLowerCase()}/${path}.git`;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export async function listWorkspaceGitHubRepositoryBranches(
|
|
230
|
+
deps: ApiRouteDeps,
|
|
231
|
+
input: {
|
|
232
|
+
accountId: string;
|
|
233
|
+
workspaceId: string;
|
|
234
|
+
installationId: number;
|
|
235
|
+
repositoryId: number;
|
|
236
|
+
query: ListGitHubRepositoryBranchesQuery;
|
|
237
|
+
},
|
|
238
|
+
services: WorkspaceGitHubRepositoryBranchServices = workspaceGitHubRepositoryBranchServices,
|
|
239
|
+
): Promise<GitHubRepositoryBranchesResponse> {
|
|
240
|
+
const installations = await services.listInstallationAccess(deps.db, input.workspaceId);
|
|
241
|
+
const installation = installations.find(
|
|
242
|
+
(candidate) => candidate.installationId === input.installationId,
|
|
243
|
+
);
|
|
244
|
+
if (
|
|
245
|
+
!installation ||
|
|
246
|
+
installation.accountId !== input.accountId ||
|
|
247
|
+
!hasAuditableGitHubInstallationAuthority(installation) ||
|
|
248
|
+
!installation.repositoryIds.includes(input.repositoryId)
|
|
249
|
+
) {
|
|
250
|
+
throw new GitHubRepositoryBranchAuthorityError("not_authorized");
|
|
251
|
+
}
|
|
252
|
+
if (
|
|
253
|
+
!(await services.areRepositoriesAllowed(deps.db, input.workspaceId, input.installationId, [
|
|
254
|
+
input.repositoryId,
|
|
255
|
+
]))
|
|
256
|
+
) {
|
|
257
|
+
throw new GitHubRepositoryBranchAuthorityError("changed");
|
|
258
|
+
}
|
|
259
|
+
const page = await services.listProviderBranches(deps, {
|
|
260
|
+
installationId: input.installationId,
|
|
261
|
+
repositoryId: input.repositoryId,
|
|
262
|
+
page: input.query.cursor,
|
|
263
|
+
limit: input.query.limit,
|
|
264
|
+
});
|
|
265
|
+
if (!page) {
|
|
266
|
+
throw new GitHubAppApiError(
|
|
267
|
+
"The configured GitHub provider cannot list exact repository branches",
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
if (
|
|
271
|
+
page.installationId !== input.installationId ||
|
|
272
|
+
page.repositoryId !== input.repositoryId ||
|
|
273
|
+
page.branches.length > input.query.limit ||
|
|
274
|
+
(page.nextPage !== null && page.nextPage !== input.query.cursor + 1) ||
|
|
275
|
+
(page.branches.length < input.query.limit && page.nextPage !== null)
|
|
276
|
+
) {
|
|
277
|
+
throw new GitHubAppApiError("GitHub returned an invalid repository branches page");
|
|
278
|
+
}
|
|
279
|
+
const response = GitHubRepositoryBranchesResponseSchema.safeParse({
|
|
280
|
+
branches: page.branches.map((name) => ({
|
|
281
|
+
name,
|
|
282
|
+
isDefault: name === page.defaultBranch,
|
|
283
|
+
})),
|
|
284
|
+
nextCursor: page.nextPage,
|
|
285
|
+
});
|
|
286
|
+
if (!response.success) {
|
|
287
|
+
throw new GitHubAppApiError("GitHub returned an invalid repository branches page");
|
|
288
|
+
}
|
|
289
|
+
if (
|
|
290
|
+
!(await services.areRepositoriesAllowed(deps.db, input.workspaceId, input.installationId, [
|
|
291
|
+
input.repositoryId,
|
|
292
|
+
]))
|
|
293
|
+
) {
|
|
294
|
+
throw new GitHubRepositoryBranchAuthorityError("changed");
|
|
295
|
+
}
|
|
296
|
+
return response.data;
|
|
297
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { Permission } from "@opengeni/contracts";
|
|
2
|
+
import { verifiedDelegatedHumanAuthorizationForRequest } from "@opengeni/core";
|
|
3
|
+
import type { Context } from "hono";
|
|
4
|
+
import { HTTPException } from "hono/http-exception";
|
|
5
|
+
|
|
6
|
+
/* ----------------------------------------------------------------------------
|
|
7
|
+
An agent acting as a person: an organization MCP action this server
|
|
8
|
+
dispatched in process for someone who signed the agent in (see
|
|
9
|
+
organization-mcp.ts). Routes that otherwise need the person's browser
|
|
10
|
+
cookie accept it, within the connection's organization and access setting.
|
|
11
|
+
The person's live role is still checked by the route, exactly as for the
|
|
12
|
+
browser.
|
|
13
|
+
|
|
14
|
+
Only Opengeni sign-in, approving a connection, third-party provider consent
|
|
15
|
+
and account recovery stay in the browser; those routes don't call this.
|
|
16
|
+
-------------------------------------------------------------------------- */
|
|
17
|
+
|
|
18
|
+
export type ActingPerson = { subjectId: string };
|
|
19
|
+
|
|
20
|
+
/** True when this request is an agent acting as a person. */
|
|
21
|
+
export function isAgentActingAsPerson(c: Context): boolean {
|
|
22
|
+
return verifiedDelegatedHumanAuthorizationForRequest(c.req.raw) !== null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The person this agent acts as, for an action in `organizationId` that needs
|
|
27
|
+
* `permission`; null when the request is not an agent acting as a person.
|
|
28
|
+
* Another organization reads as not found; a permission the connection's
|
|
29
|
+
* access setting leaves out is refused.
|
|
30
|
+
*/
|
|
31
|
+
export function agentActingAsPerson(
|
|
32
|
+
c: Context,
|
|
33
|
+
organizationId: string,
|
|
34
|
+
permission: Permission,
|
|
35
|
+
): ActingPerson | null {
|
|
36
|
+
const proof = verifiedDelegatedHumanAuthorizationForRequest(c.req.raw);
|
|
37
|
+
if (!proof) return null;
|
|
38
|
+
if (proof.organizationId.toLowerCase() !== organizationId.toLowerCase()) {
|
|
39
|
+
throw new HTTPException(404, { message: "organization not found" });
|
|
40
|
+
}
|
|
41
|
+
if (!proof.permissions.includes(permission)) {
|
|
42
|
+
throw new HTTPException(403, {
|
|
43
|
+
message: `This connection's access doesn't include ${permission}.`,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
return { subjectId: proof.subjectId };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The person an agent acts as, with no organization or permission check here:
|
|
51
|
+
* only for a route that next requires this same person's workspace grant,
|
|
52
|
+
* which carries the connection's organization, workspaces and access.
|
|
53
|
+
*/
|
|
54
|
+
export function agentActingAsPersonBeforeGrantCheck(c: Context): ActingPerson | null {
|
|
55
|
+
const proof = verifiedDelegatedHumanAuthorizationForRequest(c.req.raw);
|
|
56
|
+
return proof ? { subjectId: proof.subjectId } : null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Organization settings: reading needs account:read, changing needs account:admin. */
|
|
60
|
+
export function organizationSettingsPermission(c: Context): Permission {
|
|
61
|
+
return c.req.method === "GET" || c.req.method === "HEAD" ? "account:read" : "account:admin";
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Refuse an agent on a browser-only step (provider consent, cross-organization actions). */
|
|
65
|
+
export function requireNotAgent(c: Context, what: string): void {
|
|
66
|
+
if (isAgentActingAsPerson(c)) {
|
|
67
|
+
throw new HTTPException(403, {
|
|
68
|
+
message: `${what} has to be done by the person in the Opengeni app in a browser.`,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { MiddlewareHandler } from "hono";
|
|
2
|
+
import { OPENGENI_API_CONTRACT_HEADER, OPENGENI_API_CONTRACT_REVISION } from "@opengeni/contracts";
|
|
3
|
+
|
|
4
|
+
const BEARER_AUTHORIZATION = /^bearer\s+\S/i;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Keep published SDKs working across additive contract-revision bumps.
|
|
8
|
+
*
|
|
9
|
+
* Every `@opengeni/sdk` release up to 7.x throws `OpenGeniApiContractMismatchError`
|
|
10
|
+
* on ANY response whose `x-opengeni-api-contract` header differs from the
|
|
11
|
+
* revision it was built with, reads included. The header exists to make a
|
|
12
|
+
* stale first-party browser tab reload (docs/design/api-compatibility-policy.md
|
|
13
|
+
* (e)); a backend integration pinned to an SDK version cannot reload, so the
|
|
14
|
+
* next additive revision bump would break every call it makes.
|
|
15
|
+
*
|
|
16
|
+
* For a bearer-authenticated caller (API key, delegated token) that announced a
|
|
17
|
+
* different revision, the response therefore omits the header instead of
|
|
18
|
+
* advertising one the caller is known to reject. Cookie/unauthenticated
|
|
19
|
+
* callers (the stock web app) keep it, and so does an explicit
|
|
20
|
+
* `API_CONTRACT_CHANGED` refusal, so a refused client can still explain the
|
|
21
|
+
* mismatch. This is not an authorization boundary: routes authorize as usual.
|
|
22
|
+
*/
|
|
23
|
+
export function bearerApiContractHeaderCompatibility(): MiddlewareHandler {
|
|
24
|
+
return async (context, next) => {
|
|
25
|
+
await next();
|
|
26
|
+
const claimed = context.req.header(OPENGENI_API_CONTRACT_HEADER);
|
|
27
|
+
if (claimed === undefined || claimed === OPENGENI_API_CONTRACT_REVISION) return;
|
|
28
|
+
if (!BEARER_AUTHORIZATION.test(context.req.header("authorization") ?? "")) return;
|
|
29
|
+
if (!context.res.headers.has(OPENGENI_API_CONTRACT_HEADER)) return;
|
|
30
|
+
if (context.res.status === 409 && (await isContractRefusal(context.res))) return;
|
|
31
|
+
try {
|
|
32
|
+
context.res.headers.delete(OPENGENI_API_CONTRACT_HEADER);
|
|
33
|
+
} catch {
|
|
34
|
+
// Immutable headers (a proxied or redirect response): copy once.
|
|
35
|
+
context.res = new Response(context.res.body, context.res);
|
|
36
|
+
context.res.headers.delete(OPENGENI_API_CONTRACT_HEADER);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async function isContractRefusal(response: Response): Promise<boolean> {
|
|
42
|
+
if (!/^application\/json/i.test(response.headers.get("content-type") ?? "")) return false;
|
|
43
|
+
try {
|
|
44
|
+
const body = (await response.clone().json()) as { code?: unknown };
|
|
45
|
+
return body?.code === "API_CONTRACT_CHANGED";
|
|
46
|
+
} catch {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
package/src/http/api-error.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
AgentConfigError,
|
|
3
|
+
AllowanceExhaustedRefusal,
|
|
4
|
+
ModelUnavailableError,
|
|
5
|
+
ScheduledTaskTargetAccessChange,
|
|
6
|
+
type ErrorCode,
|
|
7
|
+
} from "@opengeni/contracts";
|
|
8
|
+
import { WorkspaceControlBusyError } from "@opengeni/db";
|
|
2
9
|
import type { ContentfulStatusCode } from "hono/utils/http-status";
|
|
3
10
|
import { HTTPException } from "hono/http-exception";
|
|
4
11
|
|
|
@@ -6,6 +13,7 @@ type ApiHttpErrorOptions = {
|
|
|
6
13
|
code: ErrorCode;
|
|
7
14
|
message: string;
|
|
8
15
|
retryable?: boolean;
|
|
16
|
+
outcomeUnknown?: boolean;
|
|
9
17
|
details?: Record<string, unknown>;
|
|
10
18
|
};
|
|
11
19
|
|
|
@@ -13,6 +21,7 @@ type ApiHttpErrorOptions = {
|
|
|
13
21
|
export class ApiHttpError extends HTTPException {
|
|
14
22
|
readonly code: ErrorCode;
|
|
15
23
|
readonly retryable: boolean | undefined;
|
|
24
|
+
readonly outcomeUnknown: boolean | undefined;
|
|
16
25
|
readonly details: Record<string, unknown> | undefined;
|
|
17
26
|
|
|
18
27
|
constructor(status: number, options: ApiHttpErrorOptions) {
|
|
@@ -20,6 +29,111 @@ export class ApiHttpError extends HTTPException {
|
|
|
20
29
|
this.name = "ApiHttpError";
|
|
21
30
|
this.code = options.code;
|
|
22
31
|
this.retryable = options.retryable;
|
|
32
|
+
this.outcomeUnknown = options.outcomeUnknown;
|
|
23
33
|
this.details = options.details;
|
|
24
34
|
}
|
|
25
35
|
}
|
|
36
|
+
|
|
37
|
+
export function scheduledTaskTargetAccessHttpError(error: unknown): ApiHttpError | null {
|
|
38
|
+
if (!(error instanceof HTTPException) || error.status !== 409) return null;
|
|
39
|
+
const result = ScheduledTaskTargetAccessChange.safeParse(error.cause);
|
|
40
|
+
return result.success
|
|
41
|
+
? new ApiHttpError(409, {
|
|
42
|
+
code: "conflict",
|
|
43
|
+
message: error.message,
|
|
44
|
+
retryable: false,
|
|
45
|
+
outcomeUnknown: false,
|
|
46
|
+
details: result.data,
|
|
47
|
+
})
|
|
48
|
+
: null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Preserve typed admission details through the common public error envelope. */
|
|
52
|
+
export function allowanceExhaustedHttpError(error: unknown): ApiHttpError | null {
|
|
53
|
+
if (!(error instanceof HTTPException) || error.status !== 402) return null;
|
|
54
|
+
const parsed = AllowanceExhaustedRefusal.safeParse(
|
|
55
|
+
error.cause && typeof error.cause === "object"
|
|
56
|
+
? Object.fromEntries(Object.entries(error.cause).filter(([key]) => key !== "allowed"))
|
|
57
|
+
: error.cause,
|
|
58
|
+
);
|
|
59
|
+
if (!parsed.success) return null;
|
|
60
|
+
const { code, message, ...details } = parsed.data;
|
|
61
|
+
return new ApiHttpError(402, {
|
|
62
|
+
code,
|
|
63
|
+
message,
|
|
64
|
+
retryable: false,
|
|
65
|
+
outcomeUnknown: false,
|
|
66
|
+
details,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* A request-scoped session/workspace mutation could not enter the workspace
|
|
72
|
+
* control prefix within its bounded wait. The transaction rolled back before
|
|
73
|
+
* any write, so the outcome is known and the client may retry. `app.onError`
|
|
74
|
+
* applies this once for every route; Slack interactions keep the raw typed
|
|
75
|
+
* error so their retry classifier treats it as transient.
|
|
76
|
+
*/
|
|
77
|
+
export function workspaceControlBusyHttpError(error: unknown): ApiHttpError | null {
|
|
78
|
+
const busy =
|
|
79
|
+
error instanceof WorkspaceControlBusyError
|
|
80
|
+
? error
|
|
81
|
+
: error instanceof HTTPException && error.cause instanceof WorkspaceControlBusyError
|
|
82
|
+
? error.cause
|
|
83
|
+
: null;
|
|
84
|
+
if (!busy) return null;
|
|
85
|
+
return new ApiHttpError(503, {
|
|
86
|
+
code: "upstream_unavailable",
|
|
87
|
+
message: "The workspace is busy applying other session commands; retry shortly.",
|
|
88
|
+
retryable: true,
|
|
89
|
+
outcomeUnknown: false,
|
|
90
|
+
details: { code: busy.code, lockTimeoutMs: busy.lockTimeoutMs },
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* A typed agent-configuration failure (capability unavailable, conflict,
|
|
96
|
+
* widening, not enabled). Rendered as 422 validation_failed with the specific
|
|
97
|
+
* code in `details.code` so clients can branch without parsing messages.
|
|
98
|
+
*/
|
|
99
|
+
export function agentConfigHttpError(error: unknown): ApiHttpError | null {
|
|
100
|
+
const cause =
|
|
101
|
+
error instanceof AgentConfigError
|
|
102
|
+
? error
|
|
103
|
+
: error instanceof HTTPException && error.cause instanceof AgentConfigError
|
|
104
|
+
? error.cause
|
|
105
|
+
: null;
|
|
106
|
+
if (!cause) return null;
|
|
107
|
+
return new ApiHttpError(422, {
|
|
108
|
+
code: "validation_failed",
|
|
109
|
+
message: cause.message,
|
|
110
|
+
retryable: false,
|
|
111
|
+
details: {
|
|
112
|
+
code: cause.code,
|
|
113
|
+
...(cause.capability ? { capability: cause.capability } : {}),
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* The requested or stored model is not in the live catalog. Rendered as the
|
|
120
|
+
* same 422 `validation_failed` with its historical message, plus
|
|
121
|
+
* `details.code: "model_unavailable"` and the model id so clients can ask for
|
|
122
|
+
* another model rather than offer a retry that cannot succeed.
|
|
123
|
+
*/
|
|
124
|
+
export function modelUnavailableHttpError(error: unknown): ApiHttpError | null {
|
|
125
|
+
const cause =
|
|
126
|
+
error instanceof ModelUnavailableError
|
|
127
|
+
? error
|
|
128
|
+
: error instanceof HTTPException && error.cause instanceof ModelUnavailableError
|
|
129
|
+
? error.cause
|
|
130
|
+
: null;
|
|
131
|
+
if (!cause) return null;
|
|
132
|
+
return new ApiHttpError(422, {
|
|
133
|
+
code: "validation_failed",
|
|
134
|
+
message: cause.message,
|
|
135
|
+
retryable: false,
|
|
136
|
+
outcomeUnknown: false,
|
|
137
|
+
details: { code: cause.code, modelId: cause.modelId },
|
|
138
|
+
});
|
|
139
|
+
}
|
package/src/http/auth.ts
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import { resolveFirstPartyDelegationSecret, type Settings } from "@opengeni/config";
|
|
2
2
|
import { verifyDelegatedAccessToken } from "@opengeni/contracts";
|
|
3
|
+
import { verifiedDelegatedHumanAuthorizationForRequest } from "@opengeni/core";
|
|
3
4
|
import type { Context, MiddlewareHandler } from "hono";
|
|
5
|
+
import { ANALYTICS_CONSENT_PATH } from "../routes/analytics-consent";
|
|
6
|
+
import { CLIENT_ERRORS_PATH } from "../routes/client-errors";
|
|
4
7
|
import { installExactPaths, isInstallRedirectPath } from "../routes/install";
|
|
8
|
+
import {
|
|
9
|
+
isMcpOAuthPublicProtocolPath,
|
|
10
|
+
isMcpOAuthResourcePath,
|
|
11
|
+
mcpOAuthBearerToken,
|
|
12
|
+
} from "../mcp-oauth";
|
|
5
13
|
|
|
6
14
|
const githubConnectPathPattern = /^\/v1\/workspaces\/[^/]+\/github\/connect$/;
|
|
7
15
|
const githubInstallationLinkPathPattern = /^\/v1\/workspaces\/[^/]+\/github\/installations$/;
|
|
16
|
+
const prReviewGithubBrowserPathPattern =
|
|
17
|
+
/^\/v1\/workspaces\/[^/]+\/pr-review\/github\/(?:connect|installations\/select|installations\/[^/]+\/configure)$/;
|
|
8
18
|
|
|
9
19
|
export function requireAccessKey(settings: Settings): MiddlewareHandler {
|
|
10
20
|
return async (c, next) => {
|
|
@@ -30,16 +40,43 @@ function isAuthExempt(c: Context, settings: Settings): boolean {
|
|
|
30
40
|
if (c.req.method === "OPTIONS") {
|
|
31
41
|
return true;
|
|
32
42
|
}
|
|
43
|
+
// An organization MCP action dispatched in this process for a verified
|
|
44
|
+
// person. Only server code can stamp the exact Request object.
|
|
45
|
+
if (verifiedDelegatedHumanAuthorizationForRequest(c.req.raw)) {
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
33
48
|
const path = new URL(c.req.url).pathname;
|
|
49
|
+
if (settings.mcpOauthEnabled && isMcpOAuthPublicProtocolPath(path)) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
if (settings.mcpOauthEnabled && isMcpOAuthResourcePath(path) && mcpOAuthBearerToken(c.req.raw)) {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
34
55
|
if (path === "/v1/config/client") {
|
|
35
56
|
return true;
|
|
36
57
|
}
|
|
58
|
+
// The web error beacon must count failures before sign-in. Its payload is a
|
|
59
|
+
// closed, content-free report and the route bounds its own admission.
|
|
60
|
+
if (c.req.method === "POST" && path === CLIENT_ERRORS_PATH) {
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
// The analytics banner is answered before sign-in too. The report is one
|
|
64
|
+
// closed decision and the route bounds its own admission.
|
|
65
|
+
if (c.req.method === "POST" && path === ANALYTICS_CONSENT_PATH) {
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
37
68
|
if (path === "/v1/auth" || path.startsWith("/v1/auth/")) {
|
|
38
69
|
return true;
|
|
39
70
|
}
|
|
40
71
|
if (path === "/v1/webhooks/stripe") {
|
|
41
72
|
return true;
|
|
42
73
|
}
|
|
74
|
+
if (c.req.method === "POST" && path.startsWith("/v1/webhooks/automations/")) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
if (c.req.method === "POST" && path === "/v1/webhooks/pr-review/github") {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
43
80
|
if (
|
|
44
81
|
path === "/v1/github/setup" ||
|
|
45
82
|
path === "/v1/github/install/callback" ||
|
|
@@ -48,9 +85,17 @@ function isAuthExempt(c: Context, settings: Settings): boolean {
|
|
|
48
85
|
) {
|
|
49
86
|
return true;
|
|
50
87
|
}
|
|
88
|
+
if (
|
|
89
|
+
path === "/v1/pr-review/github/setup" ||
|
|
90
|
+
path === "/v1/pr-review/github/install/callback" ||
|
|
91
|
+
path === "/v1/pr-review/github/oauth/callback"
|
|
92
|
+
) {
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
51
95
|
if (
|
|
52
96
|
path === "/v1/integrations/oauth/callback" ||
|
|
53
97
|
path === "/v1/integrations/provider-oauth/callback" ||
|
|
98
|
+
path === "/v1/integrations/github-personal/oauth/callback" ||
|
|
54
99
|
path === "/v1/integrations/google-drive/callback" ||
|
|
55
100
|
path === "/v1/integrations/oauth/client-metadata.json" ||
|
|
56
101
|
path === "/v1/integrations/slack/callback" ||
|
|
@@ -79,6 +124,9 @@ function isAuthExempt(c: Context, settings: Settings): boolean {
|
|
|
79
124
|
if (githubConnectPathPattern.test(path)) {
|
|
80
125
|
return true;
|
|
81
126
|
}
|
|
127
|
+
if (prReviewGithubBrowserPathPattern.test(path)) {
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
82
130
|
// Compatibility endpoint for stale chooser submissions. It remains public
|
|
83
131
|
// only so already-rendered forms can authenticate their signed account and
|
|
84
132
|
// workspace state locally before terminating with 410; it does not parse a
|
package/src/http/cors.ts
CHANGED
|
@@ -1,3 +1,70 @@
|
|
|
1
|
+
import { HTTPException } from "hono/http-exception";
|
|
2
|
+
|
|
1
3
|
export function allowedCorsOrigin(pattern: string, origin: string): boolean {
|
|
2
4
|
return new RegExp(`^(?:${pattern})$`).test(origin);
|
|
3
5
|
}
|
|
6
|
+
|
|
7
|
+
export function validateInteractionRequestOrigin(
|
|
8
|
+
value: string | undefined,
|
|
9
|
+
input: {
|
|
10
|
+
corsAllowOriginRegex: string;
|
|
11
|
+
publicBaseUrl?: string | undefined;
|
|
12
|
+
webBaseUrl?: string | undefined;
|
|
13
|
+
},
|
|
14
|
+
): string | null {
|
|
15
|
+
if (!value) return null;
|
|
16
|
+
let url: URL;
|
|
17
|
+
try {
|
|
18
|
+
url = new URL(value);
|
|
19
|
+
} catch {
|
|
20
|
+
throw new HTTPException(400, { message: "invalid request origin" });
|
|
21
|
+
}
|
|
22
|
+
if (
|
|
23
|
+
url.origin === "null" ||
|
|
24
|
+
(url.protocol !== "http:" && url.protocol !== "https:") ||
|
|
25
|
+
url.origin !== value
|
|
26
|
+
) {
|
|
27
|
+
throw new HTTPException(400, { message: "invalid request origin" });
|
|
28
|
+
}
|
|
29
|
+
if (isConfiguredBrowserOrigin(url.origin, input)) {
|
|
30
|
+
return url.origin;
|
|
31
|
+
}
|
|
32
|
+
throw new HTTPException(403, { message: "request origin is not allowed" });
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
type BrowserOriginSettings = {
|
|
36
|
+
corsAllowOriginRegex: string;
|
|
37
|
+
publicBaseUrl?: string | undefined;
|
|
38
|
+
webBaseUrl?: string | undefined;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
function isConfiguredBrowserOrigin(origin: string, input: BrowserOriginSettings): boolean {
|
|
42
|
+
return (
|
|
43
|
+
allowedCorsOrigin(input.corsAllowOriginRegex, origin) ||
|
|
44
|
+
[input.publicBaseUrl, input.webBaseUrl].some((baseUrl) =>
|
|
45
|
+
baseUrl ? new URL(baseUrl).origin === origin : false,
|
|
46
|
+
)
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Whether a present `Origin` header names a browser origin this deployment
|
|
52
|
+
* serves its web app from: the CORS allowlist, the public base URL, or the
|
|
53
|
+
* separate web base URL. `null` and malformed values are never allowed.
|
|
54
|
+
*/
|
|
55
|
+
export function isAllowedBrowserOrigin(value: string, input: BrowserOriginSettings): boolean {
|
|
56
|
+
let url: URL;
|
|
57
|
+
try {
|
|
58
|
+
url = new URL(value);
|
|
59
|
+
} catch {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
if (
|
|
63
|
+
url.origin === "null" ||
|
|
64
|
+
(url.protocol !== "http:" && url.protocol !== "https:") ||
|
|
65
|
+
url.origin !== value
|
|
66
|
+
) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
return isConfiguredBrowserOrigin(url.origin, input);
|
|
70
|
+
}
|