@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,60 @@
|
|
|
1
|
+
import type { Context, Hono } from "hono";
|
|
2
|
+
import { matchedRoutes } from "hono/route";
|
|
3
|
+
|
|
4
|
+
type RegisteredRoute = { method: string; path: string; handler: unknown };
|
|
5
|
+
|
|
6
|
+
const PROBED_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"] as const;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Whether a matched Hono route is a terminal handler rather than middleware.
|
|
10
|
+
*
|
|
11
|
+
* Method-specific registrations (`app.get`, `app.put`, `app.on([...])`) always
|
|
12
|
+
* belong to a real route. `app.use` and `app.all` both register the `ALL`
|
|
13
|
+
* method; Hono itself tells them apart by arity - middleware takes
|
|
14
|
+
* `(context, next)` - so the same rule is applied here.
|
|
15
|
+
*/
|
|
16
|
+
function isTerminalRoute(route: RegisteredRoute): boolean {
|
|
17
|
+
if (route.method.toUpperCase() !== "ALL") return true;
|
|
18
|
+
return typeof route.handler === "function" && route.handler.length < 2;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function routesFor(app: Hono, method: string, path: string): RegisteredRoute[] {
|
|
22
|
+
// Every Hono router returns `[[ [handler, route], params ][], stash?]`.
|
|
23
|
+
const result = app.router.match(method, path) as unknown as [
|
|
24
|
+
Array<[[unknown, RegisteredRoute], unknown]>,
|
|
25
|
+
...unknown[],
|
|
26
|
+
];
|
|
27
|
+
return result[0].map(([[, route]]) => route);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type UnmatchedRoute = { status: 404 } | { status: 405; allow: string[] };
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Classify a request no registered handler can answer, BEFORE authentication
|
|
34
|
+
* or authorization middleware runs. Those layers otherwise turn a request for a
|
|
35
|
+
* route that does not exist into an authorization-shaped failure (for example
|
|
36
|
+
* the fail-closed session operation classifier answering a retryable 503), so
|
|
37
|
+
* a client probing an unknown method or path would be told to retry forever.
|
|
38
|
+
*
|
|
39
|
+
* Returns null when the request has a handler, or when classification itself
|
|
40
|
+
* fails (fail open: the request keeps its previous routing behavior).
|
|
41
|
+
*/
|
|
42
|
+
export function unmatchedRoute(app: Hono, c: Context): UnmatchedRoute | null {
|
|
43
|
+
const method = c.req.method.toUpperCase();
|
|
44
|
+
// CORS preflights are answered by middleware and have no route handlers.
|
|
45
|
+
if (method === "OPTIONS") return null;
|
|
46
|
+
try {
|
|
47
|
+
if (matchedRoutes(c).some((route) => isTerminalRoute(route as RegisteredRoute))) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
const effectiveMethod = method === "HEAD" ? "GET" : method;
|
|
51
|
+
const allow = PROBED_METHODS.filter(
|
|
52
|
+
(candidate) =>
|
|
53
|
+
candidate !== effectiveMethod &&
|
|
54
|
+
routesFor(app, candidate, c.req.path).some(isTerminalRoute),
|
|
55
|
+
);
|
|
56
|
+
return allow.length > 0 ? { status: 405, allow } : { status: 404 };
|
|
57
|
+
} catch {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Response headers for user-controlled bytes served from the API origin.
|
|
3
|
+
*
|
|
4
|
+
* Retained files, screenshots, exports, and live frames carry bytes and, for
|
|
5
|
+
* uploads, a content type chosen by a user or agent. The API shares its origin
|
|
6
|
+
* with the web console in the default deployment, so a stored `text/html` file
|
|
7
|
+
* opened by top-level navigation would otherwise run as that origin.
|
|
8
|
+
*
|
|
9
|
+
* Every such response therefore:
|
|
10
|
+
* - is a sandboxed document with no script, form, popup, plugin, or network
|
|
11
|
+
* capability (`sandbox` plus `default-src 'none'`). Raster images and text
|
|
12
|
+
* still render when a URL is opened directly;
|
|
13
|
+
* - cannot be embedded by another site as a no-cors subresource (CORP);
|
|
14
|
+
* - is never re-sniffed into a different type (`nosniff`).
|
|
15
|
+
*
|
|
16
|
+
* Audio and video keep their real origin (`sandbox allow-same-origin`, still
|
|
17
|
+
* without `allow-scripts`): the browser's synthesized media document re-fetches
|
|
18
|
+
* its own URL, and from an opaque origin that same-origin-only request would be
|
|
19
|
+
* refused. With scripts disabled and `nosniff`, such a response can only ever
|
|
20
|
+
* be a media player, never attacker markup.
|
|
21
|
+
*
|
|
22
|
+
* Markup types that a browser would render as an active document (HTML, XML,
|
|
23
|
+
* SVG, multipart) are additionally served as attachments, so a direct
|
|
24
|
+
* navigation downloads the bytes instead of showing attacker-authored markup on
|
|
25
|
+
* the app origin. The console never navigates to these routes: it reads bytes
|
|
26
|
+
* through the SDK and renders them in app-owned elements, so neither header
|
|
27
|
+
* changes an in-app preview. Signed object-storage GET URLs for active markup
|
|
28
|
+
* carry the same attachment as a signed response override
|
|
29
|
+
* (`userContentSignedGetUrlOptions`), because the storage endpoint is not
|
|
30
|
+
* always a separate site.
|
|
31
|
+
*/
|
|
32
|
+
const USER_CONTENT_FETCH_DIRECTIVES =
|
|
33
|
+
"default-src 'none'; img-src 'self' data: blob:; media-src 'self' data: blob:; style-src 'unsafe-inline'";
|
|
34
|
+
|
|
35
|
+
export const USER_CONTENT_SECURITY_POLICY = `${USER_CONTENT_FETCH_DIRECTIVES}; sandbox`;
|
|
36
|
+
|
|
37
|
+
/** Media players only; scripts stay disabled (see the module comment). */
|
|
38
|
+
export const USER_MEDIA_CONTENT_SECURITY_POLICY = `${USER_CONTENT_FETCH_DIRECTIVES}; sandbox allow-same-origin`;
|
|
39
|
+
|
|
40
|
+
export const USER_CONTENT_SECURITY_HEADERS = Object.freeze({
|
|
41
|
+
"Content-Security-Policy": USER_CONTENT_SECURITY_POLICY,
|
|
42
|
+
"Cross-Origin-Resource-Policy": "same-origin",
|
|
43
|
+
"X-Content-Type-Options": "nosniff",
|
|
44
|
+
} as const);
|
|
45
|
+
|
|
46
|
+
const ACTIVE_DOCUMENT_TYPES = new Set(["text/html", "text/xml", "text/xsl", "application/xml"]);
|
|
47
|
+
|
|
48
|
+
/** Media type essence (no parameters), lowercased. */
|
|
49
|
+
function mediaTypeEssence(contentType: string): string {
|
|
50
|
+
return (contentType.split(";", 1)[0] ?? "").trim().toLowerCase();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* True when a browser would render this type as an active document (HTML,
|
|
55
|
+
* XHTML, SVG, any XML dialect, or multipart replacement streams). Anything that
|
|
56
|
+
* is not a clean `type/subtype` token is treated as active too.
|
|
57
|
+
*/
|
|
58
|
+
export function isActiveUserContentType(contentType: string): boolean {
|
|
59
|
+
const essence = mediaTypeEssence(contentType);
|
|
60
|
+
if (!/^[a-z0-9][a-z0-9!#$&^_.+-]*\/[a-z0-9][a-z0-9!#$&^_.+-]*$/.test(essence)) return true;
|
|
61
|
+
return (
|
|
62
|
+
ACTIVE_DOCUMENT_TYPES.has(essence) ||
|
|
63
|
+
essence.endsWith("+xml") ||
|
|
64
|
+
essence.startsWith("multipart/")
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const DISPOSITION_FILENAME_MAX_CHARS = 200;
|
|
69
|
+
|
|
70
|
+
/** RFC 8187 `attr-char` percent-encoding (stricter than `encodeURIComponent`). */
|
|
71
|
+
function encodeExtendedParameterValue(value: string): string {
|
|
72
|
+
return encodeURIComponent(value).replace(
|
|
73
|
+
/['()*]/g,
|
|
74
|
+
(character) => `%${character.charCodeAt(0).toString(16).toUpperCase()}`,
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* RFC 6266 filename parameters: an ASCII-only quoted `filename` that cannot
|
|
80
|
+
* break out of the header, plus an RFC 8187 `filename*` carrying the original
|
|
81
|
+
* name (for example non-Latin names) whenever the ASCII form had to change it.
|
|
82
|
+
*/
|
|
83
|
+
function dispositionFilenameParameters(filename: string): string {
|
|
84
|
+
const cleaned = Array.from(
|
|
85
|
+
filename
|
|
86
|
+
.replace(/[\u0000-\u001f\u007f/\\]+/g, "_")
|
|
87
|
+
// Lone surrogates cannot be percent-encoded as UTF-8.
|
|
88
|
+
.replace(/[\ud800-\udbff](?![\udc00-\udfff])|(?<![\ud800-\udbff])[\udc00-\udfff]/g, "_")
|
|
89
|
+
.trim(),
|
|
90
|
+
)
|
|
91
|
+
.slice(0, DISPOSITION_FILENAME_MAX_CHARS)
|
|
92
|
+
.join("");
|
|
93
|
+
const ascii =
|
|
94
|
+
cleaned
|
|
95
|
+
.replace(/[^A-Za-z0-9._ -]+/g, "_")
|
|
96
|
+
.replace(/\s+/g, " ")
|
|
97
|
+
.trim()
|
|
98
|
+
.slice(0, DISPOSITION_FILENAME_MAX_CHARS) || "download";
|
|
99
|
+
if (!cleaned || ascii === cleaned) return `filename="${ascii}"`;
|
|
100
|
+
return `filename="${ascii}"; filename*=UTF-8''${encodeExtendedParameterValue(cleaned)}`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** `Content-Disposition: attachment` for active markup; inline types are unchanged. */
|
|
104
|
+
export function userContentDispositionHeaders(
|
|
105
|
+
contentType: string,
|
|
106
|
+
filename?: string | null,
|
|
107
|
+
): { "Content-Disposition": string } | Record<string, never> {
|
|
108
|
+
if (!isActiveUserContentType(contentType)) return {};
|
|
109
|
+
return {
|
|
110
|
+
"Content-Disposition": filename
|
|
111
|
+
? `attachment; ${dispositionFilenameParameters(filename)}`
|
|
112
|
+
: "attachment",
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Signed object-storage GET options for one stored object: active markup gets
|
|
118
|
+
* a signed `attachment` response override, so a browser that opens the URL
|
|
119
|
+
* downloads the bytes instead of rendering them with their stored type. The
|
|
120
|
+
* storage endpoint is not always a separate site (local development serves it
|
|
121
|
+
* from loopback, and a preview may route the bucket path on the app origin),
|
|
122
|
+
* so a signed URL follows the same rule as the API routes. Spread into
|
|
123
|
+
* `createGetUrl`; inline types add nothing.
|
|
124
|
+
*/
|
|
125
|
+
export function userContentSignedGetUrlOptions(
|
|
126
|
+
contentType: string,
|
|
127
|
+
filename?: string | null,
|
|
128
|
+
): { responseContentDisposition: string } | Record<string, never> {
|
|
129
|
+
const headers = userContentDispositionHeaders(contentType, filename);
|
|
130
|
+
return "Content-Disposition" in headers
|
|
131
|
+
? { responseContentDisposition: headers["Content-Disposition"] }
|
|
132
|
+
: {};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** True for audio and video types the browser plays in a synthesized media document. */
|
|
136
|
+
export function isPlayableMediaUserContentType(contentType: string): boolean {
|
|
137
|
+
const essence = mediaTypeEssence(contentType);
|
|
138
|
+
return !isActiveUserContentType(essence) && /^(audio|video)\//.test(essence);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** Sandbox policy for one response; only playable media keeps its origin. */
|
|
142
|
+
export function userContentSecurityPolicy(contentType: string): string {
|
|
143
|
+
return isPlayableMediaUserContentType(contentType)
|
|
144
|
+
? USER_MEDIA_CONTENT_SECURITY_POLICY
|
|
145
|
+
: USER_CONTENT_SECURITY_POLICY;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** Full header set for one user-content response with the given content type. */
|
|
149
|
+
export function userContentResponseHeaders(
|
|
150
|
+
contentType: string,
|
|
151
|
+
filename?: string | null,
|
|
152
|
+
): Record<string, string> {
|
|
153
|
+
return {
|
|
154
|
+
...USER_CONTENT_SECURITY_HEADERS,
|
|
155
|
+
"Content-Security-Policy": userContentSecurityPolicy(contentType),
|
|
156
|
+
...userContentDispositionHeaders(contentType, filename),
|
|
157
|
+
};
|
|
158
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { localBrowserBoundaryResponse, type LocalBrowserBoundary } from "./local-browser-boundary";
|
|
2
|
+
|
|
3
|
+
export type ApiWebSocketUpgradeRoute<Server> = {
|
|
4
|
+
handles(request: Request): boolean;
|
|
5
|
+
upgrade(request: Request, server: Server): Response | undefined;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export type ApiWebSocketUpgradeDispatch =
|
|
9
|
+
| { handled: false }
|
|
10
|
+
| { handled: true; response: Response | undefined };
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* WebSocket upgrades bypass the Hono app, so the local-mode browser boundary
|
|
14
|
+
* (./local-browser-boundary.ts) is applied here before a transport upgrades.
|
|
15
|
+
* Returns `{ handled: false }` when no transport claims the request, so the
|
|
16
|
+
* caller dispatches it to the app, where the boundary runs as middleware.
|
|
17
|
+
*/
|
|
18
|
+
export function dispatchApiWebSocketUpgrade<Server>(
|
|
19
|
+
request: Request,
|
|
20
|
+
server: Server,
|
|
21
|
+
routes: ReadonlyArray<ApiWebSocketUpgradeRoute<Server>>,
|
|
22
|
+
localBrowserBoundary: LocalBrowserBoundary | null,
|
|
23
|
+
): ApiWebSocketUpgradeDispatch {
|
|
24
|
+
const route = routes.find((candidate) => candidate.handles(request));
|
|
25
|
+
if (!route) return { handled: false };
|
|
26
|
+
const rejection = localBrowserBoundary?.rejection(request);
|
|
27
|
+
if (rejection) return { handled: true, response: localBrowserBoundaryResponse(rejection) };
|
|
28
|
+
return { handled: true, response: route.upgrade(request, server) };
|
|
29
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { scheduledTaskKnowledgeSource } from "@opengeni/contracts";
|
|
1
2
|
import {
|
|
2
3
|
dbSearchPath,
|
|
3
4
|
getSettings,
|
|
5
|
+
resolveFirstPartyDelegationSecret,
|
|
4
6
|
resolveNatsCalloutConfig,
|
|
5
7
|
resolveNatsControlPlaneAuth,
|
|
6
8
|
retryStartupDependency,
|
|
@@ -14,16 +16,24 @@ import type {
|
|
|
14
16
|
} from "@opengeni/contracts";
|
|
15
17
|
import {
|
|
16
18
|
assertRuntimeDatabasePosture,
|
|
19
|
+
isRetryableRuntimeDatabaseStartupError,
|
|
17
20
|
createDb,
|
|
18
21
|
markSessionWorkflowWakeDelivered,
|
|
19
22
|
runtimeDatabaseReadyCheck,
|
|
20
23
|
type Database,
|
|
21
24
|
} from "@opengeni/db";
|
|
22
25
|
import { createNatsEventBus, type ResponderConnection } from "@opengeni/events";
|
|
23
|
-
import {
|
|
26
|
+
import {
|
|
27
|
+
createObservability,
|
|
28
|
+
logStartupDependencyRetry,
|
|
29
|
+
type Observability,
|
|
30
|
+
} from "@opengeni/observability";
|
|
24
31
|
import { createObjectStorage } from "@opengeni/storage";
|
|
25
32
|
import { isArtifactRuntimeConfigured } from "@opengeni/artifact-tool/runtime/development";
|
|
26
|
-
import {
|
|
33
|
+
import {
|
|
34
|
+
resolveCatalogSettings,
|
|
35
|
+
SESSION_WORKFLOW_WAKE_DISPATCHER_SCHEDULE_ID,
|
|
36
|
+
} from "@opengeni/core";
|
|
27
37
|
import {
|
|
28
38
|
Connection,
|
|
29
39
|
Client as TemporalClient,
|
|
@@ -33,21 +43,31 @@ import {
|
|
|
33
43
|
} from "@temporalio/client";
|
|
34
44
|
import type { ScheduleOptions, ScheduleSpec, ScheduleUpdateOptions } from "@temporalio/client";
|
|
35
45
|
import { createAppComposition, type DocumentIndexClient, type SessionWorkflowClient } from "./app";
|
|
36
|
-
import {
|
|
46
|
+
import { observabilityEventBusOptions } from "./observability";
|
|
37
47
|
import { startAuthCalloutResponder } from "./sandbox/auth-callout";
|
|
38
48
|
import { startHelloIngestion, startMetricsIngestion } from "./sandbox/metrics-ingestion";
|
|
39
49
|
import { startSlackInteractionPump } from "./integrations/slack-interactions";
|
|
40
50
|
import { startMemorySlackPublicationPump } from "./memory-slack-delivery";
|
|
41
51
|
import { startTemporalScheduleCleanupPump } from "./temporal-schedule-cleanup";
|
|
52
|
+
import { createTemporalScheduleSynchronizer } from "./temporal-schedule-sync";
|
|
53
|
+
import { startWorkspaceWebhookDispatchPump } from "./workspace-webhook-dispatch";
|
|
54
|
+
import { cleanupScheduledTaskConnectorAuthorization } from "./scheduled-task-deletion";
|
|
42
55
|
import {
|
|
43
56
|
EDITABLE_ARTIFACT_LIVE_WEBSOCKET_MAX_MESSAGE_BYTES,
|
|
44
57
|
EditableArtifactWebSocketTransport,
|
|
45
|
-
type EditableArtifactWebSocketConnection,
|
|
46
58
|
} from "./editable-artifact-websocket";
|
|
59
|
+
import { editableArtifactSourceSessionAuthorizer } from "./editable-artifact-source-session";
|
|
60
|
+
import type { ApiWebSocketConnection } from "./api-websocket";
|
|
61
|
+
import { InteractionFrameProxyTransport } from "./interaction-frame-proxy";
|
|
62
|
+
import { apiRequestBindingsForTransportPeer } from "./http/request-source";
|
|
63
|
+
import { startApiMetricsListener } from "./http/metrics-listener";
|
|
64
|
+
import { createLocalBrowserBoundary } from "./http/local-browser-boundary";
|
|
65
|
+
import { dispatchApiWebSocketUpgrade } from "./http/websocket-upgrade-dispatch";
|
|
47
66
|
import {
|
|
48
67
|
createStandaloneEditableArtifactApplication,
|
|
49
68
|
type StandaloneEditableArtifactApplication,
|
|
50
69
|
} from "./editable-artifact-production";
|
|
70
|
+
import { installApiFatalProcessBoundary } from "./fatal-process-boundary";
|
|
51
71
|
|
|
52
72
|
/**
|
|
53
73
|
* A REJECT_DUPLICATE start collides on the deterministic workflowId when the
|
|
@@ -87,7 +107,42 @@ export async function createTemporalWorkflowClient(
|
|
|
87
107
|
connection,
|
|
88
108
|
namespace: settings.temporalNamespace,
|
|
89
109
|
});
|
|
110
|
+
const scheduledTasks = createTemporalScheduleSynchronizer({
|
|
111
|
+
db,
|
|
112
|
+
withDeadline: (deadline, work) => temporal.withDeadline(deadline, work),
|
|
113
|
+
upsert: async (task) => {
|
|
114
|
+
const options = temporalScheduleOptions(task, settings.temporalTaskQueue);
|
|
115
|
+
try {
|
|
116
|
+
await temporal.schedule
|
|
117
|
+
.getHandle(task.temporalScheduleId)
|
|
118
|
+
.update(() => temporalScheduleUpdateOptions(options));
|
|
119
|
+
} catch (error) {
|
|
120
|
+
if (!shouldCreateScheduleAfterUpdateError(error)) throw error;
|
|
121
|
+
await temporal.schedule.create(options);
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
remove: async (temporalScheduleId) => {
|
|
125
|
+
try {
|
|
126
|
+
await temporal.schedule.getHandle(temporalScheduleId).delete();
|
|
127
|
+
} catch (error) {
|
|
128
|
+
if (!(error instanceof ScheduleNotFoundError)) throw error;
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
});
|
|
90
132
|
const client: SessionWorkflowClient = {
|
|
133
|
+
triggerAutomationRun: async ({ accountId, workspaceId, runId }) => {
|
|
134
|
+
try {
|
|
135
|
+
await temporal.workflow.start("automationRunWorkflow", {
|
|
136
|
+
taskQueue: settings.temporalTaskQueue,
|
|
137
|
+
workflowId: `automation-run:${runId}`,
|
|
138
|
+
workflowIdReusePolicy: "REJECT_DUPLICATE",
|
|
139
|
+
args: [{ accountId, workspaceId, runId }],
|
|
140
|
+
});
|
|
141
|
+
} catch (error) {
|
|
142
|
+
if (isWorkflowAlreadyStarted(error)) return;
|
|
143
|
+
throw error;
|
|
144
|
+
}
|
|
145
|
+
},
|
|
91
146
|
signalUserMessage: async ({ eventId, workflowId }) => {
|
|
92
147
|
await temporal.workflow.getHandle(workflowId).signal("userMessage", eventId);
|
|
93
148
|
},
|
|
@@ -98,6 +153,7 @@ export async function createTemporalWorkflowClient(
|
|
|
98
153
|
workflowId,
|
|
99
154
|
wakeRevision,
|
|
100
155
|
interruptionRequested,
|
|
156
|
+
onSignalAccepted,
|
|
101
157
|
}) => {
|
|
102
158
|
await temporal.workflow.signalWithStart("sessionWorkflow", {
|
|
103
159
|
taskQueue: settings.temporalTaskQueue,
|
|
@@ -106,7 +162,8 @@ export async function createTemporalWorkflowClient(
|
|
|
106
162
|
args: [{ accountId, workspaceId, sessionId }],
|
|
107
163
|
signal: interruptionRequested ? "sessionControl" : "queueChanged",
|
|
108
164
|
});
|
|
109
|
-
|
|
165
|
+
onSignalAccepted?.();
|
|
166
|
+
return await markSessionWorkflowWakeDelivered(db, {
|
|
110
167
|
accountId,
|
|
111
168
|
workspaceId,
|
|
112
169
|
sessionId,
|
|
@@ -167,41 +224,15 @@ export async function createTemporalWorkflowClient(
|
|
|
167
224
|
wakeRevision: workflowWakeRevision,
|
|
168
225
|
});
|
|
169
226
|
},
|
|
170
|
-
syncScheduledTask: async ({ task }) =>
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
try {
|
|
174
|
-
await schedule.delete();
|
|
175
|
-
} catch (error) {
|
|
176
|
-
if (!(error instanceof ScheduleNotFoundError)) throw error;
|
|
177
|
-
}
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
const options = temporalScheduleOptions(task, settings.temporalTaskQueue);
|
|
181
|
-
try {
|
|
182
|
-
await schedule.update(() => temporalScheduleUpdateOptions(options));
|
|
183
|
-
} catch (error) {
|
|
184
|
-
if (!shouldCreateScheduleAfterUpdateError(error)) {
|
|
185
|
-
throw error;
|
|
186
|
-
}
|
|
187
|
-
await temporal.schedule.create(options);
|
|
188
|
-
}
|
|
189
|
-
},
|
|
190
|
-
deleteScheduledTaskSchedule: async ({ temporalScheduleId }) => {
|
|
191
|
-
try {
|
|
192
|
-
await temporal.withDeadline(Date.now() + 5_000, async () => {
|
|
193
|
-
await temporal.schedule.getHandle(temporalScheduleId).delete();
|
|
194
|
-
});
|
|
195
|
-
} catch (error) {
|
|
196
|
-
if (error instanceof ScheduleNotFoundError) return;
|
|
197
|
-
throw error;
|
|
198
|
-
}
|
|
199
|
-
},
|
|
227
|
+
syncScheduledTask: async ({ task, onFailure }) => scheduledTasks.sync(task, onFailure),
|
|
228
|
+
deleteScheduledTaskSchedule: async ({ temporalScheduleId }) =>
|
|
229
|
+
scheduledTasks.remove(temporalScheduleId),
|
|
200
230
|
triggerScheduledTask: async ({
|
|
201
231
|
task,
|
|
202
232
|
agentRunUsageIdempotencyKey,
|
|
203
233
|
triggerWorkflowId,
|
|
204
234
|
initiator,
|
|
235
|
+
credentialRestriction,
|
|
205
236
|
triggerType = "manual",
|
|
206
237
|
}) => {
|
|
207
238
|
// Deterministic workflowId (derived from the trigger token by the
|
|
@@ -222,6 +253,7 @@ export async function createTemporalWorkflowClient(
|
|
|
222
253
|
triggerType,
|
|
223
254
|
agentRunUsageIdempotencyKey,
|
|
224
255
|
initiator,
|
|
256
|
+
...(credentialRestriction ? { credentialRestriction } : {}),
|
|
225
257
|
},
|
|
226
258
|
],
|
|
227
259
|
});
|
|
@@ -237,7 +269,7 @@ export async function createTemporalWorkflowClient(
|
|
|
237
269
|
startRigVerification: async ({ workspaceId, changeId, versionId, workflowId }) => {
|
|
238
270
|
const targetId = changeId ?? versionId;
|
|
239
271
|
if (!targetId) {
|
|
240
|
-
throw new Error("
|
|
272
|
+
throw new Error("sandbox environment verification requires changeId or versionId");
|
|
241
273
|
}
|
|
242
274
|
try {
|
|
243
275
|
await temporal.workflow.start("rigVerificationWorkflow", {
|
|
@@ -283,14 +315,21 @@ export async function createTemporalWorkflowClient(
|
|
|
283
315
|
};
|
|
284
316
|
}
|
|
285
317
|
|
|
286
|
-
export async function startApi(
|
|
287
|
-
|
|
288
|
-
|
|
318
|
+
export async function startApi(
|
|
319
|
+
options: {
|
|
320
|
+
settings?: ReturnType<typeof getSettings>;
|
|
321
|
+
observability?: Observability;
|
|
322
|
+
} = {},
|
|
323
|
+
) {
|
|
324
|
+
const settings = options.settings ?? getSettings();
|
|
325
|
+
const observability =
|
|
326
|
+
options.observability ?? createObservability(settings, { component: "api" });
|
|
289
327
|
// Step I: standalone → dbSchema unset → searchPath undefined → today's plain
|
|
290
328
|
// handle (public). Embedded → scoped to the dedicated schema + the host's RLS
|
|
291
329
|
// strategy.
|
|
292
330
|
const searchPath = dbSearchPath(settings);
|
|
293
331
|
const dbClient = createDb(settings.databaseUrl, {
|
|
332
|
+
max: settings.apiDatabasePoolMax,
|
|
294
333
|
...(searchPath ? { searchPath } : {}),
|
|
295
334
|
rlsStrategy: settings.rlsStrategy,
|
|
296
335
|
});
|
|
@@ -303,17 +342,41 @@ export async function startApi() {
|
|
|
303
342
|
rlsStrategy: settings.rlsStrategy,
|
|
304
343
|
expectedRole: settings.runtimeDatabaseRole,
|
|
305
344
|
targetSchema: settings.dbSchema.trim() || "public",
|
|
345
|
+
organizationTenancyCanonicalActivationEnabled:
|
|
346
|
+
settings.organizationTenancyCanonicalActivationEnabled,
|
|
306
347
|
} as const;
|
|
307
348
|
// The PRIVILEGED control-plane NATS login (M-AUTH): when the server runs with
|
|
308
349
|
// auth_callout, api/worker authenticate as a static account user permitted to
|
|
309
|
-
// request
|
|
350
|
+
// request exact generation-fenced agent RPC subjects. Null in local dev
|
|
351
|
+
// (anonymous connect — the bus default).
|
|
310
352
|
const controlPlaneAuth = resolveNatsControlPlaneAuth(settings);
|
|
311
353
|
try {
|
|
354
|
+
// Browser, Computer, Terminal, and Files can cold-create the home sandbox
|
|
355
|
+
// directly from this API process. Resolve the same private-registry Modal
|
|
356
|
+
// image before the API becomes reachable so the first human interaction
|
|
357
|
+
// does not pay the provider import/build latency. This mirrors the turn
|
|
358
|
+
// worker's startup boundary and is a no-op for provider-native image IDs,
|
|
359
|
+
// public images, and non-Modal backends.
|
|
360
|
+
const { ensureModalRegistryImage } = await import("@opengeni/runtime/sandbox");
|
|
361
|
+
await retryStartupDependency(
|
|
362
|
+
"Modal private-registry image",
|
|
363
|
+
() => ensureModalRegistryImage(settings),
|
|
364
|
+
{ ...retryOptions, onRetry },
|
|
365
|
+
);
|
|
312
366
|
await retryStartupDependency(
|
|
313
367
|
"PostgreSQL runtime posture",
|
|
314
368
|
() => assertRuntimeDatabasePosture(dbClient.db, databasePosture),
|
|
369
|
+
{ ...retryOptions, onRetry, shouldRetry: isRetryableRuntimeDatabaseStartupError },
|
|
370
|
+
);
|
|
371
|
+
const resolvedCatalog = await retryStartupDependency(
|
|
372
|
+
"model catalog",
|
|
373
|
+
() => resolveCatalogSettings(dbClient.db, settings),
|
|
315
374
|
{ ...retryOptions, onRetry },
|
|
316
375
|
);
|
|
376
|
+
observability.info("OpenGeni model catalog resolved", {
|
|
377
|
+
catalogSource: resolvedCatalog.source,
|
|
378
|
+
catalogVersion: resolvedCatalog.version,
|
|
379
|
+
});
|
|
317
380
|
bus = await retryStartupDependency(
|
|
318
381
|
"NATS",
|
|
319
382
|
() =>
|
|
@@ -322,7 +385,7 @@ export async function startApi() {
|
|
|
322
385
|
controlPlaneAuth
|
|
323
386
|
? { user: controlPlaneAuth.user, pass: controlPlaneAuth.password }
|
|
324
387
|
: undefined,
|
|
325
|
-
|
|
388
|
+
observabilityEventBusOptions(observability),
|
|
326
389
|
),
|
|
327
390
|
{
|
|
328
391
|
...retryOptions,
|
|
@@ -385,32 +448,60 @@ export async function startApi() {
|
|
|
385
448
|
behavior: "http_and_websocket_fail_closed",
|
|
386
449
|
});
|
|
387
450
|
}
|
|
388
|
-
const artifactWebSockets = new EditableArtifactWebSocketTransport(
|
|
389
|
-
|
|
451
|
+
const artifactWebSockets = new EditableArtifactWebSocketTransport(
|
|
452
|
+
routeDeps.editableArtifacts,
|
|
453
|
+
editableArtifactSourceSessionAuthorizer(routeDeps),
|
|
454
|
+
);
|
|
455
|
+
const interactionFrameProxies = new InteractionFrameProxyTransport(
|
|
456
|
+
resolveFirstPartyDelegationSecret(settings),
|
|
457
|
+
);
|
|
458
|
+
// WebSocket upgrades bypass the Hono app, so the local-mode browser boundary
|
|
459
|
+
// (http/local-browser-boundary.ts) is applied to them in the dispatcher;
|
|
460
|
+
// every other request meets it in the Hono middleware.
|
|
461
|
+
const localBrowserBoundary = createLocalBrowserBoundary(settings, {
|
|
462
|
+
warn: (message, attributes) => observability.warn(message, attributes),
|
|
463
|
+
});
|
|
464
|
+
const webSocketUpgrades = [interactionFrameProxies, artifactWebSockets];
|
|
465
|
+
const server = Bun.serve<ApiWebSocketConnection>({
|
|
390
466
|
hostname: settings.apiHost,
|
|
391
467
|
port: settings.apiPort,
|
|
392
468
|
idleTimeout: 255,
|
|
393
469
|
fetch: (request, bunServer) => {
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
470
|
+
const upgrade = dispatchApiWebSocketUpgrade(
|
|
471
|
+
request,
|
|
472
|
+
bunServer,
|
|
473
|
+
webSocketUpgrades,
|
|
474
|
+
localBrowserBoundary,
|
|
475
|
+
);
|
|
476
|
+
if (upgrade.handled) return upgrade.response;
|
|
477
|
+
return app.fetch(
|
|
478
|
+
request,
|
|
479
|
+
apiRequestBindingsForTransportPeer(bunServer.requestIP(request)?.address),
|
|
480
|
+
);
|
|
398
481
|
},
|
|
399
482
|
websocket: {
|
|
400
483
|
maxPayloadLength: EDITABLE_ARTIFACT_LIVE_WEBSOCKET_MAX_MESSAGE_BYTES,
|
|
401
484
|
backpressureLimit: 16 * 1024 * 1024,
|
|
402
485
|
closeOnBackpressureLimit: true,
|
|
403
|
-
open: (socket) =>
|
|
404
|
-
message: (socket, message) =>
|
|
405
|
-
close: (socket) =>
|
|
486
|
+
open: (socket) => socket.data.attach(socket),
|
|
487
|
+
message: (socket, message) => socket.data.receive(message),
|
|
488
|
+
close: (socket) => socket.data.transportClosed(),
|
|
406
489
|
},
|
|
407
490
|
});
|
|
491
|
+
const metricsServer = startApiMetricsListener(settings, observability);
|
|
408
492
|
const stopSlackInteractionPump = settings.slackSigningSecret
|
|
409
493
|
? startSlackInteractionPump(routeDeps)
|
|
410
494
|
: undefined;
|
|
411
495
|
const stopMemorySlackPublicationPump = startMemorySlackPublicationPump(routeDeps);
|
|
496
|
+
const stopWorkspaceWebhookDispatchPump = startWorkspaceWebhookDispatchPump({
|
|
497
|
+
db: dbClient.db,
|
|
498
|
+
settings,
|
|
499
|
+
observability,
|
|
500
|
+
});
|
|
412
501
|
const stopTemporalScheduleCleanupPump = startTemporalScheduleCleanupPump({
|
|
413
502
|
db: dbClient.db,
|
|
503
|
+
cleanupConnectorAuthorization: async (claim) =>
|
|
504
|
+
await cleanupScheduledTaskConnectorAuthorization(routeDeps, claim),
|
|
414
505
|
deleteSchedule: async (temporalScheduleId) => {
|
|
415
506
|
await workflowClient.client.deleteScheduledTaskSchedule({ temporalScheduleId });
|
|
416
507
|
},
|
|
@@ -469,16 +560,21 @@ export async function startApi() {
|
|
|
469
560
|
observability.info("OpenGeni API listening", {
|
|
470
561
|
host: settings.apiHost,
|
|
471
562
|
port: settings.apiPort,
|
|
563
|
+
...(metricsServer ? { metricsPort: settings.apiMetricsPort } : {}),
|
|
472
564
|
});
|
|
473
565
|
return {
|
|
474
566
|
server,
|
|
475
567
|
close: async () => {
|
|
476
568
|
server.stop(true);
|
|
569
|
+
metricsServer?.stop(true);
|
|
477
570
|
stopSlackInteractionPump?.();
|
|
478
571
|
await stopMemorySlackPublicationPump();
|
|
479
572
|
stopMetricsIngestion?.();
|
|
480
573
|
stopHelloIngestion?.();
|
|
481
574
|
await stopTemporalScheduleCleanupPump();
|
|
575
|
+
await stopWorkspaceWebhookDispatchPump();
|
|
576
|
+
// Write queued presence before the database pool closes.
|
|
577
|
+
await routeDeps.userPresence?.close().catch(() => undefined);
|
|
482
578
|
await Promise.allSettled([
|
|
483
579
|
Promise.resolve(editableArtifactComposition?.close()),
|
|
484
580
|
authCalloutResponder?.close(),
|
|
@@ -491,7 +587,16 @@ export async function startApi() {
|
|
|
491
587
|
}
|
|
492
588
|
|
|
493
589
|
if (import.meta.main) {
|
|
494
|
-
|
|
590
|
+
const fatalBoundary = installApiFatalProcessBoundary();
|
|
591
|
+
try {
|
|
592
|
+
const settings = getSettings();
|
|
593
|
+
const observability = createObservability(settings, { component: "api" });
|
|
594
|
+
fatalBoundary.attachObservability(observability);
|
|
595
|
+
await startApi({ settings, observability });
|
|
596
|
+
fatalBoundary.markRunning();
|
|
597
|
+
} catch (error) {
|
|
598
|
+
await fatalBoundary.reportStartupFailure(error);
|
|
599
|
+
}
|
|
495
600
|
}
|
|
496
601
|
|
|
497
602
|
export function temporalOverlapPolicy(policy: ScheduledTaskOverlapPolicy): ScheduleOverlapPolicy {
|
|
@@ -612,7 +717,7 @@ function temporalScheduleOptions(task: ScheduledTask, taskQueue: string): Schedu
|
|
|
612
717
|
|
|
613
718
|
function scheduledTaskEffectivelyPaused(task: ScheduledTask): boolean {
|
|
614
719
|
if (task.status === "paused") return true;
|
|
615
|
-
if (task
|
|
720
|
+
if (!scheduledTaskKnowledgeSource(task)) return false;
|
|
616
721
|
const control = task.metadata.knowledgeSourceSync;
|
|
617
722
|
if (!control || typeof control !== "object") return false;
|
|
618
723
|
const record = control as Record<string, unknown>;
|