@opengeni/api-router 3.0.1 → 3.1.2
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-OGQDXVXY.js +18 -0
- package/dist/chunk-OGQDXVXY.js.map +1 -0
- package/dist/{chunk-AJ62T5QN.js → chunk-OT56OY4V.js} +80503 -39869
- package/dist/chunk-OT56OY4V.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 +165 -55
- 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
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
normalizeMimeType,
|
|
16
16
|
requireAccessGrant,
|
|
17
17
|
TRANSCRIPTION_PROVIDER_REQUEST_TIMEOUT_MILLISECONDS,
|
|
18
|
+
TranscriptionBillingRefusedError,
|
|
18
19
|
TranscriptionServiceError,
|
|
19
20
|
type ApiRouteDeps,
|
|
20
21
|
} from "@opengeni/core";
|
|
@@ -45,10 +46,13 @@ import {
|
|
|
45
46
|
TranscriptionRecordingStateError,
|
|
46
47
|
isSessionEventPersistenceError,
|
|
47
48
|
} from "@opengeni/db";
|
|
48
|
-
import { getWorkspace } from "@opengeni/db";
|
|
49
|
+
import { getWorkspace, type CreditDebitAttribution } from "@opengeni/db";
|
|
49
50
|
import type { Context, Hono } from "hono";
|
|
51
|
+
import { creditDebitAttributionForGrant } from "../access-grant-rls";
|
|
50
52
|
import { ApiHttpError } from "../http/api-error";
|
|
53
|
+
import { wavDurationSeconds } from "../transcription/wav-duration";
|
|
51
54
|
import { TranscriptionSegmenterError } from "../transcription/segmenter";
|
|
55
|
+
import { transcriptionBillingRefusal } from "../transcription/billing-refusal";
|
|
52
56
|
|
|
53
57
|
const CHUNK_SHA256_HEADER = "x-opengeni-chunk-sha256";
|
|
54
58
|
const CHUNK_START_HEADER = "x-opengeni-chunk-start-milliseconds";
|
|
@@ -60,6 +64,8 @@ type RecordingAuthority = {
|
|
|
60
64
|
workspaceId: string;
|
|
61
65
|
subjectId: string;
|
|
62
66
|
voiceInput?: WorkspaceVoiceInputSettings | undefined;
|
|
67
|
+
/** Trusted payer for deployment-funded segments. */
|
|
68
|
+
attribution: CreditDebitAttribution;
|
|
63
69
|
};
|
|
64
70
|
|
|
65
71
|
class RecordingProcessingError extends Error {
|
|
@@ -370,6 +376,8 @@ export function registerResumableTranscriptionRoutes(app: Hono, deps: ApiRouteDe
|
|
|
370
376
|
!(await service.available({
|
|
371
377
|
workspaceId: authority.workspaceId,
|
|
372
378
|
subjectId: authority.subjectId,
|
|
379
|
+
preferredProvider: authority.voiceInput?.preferredProvider,
|
|
380
|
+
fallbackEnabled: authority.voiceInput?.fallbackEnabled,
|
|
373
381
|
}))
|
|
374
382
|
) {
|
|
375
383
|
return c.json({ code: "unavailable" }, 503);
|
|
@@ -420,6 +428,37 @@ export function registerResumableTranscriptionRoutes(app: Hono, deps: ApiRouteDe
|
|
|
420
428
|
false,
|
|
421
429
|
);
|
|
422
430
|
}
|
|
431
|
+
const segmentProviderId =
|
|
432
|
+
claim.segment.providerId && claim.segment.providerId !== "host"
|
|
433
|
+
? claim.segment.providerId
|
|
434
|
+
: null;
|
|
435
|
+
// Credit admission for the exact pinned provider, before the durable
|
|
436
|
+
// provider-start fence. A refusal releases the claim untouched (no
|
|
437
|
+
// audio sent) and surfaces 402 so the client stops retrying.
|
|
438
|
+
if (segmentProviderId && service.admit) {
|
|
439
|
+
try {
|
|
440
|
+
await service.admit({
|
|
441
|
+
providerId: segmentProviderId,
|
|
442
|
+
accountId: authority.accountId,
|
|
443
|
+
workspaceId: authority.workspaceId,
|
|
444
|
+
attribution: authority.attribution,
|
|
445
|
+
});
|
|
446
|
+
} catch (error) {
|
|
447
|
+
if (!(error instanceof TranscriptionBillingRefusedError)) throw error;
|
|
448
|
+
await failTranscriptionRecordingSegment(deps.db, {
|
|
449
|
+
workspaceId: authority.workspaceId,
|
|
450
|
+
subjectId: authority.subjectId,
|
|
451
|
+
recordingId: uuidParam(c, "recordingId"),
|
|
452
|
+
segmentNumber,
|
|
453
|
+
attemptId,
|
|
454
|
+
fallbackProviderId: null,
|
|
455
|
+
// The real refusal, so a reloaded recording still explains it.
|
|
456
|
+
errorCode: error.code,
|
|
457
|
+
retryable: true,
|
|
458
|
+
}).catch(() => null);
|
|
459
|
+
return transcriptionBillingRefusal(c, error);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
423
462
|
const providerStartedAt = new Date();
|
|
424
463
|
const providerDeadlineAt = new Date(
|
|
425
464
|
providerStartedAt.getTime() + TRANSCRIPTION_PROVIDER_REQUEST_TIMEOUT_MILLISECONDS,
|
|
@@ -442,10 +481,22 @@ export function registerResumableTranscriptionRoutes(app: Hono, deps: ApiRouteDe
|
|
|
442
481
|
durationSeconds: claim.segment.durationMilliseconds / 1_000,
|
|
443
482
|
requestId: attemptId,
|
|
444
483
|
providerDeadlineAt,
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
484
|
+
deferBillingSettlement: true,
|
|
485
|
+
...(segmentProviderId ? { providerId: segmentProviderId } : {}),
|
|
486
|
+
billing: {
|
|
487
|
+
// One settlement per prepared segment of this exact recording,
|
|
488
|
+
// however many provider attempts it takes. The recording id is
|
|
489
|
+
// client-chosen, so the unit id also binds its server creation
|
|
490
|
+
// time and the server-produced segment bytes.
|
|
491
|
+
sourceId: `${claim.recording.recording.id}:${Date.parse(claim.recording.recording.createdAt)}:${segmentNumber}:${claim.segment.sha256}`,
|
|
492
|
+
attribution: authority.attribution,
|
|
493
|
+
trustedDurationSeconds: wavDurationSeconds(stored.bytes) ?? undefined,
|
|
494
|
+
},
|
|
448
495
|
});
|
|
496
|
+
// The transcript commits first and on its own: a billing failure can
|
|
497
|
+
// never roll back text the user already waited for. Only the attempt
|
|
498
|
+
// that durably completed the segment settles it (a stale attempt is
|
|
499
|
+
// refused here and never charges); settlement itself never throws.
|
|
449
500
|
const completed = await completeTranscriptionRecordingSegment(deps.db, {
|
|
450
501
|
workspaceId: authority.workspaceId,
|
|
451
502
|
subjectId: authority.subjectId,
|
|
@@ -456,6 +507,9 @@ export function registerResumableTranscriptionRoutes(app: Hono, deps: ApiRouteDe
|
|
|
456
507
|
languages: result.languages,
|
|
457
508
|
providerId: claim.segment.providerId ?? result.providerId,
|
|
458
509
|
});
|
|
510
|
+
// Never rejects for the built-in service (it logs and retries); a
|
|
511
|
+
// custom service's failure must not turn a durable transcript into an error.
|
|
512
|
+
await result.settleBilling?.().catch(() => undefined);
|
|
459
513
|
return c.json(await cleanupTerminalObjects(deps, authority, completed));
|
|
460
514
|
} catch (error) {
|
|
461
515
|
if (authority && attemptId && segmentNumber !== null) {
|
|
@@ -489,6 +543,11 @@ export function registerResumableTranscriptionRoutes(app: Hono, deps: ApiRouteDe
|
|
|
489
543
|
errorCode: failure.code,
|
|
490
544
|
retryable: failure.retryable,
|
|
491
545
|
}).catch(() => null);
|
|
546
|
+
// A credit refusal sent no audio; the released segment stays
|
|
547
|
+
// retryable, but the client must see the definitive refusal.
|
|
548
|
+
if (error instanceof TranscriptionBillingRefusedError) {
|
|
549
|
+
return transcriptionBillingRefusal(c, error);
|
|
550
|
+
}
|
|
492
551
|
if (persisted) return c.json(persisted);
|
|
493
552
|
}
|
|
494
553
|
return routeError(c, error);
|
|
@@ -545,6 +604,7 @@ async function requireRecordingAuthority(
|
|
|
545
604
|
accountId: grant.accountId,
|
|
546
605
|
workspaceId,
|
|
547
606
|
subjectId: grant.subjectId,
|
|
607
|
+
attribution: creditDebitAttributionForGrant(grant),
|
|
548
608
|
};
|
|
549
609
|
}
|
|
550
610
|
|
|
@@ -641,6 +701,10 @@ function processingFailure(error: unknown): {
|
|
|
641
701
|
if (error instanceof TranscriptionSegmenterError) {
|
|
642
702
|
return { code: error.code, retryable: error.retryable };
|
|
643
703
|
}
|
|
704
|
+
if (error instanceof TranscriptionBillingRefusedError) {
|
|
705
|
+
// Refused before any audio was sent; retryable once the payer is funded.
|
|
706
|
+
return { code: error.code, retryable: true };
|
|
707
|
+
}
|
|
644
708
|
if (error instanceof TranscriptionServiceError) {
|
|
645
709
|
return {
|
|
646
710
|
code: error.code,
|
|
@@ -663,6 +727,9 @@ function routeError(c: Context, error: unknown): Response | Promise<Response> {
|
|
|
663
727
|
if (error instanceof TranscriptionRecordingNotFoundError) {
|
|
664
728
|
return c.json({ code: "not_found" }, 404);
|
|
665
729
|
}
|
|
730
|
+
if (error instanceof TranscriptionBillingRefusedError) {
|
|
731
|
+
return transcriptionBillingRefusal(c, error);
|
|
732
|
+
}
|
|
666
733
|
if (error instanceof TranscriptionRecordingConflictError) {
|
|
667
734
|
return c.json({ code: "conflict" }, 409);
|
|
668
735
|
}
|
|
@@ -3,9 +3,16 @@ import {
|
|
|
3
3
|
WorkspaceVoiceInputSettings,
|
|
4
4
|
type TranscribeAudioResponse,
|
|
5
5
|
} from "@opengeni/contracts";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
type ApiRouteDeps,
|
|
8
|
+
requireAccessGrant,
|
|
9
|
+
TranscriptionBillingRefusedError,
|
|
10
|
+
TranscriptionServiceError,
|
|
11
|
+
} from "@opengeni/core";
|
|
7
12
|
import { getWorkspace } from "@opengeni/db";
|
|
8
13
|
import type { Hono } from "hono";
|
|
14
|
+
import { creditDebitAttributionForGrant } from "../access-grant-rls";
|
|
15
|
+
import { transcriptionBillingRefusal } from "../transcription/billing-refusal";
|
|
9
16
|
import { registerResumableTranscriptionRoutes } from "./transcription-recordings";
|
|
10
17
|
|
|
11
18
|
export function registerTranscriptionRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
@@ -20,12 +27,26 @@ export function registerTranscriptionRoutes(app: Hono, deps: ApiRouteDeps): void
|
|
|
20
27
|
}
|
|
21
28
|
const preferences = WorkspaceVoiceInputSettings.safeParse(workspace.settings.voiceInput).data;
|
|
22
29
|
const service = deps.transcription;
|
|
23
|
-
if (
|
|
30
|
+
if (
|
|
31
|
+
!service ||
|
|
32
|
+
!(await service.available({
|
|
33
|
+
workspaceId,
|
|
34
|
+
subjectId: grant.subjectId,
|
|
35
|
+
preferredProvider: preferences?.preferredProvider,
|
|
36
|
+
fallbackEnabled: preferences?.fallbackEnabled,
|
|
37
|
+
}))
|
|
38
|
+
) {
|
|
24
39
|
return c.json({ code: "unavailable" }, 503);
|
|
25
40
|
}
|
|
26
41
|
try {
|
|
27
42
|
const body = await audioRequest(c.req.raw, service.limits().maxSizeBytes);
|
|
43
|
+
// Server-generated: the correlation id is client-chosen and a reused
|
|
44
|
+
// settlement key would make every later call with it free.
|
|
28
45
|
const result = await service.transcribe({
|
|
46
|
+
billing: {
|
|
47
|
+
sourceId: crypto.randomUUID(),
|
|
48
|
+
attribution: creditDebitAttributionForGrant(grant),
|
|
49
|
+
},
|
|
29
50
|
preferredProvider: preferences?.preferredProvider,
|
|
30
51
|
fallbackEnabled: preferences?.fallbackEnabled,
|
|
31
52
|
workspaceId,
|
|
@@ -46,6 +67,9 @@ export function registerTranscriptionRoutes(app: Hono, deps: ApiRouteDeps): void
|
|
|
46
67
|
if (error instanceof TranscriptionServiceError) {
|
|
47
68
|
return c.json({ code: error.code }, error.status as never);
|
|
48
69
|
}
|
|
70
|
+
if (error instanceof TranscriptionBillingRefusedError) {
|
|
71
|
+
return transcriptionBillingRefusal(c, error);
|
|
72
|
+
}
|
|
49
73
|
if (isAbort(error)) return c.json({ code: "cancelled" }, 499 as never);
|
|
50
74
|
return c.json({ code: "unknown" }, 500);
|
|
51
75
|
}
|
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
import type { Context, Hono } from "hono";
|
|
2
|
+
import { HTTPException } from "hono/http-exception";
|
|
3
|
+
import {
|
|
4
|
+
ClearWorkspaceAllowanceRequest,
|
|
5
|
+
GetMyUsageRequest,
|
|
6
|
+
GetUsageRequest,
|
|
7
|
+
GrantWorkspaceCreditsRequest,
|
|
8
|
+
SetMemberAllowanceRequest,
|
|
9
|
+
SetWorkspaceAllowanceRequest,
|
|
10
|
+
WorkspaceAllowance,
|
|
11
|
+
WorkspaceAllowanceState,
|
|
12
|
+
WorkspaceCreditGrant,
|
|
13
|
+
WorkspaceUsageResponse,
|
|
14
|
+
MemberAllowance,
|
|
15
|
+
ClearWorkspaceAllowanceResponse,
|
|
16
|
+
type AccessContext,
|
|
17
|
+
} from "@opengeni/contracts";
|
|
18
|
+
import { ExternalIdentityReference } from "@opengeni/contracts/external-identities";
|
|
19
|
+
import {
|
|
20
|
+
accountScopedApiKeyWorkspaceAuthority,
|
|
21
|
+
accessGrantAuthorizationFromContext,
|
|
22
|
+
requireAccountAdminAuthorizationStamp,
|
|
23
|
+
requireAccessContext,
|
|
24
|
+
requireAccessGrantAuthorization,
|
|
25
|
+
requireResolvedAccessGrantAuthorization,
|
|
26
|
+
type AccessGrantAuthorization,
|
|
27
|
+
type ApiRouteDeps,
|
|
28
|
+
} from "@opengeni/core";
|
|
29
|
+
import {
|
|
30
|
+
clearWorkspaceAllowance,
|
|
31
|
+
findWorkspaceByExternalIdentity,
|
|
32
|
+
getWorkspaceAllowance,
|
|
33
|
+
getWorkspaceAllowanceState,
|
|
34
|
+
getWorkspace,
|
|
35
|
+
getWorkspaceUsage,
|
|
36
|
+
grantWorkspaceCredits,
|
|
37
|
+
nestedPostgresSqlState,
|
|
38
|
+
setMemberAllowance,
|
|
39
|
+
setWorkspaceAllowance,
|
|
40
|
+
withAccountRls,
|
|
41
|
+
UsageAllowanceVersionConflictError,
|
|
42
|
+
} from "@opengeni/db";
|
|
43
|
+
import { parseRequestBody, parseRequestJson } from "../http/request-body";
|
|
44
|
+
|
|
45
|
+
type Authority = { authorization: AccessGrantAuthorization; context: AccessContext };
|
|
46
|
+
type Operation = "read" | "budget-read" | "workspace-write" | "member-write" | "own";
|
|
47
|
+
|
|
48
|
+
/** No workspace wildcard, service initiator, or actor label can confer budget authority. */
|
|
49
|
+
export function requireAllowanceAuthority(
|
|
50
|
+
{ authorization, context }: Authority,
|
|
51
|
+
operation: Operation,
|
|
52
|
+
): void {
|
|
53
|
+
const grant = requireResolvedAccessGrantAuthorization(
|
|
54
|
+
authorization,
|
|
55
|
+
authorization.grant.workspaceId,
|
|
56
|
+
);
|
|
57
|
+
if (grant.principalKind === "agent_attempt" || grant.metadata?.sessionId !== undefined) {
|
|
58
|
+
throw new HTTPException(403, { message: "Agents cannot access usage allowances" });
|
|
59
|
+
}
|
|
60
|
+
const organizationKey = accountScopedApiKeyWorkspaceAuthority(context);
|
|
61
|
+
const sameOrganizationKey =
|
|
62
|
+
organizationKey?.accountId === grant.accountId ? organizationKey : null;
|
|
63
|
+
const accountAdmin =
|
|
64
|
+
authorization.accountGrant?.permissions.includes("account:admin") === true &&
|
|
65
|
+
requireAccountAdminAuthorizationStamp(authorization).accountId === grant.accountId;
|
|
66
|
+
const workspaceAdmin = grant.permissions.includes("workspace:admin");
|
|
67
|
+
if (
|
|
68
|
+
sameOrganizationKey?.permissionMode === "explicit" &&
|
|
69
|
+
(operation === "workspace-write" || operation === "member-write")
|
|
70
|
+
) {
|
|
71
|
+
if (authorization.accountGrant?.permissions.includes("usage_allowances:manage")) return;
|
|
72
|
+
throw new HTTPException(403, { message: "missing permission: usage_allowances:manage" });
|
|
73
|
+
}
|
|
74
|
+
if (operation === "own") {
|
|
75
|
+
if (grant.principalKind !== "human_session" || grant.serviceInitiator) {
|
|
76
|
+
throw new HTTPException(403, { message: "Own usage requires an authenticated member" });
|
|
77
|
+
}
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (operation === "read" || operation === "budget-read") {
|
|
81
|
+
if (
|
|
82
|
+
workspaceAdmin ||
|
|
83
|
+
accountAdmin ||
|
|
84
|
+
sameOrganizationKey?.permissions.includes("workspace:read")
|
|
85
|
+
)
|
|
86
|
+
return;
|
|
87
|
+
} else if (operation === "workspace-write") {
|
|
88
|
+
// Existing full keys retain key-control budget authority. Setup keys use
|
|
89
|
+
// literal account allowance authority plus the canonical organization-key
|
|
90
|
+
// workspace stamp; asUser carries neither account scope nor key stamp.
|
|
91
|
+
if (sameOrganizationKey) {
|
|
92
|
+
if (
|
|
93
|
+
sameOrganizationKey.permissions.includes("workspace:admin") &&
|
|
94
|
+
(sameOrganizationKey.permissions.includes("api_keys:manage") ||
|
|
95
|
+
authorization.accountGrant?.permissions.includes("usage_allowances:manage"))
|
|
96
|
+
)
|
|
97
|
+
return;
|
|
98
|
+
} else if (
|
|
99
|
+
accountAdmin &&
|
|
100
|
+
grant.principalKind === "human_session" &&
|
|
101
|
+
!grant.serviceInitiator &&
|
|
102
|
+
!context.subjectId.startsWith("api_key:")
|
|
103
|
+
)
|
|
104
|
+
return;
|
|
105
|
+
} else if (operation === "member-write") {
|
|
106
|
+
if (
|
|
107
|
+
sameOrganizationKey?.permissions.includes("workspace:admin") ||
|
|
108
|
+
(workspaceAdmin &&
|
|
109
|
+
grant.principalKind === "human_session" &&
|
|
110
|
+
!grant.serviceInitiator &&
|
|
111
|
+
!context.subjectId.startsWith("api_key:"))
|
|
112
|
+
)
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
throw new HTTPException(403, { message: `Missing usage allowance authority: ${operation}` });
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async function resolveWorkspace(c: Context, deps: ApiRouteDeps): Promise<string> {
|
|
119
|
+
const workspaceId = c.req.param("workspaceId");
|
|
120
|
+
if (workspaceId) return workspaceId;
|
|
121
|
+
const context = await requireAccessContext(c, deps);
|
|
122
|
+
const organizationKey = accountScopedApiKeyWorkspaceAuthority(context);
|
|
123
|
+
// External tenant paths are host-service lookups, never caller-selected
|
|
124
|
+
// default-account guesses or provisioning.
|
|
125
|
+
const externalAccountId =
|
|
126
|
+
c.req.header("x-opengeni-external-actor") !== undefined ? context.defaultAccountId : null;
|
|
127
|
+
const accountId = organizationKey?.accountId ?? externalAccountId;
|
|
128
|
+
if (!accountId)
|
|
129
|
+
throw new HTTPException(403, { message: "Organization API key or external user required" });
|
|
130
|
+
const reference = parseRequestBody(ExternalIdentityReference, {
|
|
131
|
+
source: c.req.param("workspaceSource"),
|
|
132
|
+
externalId: c.req.param("workspaceExternalId"),
|
|
133
|
+
});
|
|
134
|
+
const workspace = await withAccountRls(deps.db, accountId, (tx) =>
|
|
135
|
+
findWorkspaceByExternalIdentity(tx, {
|
|
136
|
+
accountId,
|
|
137
|
+
externalSource: reference.source,
|
|
138
|
+
externalId: reference.externalId,
|
|
139
|
+
}),
|
|
140
|
+
);
|
|
141
|
+
if (!workspace) throw new HTTPException(404, { message: "Workspace not found" });
|
|
142
|
+
return workspace.id;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
async function authorize(c: Context, deps: ApiRouteDeps, operation: Operation) {
|
|
146
|
+
const workspaceId = await resolveWorkspace(c, deps);
|
|
147
|
+
const context = await requireAccessContext(c, deps);
|
|
148
|
+
if (
|
|
149
|
+
(operation === "workspace-write" || operation === "budget-read") &&
|
|
150
|
+
!c.req.header("x-opengeni-external-actor") &&
|
|
151
|
+
!context.subjectId.startsWith("api_key:")
|
|
152
|
+
) {
|
|
153
|
+
// Organization budget management does not require membership in the
|
|
154
|
+
// target shared workspace. Validate the existing authenticated account
|
|
155
|
+
// authority on its own anchor, never manufacture a target workspace grant.
|
|
156
|
+
for (const account of context.accountGrants) {
|
|
157
|
+
if (account.subjectId !== context.subjectId || !account.permissions.includes("account:admin"))
|
|
158
|
+
continue;
|
|
159
|
+
const anchor = context.workspaceGrants.find(
|
|
160
|
+
(grant) =>
|
|
161
|
+
grant.accountId === account.accountId &&
|
|
162
|
+
grant.subjectId === context.subjectId &&
|
|
163
|
+
grant.principalKind === "human_session" &&
|
|
164
|
+
!grant.serviceInitiator &&
|
|
165
|
+
grant.metadata?.sessionId === undefined,
|
|
166
|
+
);
|
|
167
|
+
if (!anchor) continue;
|
|
168
|
+
const stamp = requireAccountAdminAuthorizationStamp(
|
|
169
|
+
accessGrantAuthorizationFromContext(context, anchor),
|
|
170
|
+
);
|
|
171
|
+
const target = await withAccountRls(deps.db, stamp.accountId, (tx) =>
|
|
172
|
+
getWorkspace(tx, workspaceId),
|
|
173
|
+
);
|
|
174
|
+
if (!target || target.accountId !== stamp.accountId) continue;
|
|
175
|
+
if (target.kind !== "shared") {
|
|
176
|
+
throw new HTTPException(403, {
|
|
177
|
+
message: "Organization budgets require a shared workspace",
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
return {
|
|
181
|
+
accountId: stamp.accountId,
|
|
182
|
+
workspaceId,
|
|
183
|
+
actorSubjectId: stamp.actorSubjectId,
|
|
184
|
+
actorType: "human_session" as const,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
// An administrator of another organization may still hold an ordinary
|
|
188
|
+
// target grant. A budget lookup miss grants nothing and must not mask it.
|
|
189
|
+
}
|
|
190
|
+
const authorization = await requireAccessGrantAuthorization(c, deps, workspaceId);
|
|
191
|
+
requireAllowanceAuthority({ authorization, context }, operation);
|
|
192
|
+
return {
|
|
193
|
+
accountId: authorization.grant.accountId,
|
|
194
|
+
workspaceId,
|
|
195
|
+
actorSubjectId: authorization.grant.subjectId,
|
|
196
|
+
actorType: authorization.grant.principalKind ?? "subject",
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function usageQuery(c: Context, own: boolean) {
|
|
201
|
+
const input = c.req.query();
|
|
202
|
+
const parsed = parseRequestBody(own ? GetMyUsageRequest : GetUsageRequest, {
|
|
203
|
+
...input,
|
|
204
|
+
...(input.limit !== undefined ? { limit: Number(input.limit) } : {}),
|
|
205
|
+
});
|
|
206
|
+
return {
|
|
207
|
+
...(parsed.period === undefined ? {} : { period: parsed.period }),
|
|
208
|
+
...("limit" in parsed && parsed.limit !== undefined ? { limit: parsed.limit as number } : {}),
|
|
209
|
+
...("cursor" in parsed && parsed.cursor !== undefined
|
|
210
|
+
? { cursor: parsed.cursor as string }
|
|
211
|
+
: {}),
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function requireAllowanceProducersEnabled(deps: ApiRouteDeps): void {
|
|
216
|
+
if (!deps.settings.usageAllowancesEnabled) {
|
|
217
|
+
throw new HTTPException(409, {
|
|
218
|
+
message:
|
|
219
|
+
"Usage allowance changes are not enabled. Upgrade every API and worker before enabling usage allowances.",
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/** Map lifecycle refusals without treating a failed CAS as an applied mutation. */
|
|
225
|
+
async function lifecycle<T>(operation: () => Promise<T>): Promise<T> {
|
|
226
|
+
try {
|
|
227
|
+
return await operation();
|
|
228
|
+
} catch (error) {
|
|
229
|
+
if (error instanceof UsageAllowanceVersionConflictError)
|
|
230
|
+
throw new HTTPException(409, { message: error.message });
|
|
231
|
+
const state = nestedPostgresSqlState(error);
|
|
232
|
+
if (state === "40001" || state === "23505")
|
|
233
|
+
throw new HTTPException(409, { message: "Allowance version or operation conflicts" });
|
|
234
|
+
if (state === "42501")
|
|
235
|
+
throw new HTTPException(403, { message: "Allowance operation is not authorized" });
|
|
236
|
+
if (state === "P0002" || state === "23503")
|
|
237
|
+
throw new HTTPException(404, { message: "Allowance or member not found" });
|
|
238
|
+
if (state === "22023" || state === "23514")
|
|
239
|
+
throw new HTTPException(400, { message: "Invalid allowance request" });
|
|
240
|
+
throw error;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export function registerUsageAllowanceRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
245
|
+
const bases = [
|
|
246
|
+
"/v1/workspaces/:workspaceId",
|
|
247
|
+
"/v1/workspaces/external/:workspaceSource/:workspaceExternalId",
|
|
248
|
+
];
|
|
249
|
+
for (const base of bases) {
|
|
250
|
+
app.get(`${base}/allowance`, async (c) => {
|
|
251
|
+
const scope = await authorize(c, deps, "budget-read");
|
|
252
|
+
const result = await getWorkspaceAllowance(deps.db, scope);
|
|
253
|
+
return c.json(result === null ? null : WorkspaceAllowance.parse(result));
|
|
254
|
+
});
|
|
255
|
+
app.get(`${base}/allowance/state`, async (c) => {
|
|
256
|
+
const scope = await authorize(c, deps, "budget-read");
|
|
257
|
+
return c.json(
|
|
258
|
+
WorkspaceAllowanceState.parse(await getWorkspaceAllowanceState(deps.db, scope)),
|
|
259
|
+
);
|
|
260
|
+
});
|
|
261
|
+
app.put(`${base}/allowance`, async (c) => {
|
|
262
|
+
const scope = await authorize(c, deps, "workspace-write");
|
|
263
|
+
const request = await parseRequestJson(c, SetWorkspaceAllowanceRequest);
|
|
264
|
+
requireAllowanceProducersEnabled(deps);
|
|
265
|
+
return c.json(
|
|
266
|
+
WorkspaceAllowance.parse(
|
|
267
|
+
await lifecycle(() =>
|
|
268
|
+
setWorkspaceAllowance(deps.db, {
|
|
269
|
+
...scope,
|
|
270
|
+
expectedVersion: request.expectedVersion,
|
|
271
|
+
includedCredits: request.includedCredits,
|
|
272
|
+
period: request.period,
|
|
273
|
+
...(request.anchorDay === undefined ? {} : { anchorDay: request.anchorDay }),
|
|
274
|
+
...(request.memberDefault === undefined
|
|
275
|
+
? {}
|
|
276
|
+
: { memberDefault: request.memberDefault }),
|
|
277
|
+
...(request.thresholds === undefined
|
|
278
|
+
? {}
|
|
279
|
+
: {
|
|
280
|
+
thresholds: {
|
|
281
|
+
...(request.thresholds.workspace === undefined
|
|
282
|
+
? {}
|
|
283
|
+
: { workspace: request.thresholds.workspace }),
|
|
284
|
+
...(request.thresholds.member === undefined
|
|
285
|
+
? {}
|
|
286
|
+
: { member: request.thresholds.member }),
|
|
287
|
+
},
|
|
288
|
+
}),
|
|
289
|
+
...(request.unbilledUsage === undefined
|
|
290
|
+
? {}
|
|
291
|
+
: { unbilledUsage: request.unbilledUsage }),
|
|
292
|
+
}),
|
|
293
|
+
),
|
|
294
|
+
),
|
|
295
|
+
);
|
|
296
|
+
});
|
|
297
|
+
app.delete(`${base}/allowance`, async (c) => {
|
|
298
|
+
const scope = await authorize(c, deps, "workspace-write");
|
|
299
|
+
const request = await parseRequestJson(c, ClearWorkspaceAllowanceRequest);
|
|
300
|
+
return c.json(
|
|
301
|
+
ClearWorkspaceAllowanceResponse.parse(
|
|
302
|
+
await lifecycle(() =>
|
|
303
|
+
clearWorkspaceAllowance(deps.db, {
|
|
304
|
+
...scope,
|
|
305
|
+
expectedVersion: request.expectedVersion,
|
|
306
|
+
...(request.operationId === undefined ? {} : { operationId: request.operationId }),
|
|
307
|
+
}),
|
|
308
|
+
),
|
|
309
|
+
),
|
|
310
|
+
);
|
|
311
|
+
});
|
|
312
|
+
app.post(`${base}/allowance/grants`, async (c) => {
|
|
313
|
+
const scope = await authorize(c, deps, "workspace-write");
|
|
314
|
+
const request = await parseRequestJson(c, GrantWorkspaceCreditsRequest);
|
|
315
|
+
requireAllowanceProducersEnabled(deps);
|
|
316
|
+
return c.json(
|
|
317
|
+
WorkspaceCreditGrant.parse(
|
|
318
|
+
await lifecycle(() =>
|
|
319
|
+
grantWorkspaceCredits(deps.db, {
|
|
320
|
+
...scope,
|
|
321
|
+
operationId: request.operationId,
|
|
322
|
+
credits: request.credits,
|
|
323
|
+
...(request.expiresAt === undefined ? {} : { expiresAt: request.expiresAt }),
|
|
324
|
+
}),
|
|
325
|
+
),
|
|
326
|
+
),
|
|
327
|
+
);
|
|
328
|
+
});
|
|
329
|
+
for (const memberPath of [
|
|
330
|
+
"members/:subjectId",
|
|
331
|
+
"members/external/:memberSource/:memberExternalId",
|
|
332
|
+
]) {
|
|
333
|
+
app.put(`${base}/${memberPath}/allowance`, async (c) => {
|
|
334
|
+
const scope = await authorize(c, deps, "member-write");
|
|
335
|
+
const request = await parseRequestJson(c, SetMemberAllowanceRequest);
|
|
336
|
+
if (request.rule !== null) requireAllowanceProducersEnabled(deps);
|
|
337
|
+
const subjectId = c.req.param("subjectId");
|
|
338
|
+
const target = subjectId
|
|
339
|
+
? { subjectId }
|
|
340
|
+
: {
|
|
341
|
+
externalIdentity: parseRequestBody(ExternalIdentityReference, {
|
|
342
|
+
source: c.req.param("memberSource"),
|
|
343
|
+
externalId: c.req.param("memberExternalId"),
|
|
344
|
+
}),
|
|
345
|
+
};
|
|
346
|
+
// Resolve the exact external identity and live member inside the same
|
|
347
|
+
// protected mutation; never enumerate a roster or provision an identity.
|
|
348
|
+
return c.json(
|
|
349
|
+
MemberAllowance.parse(
|
|
350
|
+
await lifecycle(() => setMemberAllowance(deps.db, { ...scope, ...target, ...request })),
|
|
351
|
+
),
|
|
352
|
+
);
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
app.get(`${base}/usage`, async (c) => {
|
|
356
|
+
const scope = await authorize(c, deps, "read");
|
|
357
|
+
return c.json(
|
|
358
|
+
WorkspaceUsageResponse.parse(
|
|
359
|
+
await getWorkspaceUsage(deps.db, { ...scope, ...usageQuery(c, false) }),
|
|
360
|
+
),
|
|
361
|
+
);
|
|
362
|
+
});
|
|
363
|
+
app.get(`${base}/usage/me`, async (c) => {
|
|
364
|
+
const scope = await authorize(c, deps, "own");
|
|
365
|
+
const result = WorkspaceUsageResponse.parse(
|
|
366
|
+
await getWorkspaceUsage(deps.db, {
|
|
367
|
+
...scope,
|
|
368
|
+
...usageQuery(c, true),
|
|
369
|
+
subjectId: scope.actorSubjectId,
|
|
370
|
+
}),
|
|
371
|
+
);
|
|
372
|
+
// Defense in depth: the own endpoint never serializes another member or a
|
|
373
|
+
// roster cursor even if the storage adapter returns an overbroad page.
|
|
374
|
+
return c.json({
|
|
375
|
+
...result,
|
|
376
|
+
members: result.members.filter((member) => member.subjectId === scope.actorSubjectId),
|
|
377
|
+
nextCursor: null,
|
|
378
|
+
});
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Hono } from "hono";
|
|
2
|
+
import { variableSetsRemovedResponse } from "../http/variable-sets-removed";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Variable Sets were replaced by vaults (RM-1). Every legacy route, including
|
|
6
|
+
* the deprecated `/environments` alias, answers 410 `variable_sets_removed`
|
|
7
|
+
* with a pointer to `/vaults`. No grant is checked: the answer reveals nothing.
|
|
8
|
+
*/
|
|
9
|
+
const LEGACY_PREFIXES = [
|
|
10
|
+
"/v1/workspaces/:workspaceId/variable-sets",
|
|
11
|
+
"/v1/workspaces/:workspaceId/environments",
|
|
12
|
+
] as const;
|
|
13
|
+
|
|
14
|
+
export function registerVariableSetsRemovedRoutes(app: Hono): void {
|
|
15
|
+
for (const prefix of LEGACY_PREFIXES) {
|
|
16
|
+
app.all(prefix, (c) => variableSetsRemovedResponse(c, 410));
|
|
17
|
+
app.all(`${prefix}/*`, (c) => variableSetsRemovedResponse(c, 410));
|
|
18
|
+
}
|
|
19
|
+
}
|