@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
|
@@ -38,6 +38,8 @@ import {
|
|
|
38
38
|
clearEnrollmentWentOffline,
|
|
39
39
|
disconnectAttachedBrowserDevices,
|
|
40
40
|
advanceEnrollmentAgentUpdate,
|
|
41
|
+
enrollmentMacPermissionCapabilities,
|
|
42
|
+
enrollmentMacPermissions,
|
|
41
43
|
getEnrollment,
|
|
42
44
|
getLiveEnrollmentConnection,
|
|
43
45
|
ingestMachineMetricsSample,
|
|
@@ -50,27 +52,34 @@ import {
|
|
|
50
52
|
setEnrollmentOpStreamState,
|
|
51
53
|
type AppendEventInput,
|
|
52
54
|
type Database,
|
|
55
|
+
type EnrollmentMacPermissions,
|
|
53
56
|
type MachineMetricsSample,
|
|
54
57
|
} from "@opengeni/db";
|
|
55
58
|
import {
|
|
59
|
+
AttachedBrowserConnectionEnd as AttachedBrowserConnectionEndContract,
|
|
56
60
|
AttachedBrowserInventorySnapshot as AttachedBrowserInventoryContract,
|
|
57
61
|
type AttachedBrowserInventorySnapshot as AttachedBrowserInventoryContractValue,
|
|
62
|
+
type AttachedBrowserConnectionEnd as AttachedBrowserConnectionEndValue,
|
|
58
63
|
} from "@opengeni/contracts";
|
|
59
64
|
import { appendAndPublishEvents, type EventBus } from "@opengeni/events";
|
|
60
65
|
import type { Observability } from "@opengeni/observability";
|
|
61
66
|
import { normalizeConnectedMachineWorkspaceRoot } from "@opengeni/runtime/sandbox";
|
|
67
|
+
import type { AutomaticAgentUpdater } from "./agent-update";
|
|
62
68
|
import {
|
|
63
69
|
AgentEvent,
|
|
64
70
|
AgentUpdateStage,
|
|
65
71
|
Arch,
|
|
72
|
+
AttachedBrowserConnectionEndReason as WireConnectionEndReason,
|
|
66
73
|
GoingOfflineReason,
|
|
67
74
|
Hello,
|
|
68
75
|
Os,
|
|
69
76
|
goingOfflineReasonToJSON,
|
|
77
|
+
type AttachedBrowserConnectionEnd as WireAttachedBrowserConnectionEnd,
|
|
70
78
|
type AttachedBrowserInventorySnapshot as WireAttachedBrowserInventorySnapshot,
|
|
71
79
|
type MetricsSample,
|
|
72
80
|
} from "@opengeni/agent-proto";
|
|
73
81
|
import { AGENT_CONNECTION_LEASE_MS } from "./connection-authority";
|
|
82
|
+
import { reconcileScreenControlOnHello } from "./screen-control";
|
|
74
83
|
|
|
75
84
|
/** The wildcard subject the agent event plane publishes heartbeats on. */
|
|
76
85
|
export const AGENT_EVENTS_SUBJECT = "agent.*.*.connection.*.events";
|
|
@@ -314,9 +323,53 @@ export function wireAttachedBrowserInventoryToContract(
|
|
|
314
323
|
tabCount: safeWireInteger(device.tabCount, "attached browser tab count"),
|
|
315
324
|
capabilities: device.capabilities,
|
|
316
325
|
})),
|
|
326
|
+
connectionEnds: (wire.connectionEnds ?? []).flatMap(wireConnectionEndToContract),
|
|
317
327
|
});
|
|
318
328
|
}
|
|
319
329
|
|
|
330
|
+
const WIRE_CONNECTION_END_REASONS = new Map<
|
|
331
|
+
WireConnectionEndReason,
|
|
332
|
+
AttachedBrowserConnectionEndValue["reason"]
|
|
333
|
+
>([
|
|
334
|
+
[
|
|
335
|
+
WireConnectionEndReason.ATTACHED_BROWSER_CONNECTION_END_REASON_BROWSER_CLOSED_PORT,
|
|
336
|
+
"browser_closed_port",
|
|
337
|
+
],
|
|
338
|
+
[
|
|
339
|
+
WireConnectionEndReason.ATTACHED_BROWSER_CONNECTION_END_REASON_BROWSER_MESSAGE_INVALID,
|
|
340
|
+
"browser_message_invalid",
|
|
341
|
+
],
|
|
342
|
+
[
|
|
343
|
+
WireConnectionEndReason.ATTACHED_BROWSER_CONNECTION_END_REASON_BROWSER_OUTPUT_FAILED,
|
|
344
|
+
"browser_output_failed",
|
|
345
|
+
],
|
|
346
|
+
[
|
|
347
|
+
WireConnectionEndReason.ATTACHED_BROWSER_CONNECTION_END_REASON_NATIVE_HOST_LOST,
|
|
348
|
+
"native_host_lost",
|
|
349
|
+
],
|
|
350
|
+
[WireConnectionEndReason.ATTACHED_BROWSER_CONNECTION_END_REASON_AGENT_REJECTED, "agent_rejected"],
|
|
351
|
+
]);
|
|
352
|
+
|
|
353
|
+
/** Connection ends are diagnostics. One the contract cannot hold (a future
|
|
354
|
+
* reason, or the generation of a hello the bridge rejected as malformed) is
|
|
355
|
+
* dropped instead of rejecting the authoritative device inventory. */
|
|
356
|
+
function wireConnectionEndToContract(
|
|
357
|
+
wire: WireAttachedBrowserConnectionEnd,
|
|
358
|
+
): AttachedBrowserConnectionEndValue[] {
|
|
359
|
+
const reason = WIRE_CONNECTION_END_REASONS.get(wire.reason);
|
|
360
|
+
const endedAtMs = Number(wire.endedAtUnixMs);
|
|
361
|
+
if (!reason || !Number.isSafeInteger(endedAtMs) || endedAtMs <= 0) return [];
|
|
362
|
+
const parsed = AttachedBrowserConnectionEndContract.safeParse({
|
|
363
|
+
deviceId: wire.deviceId,
|
|
364
|
+
connectionGeneration: wire.connectionGeneration,
|
|
365
|
+
reason,
|
|
366
|
+
detail: wire.detail.slice(0, 512) || null,
|
|
367
|
+
endedAt: new Date(endedAtMs).toISOString(),
|
|
368
|
+
connectedMs: Math.min(Number(wire.connectedMs) || 0, Number.MAX_SAFE_INTEGER),
|
|
369
|
+
});
|
|
370
|
+
return parsed.success ? [parsed.data] : [];
|
|
371
|
+
}
|
|
372
|
+
|
|
320
373
|
function safeWireInteger(value: string | number, label: string): number {
|
|
321
374
|
let parsed: bigint;
|
|
322
375
|
try {
|
|
@@ -452,6 +505,7 @@ export async function handleAgentEventPayload(
|
|
|
452
505
|
payload: Uint8Array,
|
|
453
506
|
subject: string,
|
|
454
507
|
bus?: EventBus,
|
|
508
|
+
agentUpdates?: AutomaticAgentUpdater | null,
|
|
455
509
|
): Promise<void> {
|
|
456
510
|
const ids = parseAgentEventSubject(subject);
|
|
457
511
|
if (!ids) {
|
|
@@ -619,6 +673,9 @@ export async function handleAgentEventPayload(
|
|
|
619
673
|
});
|
|
620
674
|
return;
|
|
621
675
|
}
|
|
676
|
+
// A live machine behind its promoted build is asked to update; the decision
|
|
677
|
+
// reads only this enrollment, and a request never blocks heartbeat ingestion.
|
|
678
|
+
agentUpdates?.consider(enrollment);
|
|
622
679
|
if (heartbeat.attachedBrowserInventory) {
|
|
623
680
|
try {
|
|
624
681
|
await ingestAttachedBrowserInventory(db, {
|
|
@@ -633,6 +690,41 @@ export async function handleAgentEventPayload(
|
|
|
633
690
|
});
|
|
634
691
|
}
|
|
635
692
|
}
|
|
693
|
+
if (heartbeat.desktopStatus) {
|
|
694
|
+
try {
|
|
695
|
+
const status = heartbeat.desktopStatus;
|
|
696
|
+
const available = status.available && !status.unavailableReason;
|
|
697
|
+
const reason = status.unavailableReason || null;
|
|
698
|
+
const macPermissions = status.macPermissions;
|
|
699
|
+
const stored = enrollmentMacPermissions(enrollment.agentCapabilities);
|
|
700
|
+
// The heartbeat already read the exact enrollment. Steady state adds no
|
|
701
|
+
// extra query; the change path re-reads and fences its eventual write.
|
|
702
|
+
if (
|
|
703
|
+
enrollment.hasDisplay !== available ||
|
|
704
|
+
(enrollment.desktopUnavailableReason ?? null) !== reason ||
|
|
705
|
+
enrollment.agentCapabilities?.desktop !== available ||
|
|
706
|
+
(macPermissions !== undefined &&
|
|
707
|
+
(stored?.screenRecording !== macPermissions.screenRecording ||
|
|
708
|
+
stored?.accessibility !== macPermissions.accessibility ||
|
|
709
|
+
stored?.inputMonitoring !== macPermissions.inputMonitoring))
|
|
710
|
+
) {
|
|
711
|
+
await refreshEnrollmentDisplay(db, {
|
|
712
|
+
workspaceId: ids.workspaceId,
|
|
713
|
+
agentId: ids.agentId,
|
|
714
|
+
hasDisplay: available,
|
|
715
|
+
desktopUnavailableReason: reason,
|
|
716
|
+
runtimeDesktop: available,
|
|
717
|
+
...(macPermissions ? { macPermissions } : {}),
|
|
718
|
+
connectionInstanceId: ids.connectionInstanceId,
|
|
719
|
+
});
|
|
720
|
+
}
|
|
721
|
+
} catch (error) {
|
|
722
|
+
observability?.warn?.("Failed to refresh a machine desktop heartbeat", {
|
|
723
|
+
subject,
|
|
724
|
+
error: error instanceof Error ? error.message : String(error),
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
}
|
|
636
728
|
const metrics = heartbeat.metrics;
|
|
637
729
|
if (!metrics) return;
|
|
638
730
|
try {
|
|
@@ -659,10 +751,18 @@ export function startMetricsIngestion(deps: {
|
|
|
659
751
|
db: Database;
|
|
660
752
|
bus: EventBus;
|
|
661
753
|
observability?: Observability;
|
|
754
|
+
agentUpdates?: AutomaticAgentUpdater | null;
|
|
662
755
|
}): () => void {
|
|
663
756
|
const scheduler = createAgentEventIngestionScheduler(
|
|
664
757
|
(payload, subject) =>
|
|
665
|
-
handleAgentEventPayload(
|
|
758
|
+
handleAgentEventPayload(
|
|
759
|
+
deps.db,
|
|
760
|
+
deps.observability,
|
|
761
|
+
payload,
|
|
762
|
+
subject,
|
|
763
|
+
deps.bus,
|
|
764
|
+
deps.agentUpdates,
|
|
765
|
+
),
|
|
666
766
|
{
|
|
667
767
|
onHeartbeatCoalesced: () =>
|
|
668
768
|
deps.observability?.incrementCounter({
|
|
@@ -742,6 +842,9 @@ export function helloRuntimeCapabilities(hello: Hello): Record<string, boolean>
|
|
|
742
842
|
operationResourcePolicy: caps.operationResourcePolicy === true,
|
|
743
843
|
operationCpuQuota: caps.operationCpuQuota === true,
|
|
744
844
|
transactionalFsWrite: caps.transactionalFsWrite === true,
|
|
845
|
+
credentialRenew: caps.credentialRenew === true,
|
|
846
|
+
screenControl: caps.consentedScreenControl === true,
|
|
847
|
+
...(caps.macPermissions ? enrollmentMacPermissionCapabilities(caps.macPermissions) : {}),
|
|
745
848
|
};
|
|
746
849
|
}
|
|
747
850
|
|
|
@@ -781,6 +884,8 @@ export async function refreshEnrollmentDisplay(
|
|
|
781
884
|
agentId: string;
|
|
782
885
|
hasDisplay: boolean;
|
|
783
886
|
desktopUnavailableReason?: string | null;
|
|
887
|
+
runtimeDesktop?: boolean;
|
|
888
|
+
macPermissions?: EnrollmentMacPermissions;
|
|
784
889
|
connectionInstanceId?: string;
|
|
785
890
|
},
|
|
786
891
|
): Promise<{ updated: boolean }> {
|
|
@@ -791,7 +896,16 @@ export async function refreshEnrollmentDisplay(
|
|
|
791
896
|
}
|
|
792
897
|
if (
|
|
793
898
|
enrollment.hasDisplay === input.hasDisplay &&
|
|
794
|
-
(enrollment.desktopUnavailableReason ?? null) === desktopUnavailableReason
|
|
899
|
+
(enrollment.desktopUnavailableReason ?? null) === desktopUnavailableReason &&
|
|
900
|
+
(input.runtimeDesktop === undefined ||
|
|
901
|
+
enrollment.agentCapabilities?.desktop === input.runtimeDesktop) &&
|
|
902
|
+
(input.macPermissions === undefined ||
|
|
903
|
+
JSON.stringify(enrollmentMacPermissions(enrollment.agentCapabilities)) ===
|
|
904
|
+
JSON.stringify({
|
|
905
|
+
screenRecording: input.macPermissions.screenRecording,
|
|
906
|
+
accessibility: input.macPermissions.accessibility,
|
|
907
|
+
inputMonitoring: input.macPermissions.inputMonitoring,
|
|
908
|
+
}))
|
|
795
909
|
) {
|
|
796
910
|
// Both fields unchanged — do not even issue the UPDATE (no churn on a
|
|
797
911
|
// steady-state Hello).
|
|
@@ -803,6 +917,8 @@ export async function refreshEnrollmentDisplay(
|
|
|
803
917
|
enrollmentId: input.agentId,
|
|
804
918
|
hasDisplay: input.hasDisplay,
|
|
805
919
|
desktopUnavailableReason,
|
|
920
|
+
...(input.runtimeDesktop !== undefined ? { runtimeDesktop: input.runtimeDesktop } : {}),
|
|
921
|
+
...(input.macPermissions ? { macPermissions: input.macPermissions } : {}),
|
|
806
922
|
...(input.connectionInstanceId ? { connectionInstanceId: input.connectionInstanceId } : {}),
|
|
807
923
|
});
|
|
808
924
|
}
|
|
@@ -926,6 +1042,21 @@ export async function handleHelloPayload(
|
|
|
926
1042
|
error: error instanceof Error ? error.message : String(error),
|
|
927
1043
|
});
|
|
928
1044
|
}
|
|
1045
|
+
// Screen control allowed while this machine was offline (or before its agent
|
|
1046
|
+
// could renew on request) applies now. Detached: it waits for the agent to
|
|
1047
|
+
// subscribe and must not hold up Hello ingestion.
|
|
1048
|
+
void reconcileScreenControlOnHello(
|
|
1049
|
+
{ bus, observability },
|
|
1050
|
+
{
|
|
1051
|
+
authority,
|
|
1052
|
+
hello,
|
|
1053
|
+
target: {
|
|
1054
|
+
workspaceId: ids.workspaceId,
|
|
1055
|
+
enrollmentId: ids.agentId,
|
|
1056
|
+
connectionInstanceId: ids.connectionInstanceId,
|
|
1057
|
+
},
|
|
1058
|
+
},
|
|
1059
|
+
);
|
|
929
1060
|
// A reconnect Hello re-announces the machine, so any pending clean going-offline
|
|
930
1061
|
// marker no longer holds — clear it so the liveness derivation stops reading the
|
|
931
1062
|
// machine offline. Best-effort + fail-soft, and change-guarded in the DB (a
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
failSandboxRematerialization,
|
|
8
8
|
failWarmingToCold,
|
|
9
9
|
markSandboxRestoreVerifying,
|
|
10
|
+
sessionHoldsFreshWorkspaceRecovery,
|
|
10
11
|
recordWarmingSandboxCreated,
|
|
11
12
|
SandboxLeaseRecoveryBlockedError,
|
|
12
13
|
SandboxLeaseSupersededError,
|
|
@@ -29,6 +30,7 @@ import {
|
|
|
29
30
|
verifySandboxExecReadiness,
|
|
30
31
|
withoutSandboxProviderIdentity,
|
|
31
32
|
WorkspaceArchiveIntegrityError,
|
|
33
|
+
workspaceArchiveDownloadTemporaryDirectory,
|
|
32
34
|
type EstablishedSandboxSession,
|
|
33
35
|
type WorkspaceArchiveDescriptor,
|
|
34
36
|
} from "@opengeni/runtime/sandbox";
|
|
@@ -73,8 +75,9 @@ async function materializeArchiveObjectRef(
|
|
|
73
75
|
}
|
|
74
76
|
if (!objectStorage) {
|
|
75
77
|
throw new WorkspaceArchiveIntegrityError(
|
|
76
|
-
"
|
|
78
|
+
"archive_storage_unavailable",
|
|
77
79
|
"workspace archive object storage is not configured",
|
|
80
|
+
{ retryable: true },
|
|
78
81
|
);
|
|
79
82
|
}
|
|
80
83
|
const descriptor = parseWorkspaceArchiveDescriptor(sessionState.workspaceArchiveMeta);
|
|
@@ -136,13 +139,29 @@ export async function establishApiSandboxSpawner(input: {
|
|
|
136
139
|
dataPlaneUrl: string | null;
|
|
137
140
|
objectStorage?: ObjectStorage | null;
|
|
138
141
|
}): Promise<{ established: EstablishedSandboxSession; lease: LeaseSnapshot }> {
|
|
142
|
+
// An audited decision to continue a definitively lost workspace on a new
|
|
143
|
+
// EMPTY box: hydrate nothing, including a per-session legacy archive, and
|
|
144
|
+
// never resume a prior provider identity. Commit verifies the decision.
|
|
145
|
+
const freshWorkspaceRecoveryId = input.acquiredLease.freshWorkspaceRecoveryId ?? null;
|
|
146
|
+
// Backstop: a session already told its workspace is empty never gets a
|
|
147
|
+
// legacy per-session archive back, even if the lease marker was lost.
|
|
148
|
+
const legacyFallbackRefused =
|
|
149
|
+
!freshWorkspaceRecoveryId &&
|
|
150
|
+
input.acquiredLease.recovery.archive.status === "none" &&
|
|
151
|
+
hasWorkspaceArchive(input.fallbackEnvelope) &&
|
|
152
|
+
(await sessionHoldsFreshWorkspaceRecovery(input.db, input.workspaceId, input.sessionId));
|
|
139
153
|
const fallbackArchiveEnvelope =
|
|
154
|
+
!freshWorkspaceRecoveryId &&
|
|
155
|
+
!legacyFallbackRefused &&
|
|
140
156
|
input.acquiredLease.recovery.archive.status === "none" &&
|
|
141
157
|
hasWorkspaceArchive(input.fallbackEnvelope)
|
|
142
158
|
? withoutSandboxProviderIdentity(input.fallbackEnvelope)
|
|
143
159
|
: null;
|
|
144
|
-
let spawnEnvelope =
|
|
145
|
-
|
|
160
|
+
let spawnEnvelope = freshWorkspaceRecoveryId
|
|
161
|
+
? null
|
|
162
|
+
: legacyFallbackRefused
|
|
163
|
+
? (input.acquiredLease.resumeState ?? null)
|
|
164
|
+
: (fallbackArchiveEnvelope ?? input.acquiredLease.resumeState ?? input.fallbackEnvelope);
|
|
146
165
|
const archiveSource =
|
|
147
166
|
input.acquiredLease.recovery.archive.status === "none"
|
|
148
167
|
? fallbackArchiveEnvelope
|
|
@@ -161,9 +180,12 @@ export async function establishApiSandboxSpawner(input: {
|
|
|
161
180
|
const continuityRecovery = input.acquiredLease.recovery.continuity;
|
|
162
181
|
try {
|
|
163
182
|
if (
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
183
|
+
!freshWorkspaceRecoveryId &&
|
|
184
|
+
((input.acquiredLease.recovery.archive.status === "available" &&
|
|
185
|
+
(input.acquiredLease.archiveComplete ||
|
|
186
|
+
input.acquiredLease.historicalRecoveryAuthorized === true)) ||
|
|
187
|
+
(input.acquiredLease.recovery.archive.status === "none" &&
|
|
188
|
+
hasWorkspaceArchive(archiveSource)))
|
|
167
189
|
) {
|
|
168
190
|
const id = crypto.randomUUID();
|
|
169
191
|
const legacyNativeArchive = legacyNativeArchiveFromEnvelope(archiveSource);
|
|
@@ -206,7 +228,11 @@ export async function establishApiSandboxSpawner(input: {
|
|
|
206
228
|
legacyCheckpoint: begun.checkpointArtifact === null ? legacyNativeArchive : null,
|
|
207
229
|
legacyProviderBinding: null,
|
|
208
230
|
};
|
|
209
|
-
} else if (
|
|
231
|
+
} else if (
|
|
232
|
+
!freshWorkspaceRecoveryId &&
|
|
233
|
+
input.acquiredLease.recovery.archive.status !== "none" &&
|
|
234
|
+
!continuityRecovery
|
|
235
|
+
) {
|
|
210
236
|
throw new SandboxLeaseRecoveryBlockedError(
|
|
211
237
|
input.sandboxGroupId,
|
|
212
238
|
input.expectedEpoch,
|
|
@@ -225,10 +251,12 @@ export async function establishApiSandboxSpawner(input: {
|
|
|
225
251
|
? {
|
|
226
252
|
loadHostWorkspaceArchive: async (ref) => {
|
|
227
253
|
try {
|
|
228
|
-
return await downloadWorkspaceArchiveSpool(
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
254
|
+
return await downloadWorkspaceArchiveSpool(
|
|
255
|
+
input.objectStorage!,
|
|
256
|
+
ref.key,
|
|
257
|
+
{ bytes: ref.bytes, sha256: ref.sha256 },
|
|
258
|
+
{ temporaryDirectory: workspaceArchiveDownloadTemporaryDirectory },
|
|
259
|
+
);
|
|
232
260
|
} catch (error) {
|
|
233
261
|
if (error instanceof WorkspaceArchiveStorageError) {
|
|
234
262
|
throw new WorkspaceArchiveIntegrityError(error.code, error.message, {
|
|
@@ -383,16 +411,18 @@ export async function establishApiSandboxSpawner(input: {
|
|
|
383
411
|
dataPlaneUrl: input.dataPlaneUrl,
|
|
384
412
|
resumeBackendId: established.backendId,
|
|
385
413
|
resumeState,
|
|
386
|
-
...(
|
|
387
|
-
? {
|
|
388
|
-
:
|
|
389
|
-
? {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
414
|
+
...(freshWorkspaceRecoveryId
|
|
415
|
+
? { freshWorkspace: { operationId: freshWorkspaceRecoveryId } }
|
|
416
|
+
: established.providerContinuity
|
|
417
|
+
? { continuityRecovery: established.providerContinuity }
|
|
418
|
+
: rematerialization
|
|
419
|
+
? {
|
|
420
|
+
rematerialization: {
|
|
421
|
+
id: rematerialization.id,
|
|
422
|
+
verifiedRevision: rematerialization.selectedRevision,
|
|
423
|
+
},
|
|
424
|
+
}
|
|
425
|
+
: {}),
|
|
396
426
|
leaseTtlMs: input.settings.sandboxLeaseTtlMs,
|
|
397
427
|
});
|
|
398
428
|
if (!committed.committed || !committed.lease) {
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
// Screen control and macOS permission setup for an already-connected machine.
|
|
2
|
+
//
|
|
3
|
+
// Screen-control consent lives on the enrollment row and in the credentials the
|
|
4
|
+
// machine holds (the agent's own dispatch gate checks them). Turning it on
|
|
5
|
+
// records the consent on the row, in place (same id, scope, owner and
|
|
6
|
+
// credential generation), then asks the live agent to renew its credentials
|
|
7
|
+
// now. That renewal is the same install-key-signed exchange the agent runs on
|
|
8
|
+
// its own schedule, and it re-reads consent from the row, so nothing new is
|
|
9
|
+
// trusted: no token, no installer, no restart, no second connection file. A
|
|
10
|
+
// machine that is offline, or whose agent predates credential_renew, picks the
|
|
11
|
+
// consent up when it next says Hello (reconcileScreenControlOnHello).
|
|
12
|
+
|
|
13
|
+
import { ControlRequest, ErrorCode, type Hello } from "@opengeni/agent-proto";
|
|
14
|
+
import {
|
|
15
|
+
EnableMachineScreenControlResponse,
|
|
16
|
+
OpenMachinePrivacySettingsResponse,
|
|
17
|
+
type MachinePrivacySettingsPane,
|
|
18
|
+
} from "@opengeni/contracts";
|
|
19
|
+
import { runOnEnrollmentDirect, type FleetServices } from "@opengeni/core";
|
|
20
|
+
import {
|
|
21
|
+
allowEnrollmentScreenControl,
|
|
22
|
+
getLiveEnrollmentConnection,
|
|
23
|
+
type EnrollmentRecord,
|
|
24
|
+
} from "@opengeni/db";
|
|
25
|
+
import type { EventBus } from "@opengeni/events";
|
|
26
|
+
import type { Observability } from "@opengeni/observability";
|
|
27
|
+
import { NatsControlRpc, subjectFor } from "@opengeni/runtime/sandbox";
|
|
28
|
+
|
|
29
|
+
type Services = Pick<FleetServices, "db" | "settings" | "bus"> & {
|
|
30
|
+
observability?: Observability | undefined;
|
|
31
|
+
};
|
|
32
|
+
type EnrollmentAccess = string | { accountId: string; workspaceId: string; subjectId: string };
|
|
33
|
+
|
|
34
|
+
/** The agent's renewal HTTP call is bounded at 20s; leave room for the reply. */
|
|
35
|
+
const CREDENTIAL_RENEW_TIMEOUT_MS = 30_000;
|
|
36
|
+
/** Opening a System Settings pane is instant; never hold a request open longer. */
|
|
37
|
+
const PRIVACY_PANE_TIMEOUT_MS = 15_000;
|
|
38
|
+
|
|
39
|
+
/** macOS System Settings deep links for the three desktop permissions. */
|
|
40
|
+
export const MAC_PRIVACY_PANE_URLS: Record<MachinePrivacySettingsPane, string> = {
|
|
41
|
+
screen_recording: "x-apple.systempreferences:com.apple.preference.security?Privacy_ScreenCapture",
|
|
42
|
+
accessibility: "x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility",
|
|
43
|
+
input_monitoring: "x-apple.systempreferences:com.apple.preference.security?Privacy_ListenEvent",
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/** Read access for live-connection lookups, matching the machine's scope. */
|
|
47
|
+
export function enrollmentAccess(
|
|
48
|
+
enrollment: Pick<EnrollmentRecord, "scope" | "workspaceId">,
|
|
49
|
+
personal: { accountId: string; workspaceId: string; subjectId: string },
|
|
50
|
+
): EnrollmentAccess {
|
|
51
|
+
return enrollment.scope === "user" ? personal : enrollment.workspaceId;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export type CredentialRenewOutcome =
|
|
55
|
+
| { kind: "renewed"; consentedScreenControl: boolean }
|
|
56
|
+
| { kind: "offline" }
|
|
57
|
+
| { kind: "failed"; failureCode: string };
|
|
58
|
+
|
|
59
|
+
/** Ask one exact live runner process to renew its credentials now. */
|
|
60
|
+
export async function requestCredentialRenew(
|
|
61
|
+
bus: EventBus | undefined,
|
|
62
|
+
target: { workspaceId: string; enrollmentId: string; connectionInstanceId: string },
|
|
63
|
+
): Promise<CredentialRenewOutcome> {
|
|
64
|
+
if (!bus) return { kind: "offline" };
|
|
65
|
+
const rpc = new NatsControlRpc(async () => bus.getRequestConnection() ?? null);
|
|
66
|
+
const request: ControlRequest = {
|
|
67
|
+
requestId: crypto.randomUUID(),
|
|
68
|
+
// Process-scoped, like agentUpdateApply: the subject names the instance.
|
|
69
|
+
epoch: 0,
|
|
70
|
+
resourcePolicy: undefined,
|
|
71
|
+
op: { $case: "credentialRenew", credentialRenew: {} },
|
|
72
|
+
};
|
|
73
|
+
const response = await rpc.request(
|
|
74
|
+
subjectFor(target.workspaceId, target.enrollmentId, target.connectionInstanceId),
|
|
75
|
+
request,
|
|
76
|
+
{ timeoutMs: CREDENTIAL_RENEW_TIMEOUT_MS },
|
|
77
|
+
);
|
|
78
|
+
if (response.error) {
|
|
79
|
+
if (response.error.code === ErrorCode.ERROR_CODE_AGENT_OFFLINE) return { kind: "offline" };
|
|
80
|
+
return {
|
|
81
|
+
kind: "failed",
|
|
82
|
+
failureCode:
|
|
83
|
+
response.error.detail.failure_code ??
|
|
84
|
+
(response.error.code === ErrorCode.ERROR_CODE_TIMEOUT ? "timeout" : "agent_error"),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
if (response.result?.$case !== "credentialRenew") {
|
|
88
|
+
return { kind: "failed", failureCode: "invalid_agent_response" };
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
kind: "renewed",
|
|
92
|
+
consentedScreenControl: response.result.credentialRenew.consentedScreenControl,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const pending = (
|
|
97
|
+
reason: "offline" | "agent_update_required" | "renewal_failed" | "reconnect_required",
|
|
98
|
+
message: string,
|
|
99
|
+
): EnableMachineScreenControlResponse =>
|
|
100
|
+
EnableMachineScreenControlResponse.parse({ status: "pending", reason, message });
|
|
101
|
+
|
|
102
|
+
const ACTIVE = { status: "active", reason: null, message: null } as const;
|
|
103
|
+
|
|
104
|
+
/** Agent failure codes that no retry fixes: the connection must be redone. */
|
|
105
|
+
const PERMANENT_RENEW_FAILURES = new Set([
|
|
106
|
+
"connection_missing",
|
|
107
|
+
"legacy_origin",
|
|
108
|
+
"local_state_unavailable",
|
|
109
|
+
]);
|
|
110
|
+
|
|
111
|
+
/** The enrollment was revoked or removed between lookup and update. */
|
|
112
|
+
export class MachineNotActiveError extends Error {
|
|
113
|
+
constructor() {
|
|
114
|
+
super("machine is no longer connected to this workspace");
|
|
115
|
+
this.name = "MachineNotActiveError";
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** Who turned screen control on, for the audit trail. */
|
|
120
|
+
export type ScreenControlActor = {
|
|
121
|
+
subjectId: string | null;
|
|
122
|
+
sessionId?: string | null;
|
|
123
|
+
attemptId?: string | null;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Turn screen control on for one enrolled machine, in place. The caller has
|
|
128
|
+
* already authorized the actor for this enrollment (enrollments:manage, plus
|
|
129
|
+
* account:admin for an organization machine, plus personal-machine admission
|
|
130
|
+
* for an agent attempt). Safe to repeat: a retry re-requests the renewal.
|
|
131
|
+
*/
|
|
132
|
+
export async function enableMachineScreenControl(
|
|
133
|
+
services: Services,
|
|
134
|
+
input: { enrollment: EnrollmentRecord; access: EnrollmentAccess; actor: ScreenControlActor },
|
|
135
|
+
): Promise<EnableMachineScreenControlResponse> {
|
|
136
|
+
const { enrollment } = input;
|
|
137
|
+
if (!enrollment.allowScreenControl) {
|
|
138
|
+
const allowed = await allowEnrollmentScreenControl(services.db, {
|
|
139
|
+
accountId: enrollment.accountId,
|
|
140
|
+
workspaceId: enrollment.workspaceId,
|
|
141
|
+
enrollmentId: enrollment.id,
|
|
142
|
+
...input.actor,
|
|
143
|
+
});
|
|
144
|
+
if (!allowed.active) throw new MachineNotActiveError();
|
|
145
|
+
}
|
|
146
|
+
const live = await getLiveEnrollmentConnection(services.db, input.access, enrollment.id);
|
|
147
|
+
if (!live?.connectionInstanceId) {
|
|
148
|
+
return pending(
|
|
149
|
+
"offline",
|
|
150
|
+
"Screen control is allowed. The machine is offline, so it turns on when the machine reconnects.",
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
// The live agent's Hello already carries the consent: nothing to renew, so
|
|
154
|
+
// repeated calls never churn the connection.
|
|
155
|
+
if (live.allowScreenControl && live.agentCapabilities.screenControl === true) {
|
|
156
|
+
return EnableMachineScreenControlResponse.parse(ACTIVE);
|
|
157
|
+
}
|
|
158
|
+
if (live.agentCapabilities.credentialRenew !== true) {
|
|
159
|
+
return pending(
|
|
160
|
+
"agent_update_required",
|
|
161
|
+
"Screen control is allowed. This machine's agent is too old to switch it on while connected: update the agent and it turns on after the update.",
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
const outcome = await requestCredentialRenew(services.bus, {
|
|
165
|
+
workspaceId: live.workspaceId,
|
|
166
|
+
enrollmentId: enrollment.id,
|
|
167
|
+
connectionInstanceId: live.connectionInstanceId,
|
|
168
|
+
});
|
|
169
|
+
if (outcome.kind === "renewed" && outcome.consentedScreenControl) {
|
|
170
|
+
return EnableMachineScreenControlResponse.parse(ACTIVE);
|
|
171
|
+
}
|
|
172
|
+
services.observability?.warn?.("Screen control renewal did not complete", {
|
|
173
|
+
workspaceId: live.workspaceId,
|
|
174
|
+
enrollmentId: enrollment.id,
|
|
175
|
+
outcome: outcome.kind,
|
|
176
|
+
failureCode: outcome.kind === "failed" ? outcome.failureCode : null,
|
|
177
|
+
});
|
|
178
|
+
if (outcome.kind === "offline") {
|
|
179
|
+
return pending(
|
|
180
|
+
"offline",
|
|
181
|
+
"Screen control is allowed. The machine went offline, so it turns on when the machine reconnects.",
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
if (outcome.kind === "failed" && PERMANENT_RENEW_FAILURES.has(outcome.failureCode)) {
|
|
185
|
+
return pending(
|
|
186
|
+
"reconnect_required",
|
|
187
|
+
"Screen control is allowed, but this machine's connection can't take it in place. Run the connect command on the machine again with screen control on.",
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
return pending(
|
|
191
|
+
"renewal_failed",
|
|
192
|
+
"The machine couldn't refresh its credentials. Try again in a moment.",
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const HELLO_RENEW_DELAYS_MS = [2_000, 5_000] as const;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* A machine whose enrollment allows screen control but whose credentials do
|
|
200
|
+
* not (it was offline, or updated from an agent without credential_renew)
|
|
201
|
+
* renews them as soon as it says Hello. The agent subscribes to requests just
|
|
202
|
+
* after its Hello, so wait briefly and retry once. Never throws.
|
|
203
|
+
*/
|
|
204
|
+
export async function reconcileScreenControlOnHello(
|
|
205
|
+
deps: {
|
|
206
|
+
bus: EventBus | undefined;
|
|
207
|
+
observability?: Observability | undefined;
|
|
208
|
+
sleep?: (ms: number) => Promise<void>;
|
|
209
|
+
},
|
|
210
|
+
input: {
|
|
211
|
+
authority: Pick<EnrollmentRecord, "allowScreenControl">;
|
|
212
|
+
hello: Hello;
|
|
213
|
+
target: {
|
|
214
|
+
workspaceId: string;
|
|
215
|
+
enrollmentId: string;
|
|
216
|
+
connectionInstanceId: string;
|
|
217
|
+
};
|
|
218
|
+
},
|
|
219
|
+
): Promise<CredentialRenewOutcome | null> {
|
|
220
|
+
const capabilities = input.hello.capabilities;
|
|
221
|
+
if (
|
|
222
|
+
!input.authority.allowScreenControl ||
|
|
223
|
+
!capabilities?.credentialRenew ||
|
|
224
|
+
capabilities.consentedScreenControl
|
|
225
|
+
) {
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
const sleep = deps.sleep ?? ((ms: number) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
229
|
+
let outcome: CredentialRenewOutcome = { kind: "offline" };
|
|
230
|
+
try {
|
|
231
|
+
for (const delay of HELLO_RENEW_DELAYS_MS) {
|
|
232
|
+
await sleep(delay);
|
|
233
|
+
outcome = await requestCredentialRenew(deps.bus, input.target);
|
|
234
|
+
if (outcome.kind !== "offline") break;
|
|
235
|
+
}
|
|
236
|
+
} catch (error) {
|
|
237
|
+
outcome = {
|
|
238
|
+
kind: "failed",
|
|
239
|
+
failureCode: error instanceof Error ? error.message : "request_failed",
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
if (outcome.kind !== "renewed") {
|
|
243
|
+
deps.observability?.warn?.("Could not apply allowed screen control after a Hello", {
|
|
244
|
+
workspaceId: input.target.workspaceId,
|
|
245
|
+
enrollmentId: input.target.enrollmentId,
|
|
246
|
+
outcome: outcome.kind,
|
|
247
|
+
failureCode: outcome.kind === "failed" ? outcome.failureCode : null,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
return outcome;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/** Open one macOS Privacy & Security pane on a connected Mac. Opening a pane
|
|
254
|
+
* grants nothing; the person flips the switch for Opengeni. */
|
|
255
|
+
export async function openMachinePrivacySettings(
|
|
256
|
+
services: Services,
|
|
257
|
+
input: {
|
|
258
|
+
enrollment: EnrollmentRecord;
|
|
259
|
+
access: EnrollmentAccess;
|
|
260
|
+
pane: MachinePrivacySettingsPane;
|
|
261
|
+
},
|
|
262
|
+
): Promise<OpenMachinePrivacySettingsResponse> {
|
|
263
|
+
if (input.enrollment.os !== "macos") {
|
|
264
|
+
return OpenMachinePrivacySettingsResponse.parse({
|
|
265
|
+
opened: false,
|
|
266
|
+
message: "Privacy & Security panes exist only on macOS.",
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
const result = await runOnEnrollmentDirect(services, {
|
|
270
|
+
access: input.access,
|
|
271
|
+
enrollmentId: input.enrollment.id,
|
|
272
|
+
target: input.enrollment.id,
|
|
273
|
+
cmd: `open '${MAC_PRIVACY_PANE_URLS[input.pane]}'`,
|
|
274
|
+
execTimeoutMs: PRIVACY_PANE_TIMEOUT_MS,
|
|
275
|
+
});
|
|
276
|
+
const opened = result.ok && result.exitCode === 0;
|
|
277
|
+
if (!opened) {
|
|
278
|
+
services.observability?.warn?.("Could not open a macOS privacy pane", {
|
|
279
|
+
enrollmentId: input.enrollment.id,
|
|
280
|
+
pane: input.pane,
|
|
281
|
+
exitCode: result.ok ? (result.exitCode ?? null) : null,
|
|
282
|
+
timedOut: result.timedOut === true,
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
return OpenMachinePrivacySettingsResponse.parse({
|
|
286
|
+
opened,
|
|
287
|
+
message: opened ? null : "The Mac isn't reachable right now.",
|
|
288
|
+
});
|
|
289
|
+
}
|