@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
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
// FLAG GATE: the whole feature is behind sandboxSelfhostedEnabled (default OFF) —
|
|
29
29
|
// when off the routes 404 (the surface is invisible) and boot is unaffected.
|
|
30
30
|
|
|
31
|
-
import { randomBytes } from "node:crypto";
|
|
31
|
+
import { createPublicKey, randomBytes, verify } from "node:crypto";
|
|
32
32
|
import {
|
|
33
33
|
resolveEnrollmentSigningSecret,
|
|
34
34
|
resolveRelayTokenSecret,
|
|
@@ -36,10 +36,13 @@ import {
|
|
|
36
36
|
} from "@opengeni/config";
|
|
37
37
|
import {
|
|
38
38
|
DeviceEnrollmentState,
|
|
39
|
+
enrollmentRenewalProof,
|
|
39
40
|
signEnrollmentBearer,
|
|
40
41
|
signEnrollToken,
|
|
41
42
|
signRelayToken,
|
|
42
43
|
verifyEnrollToken,
|
|
44
|
+
verifyEnrollmentBearer,
|
|
45
|
+
type RenewEnrollmentRequest,
|
|
43
46
|
type DeviceEnrollmentLookupResponse,
|
|
44
47
|
type DeviceEnrollmentPollResponse,
|
|
45
48
|
type DeviceEnrollmentStartResponse,
|
|
@@ -52,11 +55,14 @@ import {
|
|
|
52
55
|
consumeDeviceEnrollmentRequest,
|
|
53
56
|
createDeviceEnrollmentRequest,
|
|
54
57
|
denyDeviceEnrollmentRequest,
|
|
58
|
+
EnrollTokenAlreadyRedeemedError,
|
|
59
|
+
EnrollTokenOwnerUnavailableError,
|
|
55
60
|
finalizeEnrollmentByToken,
|
|
56
61
|
getDeviceEnrollmentRequestByDeviceCode,
|
|
57
62
|
getEnrollment,
|
|
58
63
|
getPendingDeviceEnrollmentRequestByUserCode,
|
|
59
64
|
getPendingDeviceEnrollmentRequestByUserCodeGlobal,
|
|
65
|
+
PersonalMachineConnectedElsewhereError,
|
|
60
66
|
type Database,
|
|
61
67
|
type DeviceEnrollmentRequestRecord,
|
|
62
68
|
type EnrollmentOs,
|
|
@@ -71,7 +77,8 @@ export const DEVICE_POLL_INTERVAL_SECONDS = 5;
|
|
|
71
77
|
// The bearer the agent presents to the NATS auth-callout. A bring-your-own-compute
|
|
72
78
|
// machine is PERSISTENT (unlike an ephemeral Modal box, whose lifetime ~= an agent
|
|
73
79
|
// token's hour), so this is long-lived — 30 days, matching the relay token below —
|
|
74
|
-
// and re-minted on
|
|
80
|
+
// and renewed automatically by install-key proof, or re-minted on poll/re-enroll.
|
|
81
|
+
// The old 1-hour value (sized for a Modal
|
|
75
82
|
// box) caused a self-hosted agent to drop PERMANENTLY one hour after connecting: the
|
|
76
83
|
// bearer expired and the auth-callout rejected every reconnect ("re-enroll may be
|
|
77
84
|
// required"). A long-lived bearer is safe because the auth-callout RE-CHECKS the
|
|
@@ -83,10 +90,69 @@ export const ENROLLMENT_BEARER_TTL_SECONDS = 30 * 24 * 3600;
|
|
|
83
90
|
// NOT per-stream: the agent presents it on every channel registration for the life
|
|
84
91
|
// of its run, and the producer side has no per-viewer epoch fence (that is the
|
|
85
92
|
// VIEWER's `ogs_` token's job). So it is long-lived — 30 days — re-minted on every
|
|
86
|
-
// poll/re-enroll. The relay re-verifies it (authenticity + the channel-key ws+agent
|
|
93
|
+
// renewal/poll/re-enroll. The relay re-verifies it (authenticity + the channel-key ws+agent
|
|
87
94
|
// scope) on every StreamOpen; a revoked enrollment's machine goes offline at the
|
|
88
95
|
// control plane regardless, so a long-lived relay token cannot reach a dead agent.
|
|
89
96
|
export const RELAY_TOKEN_TTL_SECONDS = 30 * 24 * 3600;
|
|
97
|
+
|
|
98
|
+
/** Renew an existing grant, including after a long offline interval. The expired
|
|
99
|
+
* bearer is only an authenticated enrollment/generation locator here: current
|
|
100
|
+
* install-key possession and live enrollment authority are both required. Normal
|
|
101
|
+
* NATS/relay authentication continues to reject expired transport credentials.
|
|
102
|
+
* Nothing creates/reactivates an enrollment or changes its consent or scope. */
|
|
103
|
+
export async function renewEnrollmentCredentials(
|
|
104
|
+
services: EnrollmentServices,
|
|
105
|
+
input: RenewEnrollmentRequest,
|
|
106
|
+
nowSeconds = Math.floor(Date.now() / 1000),
|
|
107
|
+
): Promise<EnrollmentCredentialsResponse | null> {
|
|
108
|
+
if (Math.abs(nowSeconds - input.signedAt) > 120) return null;
|
|
109
|
+
const secret = resolveEnrollmentSigningSecret(services.settings);
|
|
110
|
+
if (!secret) return null;
|
|
111
|
+
const claims = await verifyEnrollmentBearer(secret, input.bearer, 0);
|
|
112
|
+
if (
|
|
113
|
+
!claims ||
|
|
114
|
+
claims.agentId !== claims.enrollmentId ||
|
|
115
|
+
claims.subjectPrefix !== `agent.${claims.workspaceId}.${claims.agentId}`
|
|
116
|
+
)
|
|
117
|
+
return null;
|
|
118
|
+
const enrollment = await getEnrollment(services.db, claims.workspaceId, claims.enrollmentId);
|
|
119
|
+
if (
|
|
120
|
+
!enrollment ||
|
|
121
|
+
enrollment.status !== "active" ||
|
|
122
|
+
enrollment.credentialGeneration !== claims.credentialGeneration
|
|
123
|
+
)
|
|
124
|
+
return null;
|
|
125
|
+
try {
|
|
126
|
+
const rawKey = Buffer.from(enrollment.pubkey, "base64");
|
|
127
|
+
const signature = Buffer.from(input.signature, "base64");
|
|
128
|
+
if (rawKey.length !== 32 || signature.length !== 64) return null;
|
|
129
|
+
const key = createPublicKey({
|
|
130
|
+
key: Buffer.concat([Buffer.from("302a300506032b6570032100", "hex"), rawKey]),
|
|
131
|
+
format: "der",
|
|
132
|
+
type: "spki",
|
|
133
|
+
});
|
|
134
|
+
if (
|
|
135
|
+
!verify(
|
|
136
|
+
null,
|
|
137
|
+
Buffer.from(enrollmentRenewalProof(input.bearer, input.signedAt)),
|
|
138
|
+
key,
|
|
139
|
+
signature,
|
|
140
|
+
)
|
|
141
|
+
)
|
|
142
|
+
return null;
|
|
143
|
+
} catch {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
// A concurrent revoke/re-enrollment still wins: issued credentials retain the
|
|
147
|
+
// captured generation, which the control-plane claim rechecks transactionally.
|
|
148
|
+
return buildEnrollmentCredentials(services, {
|
|
149
|
+
secret,
|
|
150
|
+
workspaceId: enrollment.workspaceId,
|
|
151
|
+
agentId: enrollment.id,
|
|
152
|
+
credentialGeneration: enrollment.credentialGeneration,
|
|
153
|
+
consentedScreenControl: enrollment.allowScreenControl,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
90
156
|
// The headless enroll token (`oget_`; design 11 §A2.1) TTL. 1h: long enough to
|
|
91
157
|
// script a fleet rollout, short enough to bound exposure of a workspace-scoped
|
|
92
158
|
// secret that IS the grant (no human approve). Re-mintable by an authorized user.
|
|
@@ -294,15 +360,19 @@ export async function denyDeviceEnrollment(
|
|
|
294
360
|
}
|
|
295
361
|
|
|
296
362
|
/** MINT a headless enroll token (design 11 §A2.2). Signs an `oget_` token bound to
|
|
297
|
-
* the workspace + account + the screen-control consent, with a 1h TTL.
|
|
298
|
-
*
|
|
299
|
-
*
|
|
363
|
+
* the workspace + account + the screen-control consent, with a 1h TTL. With an
|
|
364
|
+
* `ownerSubjectId` the token is personal (`enroll_user`): the machine it connects
|
|
365
|
+
* belongs to that person. Callers must pass only an authenticated human's own
|
|
366
|
+
* subject. Returns null when the credential plane is disabled (no signing secret)
|
|
367
|
+
* so the route can mirror poll's "disabled" handling. The token value is NEVER
|
|
368
|
+
* logged. */
|
|
300
369
|
export async function mintEnrollToken(
|
|
301
370
|
services: EnrollmentServices,
|
|
302
371
|
input: {
|
|
303
372
|
accountId: string;
|
|
304
373
|
workspaceId: string;
|
|
305
374
|
allowScreenControl: boolean;
|
|
375
|
+
ownerSubjectId?: string | null;
|
|
306
376
|
},
|
|
307
377
|
): Promise<MintEnrollTokenResponse | null> {
|
|
308
378
|
const { settings } = services;
|
|
@@ -312,18 +382,28 @@ export async function mintEnrollToken(
|
|
|
312
382
|
}
|
|
313
383
|
const nowSeconds = Math.floor(Date.now() / 1000);
|
|
314
384
|
const exp = nowSeconds + ENROLL_TOKEN_TTL_SECONDS;
|
|
315
|
-
const
|
|
316
|
-
typ: "enroll",
|
|
385
|
+
const claims = {
|
|
317
386
|
workspaceId: input.workspaceId,
|
|
318
387
|
accountId: input.accountId,
|
|
319
388
|
allowScreenControl: input.allowScreenControl,
|
|
320
389
|
iat: nowSeconds,
|
|
321
390
|
exp,
|
|
322
|
-
|
|
391
|
+
// Single-use: the exchange records this id, so the token connects one machine.
|
|
392
|
+
jti: randomBytes(18).toString("base64url"),
|
|
393
|
+
};
|
|
394
|
+
const ownerSubjectId = input.ownerSubjectId ?? null;
|
|
395
|
+
const token = await signEnrollToken(
|
|
396
|
+
secret,
|
|
397
|
+
ownerSubjectId !== null
|
|
398
|
+
? { typ: "enroll_user", ownerSubjectId, ...claims }
|
|
399
|
+
: { typ: "enroll", ...claims },
|
|
400
|
+
);
|
|
323
401
|
return {
|
|
324
402
|
token,
|
|
325
403
|
expiresAt: new Date(exp * 1000).toISOString(),
|
|
326
404
|
expiresInSeconds: ENROLL_TOKEN_TTL_SECONDS,
|
|
405
|
+
scope: ownerSubjectId !== null ? "user" : "workspace",
|
|
406
|
+
allowScreenControl: input.allowScreenControl,
|
|
327
407
|
};
|
|
328
408
|
}
|
|
329
409
|
|
|
@@ -331,7 +411,11 @@ export async function mintEnrollToken(
|
|
|
331
411
|
export type ExchangeEnrollTokenResult =
|
|
332
412
|
| { ok: true; credentials: EnrollTokenExchangeResponse["credentials"] }
|
|
333
413
|
| { ok: false; reason: "disabled" }
|
|
334
|
-
| { ok: false; reason: "invalid" }
|
|
414
|
+
| { ok: false; reason: "invalid" }
|
|
415
|
+
| { ok: false; reason: "used" }
|
|
416
|
+
| { ok: false; reason: "owner_unavailable" }
|
|
417
|
+
| { ok: false; reason: "connected_elsewhere" }
|
|
418
|
+
| { ok: false; reason: "busy" };
|
|
335
419
|
|
|
336
420
|
/** EXCHANGE a headless enroll token (design 11 §A2.3) — the UNAUTHENTICATED path
|
|
337
421
|
* where the token IS the auth. Verifies the `oget_` token, then performs the SAME
|
|
@@ -366,18 +450,43 @@ export async function exchangeEnrollToken(
|
|
|
366
450
|
|
|
367
451
|
// The SAME finalize as approve, but driven by the token's claims (no pending row).
|
|
368
452
|
const sandboxName = (input.machineName?.trim() || `${input.os} machine`).slice(0, 256);
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
453
|
+
let enrollment: Awaited<ReturnType<typeof finalizeEnrollmentByToken>>["enrollment"];
|
|
454
|
+
try {
|
|
455
|
+
({ enrollment } = await finalizeEnrollmentByToken(db, {
|
|
456
|
+
accountId: claims.accountId,
|
|
457
|
+
workspaceId: claims.workspaceId,
|
|
458
|
+
// A personal token connects the signed owner's own machine; the finalizer
|
|
459
|
+
// rechecks that person's live membership and workspace access.
|
|
460
|
+
...(claims.typ === "enroll_user" ? { ownerSubjectId: claims.ownerSubjectId } : {}),
|
|
461
|
+
pubkey: input.publicKey,
|
|
462
|
+
hasDisplay: input.canOfferDisplay,
|
|
463
|
+
// The token's allowScreenControl is the AUTHORITATIVE consent (NOT the agent's
|
|
464
|
+
// requestsScreenControl) — it was baked in at mint by the authorizing user.
|
|
465
|
+
allowScreenControl: claims.allowScreenControl,
|
|
466
|
+
os: input.os,
|
|
467
|
+
arch: input.arch,
|
|
468
|
+
sandboxName,
|
|
469
|
+
// A token with an id connects one machine; the same machine may retry.
|
|
470
|
+
...(claims.jti ? { tokenId: claims.jti, tokenExpiresAt: new Date(claims.exp * 1000) } : {}),
|
|
471
|
+
}));
|
|
472
|
+
} catch (error) {
|
|
473
|
+
if (error instanceof EnrollTokenAlreadyRedeemedError) {
|
|
474
|
+
return { ok: false, reason: "used" };
|
|
475
|
+
}
|
|
476
|
+
if (error instanceof EnrollTokenOwnerUnavailableError) {
|
|
477
|
+
return { ok: false, reason: "owner_unavailable" };
|
|
478
|
+
}
|
|
479
|
+
if (error instanceof PersonalMachineConnectedElsewhereError) {
|
|
480
|
+
// The owner's personal enrollment for this machine lives in another
|
|
481
|
+
// workspace; nothing was written and the token was not claimed.
|
|
482
|
+
return { ok: false, reason: "connected_elsewhere" };
|
|
483
|
+
}
|
|
484
|
+
if ((error as { code?: unknown } | null)?.code === "55P03") {
|
|
485
|
+
// The owner's organization membership is changing right now.
|
|
486
|
+
return { ok: false, reason: "busy" };
|
|
487
|
+
}
|
|
488
|
+
throw error;
|
|
489
|
+
}
|
|
381
490
|
|
|
382
491
|
const credentials = await buildEnrollmentCredentials(services, {
|
|
383
492
|
secret,
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
// Changing who can use a Connected Machine (Workspace or Only me) in place.
|
|
2
|
+
// The routes in ../routes/machines.ts stay thin: this module owns who may ask
|
|
3
|
+
// for which change, and the public shape of the preview and its refusals. The
|
|
4
|
+
// database functions recompute everything under the machine lock, so these
|
|
5
|
+
// checks only decide whether the caller may ask at all.
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
ChangeMachineAudienceResponse,
|
|
9
|
+
MachineAudiencePreview,
|
|
10
|
+
type MachineAudience,
|
|
11
|
+
} from "@opengeni/contracts";
|
|
12
|
+
import type {
|
|
13
|
+
MachineAudienceChangeRecord,
|
|
14
|
+
MachineAudiencePreviewRecord,
|
|
15
|
+
MachineAudienceRefusal,
|
|
16
|
+
} from "@opengeni/db";
|
|
17
|
+
import { ApiHttpError } from "../http/api-error";
|
|
18
|
+
|
|
19
|
+
type AudienceCaller = {
|
|
20
|
+
subjectId: string;
|
|
21
|
+
permissions: readonly string[];
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
type AudienceMachine = {
|
|
25
|
+
workspaceId: string;
|
|
26
|
+
scope: "organization" | "workspace" | "user";
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Decide whether the caller may ask for this change and who would own the
|
|
31
|
+
* machine. Narrowing to Only me: the person who will own it, or a workspace
|
|
32
|
+
* admin acting for that person. Sharing with the workspace: a workspace admin
|
|
33
|
+
* (the database also requires the caller to be the machine's owner, so nobody
|
|
34
|
+
* can expose another person's Only me machine).
|
|
35
|
+
*/
|
|
36
|
+
export function machineAudienceRequestFor(
|
|
37
|
+
caller: AudienceCaller,
|
|
38
|
+
routeWorkspaceId: string,
|
|
39
|
+
machine: AudienceMachine,
|
|
40
|
+
request: { audience: MachineAudience; ownerSubjectId?: string | undefined },
|
|
41
|
+
): { ownerSubjectId: string | null } {
|
|
42
|
+
if (machine.scope === "organization") {
|
|
43
|
+
throw new ApiHttpError(422, {
|
|
44
|
+
code: "validation_failed",
|
|
45
|
+
message:
|
|
46
|
+
"Organization machines are shared with the whole organization and can't be changed here.",
|
|
47
|
+
retryable: false,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
if (machine.workspaceId !== routeWorkspaceId) {
|
|
51
|
+
throw new ApiHttpError(409, {
|
|
52
|
+
code: "conflict",
|
|
53
|
+
message: "Change who can use this machine from the workspace it was connected to.",
|
|
54
|
+
retryable: false,
|
|
55
|
+
details: { machineWorkspaceId: machine.workspaceId },
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
const workspaceAdmin = caller.permissions.includes("workspace:admin");
|
|
59
|
+
if (request.audience === "workspace") {
|
|
60
|
+
if (request.ownerSubjectId !== undefined) {
|
|
61
|
+
throw new ApiHttpError(400, {
|
|
62
|
+
code: "validation_failed",
|
|
63
|
+
message: "A machine shared with the workspace has no single owner.",
|
|
64
|
+
retryable: false,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
if (!workspaceAdmin) {
|
|
68
|
+
throw new ApiHttpError(403, {
|
|
69
|
+
code: "forbidden",
|
|
70
|
+
message: "missing permission: workspace:admin",
|
|
71
|
+
retryable: false,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return { ownerSubjectId: null };
|
|
75
|
+
}
|
|
76
|
+
const ownerSubjectId = request.ownerSubjectId ?? caller.subjectId;
|
|
77
|
+
if (ownerSubjectId !== caller.subjectId && !workspaceAdmin) {
|
|
78
|
+
throw new ApiHttpError(403, {
|
|
79
|
+
code: "forbidden",
|
|
80
|
+
message: "missing permission: workspace:admin",
|
|
81
|
+
retryable: false,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
return { ownerSubjectId };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const REFUSALS: Record<MachineAudienceRefusal, { status: number; message: string }> = {
|
|
88
|
+
machine_not_found: { status: 404, message: "machine not found in this access scope" },
|
|
89
|
+
organization_machine: {
|
|
90
|
+
status: 422,
|
|
91
|
+
message:
|
|
92
|
+
"Organization machines are shared with the whole organization and can't be changed here.",
|
|
93
|
+
},
|
|
94
|
+
invalid_target: { status: 400, message: "Choose Workspace or Only me." },
|
|
95
|
+
already_target: { status: 409, message: "The machine already has this audience." },
|
|
96
|
+
owner_not_member: {
|
|
97
|
+
status: 422,
|
|
98
|
+
message: "The new owner must be an active member of this organization.",
|
|
99
|
+
},
|
|
100
|
+
owner_lacks_workspace_access: {
|
|
101
|
+
status: 422,
|
|
102
|
+
message: "The new owner must be able to use this workspace.",
|
|
103
|
+
},
|
|
104
|
+
not_machine_owner: {
|
|
105
|
+
status: 403,
|
|
106
|
+
message: "Only the machine's owner can share it with the workspace.",
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export function machineAudienceRefusalError(refusal: MachineAudienceRefusal): ApiHttpError {
|
|
111
|
+
const known = REFUSALS[refusal] ?? { status: 409, message: "The machine can't change now." };
|
|
112
|
+
return new ApiHttpError(known.status, {
|
|
113
|
+
code:
|
|
114
|
+
known.status === 404
|
|
115
|
+
? "not_found"
|
|
116
|
+
: known.status === 403
|
|
117
|
+
? "forbidden"
|
|
118
|
+
: known.status === 409
|
|
119
|
+
? "conflict"
|
|
120
|
+
: "validation_failed",
|
|
121
|
+
message: known.message,
|
|
122
|
+
retryable: false,
|
|
123
|
+
details: { refusal },
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function machineAudiencePreview(
|
|
128
|
+
record: MachineAudiencePreviewRecord,
|
|
129
|
+
): MachineAudiencePreview {
|
|
130
|
+
return MachineAudiencePreview.parse({
|
|
131
|
+
enrollmentId: record.enrollmentId,
|
|
132
|
+
sandboxId: record.sandboxId,
|
|
133
|
+
machineName: record.machineName,
|
|
134
|
+
currentAudience: record.currentAudience,
|
|
135
|
+
targetAudience: record.targetAudience,
|
|
136
|
+
generation: record.generation,
|
|
137
|
+
ownerSubjectId: record.targetAudience === "only_me" ? record.ownerSubjectId : null,
|
|
138
|
+
summary: record.summary,
|
|
139
|
+
ready: record.ready,
|
|
140
|
+
items: record.items.map((item) => ({
|
|
141
|
+
kind: item.kind,
|
|
142
|
+
action: item.action,
|
|
143
|
+
sessionId: item.sessionId ?? null,
|
|
144
|
+
scheduledTaskId: item.scheduledTaskId ?? null,
|
|
145
|
+
enrollmentId: item.enrollmentId ?? null,
|
|
146
|
+
workspaceId: item.workspaceId ?? null,
|
|
147
|
+
relation: item.relation ?? null,
|
|
148
|
+
visibility: item.visibility ?? null,
|
|
149
|
+
title: (item.kind === "schedule" ? item.name : item.title) ?? null,
|
|
150
|
+
ownerSubjectId: item.ownerSubjectId ?? null,
|
|
151
|
+
stopsTurn: item.stopsTurn ?? false,
|
|
152
|
+
stopsCommands: item.stopsCommands ?? 0,
|
|
153
|
+
})),
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** Map an applied change, or explain why nothing changed. */
|
|
158
|
+
export function machineAudienceChangeResponse(
|
|
159
|
+
record: MachineAudienceChangeRecord,
|
|
160
|
+
): ChangeMachineAudienceResponse {
|
|
161
|
+
switch (record.outcome) {
|
|
162
|
+
case "changed":
|
|
163
|
+
return ChangeMachineAudienceResponse.parse({
|
|
164
|
+
enrollmentId: record.enrollmentId,
|
|
165
|
+
sandboxId: record.sandboxId,
|
|
166
|
+
previousAudience: record.previousAudience,
|
|
167
|
+
audience: record.audience,
|
|
168
|
+
ownerSubjectId: record.ownerSubjectId,
|
|
169
|
+
generation: record.generation,
|
|
170
|
+
summary: record.summary,
|
|
171
|
+
detachedSessionIds: record.detachedSessionIds,
|
|
172
|
+
keptSessionIds: record.keptSessionIds,
|
|
173
|
+
});
|
|
174
|
+
case "stale":
|
|
175
|
+
throw new ApiHttpError(409, {
|
|
176
|
+
code: "conflict",
|
|
177
|
+
message: "The machine changed since you reviewed it. Review the list again.",
|
|
178
|
+
retryable: false,
|
|
179
|
+
details: { reason: "stale", generation: record.generation },
|
|
180
|
+
});
|
|
181
|
+
case "blocked":
|
|
182
|
+
throw new ApiHttpError(409, {
|
|
183
|
+
code: "conflict",
|
|
184
|
+
message:
|
|
185
|
+
"This computer is also connected as a separate machine. Remove that copy first, then try again.",
|
|
186
|
+
retryable: false,
|
|
187
|
+
details: { reason: "blocked", preview: machineAudiencePreview(record.preview) },
|
|
188
|
+
});
|
|
189
|
+
case "refused":
|
|
190
|
+
throw machineAudienceRefusalError(record.refusal);
|
|
191
|
+
}
|
|
192
|
+
}
|
package/src/sandbox/machines.ts
CHANGED
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
import type { Settings } from "@opengeni/config";
|
|
23
23
|
import {
|
|
24
|
+
enrollmentMacPermissions,
|
|
24
25
|
getSession,
|
|
25
26
|
getLiveEnrollmentConnection,
|
|
26
27
|
listEnrollments,
|
|
@@ -32,8 +33,13 @@ import {
|
|
|
32
33
|
type EnrollmentRecord,
|
|
33
34
|
type MachineMetricsRow,
|
|
34
35
|
} from "@opengeni/db";
|
|
35
|
-
import {
|
|
36
|
-
|
|
36
|
+
import {
|
|
37
|
+
MachineView,
|
|
38
|
+
MetricSample,
|
|
39
|
+
type MachineRuntime,
|
|
40
|
+
type MachinesResponse,
|
|
41
|
+
} from "@opengeni/contracts";
|
|
42
|
+
import { managedSessionGroupBackend, sessionGroupMachinePresentation } from "@opengeni/core";
|
|
37
43
|
import { selfhostedHeartbeatLiveness } from "@opengeni/runtime/sandbox";
|
|
38
44
|
|
|
39
45
|
export type MachinesServices = {
|
|
@@ -41,7 +47,7 @@ export type MachinesServices = {
|
|
|
41
47
|
settings: Settings;
|
|
42
48
|
};
|
|
43
49
|
|
|
44
|
-
const ACTIVE_UPDATE_STATUSES = new Set([
|
|
50
|
+
export const ACTIVE_UPDATE_STATUSES: ReadonlySet<string> = new Set([
|
|
45
51
|
"requested",
|
|
46
52
|
"accepted",
|
|
47
53
|
"waiting_for_idle",
|
|
@@ -51,7 +57,7 @@ const ACTIVE_UPDATE_STATUSES = new Set([
|
|
|
51
57
|
"restarting",
|
|
52
58
|
]);
|
|
53
59
|
|
|
54
|
-
function compareAgentVersions(left: string, right: string): number | null {
|
|
60
|
+
export function compareAgentVersions(left: string, right: string): number | null {
|
|
55
61
|
const parse = (value: string): { core: number[]; prerelease: string | null } | null => {
|
|
56
62
|
const match = /^(?:v)?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?$/.exec(value.trim());
|
|
57
63
|
if (!match) return null;
|
|
@@ -73,28 +79,57 @@ function compareAgentVersions(left: string, right: string): number | null {
|
|
|
73
79
|
return a.prerelease.localeCompare(b.prerelease);
|
|
74
80
|
}
|
|
75
81
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
82
|
+
/** The build the operator promoted for a machine's update channel. */
|
|
83
|
+
export function promotedAgentVersion(
|
|
84
|
+
settings: Pick<Settings, "agentStableVersion" | "agentBetaVersion">,
|
|
85
|
+
channel: string | null,
|
|
86
|
+
): string {
|
|
87
|
+
return channel === "beta"
|
|
88
|
+
? (settings.agentBetaVersion ?? settings.agentStableVersion)
|
|
89
|
+
: settings.agentStableVersion;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Older Mac updaters replace a single file inside a sealed app. They must
|
|
93
|
+
* bootstrap once through the official whole-app installer, never an RPC swap. */
|
|
94
|
+
export function machineUpdateBlockedReason(os: string, version: string | null): string | null {
|
|
95
|
+
if (os !== "macos") return null;
|
|
96
|
+
const order = version ? compareAgentVersions(version, "0.1.29") : null;
|
|
97
|
+
return order !== null && order >= 0
|
|
98
|
+
? null
|
|
99
|
+
: "Install Opengeni Agent 0.1.29 or newer with the official Mac installer first. This older updater cannot preserve the signed application.";
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
type AgentUpdateRecord = EnrollmentRecord["agentUpdate"];
|
|
103
|
+
|
|
104
|
+
/** Where the installed agent stands against the promoted build. A failed update
|
|
105
|
+
* stops mattering once its target (or newer) is installed, and a busy machine
|
|
106
|
+
* postponing an update (`update_busy_*`) has not failed: it is still outdated. */
|
|
107
|
+
export function agentVersionState(
|
|
108
|
+
installedVersion: string | null,
|
|
109
|
+
desiredVersion: string | null,
|
|
110
|
+
update: AgentUpdateRecord,
|
|
111
|
+
): MachineRuntime["versionState"] {
|
|
112
|
+
if (update && ACTIVE_UPDATE_STATUSES.has(update.status)) return "updating";
|
|
113
|
+
if (
|
|
114
|
+
update?.status === "failed" &&
|
|
115
|
+
!update.errorCode?.startsWith("update_busy") &&
|
|
116
|
+
!(installedVersion && (compareAgentVersions(installedVersion, update.targetVersion) ?? -1) >= 0)
|
|
117
|
+
) {
|
|
118
|
+
return "update_failed";
|
|
119
|
+
}
|
|
83
120
|
const order =
|
|
84
|
-
|
|
85
|
-
? compareAgentVersions(
|
|
121
|
+
installedVersion && desiredVersion
|
|
122
|
+
? compareAgentVersions(installedVersion, desiredVersion)
|
|
86
123
|
: null;
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
? "outdated"
|
|
97
|
-
: "ahead";
|
|
124
|
+
if (order === null) return "unknown";
|
|
125
|
+
if (order === 0) return "current";
|
|
126
|
+
return order < 0 ? "outdated" : "ahead";
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function runtimeFor(settings: Settings, enrollment: EnrollmentRecord): MachineView["runtime"] {
|
|
130
|
+
const desiredVersion = promotedAgentVersion(settings, enrollment.agentUpdateChannel);
|
|
131
|
+
const update = enrollment.agentUpdate;
|
|
132
|
+
const versionState = agentVersionState(enrollment.agentVersion, desiredVersion, update);
|
|
98
133
|
const capability = (name: string): boolean => enrollment.agentCapabilities[name] === true;
|
|
99
134
|
return {
|
|
100
135
|
installedVersion: enrollment.agentVersion,
|
|
@@ -102,6 +137,7 @@ function runtimeFor(settings: Settings, enrollment: EnrollmentRecord): MachineVi
|
|
|
102
137
|
updateChannel: enrollment.agentUpdateChannel,
|
|
103
138
|
desiredVersion,
|
|
104
139
|
versionState,
|
|
140
|
+
updateBlockedReason: machineUpdateBlockedReason(enrollment.os, enrollment.agentVersion),
|
|
105
141
|
capabilities: {
|
|
106
142
|
exec: capability("exec"),
|
|
107
143
|
filesystem: capability("filesystem"),
|
|
@@ -113,8 +149,15 @@ function runtimeFor(settings: Settings, enrollment: EnrollmentRecord): MachineVi
|
|
|
113
149
|
operationResourcePolicy: capability("operationResourcePolicy"),
|
|
114
150
|
operationCpuQuota: capability("operationCpuQuota"),
|
|
115
151
|
transactionalFsWrite: capability("transactionalFsWrite"),
|
|
152
|
+
credentialRenew: capability("credentialRenew"),
|
|
153
|
+
screenControl:
|
|
154
|
+
typeof enrollment.agentCapabilities.screenControl === "boolean"
|
|
155
|
+
? enrollment.agentCapabilities.screenControl
|
|
156
|
+
: null,
|
|
116
157
|
},
|
|
117
158
|
update,
|
|
159
|
+
macPermissions:
|
|
160
|
+
enrollment.os === "macos" ? enrollmentMacPermissions(enrollment.agentCapabilities) : null,
|
|
118
161
|
};
|
|
119
162
|
}
|
|
120
163
|
|
|
@@ -258,23 +301,24 @@ export async function listMachines(
|
|
|
258
301
|
if (session && groupBackend) {
|
|
259
302
|
const groupActive = activeSandboxId === null;
|
|
260
303
|
const groupLease = await readLease(db, workspaceId, session.sandboxGroupId);
|
|
304
|
+
const presentation = sessionGroupMachinePresentation(groupBackend);
|
|
305
|
+
const localHost = groupBackend === "local";
|
|
261
306
|
machines.push(
|
|
262
307
|
MachineView.parse({
|
|
263
308
|
sandboxId: session.sandboxGroupId,
|
|
264
309
|
enrollmentId: null,
|
|
265
|
-
name:
|
|
266
|
-
kind:
|
|
310
|
+
name: presentation.name,
|
|
311
|
+
kind: presentation.kind,
|
|
267
312
|
state: "online",
|
|
268
313
|
active: groupActive,
|
|
269
314
|
isSessionGroup: true,
|
|
270
315
|
workspaceGeneration: groupLease?.workspaceGeneration ?? null,
|
|
271
316
|
archiveGeneration: groupLease?.archiveGeneration ?? null,
|
|
272
317
|
archiveComplete: groupLease?.archiveComplete ?? false,
|
|
273
|
-
//
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
hasDisplay: false,
|
|
318
|
+
// A local sandbox is this machine. Other managed providers run a Linux box.
|
|
319
|
+
os: localHost ? process.platform : "linux",
|
|
320
|
+
arch: localHost ? process.arch : "x86_64",
|
|
321
|
+
hasDisplay: localHost,
|
|
278
322
|
desktopUnavailableReason: null,
|
|
279
323
|
allowScreenControl: false,
|
|
280
324
|
sharedSessionCount: 1,
|