@opengeni/api-router 0.30.3 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-grant-rls.d.ts +3 -0
- package/dist/admission-trace.d.ts +8 -0
- package/dist/api-websocket.d.ts +18 -0
- package/dist/app.d.ts +50 -2
- package/dist/app.js +12 -1
- package/dist/artifact-catalog-cursor.d.ts +27 -0
- package/dist/auth/managed-auth-attempt-context.d.ts +10 -0
- package/dist/auth/managed-auth-rate-limits.d.ts +167 -0
- package/dist/auth/managed-auth-session-adapter.d.ts +6 -0
- package/dist/auth/managed-auth.d.ts +102 -3
- package/dist/auth/managed-email.d.ts +29 -0
- package/dist/auth/managed-sign-in-notifications.d.ts +4 -0
- package/dist/auth/new-signups-gate.d.ts +23 -0
- package/dist/auth/organization-user-setup.d.ts +80 -0
- package/dist/auth/signup-funnel-metrics.d.ts +44 -0
- package/dist/browser-controller-authority.d.ts +1 -61
- package/dist/browser-ephemeral.d.ts +5 -0
- package/dist/browser-state-authority.d.ts +1 -27
- package/dist/chunk-6TZ5LG3O.js +123948 -0
- package/dist/chunk-6TZ5LG3O.js.map +1 -0
- package/dist/chunk-OGQDXVXY.js +18 -0
- package/dist/chunk-OGQDXVXY.js.map +1 -0
- package/dist/claude-subscription-account-conflicts.d.ts +1 -0
- package/dist/claude-subscription-account-usage.d.ts +39 -0
- package/dist/claude-subscription-oauth.d.ts +25 -0
- package/dist/claude-subscription-profile.d.ts +9 -0
- package/dist/claude-subscription-usage.d.ts +44 -0
- package/dist/claude-workspace-connection.d.ts +15 -0
- package/dist/codemode.d.ts +32 -1
- package/dist/company-brain-okf.d.ts +24 -0
- package/dist/connected-machine-computer-access.d.ts +11 -0
- package/dist/connection-ownership.d.ts +54 -0
- package/dist/controller-data-plane.d.ts +32 -0
- package/dist/editable-artifact-source-session.d.ts +3 -0
- package/dist/editable-artifact-websocket.d.ts +10 -18
- package/dist/editable-artifact-workspace-files.d.ts +1 -1
- package/dist/fatal-process-boundary.d.ts +25 -0
- package/dist/github-access.d.ts +31 -2
- package/dist/http/acting-person.d.ts +24 -0
- package/dist/http/api-contract-compat.d.ts +19 -0
- package/dist/http/api-error.d.ts +27 -1
- package/dist/http/cors.d.ts +17 -0
- package/dist/http/deprecation.d.ts +42 -0
- package/dist/http/interaction-control-error.d.ts +13 -0
- package/dist/http/keyed-admission.d.ts +12 -0
- package/dist/http/local-browser-boundary.d.ts +72 -0
- package/dist/http/metrics-listener.d.ts +22 -0
- package/dist/http/path-identifier.d.ts +17 -0
- package/dist/http/registered-route-label.d.ts +16 -0
- package/dist/http/request-body.d.ts +27 -0
- package/dist/http/request-source.d.ts +52 -0
- package/dist/http/sse.d.ts +17 -6
- package/dist/http/unmatched-route.d.ts +18 -0
- package/dist/http/user-content.d.ts +36 -0
- package/dist/http/websocket-upgrade-dispatch.d.ts +18 -0
- package/dist/index.d.ts +10 -3
- package/dist/index.js +1091 -162
- package/dist/index.js.map +1 -1
- package/dist/integration-endpoint-test.d.ts +20 -0
- package/dist/integrations/api-integrations.d.ts +2 -2
- package/dist/integrations/atlassian.d.ts +29 -3
- package/dist/integrations/connect-authority.d.ts +1 -0
- package/dist/integrations/connect-callback-return.d.ts +6 -0
- package/dist/integrations/fiken.d.ts +16 -2
- package/dist/integrations/github-app-connect.d.ts +47 -0
- package/dist/integrations/github-installation-proof.d.ts +3 -0
- package/dist/integrations/github-lens-connect.d.ts +116 -0
- package/dist/integrations/github-skill-source.d.ts +1 -5
- package/dist/integrations/google-drive.d.ts +24 -0
- package/dist/integrations/integration-commit-authority.d.ts +13 -0
- package/dist/integrations/marketplace-plugin.d.ts +2691 -0
- package/dist/integrations/oauth-client.d.ts +178 -18
- package/dist/integrations/oauth-profiles.d.ts +222 -0
- package/dist/integrations/oauth-return-path.d.ts +1 -0
- package/dist/integrations/personal-github-repositories.d.ts +84 -0
- package/dist/integrations/personal-github.d.ts +42 -0
- package/dist/integrations/pr-review-provider.d.ts +22 -0
- package/dist/integrations/provider-oauth.d.ts +19 -1
- package/dist/integrations/slack-app-home.d.ts +24 -0
- package/dist/integrations/slack-bot.d.ts +367 -12
- package/dist/integrations/slack-file-upload-flow.d.ts +62 -0
- package/dist/integrations/slack-install.d.ts +20 -0
- package/dist/integrations/slack-interactions.d.ts +107 -9
- package/dist/integrations/slack-mrkdwn.d.ts +41 -0
- package/dist/integrations/slack-routing.d.ts +120 -0
- package/dist/integrations/slack-session-defaults.d.ts +58 -0
- package/dist/integrations/slack-task-file-upload.d.ts +36 -0
- package/dist/integrations/social-oauth.d.ts +7 -0
- package/dist/interaction-agent-access.d.ts +15 -0
- package/dist/interaction-frame-proxy.d.ts +68 -0
- package/dist/interaction-metrics.d.ts +2 -0
- package/dist/mcp/action-catalog-types.d.ts +9 -0
- package/dist/mcp/action-catalog.gen.d.ts +2 -0
- package/dist/mcp/capability-account-readiness.d.ts +7 -0
- package/dist/mcp/child-read-evidence.d.ts +9 -0
- package/dist/mcp/command-read.d.ts +24 -0
- package/dist/mcp/company-profile-agent-admin.d.ts +44 -0
- package/dist/mcp/contract-input.d.ts +11 -0
- package/dist/mcp/documents.d.ts +7 -5
- package/dist/mcp/files.d.ts +2 -2
- package/dist/mcp/first-party-tool-permissions.d.ts +650 -0
- package/dist/mcp/knowledge-entries.d.ts +5 -0
- package/dist/mcp/orchestration-failure-diagnostic.d.ts +43 -0
- package/dist/mcp/receipts.d.ts +9 -0
- package/dist/mcp/request-abort.d.ts +19 -0
- package/dist/mcp/scheduled-task-input.d.ts +1189 -0
- package/dist/mcp/scheduled-task-view.d.ts +22 -4
- package/dist/mcp/server.d.ts +255 -3
- package/dist/mcp/session-event-view.d.ts +94 -0
- package/dist/mcp/session-view.d.ts +66 -2
- package/dist/mcp/session-wait.d.ts +174 -0
- package/dist/mcp-oauth.d.ts +52 -0
- package/dist/model-catalog.d.ts +11 -31
- package/dist/observability.d.ts +3 -1
- package/dist/organization-mcp.d.ts +52 -0
- package/dist/organization-recovery-notifications.d.ts +41 -0
- package/dist/routes/analytics-consent.d.ts +26 -0
- package/dist/routes/api-integrations.d.ts +25 -0
- package/dist/routes/api-keys.d.ts +17 -0
- package/dist/routes/artifact-catalog.d.ts +6 -0
- package/dist/routes/automations.d.ts +19 -0
- package/dist/routes/billing.d.ts +49 -0
- package/dist/routes/browser-sessions.d.ts +59 -2
- package/dist/routes/claude-subscription-accounts.d.ts +3 -0
- package/dist/routes/claude-subscription-oauth.d.ts +3 -0
- package/dist/routes/client-errors.d.ts +146 -0
- package/dist/routes/codex.d.ts +76 -2
- package/dist/routes/company-brain.d.ts +3 -0
- package/dist/routes/company-profile.d.ts +2 -1
- package/dist/routes/computer-sessions.d.ts +14 -0
- package/dist/routes/connect.d.ts +5 -0
- package/dist/routes/editable-artifacts.d.ts +2 -0
- package/dist/routes/external-identity-links.d.ts +6 -0
- package/dist/routes/feedback.d.ts +3 -0
- package/dist/routes/github-browser-pages.d.ts +12 -0
- package/dist/routes/github.d.ts +2 -0
- package/dist/routes/insights-response-cache.d.ts +10 -0
- package/dist/routes/insights-usage.d.ts +12 -0
- package/dist/routes/insights.d.ts +30 -1
- package/dist/routes/knowledge.d.ts +3 -0
- package/dist/routes/managed-auth-session-sets.d.ts +26 -0
- package/dist/routes/managed-onboarding.d.ts +29 -0
- package/dist/routes/managed-sign-in-methods.d.ts +6 -0
- package/dist/routes/model-connection-access.d.ts +3 -0
- package/dist/routes/organization-integration-policy.d.ts +3 -0
- package/dist/routes/organization-integrations.d.ts +6 -0
- package/dist/routes/organization-mcp-connections.d.ts +3 -0
- package/dist/routes/organization-model-providers.d.ts +3 -0
- package/dist/routes/organization-recovery.d.ts +19 -0
- package/dist/routes/organization-service-accounts.d.ts +3 -0
- package/dist/routes/organization-sessions.d.ts +26 -0
- package/dist/routes/personal-github-git-broker.d.ts +29 -0
- package/dist/routes/personal-github.d.ts +3 -0
- package/dist/routes/pr-review-github.d.ts +3 -0
- package/dist/routes/pr-review.d.ts +3 -0
- package/dist/routes/session-artifact-associations.d.ts +4 -0
- package/dist/routes/session-history-imports.d.ts +9 -0
- package/dist/routes/sessions.d.ts +44 -6
- package/dist/routes/skill-content.d.ts +4 -0
- package/dist/routes/skill-install-authority.d.ts +6 -0
- package/dist/routes/subscription-account-pools.d.ts +34 -0
- package/dist/routes/subscription-pool-access.d.ts +16 -0
- package/dist/routes/supergrok.d.ts +6 -1
- package/dist/routes/usage-allowances.d.ts +12 -0
- package/dist/routes/user-resource-authorities.d.ts +3 -0
- package/dist/routes/workspace-artifacts.d.ts +2 -1
- package/dist/routes/workspace-capture.d.ts +10 -2
- package/dist/routes/workspace-integrations.d.ts +35 -0
- package/dist/routes/workspace-learning.d.ts +3 -0
- package/dist/routes/workspace-model-providers.d.ts +4 -0
- package/dist/routes/workspaces.d.ts +29 -0
- package/dist/sandbox/auth-callout.d.ts +8 -0
- package/dist/sandbox/channel-a.d.ts +19 -1
- package/dist/sandbox/connection-authority.d.ts +3 -0
- package/dist/sandbox/enrollment.d.ts +9 -1
- package/dist/sandbox/machines.d.ts +5 -2
- package/dist/sandbox/metrics-ingestion.d.ts +28 -20
- package/dist/sandbox/rematerialize.d.ts +2 -0
- package/dist/sandbox/session-attach-variable-sets.d.ts +30 -0
- package/dist/sandbox/viewer.d.ts +26 -1
- package/dist/sandbox-file-artifacts.d.ts +50 -0
- package/dist/scheduled-task-deletion.d.ts +13 -0
- package/dist/session-create-observability.d.ts +5 -0
- package/dist/session-event-view-MPS2OZD3.js +292 -0
- package/dist/session-event-view-MPS2OZD3.js.map +1 -0
- package/dist/site-session-origin.d.ts +13 -0
- package/dist/site-uploads.d.ts +41 -0
- package/dist/slack-reaction-files.d.ts +1 -1
- package/dist/temporal-schedule-cleanup.d.ts +1 -0
- package/dist/temporal-schedule-sync.d.ts +26 -0
- package/dist/transcription/providers/xai-subscription.d.ts +1 -0
- package/dist/transcription/service.d.ts +2 -1
- package/dist/work-discovery-observability.d.ts +33 -0
- package/dist/workspace-artifact-content.d.ts +28 -0
- package/dist/workspace-artifact-provenance.d.ts +7 -0
- package/dist/workspace-delete-observability.d.ts +10 -0
- package/dist/workspace-deletion.d.ts +6 -0
- package/dist/workspace-state-projection.d.ts +3 -5
- package/dist/workspace-tool-gateway-observability.d.ts +17 -0
- package/dist/workspace-tool-gateway.d.ts +123 -0
- package/dist/workspace-webhook-dispatch.d.ts +26 -0
- package/package.json +23 -19
- package/src/access-grant-rls.ts +75 -0
- package/src/admission-trace.ts +14 -0
- package/src/api-websocket.ts +23 -0
- package/src/app.ts +1967 -252
- package/src/artifact-catalog-cursor.ts +60 -0
- package/src/auth/managed-auth-attempt-context.ts +70 -0
- package/src/auth/managed-auth-rate-limits.ts +252 -0
- package/src/auth/managed-auth-session-adapter.ts +222 -0
- package/src/auth/managed-auth.ts +536 -60
- package/src/auth/managed-email.ts +174 -0
- package/src/auth/managed-sign-in-notifications.ts +81 -0
- package/src/auth/new-signups-gate.ts +49 -0
- package/src/auth/organization-user-setup.ts +307 -0
- package/src/auth/signup-funnel-metrics.ts +164 -0
- package/src/browser-controller-authority.ts +1 -186
- package/src/browser-ephemeral.ts +39 -0
- package/src/browser-state-authority.ts +1 -236
- package/src/claude-subscription-account-conflicts.ts +12 -0
- package/src/claude-subscription-account-usage.ts +48 -0
- package/src/claude-subscription-oauth.ts +362 -0
- package/src/claude-subscription-profile.ts +73 -0
- package/src/claude-subscription-usage.ts +97 -0
- package/src/claude-workspace-connection.ts +82 -0
- package/src/codemode.ts +194 -30
- package/src/codex-realtime.ts +8 -2
- package/src/company-brain-okf.ts +340 -0
- package/src/connected-machine-computer-access.ts +33 -0
- package/src/connection-ownership.ts +199 -0
- package/src/controller-data-plane.ts +81 -0
- package/src/editable-artifact-native-kernel.ts +26 -15
- package/src/editable-artifact-office-import.ts +28 -3
- package/src/editable-artifact-production.ts +23 -7
- package/src/editable-artifact-source-session.ts +123 -0
- package/src/editable-artifact-websocket.ts +27 -21
- package/src/editable-artifact-workspace-files.ts +31 -6
- package/src/fatal-process-boundary.ts +246 -0
- package/src/gateway-realtime.ts +1 -1
- package/src/github-access.ts +147 -5
- package/src/http/acting-person.ts +71 -0
- package/src/http/api-contract-compat.ts +49 -0
- package/src/http/api-error.ts +115 -1
- package/src/http/auth.ts +48 -0
- package/src/http/cors.ts +67 -0
- package/src/http/deprecation.ts +118 -0
- package/src/http/interaction-control-error.ts +164 -0
- package/src/http/keyed-admission.ts +29 -0
- package/src/http/local-browser-boundary.ts +343 -0
- package/src/http/metrics-listener.ts +57 -0
- package/src/http/path-identifier.ts +54 -0
- package/src/http/registered-route-label.ts +34 -0
- package/src/http/request-body.ts +127 -0
- package/src/http/request-source.ts +178 -0
- package/src/http/sse.ts +486 -132
- package/src/http/unmatched-route.ts +60 -0
- package/src/http/user-content.ts +158 -0
- package/src/http/websocket-upgrade-dispatch.ts +29 -0
- package/src/index.ts +157 -52
- package/src/integration-endpoint-test.ts +291 -0
- package/src/integrations/api-integrations.ts +98 -11
- package/src/integrations/atlassian.ts +474 -136
- package/src/integrations/connect-authority.ts +2 -0
- package/src/integrations/connect-callback-return.ts +86 -0
- package/src/integrations/fiken.ts +354 -64
- package/src/integrations/github-app-connect.ts +435 -0
- package/src/integrations/github-installation-proof.ts +60 -0
- package/src/integrations/github-lens-connect.ts +76 -0
- package/src/integrations/github-skill-source.ts +2 -142
- package/src/integrations/google-drive.ts +717 -225
- package/src/integrations/integration-commit-authority.ts +69 -0
- package/src/integrations/marketplace-plugin.ts +48 -0
- package/src/integrations/oauth-client.ts +1356 -459
- package/src/integrations/oauth-profiles.ts +537 -0
- package/src/integrations/oauth-return-path.ts +18 -0
- package/src/integrations/personal-github-repositories.ts +674 -0
- package/src/integrations/personal-github.ts +825 -0
- package/src/integrations/pr-review-provider.ts +246 -0
- package/src/integrations/provider-oauth.ts +250 -22
- package/src/integrations/slack-app-home.ts +300 -0
- package/src/integrations/slack-bot.ts +963 -239
- package/src/integrations/slack-file-upload-flow.ts +147 -0
- package/src/integrations/slack-install.ts +83 -0
- package/src/integrations/slack-interactions.ts +3167 -474
- package/src/integrations/slack-mrkdwn.ts +193 -0
- package/src/integrations/slack-routing.ts +337 -0
- package/src/integrations/slack-session-defaults.ts +224 -0
- package/src/integrations/slack-task-file-upload.ts +323 -0
- package/src/integrations/social-oauth.ts +213 -15
- package/src/interaction-agent-access.ts +48 -0
- package/src/interaction-frame-proxy.ts +409 -0
- package/src/interaction-metrics.ts +30 -0
- package/src/mcp/action-catalog-types.ts +9 -0
- package/src/mcp/action-catalog.gen.ts +6696 -0
- package/src/mcp/capability-account-readiness.ts +17 -0
- package/src/mcp/child-read-evidence.ts +19 -0
- package/src/mcp/command-read.ts +109 -0
- package/src/mcp/company-profile-agent-admin.ts +198 -0
- package/src/mcp/contract-input.ts +141 -0
- package/src/mcp/documents.ts +65 -377
- package/src/mcp/editable-artifacts.ts +12 -6
- package/src/mcp/files.ts +80 -43
- package/src/mcp/first-party-tool-permissions.ts +305 -0
- package/src/mcp/knowledge-entries.ts +322 -0
- package/src/mcp/orchestration-failure-diagnostic.ts +43 -0
- package/src/mcp/receipts.ts +34 -0
- package/src/mcp/request-abort.ts +44 -0
- package/src/mcp/scheduled-task-input.ts +76 -0
- package/src/mcp/scheduled-task-view.ts +44 -3
- package/src/mcp/server.ts +3030 -1267
- package/src/mcp/session-event-view.ts +383 -0
- package/src/mcp/session-view.ts +84 -3
- package/src/mcp/session-wait.ts +665 -0
- package/src/mcp-oauth.ts +1123 -0
- package/src/model-catalog.ts +91 -333
- package/src/observability.ts +15 -1
- package/src/organization-mcp.ts +397 -0
- package/src/organization-recovery-notifications.ts +103 -0
- package/src/routes/analytics-consent.ts +123 -0
- package/src/routes/api-integrations.ts +364 -74
- package/src/routes/api-keys.ts +336 -10
- package/src/routes/artifact-catalog.ts +279 -0
- package/src/routes/automations.ts +768 -0
- package/src/routes/billing.ts +461 -46
- package/src/routes/browser-sessions.ts +780 -112
- package/src/routes/canonical-human-identities.ts +90 -14
- package/src/routes/capabilities.ts +107 -6
- package/src/routes/channels.ts +20 -3
- package/src/routes/claude-subscription-accounts.ts +334 -0
- package/src/routes/claude-subscription-oauth.ts +142 -0
- package/src/routes/client-errors.ts +362 -0
- package/src/routes/codex.ts +833 -116
- package/src/routes/company-brain.ts +322 -0
- package/src/routes/company-profile.ts +65 -1
- package/src/routes/computer-sessions.ts +557 -106
- package/src/routes/connect.ts +1938 -0
- package/src/routes/connections.ts +1039 -349
- package/src/routes/documents.ts +488 -287
- package/src/routes/editable-artifacts.ts +79 -9
- package/src/routes/enrollments.ts +135 -39
- package/src/routes/environments.ts +154 -58
- package/src/routes/external-identity-links.ts +201 -0
- package/src/routes/feedback.ts +113 -0
- package/src/routes/files.ts +267 -33
- package/src/routes/github-browser-pages.ts +162 -0
- package/src/routes/github.ts +446 -144
- package/src/routes/insights-response-cache.ts +83 -0
- package/src/routes/insights-usage.ts +345 -0
- package/src/routes/insights.ts +153 -19
- package/src/routes/install.ts +133 -38
- package/src/routes/integration-facets.ts +107 -33
- package/src/routes/interaction-resources.ts +30 -3
- package/src/routes/knowledge.ts +488 -0
- package/src/routes/machines.ts +313 -15
- package/src/routes/managed-auth-session-sets.ts +1218 -0
- package/src/routes/managed-onboarding.ts +337 -0
- package/src/routes/managed-sign-in-methods.ts +433 -0
- package/src/routes/memory-slack-publications.ts +3 -2
- package/src/routes/model-connection-access.ts +208 -0
- package/src/routes/organization-integration-policy.ts +116 -0
- package/src/routes/organization-integrations.ts +326 -0
- package/src/routes/organization-mcp-connections.ts +178 -0
- package/src/routes/organization-memberships.ts +1019 -27
- package/src/routes/organization-model-providers.ts +293 -0
- package/src/routes/organization-recovery.ts +325 -0
- package/src/routes/organization-service-accounts.ts +128 -0
- package/src/routes/organization-sessions.ts +350 -0
- package/src/routes/personal-github-git-broker.ts +785 -0
- package/src/routes/personal-github.ts +370 -0
- package/src/routes/plugins.ts +251 -22
- package/src/routes/pr-review-github.ts +881 -0
- package/src/routes/pr-review.ts +622 -0
- package/src/routes/preference-registry.ts +12 -93
- package/src/routes/rigs.ts +167 -50
- package/src/routes/scheduled-tasks.ts +346 -41
- package/src/routes/session-artifact-associations.ts +87 -0
- package/src/routes/session-history-imports.ts +280 -0
- package/src/routes/sessions.ts +2306 -264
- package/src/routes/skill-content.ts +297 -0
- package/src/routes/skill-install-authority.ts +64 -0
- package/src/routes/skills.ts +62 -9
- package/src/routes/social.ts +46 -18
- package/src/routes/subscription-account-pools.ts +436 -0
- package/src/routes/subscription-pool-access.ts +126 -0
- package/src/routes/supergrok.ts +219 -303
- package/src/routes/transcription-recordings.ts +38 -3
- package/src/routes/transcriptions.ts +4 -0
- package/src/routes/usage-allowances.ts +378 -0
- package/src/routes/user-resource-authorities.ts +138 -0
- package/src/routes/video-generation.ts +14 -10
- package/src/routes/workspace-artifacts.ts +275 -69
- package/src/routes/workspace-capture.ts +21 -0
- package/src/routes/workspace-integrations.ts +576 -0
- package/src/routes/workspace-learning.ts +159 -0
- package/src/routes/workspace-model-providers.ts +148 -0
- package/src/routes/workspace-state.ts +38 -25
- package/src/routes/workspaces.ts +1004 -127
- package/src/sandbox/auth-callout.ts +96 -19
- package/src/sandbox/channel-a.ts +323 -24
- package/src/sandbox/connection-authority.ts +3 -0
- package/src/sandbox/enrollment.ts +81 -6
- package/src/sandbox/machines.ts +218 -76
- package/src/sandbox/metrics-ingestion.ts +411 -62
- package/src/sandbox/rematerialize.ts +121 -19
- package/src/sandbox/session-attach-variable-sets.ts +131 -0
- package/src/sandbox/viewer.ts +280 -25
- package/src/sandbox-file-artifacts.ts +413 -0
- package/src/scheduled-task-deletion.ts +138 -0
- package/src/session-create-observability.ts +46 -0
- package/src/session-realtime-context.ts +6 -3
- package/src/site-session-origin.ts +48 -0
- package/src/site-uploads.ts +224 -0
- package/src/slack-reaction-files.ts +16 -5
- package/src/temporal-schedule-cleanup.ts +13 -0
- package/src/temporal-schedule-sync.ts +74 -0
- package/src/transcription/providers/codex-subscription.ts +2 -0
- package/src/transcription/providers/openai.ts +1 -0
- package/src/transcription/providers/xai-subscription.ts +49 -3
- package/src/transcription/segmenter.ts +8 -2
- package/src/transcription/service.ts +43 -6
- package/src/work-discovery-observability.ts +121 -0
- package/src/workspace-artifact-content.ts +144 -0
- package/src/workspace-artifact-provenance.ts +104 -0
- package/src/workspace-delete-observability.ts +75 -0
- package/src/workspace-deletion.ts +73 -0
- package/src/workspace-state-projection.ts +18 -148
- package/src/workspace-tool-gateway-observability.ts +100 -0
- package/src/workspace-tool-gateway.ts +870 -0
- package/src/workspace-webhook-dispatch.ts +190 -0
- package/src/xai-subscription-auth.ts +9 -2
- package/dist/chunk-WCXHI3FF.js +0 -49920
- package/dist/chunk-WCXHI3FF.js.map +0 -1
- package/dist/routes/packs.d.ts +0 -3
- package/src/routes/packs.ts +0 -729
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { WorkDiscoveryMatchClass } from "@opengeni/contracts";
|
|
2
|
+
import type { Observability } from "@opengeni/observability";
|
|
3
|
+
|
|
4
|
+
export type WorkDiscoverySurface = "first_party_mcp" | "agent_topology";
|
|
5
|
+
export type WorkDiscoveryMode = "browse" | "query" | "subject";
|
|
6
|
+
export type WorkDiscoveryOutcome = "ok" | "empty" | "disabled" | "error";
|
|
7
|
+
export type WorkDiscoveryAuthorizationScope = "workspace" | "scoped";
|
|
8
|
+
|
|
9
|
+
export type WorkDiscoveryObservation = {
|
|
10
|
+
surface: WorkDiscoverySurface;
|
|
11
|
+
mode: WorkDiscoveryMode;
|
|
12
|
+
outcome: WorkDiscoveryOutcome;
|
|
13
|
+
authorizationScope: WorkDiscoveryAuthorizationScope;
|
|
14
|
+
durationMs: number;
|
|
15
|
+
responseBytes: number;
|
|
16
|
+
resultCount: number;
|
|
17
|
+
overlapCount: number;
|
|
18
|
+
matchCounts: Partial<Record<WorkDiscoveryMatchClass, number>>;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
type WorkDiscoveryObservedRow = {
|
|
22
|
+
relatedWork?: {
|
|
23
|
+
match: { class: WorkDiscoveryMatchClass } | null;
|
|
24
|
+
possibleOverlap: boolean;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const RESULT_BUCKETS = [0, 1, 2, 4, 8, 16, 32, 64, 100];
|
|
29
|
+
const RESPONSE_BYTE_BUCKETS = [512, 1_024, 4_096, 16_384, 65_536, 128_000, 262_144];
|
|
30
|
+
const DURATION_BUCKETS = [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5];
|
|
31
|
+
|
|
32
|
+
export function summarizeWorkDiscoveryRows(
|
|
33
|
+
rows: readonly WorkDiscoveryObservedRow[],
|
|
34
|
+
): Pick<WorkDiscoveryObservation, "resultCount" | "overlapCount" | "matchCounts"> {
|
|
35
|
+
const matchCounts: WorkDiscoveryObservation["matchCounts"] = {};
|
|
36
|
+
let overlapCount = 0;
|
|
37
|
+
for (const row of rows) {
|
|
38
|
+
if (row.relatedWork?.possibleOverlap) overlapCount += 1;
|
|
39
|
+
const matchClass = row.relatedWork?.match?.class;
|
|
40
|
+
if (matchClass) matchCounts[matchClass] = (matchCounts[matchClass] ?? 0) + 1;
|
|
41
|
+
}
|
|
42
|
+
return { resultCount: rows.length, overlapCount, matchCounts };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Low-cardinality work-discovery telemetry. Identifiers, search text, subject
|
|
47
|
+
* keys, titles, goals, claim labels, versions, and provenance are excluded by
|
|
48
|
+
* construction. An observability failure never changes product behavior.
|
|
49
|
+
*/
|
|
50
|
+
export function observeWorkDiscovery(
|
|
51
|
+
observability: Observability | null | undefined,
|
|
52
|
+
observation: WorkDiscoveryObservation,
|
|
53
|
+
): void {
|
|
54
|
+
if (!observability) return;
|
|
55
|
+
const labels = {
|
|
56
|
+
surface: observation.surface,
|
|
57
|
+
mode: observation.mode,
|
|
58
|
+
outcome: observation.outcome,
|
|
59
|
+
authorization_scope: observation.authorizationScope,
|
|
60
|
+
};
|
|
61
|
+
try {
|
|
62
|
+
observability.incrementCounter({
|
|
63
|
+
name: "opengeni_work_discovery_requests_total",
|
|
64
|
+
help: "Advisory work-discovery requests by bounded surface, mode, outcome, and authorization scope.",
|
|
65
|
+
labels,
|
|
66
|
+
});
|
|
67
|
+
observability.observeHistogram({
|
|
68
|
+
name: "opengeni_work_discovery_duration_seconds",
|
|
69
|
+
help: "Advisory work-discovery request duration in seconds.",
|
|
70
|
+
labels,
|
|
71
|
+
buckets: DURATION_BUCKETS,
|
|
72
|
+
value: Math.max(0, observation.durationMs) / 1_000,
|
|
73
|
+
});
|
|
74
|
+
observability.observeHistogram({
|
|
75
|
+
name: "opengeni_work_discovery_results",
|
|
76
|
+
help: "Bounded advisory work-discovery result rows per request.",
|
|
77
|
+
labels: { surface: observation.surface, mode: observation.mode },
|
|
78
|
+
buckets: RESULT_BUCKETS,
|
|
79
|
+
value: Math.max(0, Math.floor(observation.resultCount)),
|
|
80
|
+
});
|
|
81
|
+
observability.observeHistogram({
|
|
82
|
+
name: "opengeni_work_discovery_response_bytes",
|
|
83
|
+
help: "Serialized advisory work-discovery response bytes.",
|
|
84
|
+
labels: { surface: observation.surface, mode: observation.mode },
|
|
85
|
+
buckets: RESPONSE_BYTE_BUCKETS,
|
|
86
|
+
value: Math.max(0, Math.floor(observation.responseBytes)),
|
|
87
|
+
});
|
|
88
|
+
if (observation.overlapCount > 0) {
|
|
89
|
+
observability.incrementCounter({
|
|
90
|
+
name: "opengeni_work_discovery_overlap_results_total",
|
|
91
|
+
help: "Advisory discovery rows carrying a possible-overlap explanation.",
|
|
92
|
+
labels: { surface: observation.surface, mode: observation.mode },
|
|
93
|
+
amount: Math.floor(observation.overlapCount),
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
for (const matchClass of ["exact_subject", "title", "goal", "fuzzy"] as const) {
|
|
97
|
+
const amount = Math.floor(observation.matchCounts[matchClass] ?? 0);
|
|
98
|
+
if (amount < 1) continue;
|
|
99
|
+
observability.incrementCounter({
|
|
100
|
+
name: "opengeni_work_discovery_matches_total",
|
|
101
|
+
help: "Advisory discovery matches by stable explanation class.",
|
|
102
|
+
labels: {
|
|
103
|
+
surface: observation.surface,
|
|
104
|
+
mode: observation.mode,
|
|
105
|
+
match_class: matchClass,
|
|
106
|
+
},
|
|
107
|
+
amount,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
} catch {
|
|
111
|
+
try {
|
|
112
|
+
observability.incrementCounter({
|
|
113
|
+
name: "opengeni_observability_observer_errors_total",
|
|
114
|
+
help: "Observability observer failures isolated from product execution.",
|
|
115
|
+
labels: { observer: "work_discovery" },
|
|
116
|
+
});
|
|
117
|
+
} catch {
|
|
118
|
+
// The metrics registry itself is unhealthy. Discovery remains authoritative.
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import {
|
|
2
|
+
WorkspaceArtifactHtml,
|
|
3
|
+
WorkspaceArtifactRequestedTools,
|
|
4
|
+
WorkspaceArtifactSourceBundle,
|
|
5
|
+
type ToolGatewayIdentity,
|
|
6
|
+
type WorkspaceArtifactSourceBundle as WorkspaceArtifactSourceBundleValue,
|
|
7
|
+
type WorkspaceArtifactVersion,
|
|
8
|
+
} from "@opengeni/contracts";
|
|
9
|
+
import type { ObjectStorageDependency } from "@opengeni/core";
|
|
10
|
+
import { retryWhileMissing } from "@opengeni/storage";
|
|
11
|
+
|
|
12
|
+
const encoder = new TextEncoder();
|
|
13
|
+
const decoder = new TextDecoder("utf-8", { fatal: true });
|
|
14
|
+
|
|
15
|
+
export type PreparedWorkspaceArtifactContent = {
|
|
16
|
+
contentKey: string;
|
|
17
|
+
contentSha256: null;
|
|
18
|
+
sizeBytes: number;
|
|
19
|
+
sourceKey: string | null;
|
|
20
|
+
sourceSha256: null;
|
|
21
|
+
sourceSizeBytes: number | null;
|
|
22
|
+
requestedTools?: ToolGatewayIdentity[];
|
|
23
|
+
persistContent: () => Promise<void>;
|
|
24
|
+
discardContent: () => Promise<void>;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export function prepareWorkspaceArtifactContent(
|
|
28
|
+
objectStorage: NonNullable<ObjectStorageDependency>,
|
|
29
|
+
workspaceId: string,
|
|
30
|
+
input: {
|
|
31
|
+
html: string;
|
|
32
|
+
source?: WorkspaceArtifactSourceBundleValue;
|
|
33
|
+
requestedTools?: ToolGatewayIdentity[];
|
|
34
|
+
},
|
|
35
|
+
): PreparedWorkspaceArtifactContent {
|
|
36
|
+
const html = WorkspaceArtifactHtml.parse(input.html);
|
|
37
|
+
const source = input.source ? WorkspaceArtifactSourceBundle.parse(input.source) : null;
|
|
38
|
+
const requestedTools =
|
|
39
|
+
input.requestedTools === undefined
|
|
40
|
+
? undefined
|
|
41
|
+
: WorkspaceArtifactRequestedTools.parse(input.requestedTools);
|
|
42
|
+
const contentBytes = encoder.encode(html);
|
|
43
|
+
const sourceBytes = source ? encoder.encode(JSON.stringify(source)) : null;
|
|
44
|
+
const contentSha256 = null;
|
|
45
|
+
const sourceSha256 = null;
|
|
46
|
+
const storageGroupId = crypto.randomUUID();
|
|
47
|
+
const contentKey = `workspaces/${workspaceId}/workspace-artifacts/blobs/${storageGroupId}.html`;
|
|
48
|
+
const sourceKey = `workspaces/${workspaceId}/workspace-artifacts/sources/${storageGroupId}.json`;
|
|
49
|
+
const discardContent = async (): Promise<void> => {
|
|
50
|
+
await Promise.allSettled([
|
|
51
|
+
objectStorage.deleteObject(contentKey),
|
|
52
|
+
...(source ? [objectStorage.deleteObject(sourceKey)] : []),
|
|
53
|
+
]);
|
|
54
|
+
};
|
|
55
|
+
return {
|
|
56
|
+
contentKey,
|
|
57
|
+
contentSha256,
|
|
58
|
+
sizeBytes: contentBytes.byteLength,
|
|
59
|
+
sourceKey: source ? sourceKey : null,
|
|
60
|
+
sourceSha256,
|
|
61
|
+
sourceSizeBytes: sourceBytes?.byteLength ?? null,
|
|
62
|
+
...(requestedTools === undefined ? {} : { requestedTools }),
|
|
63
|
+
discardContent,
|
|
64
|
+
persistContent: async () => {
|
|
65
|
+
const writes = await Promise.allSettled([
|
|
66
|
+
objectStorage.putObject({
|
|
67
|
+
key: contentKey,
|
|
68
|
+
contentType: "text/html; charset=utf-8",
|
|
69
|
+
body: contentBytes,
|
|
70
|
+
}),
|
|
71
|
+
sourceBytes
|
|
72
|
+
? objectStorage.putObject({
|
|
73
|
+
key: sourceKey,
|
|
74
|
+
contentType: "application/json; charset=utf-8",
|
|
75
|
+
body: sourceBytes,
|
|
76
|
+
})
|
|
77
|
+
: Promise.resolve(),
|
|
78
|
+
]);
|
|
79
|
+
const failed = writes.find((write) => write.status === "rejected");
|
|
80
|
+
if (!failed) return;
|
|
81
|
+
await Promise.allSettled(
|
|
82
|
+
writes.flatMap((write, index) =>
|
|
83
|
+
write.status === "fulfilled"
|
|
84
|
+
? [objectStorage.deleteObject(index === 0 ? contentKey : sourceKey)]
|
|
85
|
+
: [],
|
|
86
|
+
),
|
|
87
|
+
);
|
|
88
|
+
throw failed.reason;
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export async function readWorkspaceArtifactContent(
|
|
94
|
+
objectStorage: NonNullable<ObjectStorageDependency>,
|
|
95
|
+
input: {
|
|
96
|
+
contentKey: string;
|
|
97
|
+
sourceKey: string | null;
|
|
98
|
+
version: WorkspaceArtifactVersion;
|
|
99
|
+
},
|
|
100
|
+
): Promise<{
|
|
101
|
+
html: string;
|
|
102
|
+
source: WorkspaceArtifactSourceBundleValue;
|
|
103
|
+
requestedTools: ToolGatewayIdentity[];
|
|
104
|
+
}> {
|
|
105
|
+
const [contentObject, sourceObject] = await Promise.all([
|
|
106
|
+
retryWhileMissing(async () => await objectStorage.getObjectBytes(input.contentKey)),
|
|
107
|
+
input.sourceKey
|
|
108
|
+
? retryWhileMissing(async () => await objectStorage.getObjectBytes(input.sourceKey!))
|
|
109
|
+
: Promise.resolve(null),
|
|
110
|
+
]);
|
|
111
|
+
if (!contentObject) throw new Error("Artifact content is unavailable");
|
|
112
|
+
const html = decode(contentObject.bytes, "Artifact content is not valid UTF-8");
|
|
113
|
+
let source = sourceBundleFromHtml(html);
|
|
114
|
+
if (input.sourceKey) {
|
|
115
|
+
if (!sourceObject) throw new Error("Artifact source is unavailable");
|
|
116
|
+
try {
|
|
117
|
+
source = WorkspaceArtifactSourceBundle.parse(
|
|
118
|
+
JSON.parse(decode(sourceObject.bytes, "Artifact source is not valid UTF-8")),
|
|
119
|
+
);
|
|
120
|
+
} catch (error) {
|
|
121
|
+
if (error instanceof Error && error.message === "Artifact source is not valid UTF-8") {
|
|
122
|
+
throw error;
|
|
123
|
+
}
|
|
124
|
+
throw new Error("Artifact source is invalid", { cause: error });
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
html,
|
|
129
|
+
source,
|
|
130
|
+
requestedTools: WorkspaceArtifactRequestedTools.parse(input.version.requestedTools),
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export function sourceBundleFromHtml(html: string): WorkspaceArtifactSourceBundleValue {
|
|
135
|
+
return { entrypoint: "index.html", files: [{ path: "index.html", content: html }] };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function decode(bytes: Uint8Array, message: string): string {
|
|
139
|
+
try {
|
|
140
|
+
return decoder.decode(bytes);
|
|
141
|
+
} catch (error) {
|
|
142
|
+
throw new Error(message, { cause: error });
|
|
143
|
+
}
|
|
144
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
WorkspaceArtifactDetailResponse,
|
|
3
|
+
WorkspaceArtifactListResponse,
|
|
4
|
+
WorkspaceArtifactMutationResponse,
|
|
5
|
+
WorkspaceArtifactVersion,
|
|
6
|
+
} from "@opengeni/contracts";
|
|
7
|
+
|
|
8
|
+
type ArtifactProvenance = {
|
|
9
|
+
sourceSessionId: string | null;
|
|
10
|
+
sourceTurnId: string | null;
|
|
11
|
+
sourceAttemptId: string | null;
|
|
12
|
+
sourceExecutionGeneration: number | null;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
type CanReadSession = (sessionId: string) => Promise<boolean>;
|
|
16
|
+
|
|
17
|
+
function redactProvenance<Value extends ArtifactProvenance>(value: Value): Value {
|
|
18
|
+
return {
|
|
19
|
+
...value,
|
|
20
|
+
sourceSessionId: null,
|
|
21
|
+
sourceTurnId: null,
|
|
22
|
+
sourceAttemptId: null,
|
|
23
|
+
sourceExecutionGeneration: null,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function artifactProvenanceProjector(canReadSession: CanReadSession) {
|
|
28
|
+
const decisions = new Map<string, Promise<boolean>>();
|
|
29
|
+
const canRead = (sessionId: string): Promise<boolean> => {
|
|
30
|
+
const existing = decisions.get(sessionId);
|
|
31
|
+
if (existing) return existing;
|
|
32
|
+
const decision = canReadSession(sessionId);
|
|
33
|
+
decisions.set(sessionId, decision);
|
|
34
|
+
return decision;
|
|
35
|
+
};
|
|
36
|
+
return async <Value extends ArtifactProvenance>(value: Value): Promise<Value> => {
|
|
37
|
+
if (!value.sourceSessionId || (await canRead(value.sourceSessionId))) return value;
|
|
38
|
+
return redactProvenance(value);
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function redactWorkspaceArtifactListProvenance(
|
|
43
|
+
response: WorkspaceArtifactListResponse,
|
|
44
|
+
): WorkspaceArtifactListResponse {
|
|
45
|
+
return {
|
|
46
|
+
...response,
|
|
47
|
+
artifacts: response.artifacts.map((artifact) => ({
|
|
48
|
+
...artifact,
|
|
49
|
+
currentVersion: artifact.currentVersion ? redactProvenance(artifact.currentVersion) : null,
|
|
50
|
+
})),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export async function projectWorkspaceArtifactVersionProvenance(
|
|
55
|
+
version: WorkspaceArtifactVersion,
|
|
56
|
+
canReadSession: CanReadSession,
|
|
57
|
+
): Promise<WorkspaceArtifactVersion> {
|
|
58
|
+
return await artifactProvenanceProjector(canReadSession)(version);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export async function projectWorkspaceArtifactDetailProvenance(
|
|
62
|
+
detail: WorkspaceArtifactDetailResponse,
|
|
63
|
+
canReadSession: CanReadSession,
|
|
64
|
+
): Promise<WorkspaceArtifactDetailResponse> {
|
|
65
|
+
const project = artifactProvenanceProjector(canReadSession);
|
|
66
|
+
const [currentVersion, versions, events] = await Promise.all([
|
|
67
|
+
detail.artifact.currentVersion ? project(detail.artifact.currentVersion) : null,
|
|
68
|
+
Promise.all(detail.versions.map(project)),
|
|
69
|
+
Promise.all(detail.events.map(project)),
|
|
70
|
+
]);
|
|
71
|
+
return {
|
|
72
|
+
...detail,
|
|
73
|
+
artifact: { ...detail.artifact, currentVersion },
|
|
74
|
+
versions,
|
|
75
|
+
events,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export async function projectWorkspaceArtifactMutationProvenance(
|
|
80
|
+
response: WorkspaceArtifactMutationResponse,
|
|
81
|
+
canReadSession: CanReadSession,
|
|
82
|
+
): Promise<WorkspaceArtifactMutationResponse> {
|
|
83
|
+
// The mutation is already durable before this response projection runs. A
|
|
84
|
+
// transient source-session lookup must fail closed to redaction rather than
|
|
85
|
+
// turn a committed, idempotent mutation into an ambiguous HTTP/tool error.
|
|
86
|
+
const project = artifactProvenanceProjector(async (sessionId) => {
|
|
87
|
+
try {
|
|
88
|
+
return await canReadSession(sessionId);
|
|
89
|
+
} catch {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
const [currentVersion, version, event] = await Promise.all([
|
|
94
|
+
response.artifact.currentVersion ? project(response.artifact.currentVersion) : null,
|
|
95
|
+
project(response.version),
|
|
96
|
+
project(response.event),
|
|
97
|
+
]);
|
|
98
|
+
return {
|
|
99
|
+
...response,
|
|
100
|
+
artifact: { ...response.artifact, currentVersion },
|
|
101
|
+
version,
|
|
102
|
+
event,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { WorkspaceDeleteObservation, WorkspaceDeleteObserver } from "@opengeni/db";
|
|
2
|
+
import type { Observability } from "@opengeni/observability";
|
|
3
|
+
|
|
4
|
+
const DURATION_BUCKETS = [
|
|
5
|
+
0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 30, 60, 120, 300, 600, 1_200, 2_400,
|
|
6
|
+
3_600,
|
|
7
|
+
];
|
|
8
|
+
const INVENTORY_BUCKETS = [0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1_000, 5_000, 10_000];
|
|
9
|
+
|
|
10
|
+
function recordWorkspaceDeleteObservation(
|
|
11
|
+
observability: Observability,
|
|
12
|
+
identity: { accountId: string; workspaceId: string },
|
|
13
|
+
observation: WorkspaceDeleteObservation,
|
|
14
|
+
): void {
|
|
15
|
+
const labels = { phase: observation.phase, outcome: observation.outcome };
|
|
16
|
+
observability.observeHistogram({
|
|
17
|
+
name: "opengeni_workspace_delete_phase_seconds",
|
|
18
|
+
help: "Workspace deletion transaction and bounded internal phase duration in seconds.",
|
|
19
|
+
labels,
|
|
20
|
+
buckets: DURATION_BUCKETS,
|
|
21
|
+
value: Math.max(0, observation.durationSeconds),
|
|
22
|
+
});
|
|
23
|
+
if (observation.phase === "transaction") {
|
|
24
|
+
observability.incrementCounter({
|
|
25
|
+
name: "opengeni_workspace_delete_attempts_total",
|
|
26
|
+
help: "Workspace deletion attempts by terminal database outcome.",
|
|
27
|
+
labels: { outcome: observation.outcome },
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
for (const [kind, count] of Object.entries(observation.inventory ?? {})) {
|
|
31
|
+
observability.observeHistogram({
|
|
32
|
+
name: "opengeni_workspace_delete_inventory_rows",
|
|
33
|
+
help: "Rows or live owners observed by workspace deletion preflight inventory class.",
|
|
34
|
+
labels: { kind },
|
|
35
|
+
buckets: INVENTORY_BUCKETS,
|
|
36
|
+
value: Math.max(0, Math.floor(count ?? 0)),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
observability.info("Workspace deletion phase", {
|
|
40
|
+
accountId: identity.accountId,
|
|
41
|
+
workspaceId: identity.workspaceId,
|
|
42
|
+
phase: observation.phase,
|
|
43
|
+
outcome: observation.outcome,
|
|
44
|
+
durationSeconds: observation.durationSeconds,
|
|
45
|
+
inventoryJson: JSON.stringify(observation.inventory ?? {}),
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Retain exact workspace deletion timing and inventory without putting tenant
|
|
51
|
+
* identifiers in metric labels. Observer failures never change deletion truth.
|
|
52
|
+
*/
|
|
53
|
+
export function workspaceDeleteObserver(
|
|
54
|
+
observability: Observability | null | undefined,
|
|
55
|
+
identity: { accountId: string; workspaceId: string },
|
|
56
|
+
): WorkspaceDeleteObserver | undefined {
|
|
57
|
+
if (!observability) return undefined;
|
|
58
|
+
return {
|
|
59
|
+
onPhase: (observation) => {
|
|
60
|
+
try {
|
|
61
|
+
recordWorkspaceDeleteObservation(observability, identity, observation);
|
|
62
|
+
} catch {
|
|
63
|
+
try {
|
|
64
|
+
observability.incrementCounter({
|
|
65
|
+
name: "opengeni_observability_observer_errors_total",
|
|
66
|
+
help: "Observability observer failures isolated from product execution.",
|
|
67
|
+
labels: { observer: "workspace_delete" },
|
|
68
|
+
});
|
|
69
|
+
} catch {
|
|
70
|
+
// The metrics registry itself is unhealthy. Deletion remains authoritative.
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { deleteWorkspaceIfQuiescent, nestedPostgresSqlState } from "@opengeni/db";
|
|
2
|
+
import type { ApiRouteDeps } from "@opengeni/core";
|
|
3
|
+
import { HTTPException } from "hono/http-exception";
|
|
4
|
+
|
|
5
|
+
import { processTemporalScheduleCleanupClaims } from "./temporal-schedule-cleanup";
|
|
6
|
+
import { workspaceDeleteObserver } from "./workspace-delete-observability";
|
|
7
|
+
|
|
8
|
+
export async function deleteWorkspaceForRequest(
|
|
9
|
+
deps: ApiRouteDeps,
|
|
10
|
+
input: {
|
|
11
|
+
accountId: string;
|
|
12
|
+
workspaceId: string;
|
|
13
|
+
organizationAdministratorSubjectId?: string;
|
|
14
|
+
},
|
|
15
|
+
): Promise<void> {
|
|
16
|
+
const observer = workspaceDeleteObserver(deps.observability, input);
|
|
17
|
+
let deleted;
|
|
18
|
+
try {
|
|
19
|
+
deleted = await deleteWorkspaceIfQuiescent(deps.db, {
|
|
20
|
+
...input,
|
|
21
|
+
...(observer ? { observer } : {}),
|
|
22
|
+
});
|
|
23
|
+
} catch (error) {
|
|
24
|
+
const state = nestedPostgresSqlState(error);
|
|
25
|
+
if (state === "42501") {
|
|
26
|
+
throw new HTTPException(403, { message: "organization administration is not authorized" });
|
|
27
|
+
}
|
|
28
|
+
if (state === "P0002") {
|
|
29
|
+
throw new HTTPException(404, { message: "workspace not found" });
|
|
30
|
+
}
|
|
31
|
+
if (state === "23503") {
|
|
32
|
+
// Retention and linked-record FKs are intentional deletion boundaries.
|
|
33
|
+
// The failed transaction has rolled back: do not erase history, retry
|
|
34
|
+
// the cascade, or dispatch any external schedule cleanup.
|
|
35
|
+
throw new HTTPException(409, {
|
|
36
|
+
message:
|
|
37
|
+
"workspace deletion is blocked by retained or linked records; keep the workspace, revoke access, and disable scheduled work instead",
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (deleted.status === "not_found") {
|
|
44
|
+
throw new HTTPException(404, { message: "workspace not found" });
|
|
45
|
+
}
|
|
46
|
+
const conflicts = {
|
|
47
|
+
only_workspace: "cannot delete the account's only workspace",
|
|
48
|
+
active_sessions: "stop the workspace's running sessions before deleting it",
|
|
49
|
+
active_video_generations:
|
|
50
|
+
"wait for the workspace's active video generations to finish before deleting it",
|
|
51
|
+
active_background_commands:
|
|
52
|
+
"pause or cancel the workspace's background commands before deleting it",
|
|
53
|
+
live_sandboxes:
|
|
54
|
+
"wait for the workspace's active sandboxes to finish draining before deleting it",
|
|
55
|
+
} as const;
|
|
56
|
+
if (deleted.status in conflicts) {
|
|
57
|
+
throw new HTTPException(409, { message: conflicts[deleted.status as keyof typeof conflicts] });
|
|
58
|
+
}
|
|
59
|
+
if (deleted.status !== "deleted") {
|
|
60
|
+
throw new Error(`Unhandled workspace deletion outcome: ${deleted.status}`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
await processTemporalScheduleCleanupClaims(
|
|
64
|
+
{
|
|
65
|
+
db: deps.db,
|
|
66
|
+
deleteSchedule: async (temporalScheduleId) => {
|
|
67
|
+
await deps.workflowClient.deleteScheduledTaskSchedule({ temporalScheduleId });
|
|
68
|
+
},
|
|
69
|
+
...(deps.observability ? { observability: deps.observability } : {}),
|
|
70
|
+
},
|
|
71
|
+
deleted.temporalScheduleCleanups,
|
|
72
|
+
);
|
|
73
|
+
}
|