@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
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CreateVariableSetRequest,
|
|
3
|
+
ResolveVariableSetAttachmentsRequest,
|
|
4
|
+
ResolveVariableSetAttachmentsResponse,
|
|
3
5
|
SetVariableSetVariableRequest,
|
|
4
6
|
UpdateVariableSetRequest,
|
|
5
7
|
VariableSetVariableName,
|
|
6
8
|
} from "@opengeni/contracts";
|
|
7
9
|
import {
|
|
8
|
-
countActiveSessionsUsingVariableSet,
|
|
9
|
-
countScheduledTasksUsingVariableSet,
|
|
10
10
|
countVariableSets,
|
|
11
11
|
createVariableSet,
|
|
12
12
|
decryptVariableSetValue,
|
|
@@ -16,12 +16,19 @@ import {
|
|
|
16
16
|
getVariableSetByName,
|
|
17
17
|
listVariableSets,
|
|
18
18
|
readVariableSetSecretAtomically,
|
|
19
|
+
resolveVariableSetAttachments,
|
|
19
20
|
setVariableSetVariable,
|
|
20
21
|
updateVariableSet,
|
|
22
|
+
VariableSetAttachedError,
|
|
21
23
|
} from "@opengeni/db";
|
|
22
24
|
import type { Hono } from "hono";
|
|
23
25
|
import { HTTPException } from "hono/http-exception";
|
|
24
|
-
import {
|
|
26
|
+
import {
|
|
27
|
+
requireAccessGrant,
|
|
28
|
+
requireAccessGrantAuthorization,
|
|
29
|
+
requireLiteralPermission,
|
|
30
|
+
requirePermission,
|
|
31
|
+
} from "@opengeni/core";
|
|
25
32
|
import type { ApiRouteDeps } from "@opengeni/core";
|
|
26
33
|
import {
|
|
27
34
|
assertAllowedVariableSetVariableName,
|
|
@@ -31,6 +38,7 @@ import {
|
|
|
31
38
|
requireVariableSetEncryption,
|
|
32
39
|
requireVariableSetForApi,
|
|
33
40
|
} from "@opengeni/core";
|
|
41
|
+
import { parseRequestJson } from "../http/request-body";
|
|
34
42
|
|
|
35
43
|
export function registerVariableSetRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
36
44
|
const { settings, db } = deps;
|
|
@@ -45,15 +53,35 @@ export function registerVariableSetRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
45
53
|
const grant = await requireAccessGrant(c, deps, workspaceId);
|
|
46
54
|
requirePermission(grant, "variable-sets:list");
|
|
47
55
|
requirePermission(grant, "secrets:list");
|
|
48
|
-
return c.json(
|
|
56
|
+
return c.json(
|
|
57
|
+
await listVariableSets(db, {
|
|
58
|
+
accountId: grant.accountId,
|
|
59
|
+
workspaceId,
|
|
60
|
+
subjectId: grant.subjectId,
|
|
61
|
+
}),
|
|
62
|
+
);
|
|
49
63
|
});
|
|
50
64
|
|
|
51
65
|
app.post(`${prefix}`, async (c) => {
|
|
52
66
|
const workspaceId = c.req.param("workspaceId")!;
|
|
53
|
-
const
|
|
67
|
+
const authorization = await requireAccessGrantAuthorization(c, deps, workspaceId);
|
|
68
|
+
const grant = authorization.grant;
|
|
54
69
|
requirePermission(grant, "variable-sets:write");
|
|
55
70
|
const key = requireVariableSetEncryption(settings);
|
|
56
|
-
const payload =
|
|
71
|
+
const payload = await parseRequestJson(c, CreateVariableSetRequest);
|
|
72
|
+
if (prefix.endsWith("/environments") && payload.scope !== "workspace") {
|
|
73
|
+
throw new HTTPException(422, {
|
|
74
|
+
message: "the legacy environments route only creates workspace-scoped variable sets",
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
if (
|
|
78
|
+
payload.scope === "organization" &&
|
|
79
|
+
authorization.accountGrant?.permissions.includes("account:admin") !== true
|
|
80
|
+
) {
|
|
81
|
+
throw new HTTPException(403, {
|
|
82
|
+
message: "missing permission: account:admin",
|
|
83
|
+
});
|
|
84
|
+
}
|
|
57
85
|
if (payload.variables.length > 0) {
|
|
58
86
|
requirePermission(grant, "secrets:write");
|
|
59
87
|
}
|
|
@@ -73,12 +101,17 @@ export function registerVariableSetRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
73
101
|
}
|
|
74
102
|
variableNames.add(variable.name);
|
|
75
103
|
}
|
|
76
|
-
|
|
104
|
+
const access = {
|
|
105
|
+
accountId: grant.accountId,
|
|
106
|
+
workspaceId,
|
|
107
|
+
subjectId: grant.subjectId,
|
|
108
|
+
};
|
|
109
|
+
if ((await countVariableSets(db, access, payload.scope)) >= MAX_ENVIRONMENTS_PER_WORKSPACE) {
|
|
77
110
|
throw new HTTPException(422, {
|
|
78
111
|
message: `a workspace supports at most ${MAX_ENVIRONMENTS_PER_WORKSPACE} variable sets`,
|
|
79
112
|
});
|
|
80
113
|
}
|
|
81
|
-
if (await getVariableSetByName(db,
|
|
114
|
+
if (await getVariableSetByName(db, access, name, payload.scope)) {
|
|
82
115
|
throw new HTTPException(409, {
|
|
83
116
|
message: `variable set name is already in use: ${name}`,
|
|
84
117
|
});
|
|
@@ -88,6 +121,9 @@ export function registerVariableSetRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
88
121
|
const created = await createVariableSet(db, {
|
|
89
122
|
accountId: grant.accountId,
|
|
90
123
|
workspaceId,
|
|
124
|
+
scope: payload.scope,
|
|
125
|
+
subjectId: grant.subjectId,
|
|
126
|
+
allowOrganization: payload.scope === "organization",
|
|
91
127
|
name,
|
|
92
128
|
description: payload.description ?? null,
|
|
93
129
|
variables: payload.variables.map((variable) => ({
|
|
@@ -103,12 +139,32 @@ export function registerVariableSetRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
103
139
|
return c.json(created, 201);
|
|
104
140
|
});
|
|
105
141
|
|
|
142
|
+
if (prefix.endsWith("/variable-sets")) {
|
|
143
|
+
app.post(`${prefix}/resolve-attachments`, async (c) => {
|
|
144
|
+
const workspaceId = c.req.param("workspaceId")!;
|
|
145
|
+
const grant = await requireAccessGrant(c, deps, workspaceId);
|
|
146
|
+
requirePermission(grant, "variable-sets:attach");
|
|
147
|
+
requirePermission(grant, "variable-sets:use");
|
|
148
|
+
const payload = await parseRequestJson(c, ResolveVariableSetAttachmentsRequest);
|
|
149
|
+
const variableSets = await resolveVariableSetAttachments(
|
|
150
|
+
db,
|
|
151
|
+
{
|
|
152
|
+
accountId: grant.accountId,
|
|
153
|
+
workspaceId,
|
|
154
|
+
subjectId: grant.subjectId,
|
|
155
|
+
},
|
|
156
|
+
payload.variableSetIds,
|
|
157
|
+
);
|
|
158
|
+
return c.json(ResolveVariableSetAttachmentsResponse.parse({ variableSets }));
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
106
162
|
app.get(`${prefix}/:variableSetId`, async (c) => {
|
|
107
163
|
const workspaceId = c.req.param("workspaceId")!;
|
|
108
164
|
const grant = await requireAccessGrant(c, deps, workspaceId);
|
|
109
165
|
requirePermission(grant, "variable-sets:read");
|
|
110
166
|
requirePermission(grant, "secrets:list");
|
|
111
|
-
return c.json(await requireVariableSetForApi(db,
|
|
167
|
+
return c.json(await requireVariableSetForApi(db, grant, c.req.param("variableSetId")!));
|
|
112
168
|
});
|
|
113
169
|
|
|
114
170
|
if (prefix.endsWith("/variable-sets")) {
|
|
@@ -139,27 +195,47 @@ export function registerVariableSetRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
139
195
|
|
|
140
196
|
app.patch(`${prefix}/:variableSetId`, async (c) => {
|
|
141
197
|
const workspaceId = c.req.param("workspaceId")!;
|
|
142
|
-
const
|
|
198
|
+
const authorization = await requireAccessGrantAuthorization(c, deps, workspaceId);
|
|
199
|
+
const grant = authorization.grant;
|
|
143
200
|
requirePermission(grant, "variable-sets:write");
|
|
144
|
-
const variableSet = await requireVariableSetForApi(
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
)
|
|
149
|
-
|
|
201
|
+
const variableSet = await requireVariableSetForApi(db, grant, c.req.param("variableSetId")!);
|
|
202
|
+
const allowOrganization =
|
|
203
|
+
variableSet.scope === "organization" &&
|
|
204
|
+
authorization.accountGrant?.permissions.includes("account:admin") === true;
|
|
205
|
+
if (variableSet.scope === "organization" && !allowOrganization) {
|
|
206
|
+
throw new HTTPException(403, {
|
|
207
|
+
message: "missing permission: account:admin",
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
const payload = await parseRequestJson(c, UpdateVariableSetRequest);
|
|
150
211
|
const name = payload.name !== undefined ? trimmedVariableSetName(payload.name) : undefined;
|
|
151
212
|
if (name !== undefined && name !== variableSet.name) {
|
|
152
|
-
const existing = await getVariableSetByName(
|
|
213
|
+
const existing = await getVariableSetByName(
|
|
214
|
+
db,
|
|
215
|
+
{
|
|
216
|
+
accountId: grant.accountId,
|
|
217
|
+
workspaceId,
|
|
218
|
+
subjectId: grant.subjectId,
|
|
219
|
+
},
|
|
220
|
+
name,
|
|
221
|
+
variableSet.scope,
|
|
222
|
+
);
|
|
153
223
|
if (existing && existing.id !== variableSet.id) {
|
|
154
224
|
throw new HTTPException(409, {
|
|
155
225
|
message: `variable set name is already in use: ${name}`,
|
|
156
226
|
});
|
|
157
227
|
}
|
|
158
228
|
}
|
|
159
|
-
const updated = await updateVariableSet(
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
229
|
+
const updated = await updateVariableSet(
|
|
230
|
+
db,
|
|
231
|
+
{ accountId: grant.accountId, workspaceId, subjectId: grant.subjectId },
|
|
232
|
+
variableSet.id,
|
|
233
|
+
{
|
|
234
|
+
...(name !== undefined ? { name } : {}),
|
|
235
|
+
...(payload.description !== undefined ? { description: payload.description } : {}),
|
|
236
|
+
allowOrganization,
|
|
237
|
+
},
|
|
238
|
+
);
|
|
163
239
|
await recordVariableSetAuditEvent(db, {
|
|
164
240
|
grant,
|
|
165
241
|
action: "variable_set.updated",
|
|
@@ -170,35 +246,36 @@ export function registerVariableSetRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
170
246
|
|
|
171
247
|
app.delete(`${prefix}/:variableSetId`, async (c) => {
|
|
172
248
|
const workspaceId = c.req.param("workspaceId")!;
|
|
173
|
-
const
|
|
249
|
+
const authorization = await requireAccessGrantAuthorization(c, deps, workspaceId);
|
|
250
|
+
const grant = authorization.grant;
|
|
174
251
|
requirePermission(grant, "variable-sets:write");
|
|
175
252
|
requirePermission(grant, "secrets:write");
|
|
176
|
-
const variableSet = await requireVariableSetForApi(
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
)
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
workspaceId,
|
|
184
|
-
variableSet.id,
|
|
185
|
-
);
|
|
186
|
-
if (attachedTasks > 0) {
|
|
187
|
-
throw new HTTPException(409, {
|
|
188
|
-
message: `variable set is attached to ${attachedTasks} scheduled task(s); detach first`,
|
|
253
|
+
const variableSet = await requireVariableSetForApi(db, grant, c.req.param("variableSetId")!);
|
|
254
|
+
const allowOrganization =
|
|
255
|
+
variableSet.scope === "organization" &&
|
|
256
|
+
authorization.accountGrant?.permissions.includes("account:admin") === true;
|
|
257
|
+
if (variableSet.scope === "organization" && !allowOrganization) {
|
|
258
|
+
throw new HTTPException(403, {
|
|
259
|
+
message: "missing permission: account:admin",
|
|
189
260
|
});
|
|
190
261
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
262
|
+
try {
|
|
263
|
+
await deleteVariableSet(
|
|
264
|
+
db,
|
|
265
|
+
{
|
|
266
|
+
accountId: grant.accountId,
|
|
267
|
+
workspaceId,
|
|
268
|
+
subjectId: grant.subjectId,
|
|
269
|
+
},
|
|
270
|
+
variableSet.id,
|
|
271
|
+
{ allowOrganization },
|
|
272
|
+
);
|
|
273
|
+
} catch (error) {
|
|
274
|
+
if (error instanceof VariableSetAttachedError) {
|
|
275
|
+
throw new HTTPException(409, { message: error.message });
|
|
276
|
+
}
|
|
277
|
+
throw error;
|
|
200
278
|
}
|
|
201
|
-
await deleteVariableSet(db, workspaceId, variableSet.id);
|
|
202
279
|
await recordVariableSetAuditEvent(db, {
|
|
203
280
|
grant,
|
|
204
281
|
action: "variable_set.deleted",
|
|
@@ -209,17 +286,22 @@ export function registerVariableSetRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
209
286
|
|
|
210
287
|
app.put(`${prefix}/:variableSetId/variables/:name`, async (c) => {
|
|
211
288
|
const workspaceId = c.req.param("workspaceId")!;
|
|
212
|
-
const
|
|
289
|
+
const authorization = await requireAccessGrantAuthorization(c, deps, workspaceId);
|
|
290
|
+
const grant = authorization.grant;
|
|
213
291
|
requirePermission(grant, "variable-sets:write");
|
|
214
292
|
requirePermission(grant, "secrets:write");
|
|
215
293
|
const key = requireVariableSetEncryption(settings);
|
|
216
294
|
const name = parseVariableName(c.req.param("name")!);
|
|
217
|
-
const variableSet = await requireVariableSetForApi(
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
)
|
|
222
|
-
|
|
295
|
+
const variableSet = await requireVariableSetForApi(db, grant, c.req.param("variableSetId")!);
|
|
296
|
+
const allowOrganization =
|
|
297
|
+
variableSet.scope === "organization" &&
|
|
298
|
+
authorization.accountGrant?.permissions.includes("account:admin") === true;
|
|
299
|
+
if (variableSet.scope === "organization" && !allowOrganization) {
|
|
300
|
+
throw new HTTPException(403, {
|
|
301
|
+
message: "missing permission: account:admin",
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
const payload = await parseRequestJson(c, SetVariableSetVariableRequest);
|
|
223
305
|
const exists = variableSet.variables.some((variable) => variable.name === name);
|
|
224
306
|
if (!exists && variableSet.variables.length >= MAX_VARIABLES_PER_ENVIRONMENT) {
|
|
225
307
|
throw new HTTPException(422, {
|
|
@@ -229,9 +311,11 @@ export function registerVariableSetRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
229
311
|
const metadata = await setVariableSetVariable(db, {
|
|
230
312
|
accountId: grant.accountId,
|
|
231
313
|
workspaceId,
|
|
314
|
+
subjectId: grant.subjectId,
|
|
232
315
|
variableSetId: variableSet.id,
|
|
233
316
|
name,
|
|
234
317
|
valueEncrypted: encryptVariableSetValue(key, payload.value),
|
|
318
|
+
allowOrganization,
|
|
235
319
|
});
|
|
236
320
|
await recordVariableSetAuditEvent(db, {
|
|
237
321
|
grant,
|
|
@@ -244,16 +328,28 @@ export function registerVariableSetRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
244
328
|
|
|
245
329
|
app.delete(`${prefix}/:variableSetId/variables/:name`, async (c) => {
|
|
246
330
|
const workspaceId = c.req.param("workspaceId")!;
|
|
247
|
-
const
|
|
331
|
+
const authorization = await requireAccessGrantAuthorization(c, deps, workspaceId);
|
|
332
|
+
const grant = authorization.grant;
|
|
248
333
|
requirePermission(grant, "variable-sets:write");
|
|
249
334
|
requirePermission(grant, "secrets:write");
|
|
250
335
|
const name = parseVariableName(c.req.param("name")!);
|
|
251
|
-
const variableSet = await requireVariableSetForApi(
|
|
252
|
-
|
|
336
|
+
const variableSet = await requireVariableSetForApi(db, grant, c.req.param("variableSetId")!);
|
|
337
|
+
const allowOrganization =
|
|
338
|
+
variableSet.scope === "organization" &&
|
|
339
|
+
authorization.accountGrant?.permissions.includes("account:admin") === true;
|
|
340
|
+
if (variableSet.scope === "organization" && !allowOrganization) {
|
|
341
|
+
throw new HTTPException(403, {
|
|
342
|
+
message: "missing permission: account:admin",
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
const deleted = await deleteVariableSetVariable(db, {
|
|
346
|
+
accountId: grant.accountId,
|
|
253
347
|
workspaceId,
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
348
|
+
subjectId: grant.subjectId,
|
|
349
|
+
variableSetId: variableSet.id,
|
|
350
|
+
name,
|
|
351
|
+
allowOrganization,
|
|
352
|
+
});
|
|
257
353
|
if (!deleted) {
|
|
258
354
|
throw new HTTPException(404, {
|
|
259
355
|
message: "variable set variable not found",
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import type { Hono } from "hono";
|
|
2
|
+
import { HTTPException } from "hono/http-exception";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import {
|
|
5
|
+
BeginExternalIdentityLinkRequest,
|
|
6
|
+
ConfirmExternalIdentityLinkRequest,
|
|
7
|
+
} from "@opengeni/contracts/external-identities";
|
|
8
|
+
import {
|
|
9
|
+
beginExternalIdentityLink,
|
|
10
|
+
confirmExternalIdentityLink,
|
|
11
|
+
getExternalIdentityLink,
|
|
12
|
+
listExternalIdentityLinks,
|
|
13
|
+
previewExternalIdentityLink,
|
|
14
|
+
revokeExternalIdentityLink,
|
|
15
|
+
ensureExternalIdentity,
|
|
16
|
+
ExternalIdentityLinkConflictError,
|
|
17
|
+
withWorkspaceSubjectRls,
|
|
18
|
+
lockExternalWorkspaceMembershipLifecycle,
|
|
19
|
+
getWorkspaceGrant,
|
|
20
|
+
namedSubjectPersonalWorkspaceId,
|
|
21
|
+
managedPersonalWorkspacePermissions,
|
|
22
|
+
} from "@opengeni/db";
|
|
23
|
+
import {
|
|
24
|
+
requireAccessGrantAuthorization,
|
|
25
|
+
externalActorContinuationForAuthorization,
|
|
26
|
+
externalContinuationCommitAuthorizer,
|
|
27
|
+
hasPermission,
|
|
28
|
+
type AccessGrantAuthorization,
|
|
29
|
+
type ApiRouteDeps,
|
|
30
|
+
} from "@opengeni/core";
|
|
31
|
+
import { parseRequestBody, parseRequestJson, readRequestJson } from "../http/request-body";
|
|
32
|
+
|
|
33
|
+
function nativeConfirmation(authorization: AccessGrantAuthorization) {
|
|
34
|
+
if (
|
|
35
|
+
!authorization.contextIntegrity ||
|
|
36
|
+
!authorization.canonicalManagedHumanSession ||
|
|
37
|
+
authorization.authenticatedSubjectId !== authorization.grant.subjectId ||
|
|
38
|
+
!authorization.grant.subjectId.startsWith("user:")
|
|
39
|
+
)
|
|
40
|
+
throw new HTTPException(403, { message: "Confirm using your authenticated Opengeni account" });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Both products address the link through a workspace they already own. The
|
|
44
|
+
* link itself is organization-local; the host's Personal workspace need not be
|
|
45
|
+
* exposed to the native human, and neither side names the other's subject. */
|
|
46
|
+
export function registerExternalIdentityLinkRoutes(app: Hono, deps: ApiRouteDeps) {
|
|
47
|
+
const base = "/v1/workspaces/:workspaceId/identity-links";
|
|
48
|
+
app.get(base, async (c) => {
|
|
49
|
+
const authorization = await requireAccessGrantAuthorization(
|
|
50
|
+
c,
|
|
51
|
+
deps,
|
|
52
|
+
c.req.param("workspaceId"),
|
|
53
|
+
"workspace:read",
|
|
54
|
+
);
|
|
55
|
+
if (!externalActorContinuationForAuthorization(authorization))
|
|
56
|
+
nativeConfirmation(authorization);
|
|
57
|
+
const parsedCursor = z.string().uuid().optional().safeParse(c.req.query("cursor"));
|
|
58
|
+
if (!parsedCursor.success) throw new HTTPException(400, { message: "Invalid link cursor" });
|
|
59
|
+
const cursor = parsedCursor.data;
|
|
60
|
+
const grant = authorization.grant;
|
|
61
|
+
return c.json(
|
|
62
|
+
await withWorkspaceSubjectRls(deps.db, grant.workspaceId, grant.subjectId, async (tx) => {
|
|
63
|
+
await externalContinuationCommitAuthorizer(authorization)?.(tx);
|
|
64
|
+
return listExternalIdentityLinks(tx, {
|
|
65
|
+
accountId: grant.accountId,
|
|
66
|
+
subjectId: grant.subjectId,
|
|
67
|
+
...(cursor ? { cursor } : {}),
|
|
68
|
+
});
|
|
69
|
+
}),
|
|
70
|
+
);
|
|
71
|
+
});
|
|
72
|
+
app.post(base, async (c) => {
|
|
73
|
+
const authorization = await requireAccessGrantAuthorization(
|
|
74
|
+
c,
|
|
75
|
+
deps,
|
|
76
|
+
c.req.param("workspaceId"),
|
|
77
|
+
"workspace:read",
|
|
78
|
+
);
|
|
79
|
+
const continuation = externalActorContinuationForAuthorization(authorization);
|
|
80
|
+
if (!continuation || continuation.actor.actingMode !== "external")
|
|
81
|
+
throw new HTTPException(403, { message: "Start linking as the external product user" });
|
|
82
|
+
const input = await parseRequestJson(c, BeginExternalIdentityLinkRequest);
|
|
83
|
+
if (input.expiresAt !== null && Date.parse(input.expiresAt) <= Date.now())
|
|
84
|
+
throw new HTTPException(422, { message: "Link expiry must be in the future" });
|
|
85
|
+
const commit = externalContinuationCommitAuthorizer(authorization)!;
|
|
86
|
+
try {
|
|
87
|
+
const result = await withWorkspaceSubjectRls(
|
|
88
|
+
deps.db,
|
|
89
|
+
authorization.grant.workspaceId,
|
|
90
|
+
authorization.grant.subjectId,
|
|
91
|
+
async (tx) => {
|
|
92
|
+
await commit(tx);
|
|
93
|
+
const identity = await ensureExternalIdentity(tx, {
|
|
94
|
+
accountId: authorization.grant.accountId,
|
|
95
|
+
...continuation.identity,
|
|
96
|
+
});
|
|
97
|
+
return beginExternalIdentityLink(tx, identity, input);
|
|
98
|
+
},
|
|
99
|
+
);
|
|
100
|
+
return c.json(result, 201);
|
|
101
|
+
} catch (error) {
|
|
102
|
+
if (error instanceof ExternalIdentityLinkConflictError)
|
|
103
|
+
throw new HTTPException(409, { message: error.message });
|
|
104
|
+
throw error;
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
app.on(["GET", "POST"], [base + "/:linkId", base + "/:linkId/:operation"], async (c) => {
|
|
108
|
+
const workspaceId = c.req.param("workspaceId")!;
|
|
109
|
+
const linkId = z.string().uuid().parse(c.req.param("linkId"));
|
|
110
|
+
const operation = c.req.param("operation");
|
|
111
|
+
if (
|
|
112
|
+
!(
|
|
113
|
+
(c.req.method === "GET" && !operation) ||
|
|
114
|
+
(c.req.method === "POST" && ["preview", "confirm", "revoke"].includes(operation ?? ""))
|
|
115
|
+
)
|
|
116
|
+
)
|
|
117
|
+
throw new HTTPException(404, { message: "Not found" });
|
|
118
|
+
const authorization = await requireAccessGrantAuthorization(
|
|
119
|
+
c,
|
|
120
|
+
deps,
|
|
121
|
+
workspaceId,
|
|
122
|
+
"workspace:read",
|
|
123
|
+
);
|
|
124
|
+
const external = externalActorContinuationForAuthorization(authorization);
|
|
125
|
+
if (operation === "preview" || operation === "confirm" || !external)
|
|
126
|
+
nativeConfirmation(authorization);
|
|
127
|
+
const grant = authorization.grant;
|
|
128
|
+
const input = c.req.method === "POST" ? await readRequestJson(c) : null;
|
|
129
|
+
try {
|
|
130
|
+
const result = await withWorkspaceSubjectRls(
|
|
131
|
+
deps.db,
|
|
132
|
+
workspaceId,
|
|
133
|
+
grant.subjectId,
|
|
134
|
+
async (tx) => {
|
|
135
|
+
await externalContinuationCommitAuthorizer(authorization)?.(tx);
|
|
136
|
+
if (operation === "preview") {
|
|
137
|
+
const request = parseRequestBody(
|
|
138
|
+
z.object({ challenge: ConfirmExternalIdentityLinkRequest.shape.challenge }).strict(),
|
|
139
|
+
input,
|
|
140
|
+
);
|
|
141
|
+
const preview = await previewExternalIdentityLink(tx, {
|
|
142
|
+
accountId: grant.accountId,
|
|
143
|
+
linkId,
|
|
144
|
+
...request,
|
|
145
|
+
});
|
|
146
|
+
return preview
|
|
147
|
+
? { ...preview, nativeSubjectId: grant.subjectId, organizationId: grant.accountId }
|
|
148
|
+
: null;
|
|
149
|
+
}
|
|
150
|
+
if (operation === "confirm") {
|
|
151
|
+
const request = parseRequestBody(ConfirmExternalIdentityLinkRequest, input);
|
|
152
|
+
await lockExternalWorkspaceMembershipLifecycle(tx, grant.accountId);
|
|
153
|
+
const personalWorkspaceId = await namedSubjectPersonalWorkspaceId(tx, {
|
|
154
|
+
accountId: grant.accountId,
|
|
155
|
+
subjectId: grant.subjectId,
|
|
156
|
+
});
|
|
157
|
+
const current =
|
|
158
|
+
personalWorkspaceId === workspaceId
|
|
159
|
+
? { accountId: grant.accountId, permissions: managedPersonalWorkspacePermissions }
|
|
160
|
+
: await getWorkspaceGrant(tx, grant.subjectId, workspaceId, {
|
|
161
|
+
principalKind: "human_session",
|
|
162
|
+
});
|
|
163
|
+
if (
|
|
164
|
+
!current ||
|
|
165
|
+
current.accountId !== grant.accountId ||
|
|
166
|
+
request.permissions.some(
|
|
167
|
+
(permission) =>
|
|
168
|
+
!hasPermission(grant.permissions, permission) ||
|
|
169
|
+
!hasPermission(current.permissions, permission),
|
|
170
|
+
)
|
|
171
|
+
)
|
|
172
|
+
throw new HTTPException(403, {
|
|
173
|
+
message: "Link permissions exceed your authority in this workspace",
|
|
174
|
+
});
|
|
175
|
+
return confirmExternalIdentityLink(tx, {
|
|
176
|
+
accountId: grant.accountId,
|
|
177
|
+
linkId,
|
|
178
|
+
nativeSubjectId: grant.subjectId,
|
|
179
|
+
request,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
const scope = { accountId: grant.accountId, linkId, subjectId: grant.subjectId };
|
|
183
|
+
if (operation === "revoke") {
|
|
184
|
+
const request = parseRequestBody(
|
|
185
|
+
z.object({ expectedRevision: z.number().int().positive().safe() }).strict(),
|
|
186
|
+
input,
|
|
187
|
+
);
|
|
188
|
+
return revokeExternalIdentityLink(tx, { ...scope, ...request });
|
|
189
|
+
}
|
|
190
|
+
return getExternalIdentityLink(tx, scope);
|
|
191
|
+
},
|
|
192
|
+
);
|
|
193
|
+
if (!result) throw new HTTPException(404, { message: "Identity link not found or expired" });
|
|
194
|
+
return c.json(result);
|
|
195
|
+
} catch (error) {
|
|
196
|
+
if (error instanceof ExternalIdentityLinkConflictError)
|
|
197
|
+
throw new HTTPException(409, { message: error.message });
|
|
198
|
+
throw error;
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { CreateFeedbackRequest } from "@opengeni/contracts";
|
|
2
|
+
import {
|
|
3
|
+
requireAccessGrant,
|
|
4
|
+
requireSessionAuthorization,
|
|
5
|
+
withResolvedSessionAuthorization,
|
|
6
|
+
SessionAuthorizationDeniedError,
|
|
7
|
+
SessionAuthorizationUnavailableError,
|
|
8
|
+
type ApiRouteDeps,
|
|
9
|
+
} from "@opengeni/core";
|
|
10
|
+
import {
|
|
11
|
+
createFeedback,
|
|
12
|
+
listOwnFeedback,
|
|
13
|
+
FeedbackConflictError,
|
|
14
|
+
FeedbackTargetNotFoundError,
|
|
15
|
+
} from "@opengeni/db";
|
|
16
|
+
import type { Hono } from "hono";
|
|
17
|
+
import { HTTPException } from "hono/http-exception";
|
|
18
|
+
import { z } from "zod";
|
|
19
|
+
|
|
20
|
+
export function registerFeedbackRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
21
|
+
app.post("/v1/workspaces/:workspaceId/feedback", async (c) => {
|
|
22
|
+
const workspaceId = c.req.param("workspaceId");
|
|
23
|
+
const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:read");
|
|
24
|
+
await requireAccessGrant(c, deps, workspaceId, "sessions:create");
|
|
25
|
+
const parsed = CreateFeedbackRequest.safeParse(await c.req.json().catch(() => null));
|
|
26
|
+
if (!parsed.success)
|
|
27
|
+
throw new HTTPException(400, {
|
|
28
|
+
message: parsed.error.issues[0]?.message ?? "Invalid feedback",
|
|
29
|
+
});
|
|
30
|
+
// Agent turns must not manufacture user satisfaction evidence. Product SDK
|
|
31
|
+
// credentials are allowed but retain their own authenticated author/kind.
|
|
32
|
+
if (
|
|
33
|
+
grant.principalKind === "agent_attempt" ||
|
|
34
|
+
grant.metadata?.["turnId"] !== undefined ||
|
|
35
|
+
grant.metadata?.["attemptId"] !== undefined
|
|
36
|
+
)
|
|
37
|
+
throw new HTTPException(403, { message: "Agent attempts cannot submit feedback" });
|
|
38
|
+
try {
|
|
39
|
+
const save = () =>
|
|
40
|
+
createFeedback(deps.db, {
|
|
41
|
+
accountId: grant.accountId,
|
|
42
|
+
workspaceId,
|
|
43
|
+
subjectId: grant.subjectId,
|
|
44
|
+
principalKind: grant.principalKind ?? null,
|
|
45
|
+
request: parsed.data,
|
|
46
|
+
});
|
|
47
|
+
let result;
|
|
48
|
+
if (parsed.data.sessionId) {
|
|
49
|
+
await requireAccessGrant(c, deps, workspaceId, "sessions:read");
|
|
50
|
+
const authorization = await requireSessionAuthorization(deps, grant, {
|
|
51
|
+
sessionId: parsed.data.sessionId,
|
|
52
|
+
operation: "session.feedback.write",
|
|
53
|
+
surface: "http",
|
|
54
|
+
});
|
|
55
|
+
result = authorization
|
|
56
|
+
? await withResolvedSessionAuthorization(authorization, save)
|
|
57
|
+
: await save();
|
|
58
|
+
} else result = await save();
|
|
59
|
+
c.header("cache-control", "private, no-store");
|
|
60
|
+
return c.json(result, result.replayed ? 200 : 201);
|
|
61
|
+
} catch (error) {
|
|
62
|
+
throw feedbackHttpError(error);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
app.get("/v1/workspaces/:workspaceId/feedback", async (c) => {
|
|
66
|
+
const workspaceId = c.req.param("workspaceId");
|
|
67
|
+
const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:read");
|
|
68
|
+
const query = z
|
|
69
|
+
.object({
|
|
70
|
+
sessionId: z.string().uuid().optional(),
|
|
71
|
+
includeTurns: z
|
|
72
|
+
.enum(["true", "false"])
|
|
73
|
+
.default("true")
|
|
74
|
+
.transform((value) => value === "true"),
|
|
75
|
+
limit: z.coerce.number().int().min(1).max(100).default(50),
|
|
76
|
+
})
|
|
77
|
+
.safeParse(c.req.query());
|
|
78
|
+
if (!query.success) throw new HTTPException(400, { message: "Invalid feedback query" });
|
|
79
|
+
try {
|
|
80
|
+
const read = () =>
|
|
81
|
+
listOwnFeedback(deps.db, { workspaceId, subjectId: grant.subjectId, ...query.data });
|
|
82
|
+
let feedback;
|
|
83
|
+
if (query.data.sessionId) {
|
|
84
|
+
await requireAccessGrant(c, deps, workspaceId, "sessions:read");
|
|
85
|
+
const authorization = await requireSessionAuthorization(deps, grant, {
|
|
86
|
+
sessionId: query.data.sessionId,
|
|
87
|
+
operation: "session.read",
|
|
88
|
+
surface: "http",
|
|
89
|
+
});
|
|
90
|
+
feedback = authorization
|
|
91
|
+
? await withResolvedSessionAuthorization(authorization, read)
|
|
92
|
+
: await read();
|
|
93
|
+
} else feedback = await read();
|
|
94
|
+
c.header("cache-control", "private, no-store");
|
|
95
|
+
return c.json({ feedback });
|
|
96
|
+
} catch (error) {
|
|
97
|
+
throw feedbackHttpError(error);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
function feedbackHttpError(error: unknown): Error {
|
|
102
|
+
if (error instanceof FeedbackConflictError)
|
|
103
|
+
return new HTTPException(409, { message: error.message });
|
|
104
|
+
if (
|
|
105
|
+
error instanceof FeedbackTargetNotFoundError ||
|
|
106
|
+
error instanceof SessionAuthorizationDeniedError
|
|
107
|
+
)
|
|
108
|
+
return new HTTPException(404, { message: "Feedback target not found" });
|
|
109
|
+
if (error instanceof SessionAuthorizationUnavailableError)
|
|
110
|
+
return new HTTPException(503, { message: "Session authorization unavailable" });
|
|
111
|
+
if (error instanceof Error) return error;
|
|
112
|
+
return new Error("Feedback request failed");
|
|
113
|
+
}
|