@opengeni/api-router 3.0.1 → 3.0.2-canary.38894290271001
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 +8 -1
- package/dist/admission-trace.d.ts +8 -0
- package/dist/app.d.ts +50 -3
- package/dist/app.js +10 -1
- package/dist/artifact-catalog-cursor.d.ts +1 -0
- package/dist/attached-browser-viewer.d.ts +11 -0
- package/dist/auth/managed-auth-attempt-context.d.ts +2 -0
- package/dist/auth/managed-auth-rate-limits.d.ts +167 -0
- package/dist/auth/managed-auth-session-adapter.d.ts +9 -1
- package/dist/auth/managed-auth.d.ts +72 -5
- package/dist/auth/managed-sign-in-notifications.d.ts +4 -0
- package/dist/auth/new-signups-gate.d.ts +23 -0
- package/dist/auth/signup-funnel-metrics.d.ts +44 -0
- package/dist/azure-live.d.ts +28 -0
- package/dist/browser-action-fences.d.ts +13 -0
- package/dist/browser-controller-authority.d.ts +1 -61
- package/dist/browser-ephemeral.d.ts +5 -0
- package/dist/browser-lost-runtime-end.d.ts +24 -0
- package/dist/browser-state-authority.d.ts +1 -27
- package/dist/{chunk-AJ62T5QN.js → chunk-GBUJ2DYZ.js} +80507 -39878
- package/dist/chunk-GBUJ2DYZ.js.map +1 -0
- package/dist/chunk-OGQDXVXY.js +18 -0
- package/dist/chunk-OGQDXVXY.js.map +1 -0
- package/dist/claude-default-models.d.ts +19 -0
- package/dist/claude-subscription-core.d.ts +50 -0
- package/dist/claude-subscription-oauth.d.ts +36 -0
- package/dist/claude-subscription-profile.d.ts +9 -0
- package/dist/claude-subscription-usage.d.ts +6 -0
- package/dist/claude-workspace-connection.d.ts +15 -0
- package/dist/codemode.d.ts +40 -5
- package/dist/codex-realtime.d.ts +29 -3
- package/dist/codex-session-pointers.d.ts +19 -0
- package/dist/connection-ownership.d.ts +6 -3
- package/dist/controller-data-plane.d.ts +16 -0
- package/dist/credit-promotion-snapshot.d.ts +6 -0
- package/dist/editable-artifact-source-session.d.ts +3 -0
- package/dist/editable-artifact-websocket.d.ts +5 -3
- package/dist/fatal-process-boundary.d.ts +9 -1
- package/dist/github-access.d.ts +7 -1
- package/dist/github-browser-flow.d.ts +1 -1
- package/dist/http/acting-person.d.ts +36 -0
- package/dist/http/api-contract-compat.d.ts +19 -0
- package/dist/http/api-error.d.ts +50 -1
- package/dist/http/auth.d.ts +8 -1
- package/dist/http/cors.d.ts +12 -0
- package/dist/http/deprecation.d.ts +42 -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/rejection-telemetry.d.ts +34 -0
- package/dist/http/request-body.d.ts +27 -0
- package/dist/http/request-source.d.ts +41 -3
- package/dist/http/sse.d.ts +12 -1
- package/dist/http/unmatched-route.d.ts +18 -0
- package/dist/http/user-content.d.ts +36 -0
- package/dist/http/variable-sets-removed.d.ts +41 -0
- package/dist/http/websocket-upgrade-dispatch.d.ts +18 -0
- package/dist/index.js +1279 -108
- package/dist/index.js.map +1 -1
- package/dist/integration-connect-metrics.d.ts +35 -0
- package/dist/integration-endpoint-test.d.ts +20 -0
- package/dist/integrations/api-integrations.d.ts +2 -2
- package/dist/integrations/atlassian.d.ts +8 -3
- package/dist/integrations/fiken.d.ts +3 -1
- package/dist/integrations/github-lens-connect.d.ts +37 -66
- package/dist/integrations/google-drive.d.ts +2 -0
- package/dist/integrations/integration-commit-authority.d.ts +13 -0
- package/dist/integrations/marketplace-plugin.d.ts +43 -43
- package/dist/integrations/oauth-client.d.ts +171 -12
- package/dist/integrations/oauth-profiles.d.ts +42 -13
- package/dist/integrations/onepassword-vault-provider.d.ts +9 -0
- package/dist/integrations/slack-bot.d.ts +285 -7
- package/dist/integrations/slack-file-upload-flow.d.ts +62 -0
- package/dist/integrations/slack-interactions.d.ts +89 -10
- package/dist/integrations/slack-mrkdwn.d.ts +41 -0
- package/dist/integrations/slack-routing.d.ts +1 -1
- package/dist/integrations/slack-session-defaults.d.ts +58 -0
- package/dist/integrations/slack-task-file-upload.d.ts +36 -0
- package/dist/integrations/slack-tool-review.d.ts +5 -0
- package/dist/interaction-agent-access.d.ts +13 -8
- package/dist/interaction-agent-version.d.ts +21 -0
- package/dist/interaction-holder-heartbeat.d.ts +5 -0
- package/dist/interaction-metrics.d.ts +27 -2
- package/dist/interaction-route-stages.d.ts +25 -0
- package/dist/interaction-secrets-vault.d.ts +20 -0
- package/dist/interaction-secrets.d.ts +103 -0
- package/dist/mcp/action-catalog-types.d.ts +14 -0
- package/dist/mcp/action-catalog.gen.d.ts +2 -0
- package/dist/mcp/action-descriptions.d.ts +4 -0
- package/dist/mcp/action-schema-imports.gen.d.ts +1 -0
- package/dist/mcp/capability-account-readiness.d.ts +7 -0
- package/dist/mcp/child-read-evidence.d.ts +9 -0
- package/dist/mcp/company-profile-agent-admin.d.ts +12 -0
- package/dist/mcp/contract-input.d.ts +13 -0
- package/dist/mcp/documents.d.ts +2 -0
- package/dist/mcp/first-party-tool-permissions.d.ts +3 -606
- package/dist/mcp/notification-tools.d.ts +26 -0
- package/dist/mcp/orchestration-failure-diagnostic.d.ts +43 -0
- package/dist/mcp/scheduled-task-input.d.ts +1309 -0
- package/dist/mcp/scheduled-task-view.d.ts +217 -3
- package/dist/mcp/secret-tools.d.ts +14 -0
- package/dist/mcp/server.d.ts +108 -5
- package/dist/mcp/session-admin-access-tools.d.ts +33 -0
- package/dist/mcp/session-event-errors.d.ts +28 -0
- package/dist/mcp/session-event-view.d.ts +62 -0
- package/dist/mcp/session-view.d.ts +15 -0
- package/dist/mcp/session-wait.d.ts +18 -0
- package/dist/mcp/site-agent-clamp-tools.d.ts +38 -0
- package/dist/mcp/site-data-tools.d.ts +22 -0
- package/dist/mcp/site-publication-tools.d.ts +19 -0
- package/dist/mcp/site-sql-tools.d.ts +27 -0
- package/dist/mcp-oauth.d.ts +37 -4
- package/dist/model-calls/chat-completions.d.ts +87 -0
- package/dist/model-calls/pending-usage-settlements.d.ts +57 -0
- package/dist/model-calls/service.d.ts +36 -0
- package/dist/model-catalog.d.ts +9 -3
- package/dist/native-push-dispatch.d.ts +69 -0
- package/dist/observability.d.ts +3 -1
- package/dist/organization-mcp.d.ts +82 -0
- package/dist/prepared-mcp-actor.d.ts +77 -0
- package/dist/prepared-mcp-permissions.d.ts +8 -0
- package/dist/routes/analytics-consent.d.ts +26 -0
- package/dist/routes/api-integrations.d.ts +11 -0
- package/dist/routes/api-keys.d.ts +7 -7
- package/dist/routes/automations.d.ts +2 -0
- package/dist/routes/billing.d.ts +59 -0
- package/dist/routes/browser-sessions.d.ts +65 -2
- package/dist/routes/chat-completions.d.ts +11 -0
- package/dist/routes/claude-core-usage.d.ts +20 -0
- 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 +182 -0
- package/dist/routes/codex-core.d.ts +401 -0
- package/dist/routes/codex.d.ts +64 -2
- package/dist/routes/computer-sessions.d.ts +6 -1
- package/dist/routes/desktop-distribution.d.ts +32 -0
- package/dist/routes/github-browser-fonts.gen.d.ts +2 -0
- package/dist/routes/github-browser-pages.d.ts +27 -0
- package/dist/routes/inbox.d.ts +13 -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 +28 -0
- package/dist/routes/interaction-placement-message.d.ts +7 -0
- package/dist/routes/managed-sign-in-methods.d.ts +6 -0
- package/dist/routes/model-account-choice.d.ts +13 -0
- package/dist/routes/model-account-settings.d.ts +19 -0
- package/dist/routes/native-app-auth.d.ts +12 -0
- package/dist/routes/organization-integration-policy.d.ts +8 -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-defaults.d.ts +9 -0
- package/dist/routes/organization-service-accounts.d.ts +3 -0
- package/dist/routes/personal-api-keys.d.ts +3 -0
- package/dist/routes/session-admin-access.d.ts +3 -0
- package/dist/routes/session-artifact-associations.d.ts +4 -0
- package/dist/routes/session-history-imports.d.ts +20 -0
- package/dist/routes/sessions.d.ts +38 -2
- package/dist/routes/site-data.d.ts +18 -0
- package/dist/routes/site-publishing.d.ts +5 -0
- package/dist/routes/site-runtime.d.ts +31 -0
- package/dist/routes/site-sql.d.ts +16 -0
- package/dist/routes/slack-bot-access.d.ts +3 -0
- package/dist/routes/subscription-account-pools.d.ts +21 -0
- package/dist/routes/subscription-core-http.d.ts +5 -0
- package/dist/routes/subscription-pool-access.d.ts +37 -0
- package/dist/routes/subscription-pool-core.d.ts +153 -0
- package/dist/routes/supergrok.d.ts +6 -6
- package/dist/routes/usage-allowances.d.ts +12 -0
- package/dist/routes/variable-sets-removed.d.ts +2 -0
- package/dist/routes/vault-providers.d.ts +34 -0
- package/dist/routes/vaults.d.ts +3 -0
- package/dist/routes/workspace-integrations.d.ts +35 -0
- package/dist/routes/workspace-model-providers.d.ts +4 -0
- package/dist/routes/workspaces.d.ts +11 -2
- package/dist/sandbox/agent-update.d.ts +64 -0
- package/dist/sandbox/auth-callout.d.ts +8 -0
- package/dist/sandbox/channel-a.d.ts +15 -1
- package/dist/sandbox/enrollment.d.ts +26 -4
- package/dist/sandbox/machine-audience.d.ts +29 -0
- package/dist/sandbox/machines.d.ts +15 -2
- package/dist/sandbox/metrics-ingestion.d.ts +6 -2
- package/dist/sandbox/screen-control.d.ts +85 -0
- package/dist/sandbox/viewer.d.ts +5 -1
- package/dist/sandbox-file-artifacts.d.ts +17 -1
- package/dist/scheduled-task-blockers.d.ts +39 -0
- package/dist/scheduled-task-deletion.d.ts +3 -4
- package/dist/scheduled-task-lifecycle.d.ts +14 -0
- package/dist/secret-answers.d.ts +40 -0
- package/dist/session-create-observability.d.ts +5 -0
- package/dist/session-event-view-36GO3IL7.js +528 -0
- package/dist/session-event-view-36GO3IL7.js.map +1 -0
- package/dist/signed-state-secret.d.ts +18 -0
- package/dist/site-agent-guard.d.ts +53 -0
- package/dist/site-data/operations.d.ts +103 -0
- package/dist/site-data/service.d.ts +203 -0
- package/dist/site-frame-guard.d.ts +32 -0
- package/dist/site-publishing/agent-data-tools.d.ts +84 -0
- package/dist/site-publishing/agent-model.d.ts +58 -0
- package/dist/site-publishing/agent-session.d.ts +16 -0
- package/dist/site-publishing/content-scanner.d.ts +31 -0
- package/dist/site-publishing/edge-sync.d.ts +48 -0
- package/dist/site-publishing/gateway-signature.d.ts +56 -0
- package/dist/site-publishing/limits.d.ts +63 -0
- package/dist/site-publishing/page-tool-authority.d.ts +30 -0
- package/dist/site-publishing/platform-usage.d.ts +113 -0
- package/dist/site-publishing/platform.d.ts +21 -0
- package/dist/site-publishing/readiness.d.ts +62 -0
- package/dist/site-publishing/runtime.d.ts +179 -0
- package/dist/site-publishing/service.d.ts +264 -0
- package/dist/site-publishing/session-events.d.ts +22 -0
- package/dist/site-publishing/session-views.d.ts +36 -0
- package/dist/site-publishing/viewer.d.ts +40 -0
- package/dist/site-session-origin.d.ts +31 -6
- package/dist/site-sql/format.d.ts +47 -0
- package/dist/site-sql/gateway.d.ts +50 -0
- package/dist/site-sql/service.d.ts +213 -0
- package/dist/temporal-schedule-sync.d.ts +26 -0
- package/dist/transcription/billing-refusal.d.ts +8 -0
- package/dist/transcription/normalize.d.ts +23 -0
- package/dist/transcription/providers/azure-mai.d.ts +12 -0
- package/dist/transcription/providers/azure-openai.d.ts +4 -0
- package/dist/transcription/providers/openai.d.ts +16 -0
- package/dist/transcription/providers/subscription-core.d.ts +39 -0
- package/dist/transcription/service.d.ts +10 -1
- package/dist/transcription/wav-duration.d.ts +8 -0
- package/dist/workspace-tool-gateway-attestations.d.ts +37 -0
- package/dist/workspace-tool-gateway-observability.d.ts +16 -0
- package/dist/workspace-tool-gateway-secrets.d.ts +27 -0
- package/dist/workspace-tool-gateway.d.ts +102 -6
- package/dist/workspace-tool-target-fence.d.ts +116 -0
- package/dist/workspace-tool-target.d.ts +225 -0
- package/dist/workspace-webhook-dispatch.d.ts +26 -0
- package/dist/xai-subscription-core.d.ts +60 -0
- package/package.json +25 -20
- package/src/access-grant-rls.ts +64 -14
- package/src/admission-trace.ts +14 -0
- package/src/app.ts +1684 -252
- package/src/artifact-catalog-cursor.ts +1 -0
- package/src/attached-browser-viewer.ts +26 -0
- package/src/auth/managed-auth-attempt-context.ts +9 -0
- package/src/auth/managed-auth-rate-limits.ts +252 -0
- package/src/auth/managed-auth-session-adapter.ts +64 -29
- package/src/auth/managed-auth.ts +303 -35
- package/src/auth/managed-email.ts +18 -1
- 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 +3 -3
- package/src/auth/signup-funnel-metrics.ts +164 -0
- package/src/azure-live.ts +103 -0
- package/src/browser-action-fences.ts +45 -0
- package/src/browser-controller-authority.ts +1 -186
- package/src/browser-ephemeral.ts +39 -0
- package/src/browser-lost-runtime-end.ts +71 -0
- package/src/browser-state-authority.ts +1 -236
- package/src/claude-default-models.ts +37 -0
- package/src/claude-subscription-core.ts +154 -0
- package/src/claude-subscription-oauth.ts +352 -0
- package/src/claude-subscription-profile.ts +73 -0
- package/src/claude-subscription-usage.ts +51 -0
- package/src/claude-workspace-connection.ts +82 -0
- package/src/codemode.ts +236 -39
- package/src/codex-realtime.ts +181 -53
- package/src/codex-session-pointers.ts +80 -0
- package/src/company-brain-okf.ts +1 -1
- package/src/connected-machine-computer-access.ts +2 -1
- package/src/connection-ownership.ts +19 -13
- package/src/controller-data-plane.ts +34 -0
- package/src/credit-promotion-snapshot.ts +36 -0
- package/src/editable-artifact-production.ts +10 -0
- package/src/editable-artifact-source-session.ts +123 -0
- package/src/editable-artifact-websocket.ts +16 -3
- package/src/fatal-process-boundary.ts +67 -3
- package/src/gateway-realtime.ts +12 -8
- package/src/github-access.ts +31 -5
- package/src/github-browser-flow.ts +1 -1
- package/src/http/acting-person.ts +105 -0
- package/src/http/api-contract-compat.ts +49 -0
- package/src/http/api-error.ts +210 -2
- package/src/http/auth.ts +68 -4
- package/src/http/cors.ts +37 -5
- package/src/http/deprecation.ts +118 -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/rejection-telemetry.ts +120 -0
- package/src/http/request-body.ts +127 -0
- package/src/http/request-source.ts +154 -13
- package/src/http/sse.ts +88 -28
- package/src/http/unmatched-route.ts +60 -0
- package/src/http/user-content.ts +158 -0
- package/src/http/variable-sets-removed.ts +122 -0
- package/src/http/websocket-upgrade-dispatch.ts +29 -0
- package/src/index.ts +107 -57
- package/src/integration-connect-metrics.ts +228 -0
- package/src/integration-endpoint-test.ts +291 -0
- package/src/integrations/api-integrations.ts +81 -7
- package/src/integrations/atlassian.ts +202 -83
- package/src/integrations/fiken.ts +66 -38
- package/src/integrations/github-app-connect.ts +64 -18
- package/src/integrations/github-lens-connect.ts +8 -29
- package/src/integrations/google-drive.ts +448 -152
- package/src/integrations/integration-commit-authority.ts +69 -0
- package/src/integrations/marketplace-plugin.ts +1 -1
- package/src/integrations/oauth-client.ts +733 -193
- package/src/integrations/oauth-profiles.ts +116 -45
- package/src/integrations/onepassword-vault-provider.ts +16 -0
- package/src/integrations/personal-github-repositories.ts +1 -1
- package/src/integrations/personal-github.ts +61 -35
- package/src/integrations/provider-oauth.ts +67 -85
- package/src/integrations/slack-app-home.ts +5 -5
- package/src/integrations/slack-bot.ts +893 -201
- package/src/integrations/slack-file-upload-flow.ts +147 -0
- package/src/integrations/slack-install.ts +7 -7
- package/src/integrations/slack-interactions.ts +1589 -299
- package/src/integrations/slack-mrkdwn.ts +193 -0
- package/src/integrations/slack-routing.ts +2 -2
- package/src/integrations/slack-session-defaults.ts +224 -0
- package/src/integrations/slack-task-file-upload.ts +323 -0
- package/src/integrations/slack-tool-review.ts +65 -0
- package/src/integrations/social-oauth.ts +90 -58
- package/src/interaction-agent-access.ts +40 -20
- package/src/interaction-agent-version.ts +85 -0
- package/src/interaction-holder-heartbeat.ts +24 -8
- package/src/interaction-metrics.ts +164 -2
- package/src/interaction-route-stages.ts +94 -0
- package/src/interaction-secrets-vault.ts +213 -0
- package/src/interaction-secrets.ts +426 -0
- package/src/mcp/action-catalog-types.ts +14 -0
- package/src/mcp/action-catalog.gen.ts +8014 -0
- package/src/mcp/action-descriptions.ts +299 -0
- package/src/mcp/action-schema-imports.gen.ts +304 -0
- package/src/mcp/capability-account-readiness.ts +17 -0
- package/src/mcp/child-read-evidence.ts +19 -0
- package/src/mcp/company-profile-agent-admin.ts +13 -0
- package/src/mcp/contract-input.ts +165 -0
- package/src/mcp/documents.ts +9 -2
- package/src/mcp/editable-artifacts.ts +29 -11
- package/src/mcp/files.ts +5 -1
- package/src/mcp/first-party-tool-permissions.ts +7 -285
- package/src/mcp/knowledge-entries.ts +108 -34
- package/src/mcp/notification-tools.ts +480 -0
- package/src/mcp/orchestration-failure-diagnostic.ts +43 -0
- package/src/mcp/scheduled-task-input.ts +89 -0
- package/src/mcp/scheduled-task-view.ts +63 -3
- package/src/mcp/secret-tools.ts +185 -0
- package/src/mcp/server.ts +2213 -1116
- package/src/mcp/session-admin-access-tools.ts +163 -0
- package/src/mcp/session-event-errors.ts +123 -0
- package/src/mcp/session-event-view.ts +395 -13
- package/src/mcp/session-view.ts +3 -0
- package/src/mcp/session-wait.ts +67 -7
- package/src/mcp/site-agent-clamp-tools.ts +140 -0
- package/src/mcp/site-data-tools.ts +339 -0
- package/src/mcp/site-publication-tools.ts +201 -0
- package/src/mcp/site-sql-tools.ts +427 -0
- package/src/mcp-oauth.ts +635 -45
- package/src/model-calls/chat-completions.ts +352 -0
- package/src/model-calls/pending-usage-settlements.ts +125 -0
- package/src/model-calls/service.ts +694 -0
- package/src/model-catalog.ts +68 -17
- package/src/native-push-dispatch.ts +457 -0
- package/src/observability.ts +15 -1
- package/src/organization-mcp.ts +485 -0
- package/src/prepared-mcp-actor.ts +154 -0
- package/src/prepared-mcp-permissions.ts +38 -0
- package/src/routes/analytics-consent.ts +123 -0
- package/src/routes/api-integrations.ts +268 -9
- package/src/routes/api-keys.ts +164 -25
- package/src/routes/artifact-catalog.ts +111 -0
- package/src/routes/automations.ts +163 -90
- package/src/routes/billing.ts +535 -59
- package/src/routes/browser-sessions.ts +966 -342
- package/src/routes/canonical-human-identities.ts +61 -0
- package/src/routes/capabilities.ts +112 -5
- package/src/routes/channels.ts +4 -3
- package/src/routes/chat-completions.ts +235 -0
- package/src/routes/claude-core-usage.ts +147 -0
- package/src/routes/claude-subscription-accounts.ts +233 -0
- package/src/routes/claude-subscription-oauth.ts +175 -0
- package/src/routes/client-errors.ts +394 -0
- package/src/routes/codex-core.ts +687 -0
- package/src/routes/codex.ts +1277 -1119
- package/src/routes/company-brain.ts +4 -0
- package/src/routes/computer-sessions.ts +319 -85
- package/src/routes/connect.ts +277 -175
- package/src/routes/connections.ts +690 -363
- package/src/routes/desktop-distribution.ts +217 -0
- package/src/routes/documents.ts +13 -7
- package/src/routes/editable-artifacts.ts +74 -4
- package/src/routes/enrollments.ts +110 -16
- package/src/routes/external-identity-links.ts +13 -12
- package/src/routes/files.ts +41 -16
- package/src/routes/github-browser-fonts.gen.ts +12 -0
- package/src/routes/github-browser-pages.ts +258 -0
- package/src/routes/github.ts +200 -75
- package/src/routes/inbox.ts +353 -0
- package/src/routes/insights-response-cache.ts +83 -0
- package/src/routes/insights-usage.ts +345 -0
- package/src/routes/insights.ts +103 -8
- package/src/routes/install.ts +51 -10
- package/src/routes/integration-facets.ts +70 -28
- package/src/routes/interaction-placement-message.ts +12 -0
- package/src/routes/knowledge.ts +136 -27
- package/src/routes/machines.ts +189 -135
- package/src/routes/managed-auth-session-sets.ts +43 -10
- package/src/routes/managed-onboarding.ts +39 -19
- package/src/routes/managed-sign-in-methods.ts +433 -0
- package/src/routes/memory-slack-publications.ts +3 -2
- package/src/routes/model-account-choice.ts +194 -0
- package/src/routes/model-account-settings.ts +235 -0
- package/src/routes/model-connection-access.ts +210 -48
- package/src/routes/native-app-auth.ts +296 -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 +183 -0
- package/src/routes/organization-memberships.ts +205 -19
- package/src/routes/organization-model-defaults.ts +110 -0
- package/src/routes/organization-model-providers.ts +74 -3
- package/src/routes/organization-service-accounts.ts +128 -0
- package/src/routes/organization-sessions.ts +21 -5
- package/src/routes/personal-api-keys.ts +184 -0
- package/src/routes/personal-github-git-broker.ts +2 -2
- package/src/routes/personal-github.ts +9 -4
- package/src/routes/plugins.ts +46 -7
- package/src/routes/pr-review-github.ts +105 -118
- package/src/routes/pr-review.ts +88 -82
- package/src/routes/preference-registry.ts +18 -0
- package/src/routes/rigs.ts +48 -13
- package/src/routes/scheduled-tasks.ts +347 -27
- package/src/routes/session-admin-access.ts +271 -0
- package/src/routes/session-artifact-associations.ts +164 -0
- package/src/routes/session-history-imports.ts +305 -0
- package/src/routes/sessions.ts +1682 -363
- package/src/routes/site-data.ts +340 -0
- package/src/routes/site-publishing.ts +584 -0
- package/src/routes/site-runtime.ts +1944 -0
- package/src/routes/site-sql.ts +263 -0
- package/src/routes/skill-content.ts +72 -7
- package/src/routes/skills.ts +5 -4
- package/src/routes/slack-bot-access.ts +108 -0
- package/src/routes/social.ts +27 -15
- package/src/routes/subscription-account-pools.ts +209 -0
- package/src/routes/subscription-core-http.ts +18 -0
- package/src/routes/subscription-pool-access.ts +180 -0
- package/src/routes/subscription-pool-core.ts +552 -0
- package/src/routes/supergrok.ts +174 -655
- package/src/routes/transcription-recordings.ts +71 -4
- package/src/routes/transcriptions.ts +26 -2
- package/src/routes/usage-allowances.ts +381 -0
- package/src/routes/variable-sets-removed.ts +19 -0
- package/src/routes/vault-providers.ts +782 -0
- package/src/routes/vaults.ts +421 -0
- package/src/routes/video-generation.ts +30 -12
- package/src/routes/workspace-artifacts.ts +165 -53
- package/src/routes/workspace-integrations.ts +576 -0
- package/src/routes/workspace-model-providers.ts +148 -0
- package/src/routes/workspace-state.ts +4 -0
- package/src/routes/workspaces.ts +625 -117
- package/src/sandbox/agent-update.ts +315 -0
- package/src/sandbox/auth-callout.ts +104 -21
- package/src/sandbox/channel-a.ts +150 -49
- package/src/sandbox/enrollment.ts +131 -22
- package/src/sandbox/machine-audience.ts +192 -0
- package/src/sandbox/machines.ts +75 -31
- package/src/sandbox/metrics-ingestion.ts +133 -2
- package/src/sandbox/rematerialize.ts +51 -21
- package/src/sandbox/screen-control.ts +289 -0
- package/src/sandbox/viewer.ts +33 -58
- package/src/sandbox-file-artifacts.ts +53 -27
- package/src/scheduled-task-blockers.ts +293 -0
- package/src/scheduled-task-deletion.ts +13 -3
- package/src/scheduled-task-lifecycle.ts +84 -0
- package/src/secret-answers.ts +119 -0
- package/src/session-create-observability.ts +46 -0
- package/src/session-realtime-context.ts +26 -4
- package/src/signed-state-secret.ts +58 -0
- package/src/site-agent-guard.ts +261 -0
- package/src/site-data/operations.ts +777 -0
- package/src/site-data/service.ts +1043 -0
- package/src/site-frame-guard.ts +107 -0
- package/src/site-publishing/agent-data-tools.ts +250 -0
- package/src/site-publishing/agent-model.ts +127 -0
- package/src/site-publishing/agent-session.ts +148 -0
- package/src/site-publishing/content-scanner.ts +93 -0
- package/src/site-publishing/edge-sync.ts +148 -0
- package/src/site-publishing/gateway-signature.ts +198 -0
- package/src/site-publishing/limits.ts +315 -0
- package/src/site-publishing/page-tool-authority.ts +111 -0
- package/src/site-publishing/platform-usage.ts +479 -0
- package/src/site-publishing/platform.ts +98 -0
- package/src/site-publishing/readiness.ts +330 -0
- package/src/site-publishing/runtime.ts +831 -0
- package/src/site-publishing/service.ts +1282 -0
- package/src/site-publishing/session-events.ts +262 -0
- package/src/site-publishing/session-views.ts +262 -0
- package/src/site-publishing/viewer.ts +75 -0
- package/src/site-session-origin.ts +91 -6
- package/src/site-sql/format.ts +134 -0
- package/src/site-sql/gateway.ts +168 -0
- package/src/site-sql/service.ts +1636 -0
- package/src/site-uploads.ts +27 -5
- package/src/temporal-schedule-sync.ts +74 -0
- package/src/transcription/billing-refusal.ts +14 -0
- package/src/transcription/normalize.ts +77 -0
- package/src/transcription/providers/azure-mai.ts +98 -0
- package/src/transcription/providers/azure-openai.ts +16 -7
- package/src/transcription/providers/codex-subscription.ts +190 -67
- package/src/transcription/providers/openai.ts +79 -5
- package/src/transcription/providers/subscription-core.ts +125 -0
- package/src/transcription/providers/xai-subscription.ts +81 -83
- package/src/transcription/segmenter.ts +7 -1
- package/src/transcription/service.ts +239 -10
- package/src/transcription/wav-duration.ts +39 -0
- package/src/workspace-deletion.ts +25 -1
- package/src/workspace-tool-gateway-attestations.ts +133 -0
- package/src/workspace-tool-gateway-observability.ts +64 -0
- package/src/workspace-tool-gateway-secrets.ts +104 -0
- package/src/workspace-tool-gateway.ts +921 -103
- package/src/workspace-tool-target-fence.ts +380 -0
- package/src/workspace-tool-target.ts +554 -0
- package/src/workspace-webhook-dispatch.ts +225 -0
- package/src/xai-realtime.ts +85 -81
- package/src/xai-subscription-core.ts +172 -0
- package/dist/browser-auth-broker.d.ts +0 -20
- package/dist/chunk-AJ62T5QN.js.map +0 -1
- package/dist/connection-authority-owner.d.ts +0 -59
- package/dist/routes/connection-authorities.d.ts +0 -3
- package/dist/routes/environments.d.ts +0 -5
- package/dist/routes/host-mcp-bindings.d.ts +0 -5
- package/dist/routes/host-mcp-resolvers.d.ts +0 -3
- package/dist/routes/packs.d.ts +0 -3
- package/dist/session-event-view-MU3HMNV3.js +0 -264
- package/dist/session-event-view-MU3HMNV3.js.map +0 -1
- package/dist/xai-subscription-auth.d.ts +0 -23
- package/src/browser-auth-broker.ts +0 -155
- package/src/connection-authority-owner.ts +0 -61
- package/src/routes/connection-authorities.ts +0 -139
- package/src/routes/environments.ts +0 -388
- package/src/routes/host-mcp-bindings.ts +0 -122
- package/src/routes/host-mcp-resolvers.ts +0 -41
- package/src/routes/packs.ts +0 -784
- package/src/xai-subscription-auth.ts +0 -139
package/src/github-access.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import {
|
|
2
|
+
defaultRepositoryMountPath,
|
|
3
|
+
type GitHubAppRepositoryBranchPage,
|
|
4
|
+
type GitHubBindingStatus,
|
|
5
|
+
type GitHubInstallationBinding,
|
|
6
|
+
type GitHubRepository,
|
|
7
|
+
type RepositoryResourceRef,
|
|
6
8
|
} from "@opengeni/contracts";
|
|
7
9
|
import {
|
|
8
10
|
GitHubRepositoryBranchesResponse as GitHubRepositoryBranchesResponseSchema,
|
|
@@ -200,6 +202,30 @@ export async function listWorkspaceGitHubRepositories(
|
|
|
200
202
|
});
|
|
201
203
|
}
|
|
202
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
|
+
|
|
203
229
|
export async function listWorkspaceGitHubRepositoryBranches(
|
|
204
230
|
deps: ApiRouteDeps,
|
|
205
231
|
input: {
|
|
@@ -5,7 +5,7 @@ import type { GitHubSignedStatePayload } from "@opengeni/github";
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Bounded configured-token browser handoff. These signed claims preserve only
|
|
8
|
-
* the exact
|
|
8
|
+
* the exact Opengeni github:manage grant across GitHub redirects; the callback
|
|
9
9
|
* independently proves current GitHub personal/organization ownership. This
|
|
10
10
|
* state must never be interpreted as GitHub installation authority.
|
|
11
11
|
*/
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { organizationAccessPresetPermissions, 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, or who gave a
|
|
9
|
+
session admin access (see organization-mcp.ts). Routes that otherwise need
|
|
10
|
+
the person's browser cookie accept it, within the organization and the
|
|
11
|
+
access the person gave it. The person's live role is still checked by the
|
|
12
|
+
route, exactly as for the browser.
|
|
13
|
+
|
|
14
|
+
With the person's full access, the agent can do what the person can in that
|
|
15
|
+
organization, including approving agent sign-ins, managing connected agents
|
|
16
|
+
and giving sessions admin access. An agent with less can't do those, so it
|
|
17
|
+
can never widen its own access. Only Opengeni sign-in itself, sign-in
|
|
18
|
+
methods and recovery, and provider sign-in pages (Claude, integration
|
|
19
|
+
OAuth) stay in the browser. Device-code sign-in (Codex, SuperGrok) is
|
|
20
|
+
allowed: the agent relays the code and the person approves at the provider.
|
|
21
|
+
-------------------------------------------------------------------------- */
|
|
22
|
+
|
|
23
|
+
export type ActingPerson = { subjectId: string };
|
|
24
|
+
|
|
25
|
+
/** True when this request is an agent acting as a person. */
|
|
26
|
+
export function isAgentActingAsPerson(c: Context): boolean {
|
|
27
|
+
return verifiedDelegatedHumanAuthorizationForRequest(c.req.raw) !== null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The person this agent acts as, for an action in `organizationId` that needs
|
|
32
|
+
* `permission`; null when the request is not an agent acting as a person.
|
|
33
|
+
* Another organization reads as not found; a permission the connection's
|
|
34
|
+
* access setting leaves out is refused.
|
|
35
|
+
*/
|
|
36
|
+
export function agentActingAsPerson(
|
|
37
|
+
c: Context,
|
|
38
|
+
organizationId: string,
|
|
39
|
+
permission: Permission,
|
|
40
|
+
): ActingPerson | null {
|
|
41
|
+
const proof = verifiedDelegatedHumanAuthorizationForRequest(c.req.raw);
|
|
42
|
+
if (!proof) return null;
|
|
43
|
+
if (proof.organizationId.toLowerCase() !== organizationId.toLowerCase()) {
|
|
44
|
+
throw new HTTPException(404, { message: "organization not found" });
|
|
45
|
+
}
|
|
46
|
+
if (!proof.permissions.includes(permission)) {
|
|
47
|
+
throw new HTTPException(403, {
|
|
48
|
+
message: `This connection's access doesn't include ${permission}.`,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
return { subjectId: proof.subjectId };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The person an agent acts as, with no organization or permission check here:
|
|
56
|
+
* only for a route that next requires this same person's workspace grant,
|
|
57
|
+
* which carries the connection's organization, workspaces and access.
|
|
58
|
+
*/
|
|
59
|
+
export function agentActingAsPersonBeforeGrantCheck(c: Context): ActingPerson | null {
|
|
60
|
+
const proof = verifiedDelegatedHumanAuthorizationForRequest(c.req.raw);
|
|
61
|
+
return proof ? { subjectId: proof.subjectId } : null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const FULL_ACCESS = organizationAccessPresetPermissions("full");
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* True when this request is an agent with the person's full access: every
|
|
68
|
+
* permission, in every workspace. Session admin access always is; a connected
|
|
69
|
+
* agent is when the person chose full access for it.
|
|
70
|
+
*/
|
|
71
|
+
export function isAgentWithFullAccess(c: Context): boolean {
|
|
72
|
+
const proof = verifiedDelegatedHumanAuthorizationForRequest(c.req.raw);
|
|
73
|
+
return (
|
|
74
|
+
proof !== null &&
|
|
75
|
+
proof.workspaceScope.kind === "all" &&
|
|
76
|
+
FULL_ACCESS.every((permission) => proof.permissions.includes(permission))
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Refuse an agent with less than the person's full access on a step that
|
|
82
|
+
* gives or approves access (agent sign-ins, connected agents, admin access),
|
|
83
|
+
* so it can never widen its own. The person and a full-access agent pass.
|
|
84
|
+
*/
|
|
85
|
+
export function requireFullAccessIfAgent(c: Context, what: string): void {
|
|
86
|
+
if (isAgentActingAsPerson(c) && !isAgentWithFullAccess(c)) {
|
|
87
|
+
throw new HTTPException(403, {
|
|
88
|
+
message: `${what} needs full access, and this agent's access is limited. The person can do it in the Opengeni app.`,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Organization settings: reading needs account:read, changing needs account:admin. */
|
|
94
|
+
export function organizationSettingsPermission(c: Context): Permission {
|
|
95
|
+
return c.req.method === "GET" || c.req.method === "HEAD" ? "account:read" : "account:admin";
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Refuse an agent on a step that only works in a browser: signing in at a provider's own page. */
|
|
99
|
+
export function requireNotAgent(c: Context, what: string): void {
|
|
100
|
+
if (isAgentActingAsPerson(c)) {
|
|
101
|
+
throw new HTTPException(403, {
|
|
102
|
+
message: `${what} has to be done by the person in the Opengeni app in a browser.`,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -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,5 +1,17 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
AgentConfigError,
|
|
3
|
+
AllowanceExhaustedRefusal,
|
|
4
|
+
ModelUnavailableError,
|
|
5
|
+
ScheduledTaskTargetAccessChange,
|
|
6
|
+
type ErrorCode,
|
|
7
|
+
} from "@opengeni/contracts";
|
|
8
|
+
import {
|
|
9
|
+
isDatabaseConnectionLoss,
|
|
10
|
+
SessionUsageLimitUnavailableError,
|
|
11
|
+
nestedPostgresSqlState,
|
|
12
|
+
WorkspaceControlBusyError,
|
|
13
|
+
} from "@opengeni/db";
|
|
14
|
+
import { SessionUsageLimitHttpError, sessionUsageLimitRefusalFromError } from "@opengeni/core";
|
|
3
15
|
import type { ContentfulStatusCode } from "hono/utils/http-status";
|
|
4
16
|
import { HTTPException } from "hono/http-exception";
|
|
5
17
|
|
|
@@ -28,6 +40,99 @@ export class ApiHttpError extends HTTPException {
|
|
|
28
40
|
}
|
|
29
41
|
}
|
|
30
42
|
|
|
43
|
+
export function scheduledTaskTargetAccessHttpError(error: unknown): ApiHttpError | null {
|
|
44
|
+
if (!(error instanceof HTTPException) || error.status !== 409) return null;
|
|
45
|
+
const result = ScheduledTaskTargetAccessChange.safeParse(error.cause);
|
|
46
|
+
return result.success
|
|
47
|
+
? new ApiHttpError(409, {
|
|
48
|
+
code: "conflict",
|
|
49
|
+
message: error.message,
|
|
50
|
+
retryable: false,
|
|
51
|
+
outcomeUnknown: false,
|
|
52
|
+
details: result.data,
|
|
53
|
+
})
|
|
54
|
+
: null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Preserve typed admission details through the common public error envelope. */
|
|
58
|
+
export function allowanceExhaustedHttpError(error: unknown): ApiHttpError | null {
|
|
59
|
+
if (!(error instanceof HTTPException) || error.status !== 402) return null;
|
|
60
|
+
const parsed = AllowanceExhaustedRefusal.safeParse(
|
|
61
|
+
error.cause && typeof error.cause === "object"
|
|
62
|
+
? Object.fromEntries(Object.entries(error.cause).filter(([key]) => key !== "allowed"))
|
|
63
|
+
: error.cause,
|
|
64
|
+
);
|
|
65
|
+
if (!parsed.success) return null;
|
|
66
|
+
const { code, message, ...details } = parsed.data;
|
|
67
|
+
return new ApiHttpError(402, {
|
|
68
|
+
code,
|
|
69
|
+
message,
|
|
70
|
+
retryable: false,
|
|
71
|
+
outcomeUnknown: false,
|
|
72
|
+
details,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const SESSION_USAGE_LIMIT_ERROR_CODES: Record<SessionUsageLimitHttpError["code"], ErrorCode> = {
|
|
77
|
+
session_usage_limit_conflict: "conflict",
|
|
78
|
+
session_usage_limit_not_root: "conflict",
|
|
79
|
+
session_usage_limit_preparing: "conflict",
|
|
80
|
+
session_usage_limit_disabled: "validation_failed",
|
|
81
|
+
session_usage_limit_forbidden: "forbidden",
|
|
82
|
+
session_usage_limit_unavailable: "upstream_unavailable",
|
|
83
|
+
session_not_found: "not_found",
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Per-task usage limits. A reached root limit is a non-retryable 402
|
|
88
|
+
* `session_usage_limit_reached` whose details carry only the public refusal
|
|
89
|
+
* fields; it is never `allowance_exhausted`, `payment_required` or a purchase
|
|
90
|
+
* prompt. Limit writes map to stable `details.code` values. Unreadable usage
|
|
91
|
+
* state is a retryable 503 that was not applied (never unlimited).
|
|
92
|
+
*/
|
|
93
|
+
export function sessionUsageLimitHttpError(error: unknown): ApiHttpError | null {
|
|
94
|
+
const refusal = sessionUsageLimitRefusalFromError(error);
|
|
95
|
+
if (refusal) {
|
|
96
|
+
return new ApiHttpError(402, {
|
|
97
|
+
code: "session_usage_limit_reached",
|
|
98
|
+
message: refusal.message,
|
|
99
|
+
retryable: false,
|
|
100
|
+
outcomeUnknown: false,
|
|
101
|
+
details: {
|
|
102
|
+
basis: refusal.basis,
|
|
103
|
+
rootSessionId: refusal.rootSessionId,
|
|
104
|
+
limitMicros: refusal.limitMicros,
|
|
105
|
+
usedMicros: refusal.usedMicros,
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
if (error instanceof SessionUsageLimitHttpError) {
|
|
110
|
+
return new ApiHttpError(error.status, {
|
|
111
|
+
code: SESSION_USAGE_LIMIT_ERROR_CODES[error.code],
|
|
112
|
+
message: error.message,
|
|
113
|
+
retryable: error.code === "session_usage_limit_unavailable",
|
|
114
|
+
outcomeUnknown: false,
|
|
115
|
+
details: { ...error.details, code: error.code },
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
const unavailable =
|
|
119
|
+
error instanceof SessionUsageLimitUnavailableError
|
|
120
|
+
? error
|
|
121
|
+
: error instanceof HTTPException && error.cause instanceof SessionUsageLimitUnavailableError
|
|
122
|
+
? error.cause
|
|
123
|
+
: null;
|
|
124
|
+
if (unavailable) {
|
|
125
|
+
return new ApiHttpError(503, {
|
|
126
|
+
code: "upstream_unavailable",
|
|
127
|
+
message: "Usage for this task is temporarily unavailable. Try again shortly.",
|
|
128
|
+
retryable: true,
|
|
129
|
+
outcomeUnknown: false,
|
|
130
|
+
details: { code: "session_usage_limit_unavailable" },
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
|
|
31
136
|
/**
|
|
32
137
|
* A request-scoped session/workspace mutation could not enter the workspace
|
|
33
138
|
* control prefix within its bounded wait. The transaction rolled back before
|
|
@@ -51,3 +156,106 @@ export function workspaceControlBusyHttpError(error: unknown): ApiHttpError | nu
|
|
|
51
156
|
details: { code: busy.code, lockTimeoutMs: busy.lockTimeoutMs },
|
|
52
157
|
});
|
|
53
158
|
}
|
|
159
|
+
|
|
160
|
+
/** `details.code` of the retryable 503 for a request whose database connection was lost. */
|
|
161
|
+
export const DATABASE_UNAVAILABLE_ERROR_DETAIL_CODE = "DATABASE_UNAVAILABLE";
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* The request's database connection went away (an operator drain, failover,
|
|
165
|
+
* restart, or socket loss) rather than the statement being rejected. That is a
|
|
166
|
+
* brief, retryable outage, not an internal error. A read is safe to repeat. A
|
|
167
|
+
* mutation's outcome is unknown: the connection may have dropped after COMMIT,
|
|
168
|
+
* or after an earlier transaction of the same request committed, so the client
|
|
169
|
+
* must reconcile by its own idempotency key before resending.
|
|
170
|
+
*/
|
|
171
|
+
export function databaseUnavailableHttpError(error: unknown, method: string): ApiHttpError | null {
|
|
172
|
+
if (error instanceof ApiHttpError) return null;
|
|
173
|
+
if (error instanceof HTTPException && error.status < 500) return null;
|
|
174
|
+
if (!isDatabaseConnectionLoss(error)) return null;
|
|
175
|
+
const safeMethod = method === "GET" || method === "HEAD" || method === "OPTIONS";
|
|
176
|
+
return new ApiHttpError(503, {
|
|
177
|
+
code: "upstream_unavailable",
|
|
178
|
+
message: "Opengeni is temporarily unavailable. Retry shortly.",
|
|
179
|
+
retryable: true,
|
|
180
|
+
outcomeUnknown: !safeMethod,
|
|
181
|
+
details: { code: DATABASE_UNAVAILABLE_ERROR_DETAIL_CODE },
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/** `details.code` of the retryable 503 for a deadlock/serialization victim. */
|
|
186
|
+
export const DATABASE_CONTENTION_ERROR_DETAIL_CODE = "DATABASE_CONTENTION";
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* PostgreSQL aborted the request's transaction as a deadlock (40P01) or
|
|
190
|
+
* serialization (40001) victim after any in-process retry was exhausted. The
|
|
191
|
+
* aborted transaction committed nothing, so this is transient contention, not
|
|
192
|
+
* an internal error. A read is safe to repeat. For a mutation the default is
|
|
193
|
+
* `outcomeUnknown` because an earlier transaction of the same request may have
|
|
194
|
+
* committed; a route whose only write is the aborted idempotent transaction
|
|
195
|
+
* passes `outcomeUnknown: false`.
|
|
196
|
+
*/
|
|
197
|
+
export function databaseContentionHttpError(
|
|
198
|
+
error: unknown,
|
|
199
|
+
method: string,
|
|
200
|
+
options: { outcomeUnknown?: boolean } = {},
|
|
201
|
+
): ApiHttpError | null {
|
|
202
|
+
if (error instanceof ApiHttpError) return null;
|
|
203
|
+
if (error instanceof HTTPException && error.status < 500) return null;
|
|
204
|
+
const sqlState = nestedPostgresSqlState(error);
|
|
205
|
+
if (sqlState !== "40P01" && sqlState !== "40001") return null;
|
|
206
|
+
const safeMethod = method === "GET" || method === "HEAD" || method === "OPTIONS";
|
|
207
|
+
return new ApiHttpError(503, {
|
|
208
|
+
code: "upstream_unavailable",
|
|
209
|
+
message: "Opengeni hit transient database contention. Retry shortly.",
|
|
210
|
+
retryable: true,
|
|
211
|
+
outcomeUnknown: options.outcomeUnknown ?? !safeMethod,
|
|
212
|
+
details: { code: DATABASE_CONTENTION_ERROR_DETAIL_CODE, sqlState },
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* A typed agent-configuration failure (capability unavailable, conflict,
|
|
218
|
+
* widening, not enabled). Rendered as 422 validation_failed with the specific
|
|
219
|
+
* code in `details.code` so clients can branch without parsing messages.
|
|
220
|
+
*/
|
|
221
|
+
export function agentConfigHttpError(error: unknown): ApiHttpError | null {
|
|
222
|
+
const cause =
|
|
223
|
+
error instanceof AgentConfigError
|
|
224
|
+
? error
|
|
225
|
+
: error instanceof HTTPException && error.cause instanceof AgentConfigError
|
|
226
|
+
? error.cause
|
|
227
|
+
: null;
|
|
228
|
+
if (!cause) return null;
|
|
229
|
+
return new ApiHttpError(422, {
|
|
230
|
+
code: "validation_failed",
|
|
231
|
+
message: cause.message,
|
|
232
|
+
retryable: false,
|
|
233
|
+
details: {
|
|
234
|
+
code: cause.code,
|
|
235
|
+
...(cause.capability ? { capability: cause.capability } : {}),
|
|
236
|
+
},
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* The requested or stored model is not in the live catalog. Rendered as the
|
|
242
|
+
* same 422 `validation_failed` with its historical message, plus
|
|
243
|
+
* `details.code: "model_unavailable"` and the model id so clients can ask for
|
|
244
|
+
* another model rather than offer a retry that cannot succeed.
|
|
245
|
+
*/
|
|
246
|
+
export function modelUnavailableHttpError(error: unknown): ApiHttpError | null {
|
|
247
|
+
const cause =
|
|
248
|
+
error instanceof ModelUnavailableError
|
|
249
|
+
? error
|
|
250
|
+
: error instanceof HTTPException && error.cause instanceof ModelUnavailableError
|
|
251
|
+
? error.cause
|
|
252
|
+
: null;
|
|
253
|
+
if (!cause) return null;
|
|
254
|
+
return new ApiHttpError(422, {
|
|
255
|
+
code: "validation_failed",
|
|
256
|
+
message: cause.message,
|
|
257
|
+
retryable: false,
|
|
258
|
+
outcomeUnknown: false,
|
|
259
|
+
details: { code: cause.code, modelId: cause.modelId },
|
|
260
|
+
});
|
|
261
|
+
}
|
package/src/http/auth.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
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";
|
|
7
|
+
import { isDesktopDistributionPath } from "../routes/desktop-distribution";
|
|
4
8
|
import { installExactPaths, isInstallRedirectPath } from "../routes/install";
|
|
5
9
|
import {
|
|
6
10
|
isMcpOAuthPublicProtocolPath,
|
|
@@ -9,6 +13,15 @@ import {
|
|
|
9
13
|
} from "../mcp-oauth";
|
|
10
14
|
|
|
11
15
|
const githubConnectPathPattern = /^\/v1\/workspaces\/[^/]+\/github\/connect$/;
|
|
16
|
+
// The Connected Machine agent's own protocol. A machine never holds the
|
|
17
|
+
// deployment key; each route authenticates its own enroll token, device code,
|
|
18
|
+
// or signed install-key proof, and is rate limited by its route.
|
|
19
|
+
const connectedMachineProtocolPaths = new Set([
|
|
20
|
+
"/v1/enrollments/token/exchange",
|
|
21
|
+
"/v1/enrollments/device/start",
|
|
22
|
+
"/v1/enrollments/device/poll",
|
|
23
|
+
"/v1/enrollments/renew",
|
|
24
|
+
]);
|
|
12
25
|
const githubInstallationLinkPathPattern = /^\/v1\/workspaces\/[^/]+\/github\/installations$/;
|
|
13
26
|
const prReviewGithubBrowserPathPattern =
|
|
14
27
|
/^\/v1\/workspaces\/[^/]+\/pr-review\/github\/(?:connect|installations\/select|installations\/[^/]+\/configure)$/;
|
|
@@ -18,7 +31,7 @@ export function requireAccessKey(settings: Settings): MiddlewareHandler {
|
|
|
18
31
|
// §7.2 P1: requireAccessKey is the coarse NETWORK perimeter, not the
|
|
19
32
|
// per-tenant identity gate (that is resolveAccessContext). When
|
|
20
33
|
// `authRequired:false` it is a NO-OP — the embedded (Path 2) case where the
|
|
21
|
-
// host's own auth is the sole human gate and
|
|
34
|
+
// host's own auth is the sole human gate and Opengeni is mounted behind it.
|
|
22
35
|
// Standalone/separate deployments set `authRequired:true` to keep this ON as
|
|
23
36
|
// the shared-deployment-key perimeter.
|
|
24
37
|
if (!settings.authRequired || isAuthExempt(c, settings)) {
|
|
@@ -37,6 +50,11 @@ function isAuthExempt(c: Context, settings: Settings): boolean {
|
|
|
37
50
|
if (c.req.method === "OPTIONS") {
|
|
38
51
|
return true;
|
|
39
52
|
}
|
|
53
|
+
// An organization MCP action dispatched in this process for a verified
|
|
54
|
+
// person. Only server code can stamp the exact Request object.
|
|
55
|
+
if (verifiedDelegatedHumanAuthorizationForRequest(c.req.raw)) {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
40
58
|
const path = new URL(c.req.url).pathname;
|
|
41
59
|
if (settings.mcpOauthEnabled && isMcpOAuthPublicProtocolPath(path)) {
|
|
42
60
|
return true;
|
|
@@ -47,6 +65,21 @@ function isAuthExempt(c: Context, settings: Settings): boolean {
|
|
|
47
65
|
if (path === "/v1/config/client") {
|
|
48
66
|
return true;
|
|
49
67
|
}
|
|
68
|
+
// The Site gateway authenticates every site-runtime call with its own
|
|
69
|
+
// signature, which the routes verify before anything else.
|
|
70
|
+
if (path === "/v1/site-runtime" || path.startsWith("/v1/site-runtime/")) {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
// The web error beacon must count failures before sign-in. Its payload is a
|
|
74
|
+
// closed, content-free report and the route bounds its own admission.
|
|
75
|
+
if (c.req.method === "POST" && path === CLIENT_ERRORS_PATH) {
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
// The analytics banner is answered before sign-in too. The report is one
|
|
79
|
+
// closed decision and the route bounds its own admission.
|
|
80
|
+
if (c.req.method === "POST" && path === ANALYTICS_CONSENT_PATH) {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
50
83
|
if (path === "/v1/auth" || path.startsWith("/v1/auth/")) {
|
|
51
84
|
return true;
|
|
52
85
|
}
|
|
@@ -117,9 +150,18 @@ function isAuthExempt(c: Context, settings: Settings): boolean {
|
|
|
117
150
|
return true;
|
|
118
151
|
}
|
|
119
152
|
// The get.<domain> install-serving routes (install.sh/.ps1/uninstall.sh/
|
|
120
|
-
// minisign pub + the release-binary redirects)
|
|
121
|
-
// with no credentials; the bodies carry no secrets.
|
|
122
|
-
if (
|
|
153
|
+
// minisign pub + the release-binary redirects) and the desktop app downloads.
|
|
154
|
+
// Reached by a fresh machine with no credentials; the bodies carry no secrets.
|
|
155
|
+
if (
|
|
156
|
+
installExactPaths.has(path) ||
|
|
157
|
+
isInstallRedirectPath(path) ||
|
|
158
|
+
isDesktopDistributionPath(path)
|
|
159
|
+
) {
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
// Without this a key-protected deployment could never enroll or renew a
|
|
163
|
+
// machine. Human approval and lookup stay behind the key.
|
|
164
|
+
if (c.req.method === "POST" && connectedMachineProtocolPaths.has(path)) {
|
|
123
165
|
return true;
|
|
124
166
|
}
|
|
125
167
|
if (
|
|
@@ -163,6 +205,28 @@ async function isAuthorized(c: Context, settings: Settings): Promise<boolean> {
|
|
|
163
205
|
);
|
|
164
206
|
}
|
|
165
207
|
|
|
208
|
+
/**
|
|
209
|
+
* A request to a key-only (configured) deployment that presents the deployment
|
|
210
|
+
* key itself, from the operator rather than an agent acting for someone. The
|
|
211
|
+
* key travels in a request header that a page on another site can't add, so
|
|
212
|
+
* browser same-origin checks have nothing to protect on such a request.
|
|
213
|
+
*/
|
|
214
|
+
export function isConfiguredDeploymentKeyRequest(c: Context, settings: Settings): boolean {
|
|
215
|
+
const expected = settings.accessKey;
|
|
216
|
+
if (settings.productAccessMode !== "configured" || !settings.authRequired || !expected) {
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
if (verifiedDelegatedHumanAuthorizationForRequest(c.req.raw) !== null) return false;
|
|
220
|
+
const authorization = c.req.header("authorization");
|
|
221
|
+
const bearer = authorization?.startsWith("Bearer ")
|
|
222
|
+
? authorization.slice("Bearer ".length)
|
|
223
|
+
: undefined;
|
|
224
|
+
return (
|
|
225
|
+
constantTimeEqual(c.req.header("x-opengeni-access-key"), expected) ||
|
|
226
|
+
constantTimeEqual(bearer, expected)
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
|
|
166
230
|
function constantTimeEqual(actual: string | undefined, expected: string): boolean {
|
|
167
231
|
if (typeof actual !== "string") {
|
|
168
232
|
return false;
|
package/src/http/cors.ts
CHANGED
|
@@ -26,13 +26,45 @@ export function validateInteractionRequestOrigin(
|
|
|
26
26
|
) {
|
|
27
27
|
throw new HTTPException(400, { message: "invalid request origin" });
|
|
28
28
|
}
|
|
29
|
-
if (
|
|
30
|
-
|
|
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) ||
|
|
31
44
|
[input.publicBaseUrl, input.webBaseUrl].some((baseUrl) =>
|
|
32
|
-
baseUrl ? new URL(baseUrl).origin ===
|
|
45
|
+
baseUrl ? new URL(baseUrl).origin === origin : false,
|
|
33
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
|
|
34
66
|
) {
|
|
35
|
-
return
|
|
67
|
+
return false;
|
|
36
68
|
}
|
|
37
|
-
|
|
69
|
+
return isConfiguredBrowserOrigin(url.origin, input);
|
|
38
70
|
}
|