@opengeni/api-router 0.30.3 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-grant-rls.d.ts +3 -0
- package/dist/admission-trace.d.ts +8 -0
- package/dist/api-websocket.d.ts +18 -0
- package/dist/app.d.ts +50 -2
- package/dist/app.js +12 -1
- package/dist/artifact-catalog-cursor.d.ts +27 -0
- package/dist/auth/managed-auth-attempt-context.d.ts +10 -0
- package/dist/auth/managed-auth-rate-limits.d.ts +167 -0
- package/dist/auth/managed-auth-session-adapter.d.ts +6 -0
- package/dist/auth/managed-auth.d.ts +102 -3
- package/dist/auth/managed-email.d.ts +29 -0
- package/dist/auth/managed-sign-in-notifications.d.ts +4 -0
- package/dist/auth/new-signups-gate.d.ts +23 -0
- package/dist/auth/organization-user-setup.d.ts +80 -0
- package/dist/auth/signup-funnel-metrics.d.ts +44 -0
- package/dist/browser-controller-authority.d.ts +1 -61
- package/dist/browser-ephemeral.d.ts +5 -0
- package/dist/browser-state-authority.d.ts +1 -27
- package/dist/chunk-6TZ5LG3O.js +123948 -0
- package/dist/chunk-6TZ5LG3O.js.map +1 -0
- package/dist/chunk-OGQDXVXY.js +18 -0
- package/dist/chunk-OGQDXVXY.js.map +1 -0
- package/dist/claude-subscription-account-conflicts.d.ts +1 -0
- package/dist/claude-subscription-account-usage.d.ts +39 -0
- package/dist/claude-subscription-oauth.d.ts +25 -0
- package/dist/claude-subscription-profile.d.ts +9 -0
- package/dist/claude-subscription-usage.d.ts +44 -0
- package/dist/claude-workspace-connection.d.ts +15 -0
- package/dist/codemode.d.ts +32 -1
- package/dist/company-brain-okf.d.ts +24 -0
- package/dist/connected-machine-computer-access.d.ts +11 -0
- package/dist/connection-ownership.d.ts +54 -0
- package/dist/controller-data-plane.d.ts +32 -0
- package/dist/editable-artifact-source-session.d.ts +3 -0
- package/dist/editable-artifact-websocket.d.ts +10 -18
- package/dist/editable-artifact-workspace-files.d.ts +1 -1
- package/dist/fatal-process-boundary.d.ts +25 -0
- package/dist/github-access.d.ts +31 -2
- package/dist/http/acting-person.d.ts +24 -0
- package/dist/http/api-contract-compat.d.ts +19 -0
- package/dist/http/api-error.d.ts +27 -1
- package/dist/http/cors.d.ts +17 -0
- package/dist/http/deprecation.d.ts +42 -0
- package/dist/http/interaction-control-error.d.ts +13 -0
- package/dist/http/keyed-admission.d.ts +12 -0
- package/dist/http/local-browser-boundary.d.ts +72 -0
- package/dist/http/metrics-listener.d.ts +22 -0
- package/dist/http/path-identifier.d.ts +17 -0
- package/dist/http/registered-route-label.d.ts +16 -0
- package/dist/http/request-body.d.ts +27 -0
- package/dist/http/request-source.d.ts +52 -0
- package/dist/http/sse.d.ts +17 -6
- package/dist/http/unmatched-route.d.ts +18 -0
- package/dist/http/user-content.d.ts +36 -0
- package/dist/http/websocket-upgrade-dispatch.d.ts +18 -0
- package/dist/index.d.ts +10 -3
- package/dist/index.js +1091 -162
- package/dist/index.js.map +1 -1
- package/dist/integration-endpoint-test.d.ts +20 -0
- package/dist/integrations/api-integrations.d.ts +2 -2
- package/dist/integrations/atlassian.d.ts +29 -3
- package/dist/integrations/connect-authority.d.ts +1 -0
- package/dist/integrations/connect-callback-return.d.ts +6 -0
- package/dist/integrations/fiken.d.ts +16 -2
- package/dist/integrations/github-app-connect.d.ts +47 -0
- package/dist/integrations/github-installation-proof.d.ts +3 -0
- package/dist/integrations/github-lens-connect.d.ts +116 -0
- package/dist/integrations/github-skill-source.d.ts +1 -5
- package/dist/integrations/google-drive.d.ts +24 -0
- package/dist/integrations/integration-commit-authority.d.ts +13 -0
- package/dist/integrations/marketplace-plugin.d.ts +2691 -0
- package/dist/integrations/oauth-client.d.ts +178 -18
- package/dist/integrations/oauth-profiles.d.ts +222 -0
- package/dist/integrations/oauth-return-path.d.ts +1 -0
- package/dist/integrations/personal-github-repositories.d.ts +84 -0
- package/dist/integrations/personal-github.d.ts +42 -0
- package/dist/integrations/pr-review-provider.d.ts +22 -0
- package/dist/integrations/provider-oauth.d.ts +19 -1
- package/dist/integrations/slack-app-home.d.ts +24 -0
- package/dist/integrations/slack-bot.d.ts +367 -12
- package/dist/integrations/slack-file-upload-flow.d.ts +62 -0
- package/dist/integrations/slack-install.d.ts +20 -0
- package/dist/integrations/slack-interactions.d.ts +107 -9
- package/dist/integrations/slack-mrkdwn.d.ts +41 -0
- package/dist/integrations/slack-routing.d.ts +120 -0
- package/dist/integrations/slack-session-defaults.d.ts +58 -0
- package/dist/integrations/slack-task-file-upload.d.ts +36 -0
- package/dist/integrations/social-oauth.d.ts +7 -0
- package/dist/interaction-agent-access.d.ts +15 -0
- package/dist/interaction-frame-proxy.d.ts +68 -0
- package/dist/interaction-metrics.d.ts +2 -0
- package/dist/mcp/action-catalog-types.d.ts +9 -0
- package/dist/mcp/action-catalog.gen.d.ts +2 -0
- package/dist/mcp/capability-account-readiness.d.ts +7 -0
- package/dist/mcp/child-read-evidence.d.ts +9 -0
- package/dist/mcp/command-read.d.ts +24 -0
- package/dist/mcp/company-profile-agent-admin.d.ts +44 -0
- package/dist/mcp/contract-input.d.ts +11 -0
- package/dist/mcp/documents.d.ts +7 -5
- package/dist/mcp/files.d.ts +2 -2
- package/dist/mcp/first-party-tool-permissions.d.ts +650 -0
- package/dist/mcp/knowledge-entries.d.ts +5 -0
- package/dist/mcp/orchestration-failure-diagnostic.d.ts +43 -0
- package/dist/mcp/receipts.d.ts +9 -0
- package/dist/mcp/request-abort.d.ts +19 -0
- package/dist/mcp/scheduled-task-input.d.ts +1189 -0
- package/dist/mcp/scheduled-task-view.d.ts +22 -4
- package/dist/mcp/server.d.ts +255 -3
- package/dist/mcp/session-event-view.d.ts +94 -0
- package/dist/mcp/session-view.d.ts +66 -2
- package/dist/mcp/session-wait.d.ts +174 -0
- package/dist/mcp-oauth.d.ts +52 -0
- package/dist/model-catalog.d.ts +11 -31
- package/dist/observability.d.ts +3 -1
- package/dist/organization-mcp.d.ts +52 -0
- package/dist/organization-recovery-notifications.d.ts +41 -0
- package/dist/routes/analytics-consent.d.ts +26 -0
- package/dist/routes/api-integrations.d.ts +25 -0
- package/dist/routes/api-keys.d.ts +17 -0
- package/dist/routes/artifact-catalog.d.ts +6 -0
- package/dist/routes/automations.d.ts +19 -0
- package/dist/routes/billing.d.ts +49 -0
- package/dist/routes/browser-sessions.d.ts +59 -2
- package/dist/routes/claude-subscription-accounts.d.ts +3 -0
- package/dist/routes/claude-subscription-oauth.d.ts +3 -0
- package/dist/routes/client-errors.d.ts +146 -0
- package/dist/routes/codex.d.ts +76 -2
- package/dist/routes/company-brain.d.ts +3 -0
- package/dist/routes/company-profile.d.ts +2 -1
- package/dist/routes/computer-sessions.d.ts +14 -0
- package/dist/routes/connect.d.ts +5 -0
- package/dist/routes/editable-artifacts.d.ts +2 -0
- package/dist/routes/external-identity-links.d.ts +6 -0
- package/dist/routes/feedback.d.ts +3 -0
- package/dist/routes/github-browser-pages.d.ts +12 -0
- package/dist/routes/github.d.ts +2 -0
- package/dist/routes/insights-response-cache.d.ts +10 -0
- package/dist/routes/insights-usage.d.ts +12 -0
- package/dist/routes/insights.d.ts +30 -1
- package/dist/routes/knowledge.d.ts +3 -0
- package/dist/routes/managed-auth-session-sets.d.ts +26 -0
- package/dist/routes/managed-onboarding.d.ts +29 -0
- package/dist/routes/managed-sign-in-methods.d.ts +6 -0
- package/dist/routes/model-connection-access.d.ts +3 -0
- package/dist/routes/organization-integration-policy.d.ts +3 -0
- package/dist/routes/organization-integrations.d.ts +6 -0
- package/dist/routes/organization-mcp-connections.d.ts +3 -0
- package/dist/routes/organization-model-providers.d.ts +3 -0
- package/dist/routes/organization-recovery.d.ts +19 -0
- package/dist/routes/organization-service-accounts.d.ts +3 -0
- package/dist/routes/organization-sessions.d.ts +26 -0
- package/dist/routes/personal-github-git-broker.d.ts +29 -0
- package/dist/routes/personal-github.d.ts +3 -0
- package/dist/routes/pr-review-github.d.ts +3 -0
- package/dist/routes/pr-review.d.ts +3 -0
- package/dist/routes/session-artifact-associations.d.ts +4 -0
- package/dist/routes/session-history-imports.d.ts +9 -0
- package/dist/routes/sessions.d.ts +44 -6
- package/dist/routes/skill-content.d.ts +4 -0
- package/dist/routes/skill-install-authority.d.ts +6 -0
- package/dist/routes/subscription-account-pools.d.ts +34 -0
- package/dist/routes/subscription-pool-access.d.ts +16 -0
- package/dist/routes/supergrok.d.ts +6 -1
- package/dist/routes/usage-allowances.d.ts +12 -0
- package/dist/routes/user-resource-authorities.d.ts +3 -0
- package/dist/routes/workspace-artifacts.d.ts +2 -1
- package/dist/routes/workspace-capture.d.ts +10 -2
- package/dist/routes/workspace-integrations.d.ts +35 -0
- package/dist/routes/workspace-learning.d.ts +3 -0
- package/dist/routes/workspace-model-providers.d.ts +4 -0
- package/dist/routes/workspaces.d.ts +29 -0
- package/dist/sandbox/auth-callout.d.ts +8 -0
- package/dist/sandbox/channel-a.d.ts +19 -1
- package/dist/sandbox/connection-authority.d.ts +3 -0
- package/dist/sandbox/enrollment.d.ts +9 -1
- package/dist/sandbox/machines.d.ts +5 -2
- package/dist/sandbox/metrics-ingestion.d.ts +28 -20
- package/dist/sandbox/rematerialize.d.ts +2 -0
- package/dist/sandbox/session-attach-variable-sets.d.ts +30 -0
- package/dist/sandbox/viewer.d.ts +26 -1
- package/dist/sandbox-file-artifacts.d.ts +50 -0
- package/dist/scheduled-task-deletion.d.ts +13 -0
- package/dist/session-create-observability.d.ts +5 -0
- package/dist/session-event-view-MPS2OZD3.js +292 -0
- package/dist/session-event-view-MPS2OZD3.js.map +1 -0
- package/dist/site-session-origin.d.ts +13 -0
- package/dist/site-uploads.d.ts +41 -0
- package/dist/slack-reaction-files.d.ts +1 -1
- package/dist/temporal-schedule-cleanup.d.ts +1 -0
- package/dist/temporal-schedule-sync.d.ts +26 -0
- package/dist/transcription/providers/xai-subscription.d.ts +1 -0
- package/dist/transcription/service.d.ts +2 -1
- package/dist/work-discovery-observability.d.ts +33 -0
- package/dist/workspace-artifact-content.d.ts +28 -0
- package/dist/workspace-artifact-provenance.d.ts +7 -0
- package/dist/workspace-delete-observability.d.ts +10 -0
- package/dist/workspace-deletion.d.ts +6 -0
- package/dist/workspace-state-projection.d.ts +3 -5
- package/dist/workspace-tool-gateway-observability.d.ts +17 -0
- package/dist/workspace-tool-gateway.d.ts +123 -0
- package/dist/workspace-webhook-dispatch.d.ts +26 -0
- package/package.json +23 -19
- package/src/access-grant-rls.ts +75 -0
- package/src/admission-trace.ts +14 -0
- package/src/api-websocket.ts +23 -0
- package/src/app.ts +1967 -252
- package/src/artifact-catalog-cursor.ts +60 -0
- package/src/auth/managed-auth-attempt-context.ts +70 -0
- package/src/auth/managed-auth-rate-limits.ts +252 -0
- package/src/auth/managed-auth-session-adapter.ts +222 -0
- package/src/auth/managed-auth.ts +536 -60
- package/src/auth/managed-email.ts +174 -0
- package/src/auth/managed-sign-in-notifications.ts +81 -0
- package/src/auth/new-signups-gate.ts +49 -0
- package/src/auth/organization-user-setup.ts +307 -0
- package/src/auth/signup-funnel-metrics.ts +164 -0
- package/src/browser-controller-authority.ts +1 -186
- package/src/browser-ephemeral.ts +39 -0
- package/src/browser-state-authority.ts +1 -236
- package/src/claude-subscription-account-conflicts.ts +12 -0
- package/src/claude-subscription-account-usage.ts +48 -0
- package/src/claude-subscription-oauth.ts +362 -0
- package/src/claude-subscription-profile.ts +73 -0
- package/src/claude-subscription-usage.ts +97 -0
- package/src/claude-workspace-connection.ts +82 -0
- package/src/codemode.ts +194 -30
- package/src/codex-realtime.ts +8 -2
- package/src/company-brain-okf.ts +340 -0
- package/src/connected-machine-computer-access.ts +33 -0
- package/src/connection-ownership.ts +199 -0
- package/src/controller-data-plane.ts +81 -0
- package/src/editable-artifact-native-kernel.ts +26 -15
- package/src/editable-artifact-office-import.ts +28 -3
- package/src/editable-artifact-production.ts +23 -7
- package/src/editable-artifact-source-session.ts +123 -0
- package/src/editable-artifact-websocket.ts +27 -21
- package/src/editable-artifact-workspace-files.ts +31 -6
- package/src/fatal-process-boundary.ts +246 -0
- package/src/gateway-realtime.ts +1 -1
- package/src/github-access.ts +147 -5
- package/src/http/acting-person.ts +71 -0
- package/src/http/api-contract-compat.ts +49 -0
- package/src/http/api-error.ts +115 -1
- package/src/http/auth.ts +48 -0
- package/src/http/cors.ts +67 -0
- package/src/http/deprecation.ts +118 -0
- package/src/http/interaction-control-error.ts +164 -0
- package/src/http/keyed-admission.ts +29 -0
- package/src/http/local-browser-boundary.ts +343 -0
- package/src/http/metrics-listener.ts +57 -0
- package/src/http/path-identifier.ts +54 -0
- package/src/http/registered-route-label.ts +34 -0
- package/src/http/request-body.ts +127 -0
- package/src/http/request-source.ts +178 -0
- package/src/http/sse.ts +486 -132
- package/src/http/unmatched-route.ts +60 -0
- package/src/http/user-content.ts +158 -0
- package/src/http/websocket-upgrade-dispatch.ts +29 -0
- package/src/index.ts +157 -52
- package/src/integration-endpoint-test.ts +291 -0
- package/src/integrations/api-integrations.ts +98 -11
- package/src/integrations/atlassian.ts +474 -136
- package/src/integrations/connect-authority.ts +2 -0
- package/src/integrations/connect-callback-return.ts +86 -0
- package/src/integrations/fiken.ts +354 -64
- package/src/integrations/github-app-connect.ts +435 -0
- package/src/integrations/github-installation-proof.ts +60 -0
- package/src/integrations/github-lens-connect.ts +76 -0
- package/src/integrations/github-skill-source.ts +2 -142
- package/src/integrations/google-drive.ts +717 -225
- package/src/integrations/integration-commit-authority.ts +69 -0
- package/src/integrations/marketplace-plugin.ts +48 -0
- package/src/integrations/oauth-client.ts +1356 -459
- package/src/integrations/oauth-profiles.ts +537 -0
- package/src/integrations/oauth-return-path.ts +18 -0
- package/src/integrations/personal-github-repositories.ts +674 -0
- package/src/integrations/personal-github.ts +825 -0
- package/src/integrations/pr-review-provider.ts +246 -0
- package/src/integrations/provider-oauth.ts +250 -22
- package/src/integrations/slack-app-home.ts +300 -0
- package/src/integrations/slack-bot.ts +963 -239
- package/src/integrations/slack-file-upload-flow.ts +147 -0
- package/src/integrations/slack-install.ts +83 -0
- package/src/integrations/slack-interactions.ts +3167 -474
- package/src/integrations/slack-mrkdwn.ts +193 -0
- package/src/integrations/slack-routing.ts +337 -0
- package/src/integrations/slack-session-defaults.ts +224 -0
- package/src/integrations/slack-task-file-upload.ts +323 -0
- package/src/integrations/social-oauth.ts +213 -15
- package/src/interaction-agent-access.ts +48 -0
- package/src/interaction-frame-proxy.ts +409 -0
- package/src/interaction-metrics.ts +30 -0
- package/src/mcp/action-catalog-types.ts +9 -0
- package/src/mcp/action-catalog.gen.ts +6696 -0
- package/src/mcp/capability-account-readiness.ts +17 -0
- package/src/mcp/child-read-evidence.ts +19 -0
- package/src/mcp/command-read.ts +109 -0
- package/src/mcp/company-profile-agent-admin.ts +198 -0
- package/src/mcp/contract-input.ts +141 -0
- package/src/mcp/documents.ts +65 -377
- package/src/mcp/editable-artifacts.ts +12 -6
- package/src/mcp/files.ts +80 -43
- package/src/mcp/first-party-tool-permissions.ts +305 -0
- package/src/mcp/knowledge-entries.ts +322 -0
- package/src/mcp/orchestration-failure-diagnostic.ts +43 -0
- package/src/mcp/receipts.ts +34 -0
- package/src/mcp/request-abort.ts +44 -0
- package/src/mcp/scheduled-task-input.ts +76 -0
- package/src/mcp/scheduled-task-view.ts +44 -3
- package/src/mcp/server.ts +3030 -1267
- package/src/mcp/session-event-view.ts +383 -0
- package/src/mcp/session-view.ts +84 -3
- package/src/mcp/session-wait.ts +665 -0
- package/src/mcp-oauth.ts +1123 -0
- package/src/model-catalog.ts +91 -333
- package/src/observability.ts +15 -1
- package/src/organization-mcp.ts +397 -0
- package/src/organization-recovery-notifications.ts +103 -0
- package/src/routes/analytics-consent.ts +123 -0
- package/src/routes/api-integrations.ts +364 -74
- package/src/routes/api-keys.ts +336 -10
- package/src/routes/artifact-catalog.ts +279 -0
- package/src/routes/automations.ts +768 -0
- package/src/routes/billing.ts +461 -46
- package/src/routes/browser-sessions.ts +780 -112
- package/src/routes/canonical-human-identities.ts +90 -14
- package/src/routes/capabilities.ts +107 -6
- package/src/routes/channels.ts +20 -3
- package/src/routes/claude-subscription-accounts.ts +334 -0
- package/src/routes/claude-subscription-oauth.ts +142 -0
- package/src/routes/client-errors.ts +362 -0
- package/src/routes/codex.ts +833 -116
- package/src/routes/company-brain.ts +322 -0
- package/src/routes/company-profile.ts +65 -1
- package/src/routes/computer-sessions.ts +557 -106
- package/src/routes/connect.ts +1938 -0
- package/src/routes/connections.ts +1039 -349
- package/src/routes/documents.ts +488 -287
- package/src/routes/editable-artifacts.ts +79 -9
- package/src/routes/enrollments.ts +135 -39
- package/src/routes/environments.ts +154 -58
- package/src/routes/external-identity-links.ts +201 -0
- package/src/routes/feedback.ts +113 -0
- package/src/routes/files.ts +267 -33
- package/src/routes/github-browser-pages.ts +162 -0
- package/src/routes/github.ts +446 -144
- package/src/routes/insights-response-cache.ts +83 -0
- package/src/routes/insights-usage.ts +345 -0
- package/src/routes/insights.ts +153 -19
- package/src/routes/install.ts +133 -38
- package/src/routes/integration-facets.ts +107 -33
- package/src/routes/interaction-resources.ts +30 -3
- package/src/routes/knowledge.ts +488 -0
- package/src/routes/machines.ts +313 -15
- package/src/routes/managed-auth-session-sets.ts +1218 -0
- package/src/routes/managed-onboarding.ts +337 -0
- package/src/routes/managed-sign-in-methods.ts +433 -0
- package/src/routes/memory-slack-publications.ts +3 -2
- package/src/routes/model-connection-access.ts +208 -0
- package/src/routes/organization-integration-policy.ts +116 -0
- package/src/routes/organization-integrations.ts +326 -0
- package/src/routes/organization-mcp-connections.ts +178 -0
- package/src/routes/organization-memberships.ts +1019 -27
- package/src/routes/organization-model-providers.ts +293 -0
- package/src/routes/organization-recovery.ts +325 -0
- package/src/routes/organization-service-accounts.ts +128 -0
- package/src/routes/organization-sessions.ts +350 -0
- package/src/routes/personal-github-git-broker.ts +785 -0
- package/src/routes/personal-github.ts +370 -0
- package/src/routes/plugins.ts +251 -22
- package/src/routes/pr-review-github.ts +881 -0
- package/src/routes/pr-review.ts +622 -0
- package/src/routes/preference-registry.ts +12 -93
- package/src/routes/rigs.ts +167 -50
- package/src/routes/scheduled-tasks.ts +346 -41
- package/src/routes/session-artifact-associations.ts +87 -0
- package/src/routes/session-history-imports.ts +280 -0
- package/src/routes/sessions.ts +2306 -264
- package/src/routes/skill-content.ts +297 -0
- package/src/routes/skill-install-authority.ts +64 -0
- package/src/routes/skills.ts +62 -9
- package/src/routes/social.ts +46 -18
- package/src/routes/subscription-account-pools.ts +436 -0
- package/src/routes/subscription-pool-access.ts +126 -0
- package/src/routes/supergrok.ts +219 -303
- package/src/routes/transcription-recordings.ts +38 -3
- package/src/routes/transcriptions.ts +4 -0
- package/src/routes/usage-allowances.ts +378 -0
- package/src/routes/user-resource-authorities.ts +138 -0
- package/src/routes/video-generation.ts +14 -10
- package/src/routes/workspace-artifacts.ts +275 -69
- package/src/routes/workspace-capture.ts +21 -0
- package/src/routes/workspace-integrations.ts +576 -0
- package/src/routes/workspace-learning.ts +159 -0
- package/src/routes/workspace-model-providers.ts +148 -0
- package/src/routes/workspace-state.ts +38 -25
- package/src/routes/workspaces.ts +1004 -127
- package/src/sandbox/auth-callout.ts +96 -19
- package/src/sandbox/channel-a.ts +323 -24
- package/src/sandbox/connection-authority.ts +3 -0
- package/src/sandbox/enrollment.ts +81 -6
- package/src/sandbox/machines.ts +218 -76
- package/src/sandbox/metrics-ingestion.ts +411 -62
- package/src/sandbox/rematerialize.ts +121 -19
- package/src/sandbox/session-attach-variable-sets.ts +131 -0
- package/src/sandbox/viewer.ts +280 -25
- package/src/sandbox-file-artifacts.ts +413 -0
- package/src/scheduled-task-deletion.ts +138 -0
- package/src/session-create-observability.ts +46 -0
- package/src/session-realtime-context.ts +6 -3
- package/src/site-session-origin.ts +48 -0
- package/src/site-uploads.ts +224 -0
- package/src/slack-reaction-files.ts +16 -5
- package/src/temporal-schedule-cleanup.ts +13 -0
- package/src/temporal-schedule-sync.ts +74 -0
- package/src/transcription/providers/codex-subscription.ts +2 -0
- package/src/transcription/providers/openai.ts +1 -0
- package/src/transcription/providers/xai-subscription.ts +49 -3
- package/src/transcription/segmenter.ts +8 -2
- package/src/transcription/service.ts +43 -6
- package/src/work-discovery-observability.ts +121 -0
- package/src/workspace-artifact-content.ts +144 -0
- package/src/workspace-artifact-provenance.ts +104 -0
- package/src/workspace-delete-observability.ts +75 -0
- package/src/workspace-deletion.ts +73 -0
- package/src/workspace-state-projection.ts +18 -148
- package/src/workspace-tool-gateway-observability.ts +100 -0
- package/src/workspace-tool-gateway.ts +870 -0
- package/src/workspace-webhook-dispatch.ts +190 -0
- package/src/xai-subscription-auth.ts +9 -2
- package/dist/chunk-WCXHI3FF.js +0 -49920
- package/dist/chunk-WCXHI3FF.js.map +0 -1
- package/dist/routes/packs.d.ts +0 -3
- package/src/routes/packs.ts +0 -729
package/src/sandbox/viewer.ts
CHANGED
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
hasGitHubRepositorySelection,
|
|
27
27
|
resolveStreamTokenSecret,
|
|
28
28
|
sandboxLifecycleTransitionWaitMs,
|
|
29
|
+
sandboxWarmRateMicrosPerSecond,
|
|
29
30
|
stableSandboxEnvironmentForRun,
|
|
30
31
|
} from "@opengeni/config";
|
|
31
32
|
import type { Settings } from "@opengeni/config";
|
|
@@ -33,10 +34,10 @@ import { githubAppBotIdentity } from "@opengeni/github";
|
|
|
33
34
|
import { type Session, type StreamUrlRotatedPayload } from "@opengeni/contracts";
|
|
34
35
|
import {
|
|
35
36
|
acquireLease,
|
|
37
|
+
getLiveEnrollmentConnection,
|
|
36
38
|
getSandbox,
|
|
37
39
|
getSandboxSessionEnvelope,
|
|
38
|
-
|
|
39
|
-
loadWorkspaceEnvironmentForRun,
|
|
40
|
+
heartbeatLeaseHolderStatus,
|
|
40
41
|
markSandboxProviderReady,
|
|
41
42
|
markWarmLeaseInstanceLost,
|
|
42
43
|
readLease,
|
|
@@ -45,12 +46,16 @@ import {
|
|
|
45
46
|
releaseLeaseHolder,
|
|
46
47
|
SandboxLeaseSupersededError,
|
|
47
48
|
SandboxViewerAdmissionBlockedError,
|
|
49
|
+
SandboxPaidComputeAdmissionError,
|
|
48
50
|
type Database,
|
|
49
51
|
type LeaseSnapshot,
|
|
50
52
|
type SandboxRecord,
|
|
53
|
+
getSessionAuthorityEpoch,
|
|
54
|
+
namedSubjectHasLiveWorkspaceAuthority,
|
|
51
55
|
} from "@opengeni/db";
|
|
52
56
|
import { appendAndPublishEvents, type EventBus } from "@opengeni/events";
|
|
53
57
|
import { HTTPException } from "hono/http-exception";
|
|
58
|
+
import type { ObjectStorage } from "@opengeni/storage";
|
|
54
59
|
|
|
55
60
|
// The leaf — agent-loop-free. apps/api imports sandbox symbols ONLY from here
|
|
56
61
|
// (enforced by sandbox-access-import-guard.test.ts).
|
|
@@ -71,13 +76,21 @@ import {
|
|
|
71
76
|
TerminalServerUnsupportedError,
|
|
72
77
|
verifySandboxExecReadiness,
|
|
73
78
|
StreamPortUnavailableError,
|
|
79
|
+
renewSandboxProviderExpiration,
|
|
74
80
|
type ControlRpc,
|
|
75
81
|
type EstablishedSandboxSession,
|
|
76
82
|
type NatsRequestConnection,
|
|
77
83
|
} from "@opengeni/runtime/sandbox";
|
|
78
|
-
import {
|
|
84
|
+
import {
|
|
85
|
+
managedSessionGroupBackend,
|
|
86
|
+
managedSessionGroupOs,
|
|
87
|
+
providerSettingsForSessionSandboxRuntime,
|
|
88
|
+
relayConfigFromSettings,
|
|
89
|
+
resolveSessionSandboxRuntime,
|
|
90
|
+
} from "@opengeni/core";
|
|
79
91
|
import { establishApiSandboxSpawner } from "./rematerialize";
|
|
80
92
|
import { establishCachedChannelAHandle } from "./channel-a";
|
|
93
|
+
import { loadSessionAttachVariableSetValues } from "./session-attach-variable-sets";
|
|
81
94
|
|
|
82
95
|
/** The minimal services a viewer op needs: the DB + settings (lease cadence +
|
|
83
96
|
* the sandbox client construction the leaf reads from settings). The bus is
|
|
@@ -87,6 +100,7 @@ export type ViewerServices = {
|
|
|
87
100
|
db: Database;
|
|
88
101
|
settings: Settings;
|
|
89
102
|
bus?: EventBus;
|
|
103
|
+
objectStorage?: ObjectStorage | null;
|
|
90
104
|
/** Provider-establish dependency used by API-direct readiness and stream
|
|
91
105
|
* operations. Production uses the runtime leaf; isolated tests may supply a
|
|
92
106
|
* deterministic provider without replacing a process-global module. */
|
|
@@ -137,12 +151,14 @@ export async function sessionAttachEnvironment(
|
|
|
137
151
|
services: ViewerServices,
|
|
138
152
|
workspaceId: string,
|
|
139
153
|
session: Session,
|
|
154
|
+
/** The authenticated route subject driving this attach (0282); recorded on
|
|
155
|
+
* the materialization audit fact. Null records the legacy service sentinel. */
|
|
156
|
+
attachSubjectId: string | null,
|
|
140
157
|
): Promise<Record<string, string>> {
|
|
141
|
-
const
|
|
158
|
+
const workspaceEnvironmentValues = await loadSessionAttachVariableSetValues(
|
|
142
159
|
services.db,
|
|
143
160
|
services.settings,
|
|
144
|
-
workspaceId,
|
|
145
|
-
session.environmentId,
|
|
161
|
+
{ accountId: session.accountId, workspaceId, session, subjectId: attachSubjectId },
|
|
146
162
|
);
|
|
147
163
|
// Build the env with the SESSION's backend, not the deployment default: the
|
|
148
164
|
// stable base is backend-aware (HOME = the descriptor workspaceRoot, and the
|
|
@@ -158,7 +174,7 @@ export async function sessionAttachEnvironment(
|
|
|
158
174
|
: services.settings;
|
|
159
175
|
const environment = stableSandboxEnvironmentForRun(
|
|
160
176
|
settingsForSession,
|
|
161
|
-
|
|
177
|
+
workspaceEnvironmentValues,
|
|
162
178
|
{ workspaceId },
|
|
163
179
|
);
|
|
164
180
|
if (hasGitCredentialRepositorySelection(session.resources)) {
|
|
@@ -187,15 +203,40 @@ export async function attachViewer(
|
|
|
187
203
|
workspaceId: string;
|
|
188
204
|
session: Session;
|
|
189
205
|
viewerId?: string;
|
|
206
|
+
/** The authenticated subject attaching this viewer (0281): recorded on
|
|
207
|
+
* the holder row together with the live session authority epoch. */
|
|
208
|
+
viewerSubjectId?: string;
|
|
190
209
|
/** Cancel lifecycle waiting when the originating HTTP request disconnects. */
|
|
191
210
|
waitSignal?: AbortSignal;
|
|
192
211
|
},
|
|
193
212
|
): Promise<ViewerAttachResult> {
|
|
194
213
|
const { db, settings } = services;
|
|
195
|
-
const { accountId, workspaceId
|
|
214
|
+
const { accountId, workspaceId } = input;
|
|
215
|
+
const groupBackend = managedSessionGroupBackend(
|
|
216
|
+
settings.sandboxBackend,
|
|
217
|
+
input.session.sandboxBackend,
|
|
218
|
+
);
|
|
219
|
+
if (!groupBackend) {
|
|
220
|
+
throw new HTTPException(409, {
|
|
221
|
+
message: "session has no managed sandbox group to attach",
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
const session =
|
|
225
|
+
groupBackend === input.session.sandboxBackend
|
|
226
|
+
? input.session
|
|
227
|
+
: {
|
|
228
|
+
...input.session,
|
|
229
|
+
sandboxBackend: groupBackend,
|
|
230
|
+
sandboxOs: managedSessionGroupOs(input.session.sandboxBackend, input.session.sandboxOs),
|
|
231
|
+
};
|
|
196
232
|
const viewerId = input.viewerId ?? crypto.randomUUID();
|
|
233
|
+
const attachSubjectId = claimableSubjectId(input.viewerSubjectId ?? null);
|
|
234
|
+
const attachAuthorityEpoch = attachSubjectId
|
|
235
|
+
? await getSessionAuthorityEpoch(db, { accountId, workspaceId, sessionId: session.id })
|
|
236
|
+
: null;
|
|
197
237
|
const leaseTtlMs = settings.sandboxLeaseTtlMs;
|
|
198
238
|
const sandboxGroupId = session.sandboxGroupId;
|
|
239
|
+
const sandboxRuntime = await resolveSessionSandboxRuntime(db, settings, session);
|
|
199
240
|
|
|
200
241
|
const release = async (): Promise<void> => {
|
|
201
242
|
await releaseLeaseHolder(db, {
|
|
@@ -217,19 +258,31 @@ export async function attachViewer(
|
|
|
217
258
|
kind: "viewer",
|
|
218
259
|
holderId: viewerId,
|
|
219
260
|
subjectId: session.id,
|
|
261
|
+
...(attachSubjectId ? { viewerSubjectId: attachSubjectId } : {}),
|
|
262
|
+
...(attachAuthorityEpoch !== null ? { viewerAuthorityEpoch: attachAuthorityEpoch } : {}),
|
|
220
263
|
backend: session.sandboxBackend,
|
|
264
|
+
warmBilling: {
|
|
265
|
+
mode: settings.sandboxWarmBillingMode,
|
|
266
|
+
rateMicrosPerSecond: sandboxWarmRateMicrosPerSecond(settings, session.sandboxBackend),
|
|
267
|
+
},
|
|
221
268
|
os: session.sandboxOs,
|
|
269
|
+
image: sandboxRuntime.image,
|
|
270
|
+
imagePolicy: "new_creates_only",
|
|
271
|
+
rigVersionId: session.rigVersionId,
|
|
222
272
|
leaseTtlMs,
|
|
223
273
|
warmingLeaseTtlMs: settings.sandboxWarmingTimeoutMs,
|
|
224
274
|
captureWaitMs: sandboxLifecycleTransitionWaitMs(settings),
|
|
225
275
|
...(input.waitSignal ? { waitSignal: input.waitSignal } : {}),
|
|
226
276
|
});
|
|
227
277
|
} catch (error) {
|
|
278
|
+
if (error instanceof SandboxPaidComputeAdmissionError) {
|
|
279
|
+
throw new HTTPException(402, { message: error.message, cause: error });
|
|
280
|
+
}
|
|
228
281
|
if (error instanceof SandboxViewerAdmissionBlockedError) {
|
|
229
282
|
throw new HTTPException(error.reason === "balance" ? 402 : 429, {
|
|
230
283
|
message:
|
|
231
284
|
error.reason === "balance"
|
|
232
|
-
? "insufficient
|
|
285
|
+
? "insufficient Opengeni credits for an idle sandbox viewer"
|
|
233
286
|
: "workspace sandbox warm allowance exhausted",
|
|
234
287
|
cause: error,
|
|
235
288
|
});
|
|
@@ -270,7 +323,16 @@ export async function attachViewer(
|
|
|
270
323
|
// so the next turn's agent-manifest apply finds an EMPTY environment delta in
|
|
271
324
|
// the SDK's validateNoEnvironmentDelta (otherwise: "Live sandbox sessions
|
|
272
325
|
// cannot change manifest environment variables").
|
|
273
|
-
const environment = await sessionAttachEnvironment(
|
|
326
|
+
const environment = await sessionAttachEnvironment(
|
|
327
|
+
services,
|
|
328
|
+
workspaceId,
|
|
329
|
+
session,
|
|
330
|
+
input.viewerSubjectId ?? null,
|
|
331
|
+
);
|
|
332
|
+
const providerSettings = await providerSettingsForSessionSandboxRuntime(
|
|
333
|
+
sandboxRuntime,
|
|
334
|
+
session.sandboxBackend,
|
|
335
|
+
);
|
|
274
336
|
// Prefer the COLD lease's preserved resume_state when it carries a persisted
|
|
275
337
|
// /workspace snapshot (confirmDrainCold keeps a minimal archive-only envelope
|
|
276
338
|
// across draining->cold). establishSandboxSessionFromEnvelope cold-creates a
|
|
@@ -279,7 +341,7 @@ export async function attachViewer(
|
|
|
279
341
|
// session envelope (a never-warmed cold start).
|
|
280
342
|
const result = await establishApiSandboxSpawner({
|
|
281
343
|
db,
|
|
282
|
-
settings,
|
|
344
|
+
settings: providerSettings,
|
|
283
345
|
accountId,
|
|
284
346
|
workspaceId,
|
|
285
347
|
sandboxGroupId,
|
|
@@ -290,6 +352,7 @@ export async function attachViewer(
|
|
|
290
352
|
acquiredLease: acquired.lease,
|
|
291
353
|
fallbackEnvelope: envelope,
|
|
292
354
|
dataPlaneUrl: null,
|
|
355
|
+
...(services.objectStorage !== undefined ? { objectStorage: services.objectStorage } : {}),
|
|
293
356
|
});
|
|
294
357
|
established = result.established;
|
|
295
358
|
return {
|
|
@@ -353,11 +416,16 @@ export async function attachViewer(
|
|
|
353
416
|
message: `sandbox is ${live.recovery.restore.status} at epoch ${live.leaseEpoch}`,
|
|
354
417
|
});
|
|
355
418
|
}
|
|
356
|
-
const environment = await sessionAttachEnvironment(
|
|
419
|
+
const environment = await sessionAttachEnvironment(
|
|
420
|
+
services,
|
|
421
|
+
workspaceId,
|
|
422
|
+
session,
|
|
423
|
+
input.viewerSubjectId ?? null,
|
|
424
|
+
);
|
|
357
425
|
let observed: EstablishedSandboxSession | undefined;
|
|
358
426
|
try {
|
|
359
427
|
const establish = services.establishSandboxSession ?? establishSandboxSessionFromEnvelope;
|
|
360
|
-
observed = await establish(settings, live.resumeState, {
|
|
428
|
+
observed = await establish(sandboxRuntime.settings, live.resumeState, {
|
|
361
429
|
sessionId: session.id,
|
|
362
430
|
recovery: "resume-only",
|
|
363
431
|
backendOverride: session.sandboxBackend,
|
|
@@ -430,13 +498,26 @@ export type SessionGroupReadinessHold = {
|
|
|
430
498
|
* it. */
|
|
431
499
|
export async function ensureSessionGroupReady(
|
|
432
500
|
services: ViewerServices,
|
|
433
|
-
input: {
|
|
501
|
+
input: {
|
|
502
|
+
accountId: string;
|
|
503
|
+
workspaceId: string;
|
|
504
|
+
session: Session;
|
|
505
|
+
/** The authenticated subject driving the fleet attach/swap (0282): recorded
|
|
506
|
+
* on the viewer holder and the materialization audit fact. Omitting it
|
|
507
|
+
* records the explicit service sentinel, so forward the route subject. */
|
|
508
|
+
subjectId?: string | null;
|
|
509
|
+
},
|
|
434
510
|
): Promise<SessionGroupReadinessHold> {
|
|
435
511
|
let lastError: unknown;
|
|
436
512
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
437
513
|
let release: (() => Promise<void>) | undefined;
|
|
438
514
|
try {
|
|
439
|
-
const attached = await attachViewer(services,
|
|
515
|
+
const attached = await attachViewer(services, {
|
|
516
|
+
accountId: input.accountId,
|
|
517
|
+
workspaceId: input.workspaceId,
|
|
518
|
+
session: input.session,
|
|
519
|
+
...(input.subjectId ? { viewerSubjectId: input.subjectId } : {}),
|
|
520
|
+
});
|
|
440
521
|
let releasePromise: Promise<void> | undefined;
|
|
441
522
|
release = () =>
|
|
442
523
|
(releasePromise ??= detachViewer(services, {
|
|
@@ -480,7 +561,7 @@ export async function heartbeatViewer(
|
|
|
480
561
|
expectedEpoch: number;
|
|
481
562
|
},
|
|
482
563
|
): Promise<boolean> {
|
|
483
|
-
|
|
564
|
+
const status = await heartbeatLeaseHolderStatus(services.db, {
|
|
484
565
|
accountId: input.accountId,
|
|
485
566
|
workspaceId: input.workspaceId,
|
|
486
567
|
sandboxGroupId: input.sandboxGroupId,
|
|
@@ -488,7 +569,21 @@ export async function heartbeatViewer(
|
|
|
488
569
|
holderId: input.viewerId,
|
|
489
570
|
leaseTtlMs: services.settings.sandboxLeaseTtlMs,
|
|
490
571
|
expectedEpoch: input.expectedEpoch,
|
|
572
|
+
billingMode: services.settings.sandboxWarmBillingMode,
|
|
491
573
|
});
|
|
574
|
+
// A funding fence stops renewing paid provider time, but the holder is
|
|
575
|
+
// deliberately kept alive while the viewer winds down or adds funds. Other
|
|
576
|
+
// fences (epoch/rotation/drain) still require the client to re-attach.
|
|
577
|
+
if (!status.leaseExtended) return status.holderAlive && status.fence === "funding";
|
|
578
|
+
const lease = await readLease(services.db, input.workspaceId, input.sandboxGroupId);
|
|
579
|
+
if (lease?.liveness === "warm" && lease.leaseEpoch === input.expectedEpoch && lease.instanceId) {
|
|
580
|
+
await renewSandboxProviderExpiration({
|
|
581
|
+
backend: lease.backend as Settings["sandboxBackend"],
|
|
582
|
+
settings: services.settings,
|
|
583
|
+
instanceId: lease.instanceId,
|
|
584
|
+
}).catch(() => false);
|
|
585
|
+
}
|
|
586
|
+
return true;
|
|
492
587
|
}
|
|
493
588
|
|
|
494
589
|
/**
|
|
@@ -498,7 +593,12 @@ export async function heartbeatViewer(
|
|
|
498
593
|
*/
|
|
499
594
|
export async function detachViewer(
|
|
500
595
|
services: ViewerServices,
|
|
501
|
-
input: {
|
|
596
|
+
input: {
|
|
597
|
+
accountId: string;
|
|
598
|
+
workspaceId: string;
|
|
599
|
+
sandboxGroupId: string;
|
|
600
|
+
viewerId: string;
|
|
601
|
+
},
|
|
502
602
|
): Promise<{ liveness: LeaseSnapshot["liveness"]; refcount: number } | null> {
|
|
503
603
|
return await releaseLeaseHolder(services.db, {
|
|
504
604
|
accountId: input.accountId,
|
|
@@ -625,7 +725,11 @@ export function resolveActiveDesktopTransport(
|
|
|
625
725
|
if (selfhostedActive) {
|
|
626
726
|
return { transport: "relay-frames", client: "frames", mode: "read-only" };
|
|
627
727
|
}
|
|
628
|
-
return {
|
|
728
|
+
return {
|
|
729
|
+
transport: "vnc-ws",
|
|
730
|
+
client: "novnc",
|
|
731
|
+
mode: interactive ? "interactive" : "read-only",
|
|
732
|
+
};
|
|
629
733
|
}
|
|
630
734
|
|
|
631
735
|
/** The minted pixel cell the handshake/attach folds into the DesktopStream
|
|
@@ -639,9 +743,73 @@ export type DesktopStreamMint = {
|
|
|
639
743
|
leaseEpoch: number;
|
|
640
744
|
};
|
|
641
745
|
|
|
746
|
+
/** A subject claim must satisfy the StreamTokenPayload bounds and the 0281
|
|
747
|
+
* holder CHECK (non-blank, <= 512). An out-of-bounds subject (possible only
|
|
748
|
+
* from a host-signed delegated token) is omitted from the claims rather than
|
|
749
|
+
* turning the mint into a 500. */
|
|
750
|
+
function claimableSubjectId(subjectId: string | null): string | null {
|
|
751
|
+
if (!subjectId) return null;
|
|
752
|
+
const trimmed = subjectId.trim();
|
|
753
|
+
return trimmed.length >= 1 && subjectId.length <= 512 ? subjectId : null;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
/**
|
|
757
|
+
* Resolve the viewer-facing authority claims stamped into a scoped stream
|
|
758
|
+
* token and recorded on the viewer holder (0281): the authenticated viewer
|
|
759
|
+
* subject and the session's LIVE authority epoch. Re-verifies a human
|
|
760
|
+
* (`user:`) subject's current workspace authority at mint time through the
|
|
761
|
+
* same model the route-time access builder uses - a membership row with an
|
|
762
|
+
* active owning organization membership, or an active organization
|
|
763
|
+
* membership's personal-workspace pointer - so a viewer whose authority was
|
|
764
|
+
* revoked since the route authorized them degrades to null (transport:null)
|
|
765
|
+
* instead of receiving a fresh token. Delegated token-borne grants
|
|
766
|
+
* (`subjectDelegated`) are authorized by their signed token, not by rows this
|
|
767
|
+
* check can see; they keep their route authorization, as do API-key and
|
|
768
|
+
* service principals. Identity and epoch only - never a secret value.
|
|
769
|
+
*/
|
|
770
|
+
async function resolveViewerAuthorityClaims(
|
|
771
|
+
db: ViewerServices["db"],
|
|
772
|
+
input: {
|
|
773
|
+
accountId: string;
|
|
774
|
+
workspaceId: string;
|
|
775
|
+
sessionId: string;
|
|
776
|
+
subjectId: string | null;
|
|
777
|
+
subjectDelegated?: boolean;
|
|
778
|
+
},
|
|
779
|
+
): Promise<{ subjectId?: string; authorityEpoch: number } | null> {
|
|
780
|
+
const authorityEpoch = await getSessionAuthorityEpoch(db, {
|
|
781
|
+
accountId: input.accountId,
|
|
782
|
+
workspaceId: input.workspaceId,
|
|
783
|
+
sessionId: input.sessionId,
|
|
784
|
+
});
|
|
785
|
+
if (authorityEpoch === null) {
|
|
786
|
+
return null;
|
|
787
|
+
}
|
|
788
|
+
if (input.subjectId?.startsWith("user:") && input.subjectDelegated !== true) {
|
|
789
|
+
const live = await namedSubjectHasLiveWorkspaceAuthority(db, {
|
|
790
|
+
accountId: input.accountId,
|
|
791
|
+
workspaceId: input.workspaceId,
|
|
792
|
+
subjectId: input.subjectId,
|
|
793
|
+
});
|
|
794
|
+
if (!live) {
|
|
795
|
+
return null;
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
const subjectId = claimableSubjectId(input.subjectId);
|
|
799
|
+
return {
|
|
800
|
+
...(subjectId ? { subjectId } : {}),
|
|
801
|
+
authorityEpoch,
|
|
802
|
+
};
|
|
803
|
+
}
|
|
804
|
+
|
|
642
805
|
export type MintDesktopStreamInput = {
|
|
643
806
|
accountId: string;
|
|
644
807
|
workspaceId: string;
|
|
808
|
+
resourceSubjectId?: string;
|
|
809
|
+
/** True when the route grant is a signed delegated token (metadata.delegated):
|
|
810
|
+
* its authority is the token, not membership rows, so the mint-time
|
|
811
|
+
* live-authority recheck does not apply. */
|
|
812
|
+
resourceSubjectDelegated?: boolean;
|
|
645
813
|
session: Session;
|
|
646
814
|
/** The viewer holder id the scoped token is minted for. */
|
|
647
815
|
viewerId: string;
|
|
@@ -704,20 +872,44 @@ export async function mintDesktopStream(
|
|
|
704
872
|
return null;
|
|
705
873
|
}
|
|
706
874
|
|
|
875
|
+
// 0281: the viewer's authority claims. A missing epoch (session not
|
|
876
|
+
// visible) or a removed human membership degrades the mint instead of
|
|
877
|
+
// issuing a fresh token.
|
|
878
|
+
const viewerAuthority = await resolveViewerAuthorityClaims(db, {
|
|
879
|
+
accountId,
|
|
880
|
+
workspaceId,
|
|
881
|
+
sessionId: session.id,
|
|
882
|
+
subjectId: input.resourceSubjectId ?? null,
|
|
883
|
+
...(input.resourceSubjectDelegated !== undefined
|
|
884
|
+
? { subjectDelegated: input.resourceSubjectDelegated }
|
|
885
|
+
: {}),
|
|
886
|
+
});
|
|
887
|
+
if (!viewerAuthority) {
|
|
888
|
+
return null;
|
|
889
|
+
}
|
|
890
|
+
|
|
707
891
|
// SELFHOSTED ACTIVE: when the session's active sandbox is a selfhosted machine,
|
|
708
892
|
// route to the relay (NOT the Modal group-box path — it would resume the wrong
|
|
709
893
|
// box and return a Modal URL). No Modal lease required.
|
|
710
894
|
if (session.activeSandboxId) {
|
|
711
|
-
const active = await getSandbox(
|
|
895
|
+
const active = await getSandbox(
|
|
896
|
+
db,
|
|
897
|
+
input.resourceSubjectId
|
|
898
|
+
? { accountId, workspaceId, subjectId: input.resourceSubjectId }
|
|
899
|
+
: workspaceId,
|
|
900
|
+
session.activeSandboxId,
|
|
901
|
+
);
|
|
712
902
|
if (active?.kind === "selfhosted") {
|
|
713
903
|
const m = await tryMintActiveSelfhostedStream(
|
|
714
904
|
services,
|
|
715
905
|
{
|
|
716
906
|
session,
|
|
717
907
|
viewerId: input.viewerId,
|
|
718
|
-
workspaceId,
|
|
908
|
+
workspaceId: active.workspaceId,
|
|
909
|
+
...(input.resourceSubjectId ? { resourceSubjectId: input.resourceSubjectId } : {}),
|
|
719
910
|
port: DESKTOP_STREAM_PORT,
|
|
720
911
|
sandbox: active,
|
|
912
|
+
viewerAuthority,
|
|
721
913
|
},
|
|
722
914
|
input.resolveSelfhostedSession,
|
|
723
915
|
);
|
|
@@ -749,7 +941,12 @@ export async function mintDesktopStream(
|
|
|
749
941
|
try {
|
|
750
942
|
// On a cold-restore (the lease's box is gone) this create() must carry the
|
|
751
943
|
// SAME stable run-env the turn declares, so a later turn finds no env delta.
|
|
752
|
-
const environment = await sessionAttachEnvironment(
|
|
944
|
+
const environment = await sessionAttachEnvironment(
|
|
945
|
+
services,
|
|
946
|
+
workspaceId,
|
|
947
|
+
session,
|
|
948
|
+
input.resourceSubjectId ?? null,
|
|
949
|
+
);
|
|
753
950
|
try {
|
|
754
951
|
const establish = () =>
|
|
755
952
|
(services.establishSandboxSession ?? establishSandboxSessionFromEnvelope)(
|
|
@@ -799,6 +996,7 @@ export async function mintDesktopStream(
|
|
|
799
996
|
leaseEpoch: lease.leaseEpoch,
|
|
800
997
|
streamTokenSecret: secret,
|
|
801
998
|
resolution: defaultResolution(settings),
|
|
999
|
+
...viewerAuthority,
|
|
802
1000
|
});
|
|
803
1001
|
} catch (error) {
|
|
804
1002
|
// A transient/headless provider failure degrades the desktop cell.
|
|
@@ -899,6 +1097,9 @@ type SelfhostedStreamMint = Omit<TerminalStreamMint, "transport">;
|
|
|
899
1097
|
export type MintTerminalStreamInput = {
|
|
900
1098
|
accountId: string;
|
|
901
1099
|
workspaceId: string;
|
|
1100
|
+
resourceSubjectId?: string;
|
|
1101
|
+
/** See MintDesktopStreamInput.resourceSubjectDelegated. */
|
|
1102
|
+
resourceSubjectDelegated?: boolean;
|
|
902
1103
|
session: Session;
|
|
903
1104
|
/** The viewer holder / principal id the scoped token is minted for. */
|
|
904
1105
|
viewerId: string;
|
|
@@ -947,20 +1148,44 @@ export async function mintTerminalStream(
|
|
|
947
1148
|
return null;
|
|
948
1149
|
}
|
|
949
1150
|
|
|
1151
|
+
// 0281: the viewer's authority claims. A missing epoch (session not
|
|
1152
|
+
// visible) or a removed human membership degrades the mint instead of
|
|
1153
|
+
// issuing a fresh token.
|
|
1154
|
+
const viewerAuthority = await resolveViewerAuthorityClaims(db, {
|
|
1155
|
+
accountId,
|
|
1156
|
+
workspaceId,
|
|
1157
|
+
sessionId: session.id,
|
|
1158
|
+
subjectId: input.resourceSubjectId ?? null,
|
|
1159
|
+
...(input.resourceSubjectDelegated !== undefined
|
|
1160
|
+
? { subjectDelegated: input.resourceSubjectDelegated }
|
|
1161
|
+
: {}),
|
|
1162
|
+
});
|
|
1163
|
+
if (!viewerAuthority) {
|
|
1164
|
+
return null;
|
|
1165
|
+
}
|
|
1166
|
+
|
|
950
1167
|
// SELFHOSTED ACTIVE: when the session's active sandbox is a selfhosted machine,
|
|
951
1168
|
// route to the relay. NEVER fall through to the Modal group-box path (it would
|
|
952
1169
|
// resume the wrong box / return a Modal URL).
|
|
953
1170
|
if (session.activeSandboxId) {
|
|
954
|
-
const active = await getSandbox(
|
|
1171
|
+
const active = await getSandbox(
|
|
1172
|
+
db,
|
|
1173
|
+
input.resourceSubjectId
|
|
1174
|
+
? { accountId, workspaceId, subjectId: input.resourceSubjectId }
|
|
1175
|
+
: workspaceId,
|
|
1176
|
+
session.activeSandboxId,
|
|
1177
|
+
);
|
|
955
1178
|
if (active?.kind === "selfhosted") {
|
|
956
1179
|
const stream = await tryMintActiveSelfhostedStream(
|
|
957
1180
|
services,
|
|
958
1181
|
{
|
|
959
1182
|
session,
|
|
960
1183
|
viewerId: input.viewerId,
|
|
961
|
-
workspaceId,
|
|
1184
|
+
workspaceId: active.workspaceId,
|
|
1185
|
+
...(input.resourceSubjectId ? { resourceSubjectId: input.resourceSubjectId } : {}),
|
|
962
1186
|
port: TERMINAL_STREAM_PORT,
|
|
963
1187
|
sandbox: active,
|
|
1188
|
+
viewerAuthority,
|
|
964
1189
|
},
|
|
965
1190
|
input.resolveSelfhostedSession,
|
|
966
1191
|
);
|
|
@@ -982,7 +1207,12 @@ export async function mintTerminalStream(
|
|
|
982
1207
|
try {
|
|
983
1208
|
// On a cold-restore this create() must carry the SAME stable run-env the turn
|
|
984
1209
|
// declares, so a later turn finds no manifest-env delta.
|
|
985
|
-
const environment = await sessionAttachEnvironment(
|
|
1210
|
+
const environment = await sessionAttachEnvironment(
|
|
1211
|
+
services,
|
|
1212
|
+
workspaceId,
|
|
1213
|
+
session,
|
|
1214
|
+
input.resourceSubjectId ?? null,
|
|
1215
|
+
);
|
|
986
1216
|
try {
|
|
987
1217
|
const establish = () =>
|
|
988
1218
|
(services.establishSandboxSession ?? establishSandboxSessionFromEnvelope)(
|
|
@@ -1008,7 +1238,9 @@ export async function mintTerminalStream(
|
|
|
1008
1238
|
// Idempotent ttyd launch (flock-guarded; a no-op when already up). A box that
|
|
1009
1239
|
// genuinely can't run it degrades to the sse-events firehose, not a throw.
|
|
1010
1240
|
try {
|
|
1011
|
-
await ensureTerminalServer(established.session, {
|
|
1241
|
+
await ensureTerminalServer(established.session, {
|
|
1242
|
+
port: TERMINAL_STREAM_PORT,
|
|
1243
|
+
});
|
|
1012
1244
|
} catch (error) {
|
|
1013
1245
|
if (error instanceof TerminalServerUnsupportedError) {
|
|
1014
1246
|
return null;
|
|
@@ -1029,6 +1261,7 @@ export async function mintTerminalStream(
|
|
|
1029
1261
|
leaseEpoch: lease.leaseEpoch,
|
|
1030
1262
|
streamTokenSecret: secret,
|
|
1031
1263
|
port: TERMINAL_STREAM_PORT,
|
|
1264
|
+
...viewerAuthority,
|
|
1032
1265
|
});
|
|
1033
1266
|
} catch (error) {
|
|
1034
1267
|
if (error instanceof StreamPortUnavailableError) {
|
|
@@ -1104,8 +1337,11 @@ async function tryMintActiveSelfhostedStream(
|
|
|
1104
1337
|
session: Session;
|
|
1105
1338
|
viewerId: string;
|
|
1106
1339
|
workspaceId: string;
|
|
1340
|
+
resourceSubjectId?: string;
|
|
1107
1341
|
port: number;
|
|
1108
1342
|
sandbox: SandboxRecord;
|
|
1343
|
+
/** 0281 viewer authority claims stamped into the relay stream token. */
|
|
1344
|
+
viewerAuthority?: { subjectId?: string; authorityEpoch: number };
|
|
1109
1345
|
},
|
|
1110
1346
|
// optional test seam (mirrors the existing `establish?` seam pattern): inject a
|
|
1111
1347
|
// fake relay-resolving session; production NEVER passes it.
|
|
@@ -1127,11 +1363,26 @@ async function tryMintActiveSelfhostedStream(
|
|
|
1127
1363
|
if (resolveSelfhostedSession) {
|
|
1128
1364
|
shSession = await resolveSelfhostedSession(sandbox);
|
|
1129
1365
|
} else {
|
|
1366
|
+
const enrollment = await getLiveEnrollmentConnection(
|
|
1367
|
+
services.db,
|
|
1368
|
+
input.resourceSubjectId
|
|
1369
|
+
? {
|
|
1370
|
+
accountId: input.session.accountId,
|
|
1371
|
+
workspaceId: input.session.workspaceId,
|
|
1372
|
+
subjectId: input.resourceSubjectId,
|
|
1373
|
+
}
|
|
1374
|
+
: workspaceId,
|
|
1375
|
+
sandbox.enrollmentId,
|
|
1376
|
+
);
|
|
1377
|
+
if (!enrollment?.connectionInstanceId) return null;
|
|
1378
|
+
if (!enrollment.workspaceRoot) return null;
|
|
1130
1379
|
const client = new SelfhostedSandboxClient({
|
|
1131
1380
|
workspaceId,
|
|
1381
|
+
workspaceRoot: enrollment.workspaceRoot,
|
|
1132
1382
|
relay: relayConfigFromSettings(settings),
|
|
1133
1383
|
controlRpcFactory: () => controlRpc(bus),
|
|
1134
1384
|
agentId: sandbox.enrollmentId,
|
|
1385
|
+
connectionInstanceId: enrollment.connectionInstanceId,
|
|
1135
1386
|
epoch: session.activeEpoch,
|
|
1136
1387
|
// Stream authority rotates; terminal process identity does not.
|
|
1137
1388
|
terminalScopeId: session.id,
|
|
@@ -1151,6 +1402,7 @@ async function tryMintActiveSelfhostedStream(
|
|
|
1151
1402
|
sessionId: session.id,
|
|
1152
1403
|
viewerId: input.viewerId,
|
|
1153
1404
|
activeEpoch: session.activeEpoch,
|
|
1405
|
+
...(input.viewerAuthority ? { viewerAuthority: input.viewerAuthority } : {}),
|
|
1154
1406
|
port,
|
|
1155
1407
|
session: shSession,
|
|
1156
1408
|
});
|
|
@@ -1170,6 +1422,8 @@ export type MintSelfhostedStreamInput = {
|
|
|
1170
1422
|
* THIS as its leaseEpoch claim so the relay rejects a stale-epoch (swapped-away)
|
|
1171
1423
|
* viewer. */
|
|
1172
1424
|
activeEpoch: number;
|
|
1425
|
+
/** 0281 viewer authority claims stamped into the relay stream token. */
|
|
1426
|
+
viewerAuthority?: { subjectId?: string; authorityEpoch: number };
|
|
1173
1427
|
/** The exposed stream port (6080 desktop / 7681 terminal). */
|
|
1174
1428
|
port: number;
|
|
1175
1429
|
/** The resolvable selfhosted session (the routing proxy resolves the active
|
|
@@ -1213,6 +1467,7 @@ export async function mintSelfhostedStream(
|
|
|
1213
1467
|
leaseEpoch: input.activeEpoch,
|
|
1214
1468
|
streamTokenSecret: secret,
|
|
1215
1469
|
port: input.port,
|
|
1470
|
+
...(input.viewerAuthority ?? {}),
|
|
1216
1471
|
});
|
|
1217
1472
|
return {
|
|
1218
1473
|
url: exposed.url,
|