@opengeni/api-router 0.30.1 → 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-office-import.d.ts +7 -4
- 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 +1129 -166
- 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 +25 -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 +113 -10
- 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 +71 -3
- 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/files.d.ts +4 -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 +1974 -256
- 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 +77 -9
- 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 +820 -222
- 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 +3170 -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 -38
- 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 +839 -131
- 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 +1040 -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 +337 -39
- 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-2PQMSRCB.js +0 -49759
- package/dist/chunk-2PQMSRCB.js.map +0 -1
- package/dist/routes/packs.d.ts +0 -3
- package/src/routes/packs.ts +0 -729
|
@@ -0,0 +1,622 @@
|
|
|
1
|
+
import { environmentsEncryptionKeyBytes } from "@opengeni/config";
|
|
2
|
+
import { withOrganizationIntegrationAcquisition } from "@opengeni/db/organization-integration-policy";
|
|
3
|
+
import {
|
|
4
|
+
CreatePrReviewAppRegistrationRequest,
|
|
5
|
+
CreatePrReviewRepositoryBindingRequest,
|
|
6
|
+
PrReviewAppRegistration,
|
|
7
|
+
PrReviewRepositoryBinding,
|
|
8
|
+
UpdatePrReviewAppRegistrationRequest,
|
|
9
|
+
UpdatePrReviewRepositoryBindingRequest,
|
|
10
|
+
} from "@opengeni/contracts";
|
|
11
|
+
import {
|
|
12
|
+
assertWorkspaceModelPolicyAllows,
|
|
13
|
+
canonicalConfiguredModel,
|
|
14
|
+
defaultPrReviewProviderBaseUrl,
|
|
15
|
+
workspaceCustomModelReference,
|
|
16
|
+
lockActiveCustomModelForAdmission,
|
|
17
|
+
modelUnavailableHttpException,
|
|
18
|
+
prReviewWebhookAuthKind,
|
|
19
|
+
normalizePrReviewProviderBaseUrl,
|
|
20
|
+
requireAccessGrant,
|
|
21
|
+
requireAccessGrantAuthorization,
|
|
22
|
+
requirePermission,
|
|
23
|
+
resolveWorkspaceCatalogSettings,
|
|
24
|
+
type ApiRouteDeps,
|
|
25
|
+
PR_REVIEW_AUTOMATION_SETUP,
|
|
26
|
+
} from "@opengeni/core";
|
|
27
|
+
import {
|
|
28
|
+
createPrReviewAppRegistration,
|
|
29
|
+
createPrReviewRepositoryBinding,
|
|
30
|
+
deletePrReviewAppRegistration,
|
|
31
|
+
deletePrReviewRepositoryBinding,
|
|
32
|
+
decryptVariableSetValue,
|
|
33
|
+
encryptVariableSetValue,
|
|
34
|
+
getPrReviewAppRegistrationSecret,
|
|
35
|
+
listPrReviewAppRegistrations,
|
|
36
|
+
listPrReviewRepositoryBindings,
|
|
37
|
+
nestedPostgresSqlState,
|
|
38
|
+
recordAuditEvent,
|
|
39
|
+
updatePrReviewAppRegistration,
|
|
40
|
+
updatePrReviewRepositoryBinding,
|
|
41
|
+
} from "@opengeni/db";
|
|
42
|
+
import { listGitHubAppRepositoriesWithSigningSettings } from "@opengeni/github";
|
|
43
|
+
import type { Hono } from "hono";
|
|
44
|
+
import { HTTPException } from "hono/http-exception";
|
|
45
|
+
import {
|
|
46
|
+
PrReviewProviderRepositoryError,
|
|
47
|
+
verifyPrReviewProviderRepository,
|
|
48
|
+
} from "../integrations/pr-review-provider";
|
|
49
|
+
import { registerPrReviewGitHubRoutes } from "./pr-review-github";
|
|
50
|
+
import { integrationCommitGrant } from "../integrations/integration-commit-authority";
|
|
51
|
+
import { parseRequestJson } from "../http/request-body";
|
|
52
|
+
|
|
53
|
+
export function registerPrReviewRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
54
|
+
const { db, settings } = deps;
|
|
55
|
+
registerPrReviewGitHubRoutes(app, deps);
|
|
56
|
+
|
|
57
|
+
app.get("/v1/workspaces/:workspaceId/pr-review/registrations", async (c) => {
|
|
58
|
+
const workspaceId = c.req.param("workspaceId");
|
|
59
|
+
const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:read");
|
|
60
|
+
|
|
61
|
+
return c.json({
|
|
62
|
+
registrations: await listPrReviewAppRegistrations(db, grant.accountId, workspaceId),
|
|
63
|
+
repositories: await listPrReviewRepositoryBindings(db, grant.accountId, workspaceId),
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
app.post("/v1/workspaces/:workspaceId/pr-review/registrations", async (c) => {
|
|
68
|
+
const workspaceId = c.req.param("workspaceId");
|
|
69
|
+
const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:admin");
|
|
70
|
+
requirePermission(grant, "secrets:write");
|
|
71
|
+
|
|
72
|
+
assertPrReviewSandboxBackend(deps);
|
|
73
|
+
const payload = await parseRequestJson(c, CreatePrReviewAppRegistrationRequest);
|
|
74
|
+
const encryptionKey = requirePrReviewEncryptionKey(deps);
|
|
75
|
+
let providerBaseUrl: string;
|
|
76
|
+
try {
|
|
77
|
+
providerBaseUrl = normalizePrReviewProviderBaseUrl(
|
|
78
|
+
payload.provider,
|
|
79
|
+
payload.providerBaseUrl ?? defaultPrReviewProviderBaseUrl(payload.provider),
|
|
80
|
+
);
|
|
81
|
+
} catch (error) {
|
|
82
|
+
throw new HTTPException(422, {
|
|
83
|
+
message:
|
|
84
|
+
error instanceof Error
|
|
85
|
+
? error.message
|
|
86
|
+
: "PR Review providerBaseUrl must be a credential-free HTTPS origin or path",
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
if (
|
|
90
|
+
payload.provider === "azure_devops" &&
|
|
91
|
+
new URL(providerBaseUrl).pathname.split("/").filter(Boolean).length === 0
|
|
92
|
+
) {
|
|
93
|
+
throw new HTTPException(422, {
|
|
94
|
+
message: "Azure DevOps PR Review providerBaseUrl must include the organization path",
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
const registration = await mapPrReviewUniqueConflict(
|
|
98
|
+
withOrganizationIntegrationAcquisition(
|
|
99
|
+
db,
|
|
100
|
+
grant,
|
|
101
|
+
[prReviewIntegrationKey(payload.provider)],
|
|
102
|
+
(tx) =>
|
|
103
|
+
createPrReviewAppRegistration(tx, {
|
|
104
|
+
accountId: grant.accountId,
|
|
105
|
+
workspaceId,
|
|
106
|
+
name: payload.name,
|
|
107
|
+
provider: payload.provider,
|
|
108
|
+
providerBaseUrl,
|
|
109
|
+
appId: payload.appId ?? null,
|
|
110
|
+
credentialKind: payload.credentialKind,
|
|
111
|
+
credentialEncrypted: encryptVariableSetValue(
|
|
112
|
+
encryptionKey,
|
|
113
|
+
payload.privateKey ?? payload.accessToken!,
|
|
114
|
+
),
|
|
115
|
+
accessTokenExpiresAt: payload.accessTokenExpiresAt
|
|
116
|
+
? new Date(payload.accessTokenExpiresAt)
|
|
117
|
+
: null,
|
|
118
|
+
webhookAuthKind: prReviewWebhookAuthKind(payload.provider),
|
|
119
|
+
webhookSecretEncrypted: encryptVariableSetValue(encryptionKey, payload.webhookSecret),
|
|
120
|
+
webhookUsername: payload.webhookUsername ?? null,
|
|
121
|
+
createdBySubjectId: grant.subjectId,
|
|
122
|
+
}),
|
|
123
|
+
),
|
|
124
|
+
"A PR Review registration with this provider and name already exists",
|
|
125
|
+
);
|
|
126
|
+
await recordAuditEvent(db, {
|
|
127
|
+
accountId: grant.accountId,
|
|
128
|
+
workspaceId,
|
|
129
|
+
subjectId: grant.subjectId,
|
|
130
|
+
action: "prReview.app_registration.created",
|
|
131
|
+
targetType: "pr_review_app_registration",
|
|
132
|
+
targetId: registration.id,
|
|
133
|
+
metadata: {
|
|
134
|
+
provider: registration.provider,
|
|
135
|
+
credentialKind: registration.credentialKind,
|
|
136
|
+
webhookAuthKind: registration.webhookAuthKind,
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
return c.json(PrReviewAppRegistration.parse(registration), 201);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
app.patch("/v1/workspaces/:workspaceId/pr-review/registrations/:registrationId", async (c) => {
|
|
143
|
+
const workspaceId = c.req.param("workspaceId");
|
|
144
|
+
const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:admin");
|
|
145
|
+
requirePermission(grant, "secrets:write");
|
|
146
|
+
|
|
147
|
+
const payload = await parseRequestJson(c, UpdatePrReviewAppRegistrationRequest);
|
|
148
|
+
const existing = await getPrReviewAppRegistrationSecret(db, {
|
|
149
|
+
accountId: grant.accountId,
|
|
150
|
+
workspaceId,
|
|
151
|
+
registrationId: c.req.param("registrationId"),
|
|
152
|
+
});
|
|
153
|
+
if (!existing)
|
|
154
|
+
throw new HTTPException(404, {
|
|
155
|
+
message: "PR Review app registration not found",
|
|
156
|
+
});
|
|
157
|
+
if (existing.credentialKind === "managed_github_app") {
|
|
158
|
+
if (
|
|
159
|
+
payload.accessToken !== undefined ||
|
|
160
|
+
payload.privateKey !== undefined ||
|
|
161
|
+
payload.webhookSecret !== undefined ||
|
|
162
|
+
payload.webhookUsername !== undefined ||
|
|
163
|
+
payload.accessTokenExpiresAt !== undefined
|
|
164
|
+
) {
|
|
165
|
+
throw new HTTPException(422, {
|
|
166
|
+
message: "Opengeni Lens credentials are managed by the deployment",
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
if (payload.status === "active") {
|
|
170
|
+
throw new HTTPException(409, {
|
|
171
|
+
message: "Reconnect Opengeni Lens to reactivate and resync its repositories",
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (payload.accessToken && existing.credentialKind !== "provider_token") {
|
|
176
|
+
throw new HTTPException(422, {
|
|
177
|
+
message: "GitHub App registrations accept private keys, not access tokens",
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
if (payload.privateKey && existing.credentialKind !== "github_app") {
|
|
181
|
+
throw new HTTPException(422, {
|
|
182
|
+
message: "Provider-token registrations do not accept GitHub private keys",
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
if (
|
|
186
|
+
payload.accessTokenExpiresAt !== undefined &&
|
|
187
|
+
existing.credentialKind !== "provider_token"
|
|
188
|
+
) {
|
|
189
|
+
throw new HTTPException(422, {
|
|
190
|
+
message: "GitHub App registrations do not accept access-token expiry",
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
const encryptionKey =
|
|
194
|
+
payload.privateKey || payload.accessToken || payload.webhookSecret
|
|
195
|
+
? requirePrReviewEncryptionKey(deps)
|
|
196
|
+
: null;
|
|
197
|
+
const updated = await mapPrReviewUniqueConflict(
|
|
198
|
+
updatePrReviewAppRegistration(db, {
|
|
199
|
+
accountId: grant.accountId,
|
|
200
|
+
workspaceId,
|
|
201
|
+
registrationId: existing.id,
|
|
202
|
+
...(payload.name !== undefined ? { name: payload.name } : {}),
|
|
203
|
+
...(payload.accessToken !== undefined
|
|
204
|
+
? {
|
|
205
|
+
credentialEncrypted: encryptVariableSetValue(encryptionKey!, payload.accessToken),
|
|
206
|
+
}
|
|
207
|
+
: {}),
|
|
208
|
+
...(payload.privateKey !== undefined
|
|
209
|
+
? {
|
|
210
|
+
credentialEncrypted: encryptVariableSetValue(encryptionKey!, payload.privateKey),
|
|
211
|
+
}
|
|
212
|
+
: {}),
|
|
213
|
+
...(payload.accessTokenExpiresAt !== undefined
|
|
214
|
+
? {
|
|
215
|
+
accessTokenExpiresAt: payload.accessTokenExpiresAt
|
|
216
|
+
? new Date(payload.accessTokenExpiresAt)
|
|
217
|
+
: null,
|
|
218
|
+
}
|
|
219
|
+
: {}),
|
|
220
|
+
...(payload.webhookSecret !== undefined
|
|
221
|
+
? {
|
|
222
|
+
webhookSecretEncrypted: encryptVariableSetValue(
|
|
223
|
+
encryptionKey!,
|
|
224
|
+
payload.webhookSecret,
|
|
225
|
+
),
|
|
226
|
+
}
|
|
227
|
+
: {}),
|
|
228
|
+
...(payload.webhookUsername !== undefined
|
|
229
|
+
? { webhookUsername: payload.webhookUsername }
|
|
230
|
+
: {}),
|
|
231
|
+
...(payload.status !== undefined ? { status: payload.status } : {}),
|
|
232
|
+
}),
|
|
233
|
+
"A PR Review registration with this provider and name already exists",
|
|
234
|
+
);
|
|
235
|
+
await recordAuditEvent(db, {
|
|
236
|
+
accountId: grant.accountId,
|
|
237
|
+
workspaceId,
|
|
238
|
+
subjectId: grant.subjectId,
|
|
239
|
+
action: "prReview.app_registration.updated",
|
|
240
|
+
targetType: "pr_review_app_registration",
|
|
241
|
+
targetId: existing.id,
|
|
242
|
+
metadata: {
|
|
243
|
+
fields: Object.keys(payload).filter(
|
|
244
|
+
(field) => field !== "accessToken" && field !== "privateKey" && field !== "webhookSecret",
|
|
245
|
+
),
|
|
246
|
+
credentialRotated: payload.accessToken !== undefined || payload.privateKey !== undefined,
|
|
247
|
+
webhookSecretRotated: payload.webhookSecret !== undefined,
|
|
248
|
+
},
|
|
249
|
+
});
|
|
250
|
+
return c.json(PrReviewAppRegistration.parse(updated));
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
app.delete("/v1/workspaces/:workspaceId/pr-review/registrations/:registrationId", async (c) => {
|
|
254
|
+
const workspaceId = c.req.param("workspaceId");
|
|
255
|
+
const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:admin");
|
|
256
|
+
requirePermission(grant, "secrets:write");
|
|
257
|
+
const deleted = await deletePrReviewAppRegistration(db, {
|
|
258
|
+
accountId: grant.accountId,
|
|
259
|
+
workspaceId,
|
|
260
|
+
registrationId: c.req.param("registrationId"),
|
|
261
|
+
});
|
|
262
|
+
if (!deleted)
|
|
263
|
+
throw new HTTPException(404, {
|
|
264
|
+
message: "PR Review app registration not found",
|
|
265
|
+
});
|
|
266
|
+
await recordAuditEvent(db, {
|
|
267
|
+
accountId: grant.accountId,
|
|
268
|
+
workspaceId,
|
|
269
|
+
subjectId: grant.subjectId,
|
|
270
|
+
action: "prReview.app_registration.disabled",
|
|
271
|
+
targetType: "pr_review_app_registration",
|
|
272
|
+
targetId: c.req.param("registrationId"),
|
|
273
|
+
metadata: {},
|
|
274
|
+
});
|
|
275
|
+
return c.body(null, 204);
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
app.post("/v1/workspaces/:workspaceId/pr-review/repositories", async (c) => {
|
|
279
|
+
const workspaceId = c.req.param("workspaceId");
|
|
280
|
+
const grant = await integrationCommitGrant(
|
|
281
|
+
await requireAccessGrantAuthorization(c, deps, workspaceId, "workspace:admin"),
|
|
282
|
+
["workspace:admin"],
|
|
283
|
+
{ settings: deps.settings, authorizationHeader: c.req.header("authorization") },
|
|
284
|
+
);
|
|
285
|
+
|
|
286
|
+
const payload = await parseRequestJson(c, CreatePrReviewRepositoryBindingRequest);
|
|
287
|
+
const registration = await getPrReviewAppRegistrationSecret(db, {
|
|
288
|
+
accountId: grant.accountId,
|
|
289
|
+
workspaceId,
|
|
290
|
+
registrationId: payload.registrationId,
|
|
291
|
+
});
|
|
292
|
+
if (!registration)
|
|
293
|
+
throw new HTTPException(404, {
|
|
294
|
+
message: "PR Review app registration not found",
|
|
295
|
+
});
|
|
296
|
+
const integrationKey = prReviewIntegrationKey(registration.provider);
|
|
297
|
+
await withOrganizationIntegrationAcquisition(db, grant, [integrationKey], async () => {});
|
|
298
|
+
const repositoryUrl = new URL(payload.repositoryUri);
|
|
299
|
+
let canonicalRepositoryUri = repositoryUrl.href;
|
|
300
|
+
let canonicalRepositoryFullName = payload.repositoryFullName;
|
|
301
|
+
let canonicalProviderRepositoryId = String(payload.providerRepositoryId);
|
|
302
|
+
let canonicalProjectId = payload.projectId === undefined ? null : String(payload.projectId);
|
|
303
|
+
const providerUrl = new URL(registration.providerBaseUrl);
|
|
304
|
+
const providerPath = providerUrl.pathname.replace(/\/$/, "");
|
|
305
|
+
if (
|
|
306
|
+
repositoryUrl.protocol !== "https:" ||
|
|
307
|
+
repositoryUrl.username ||
|
|
308
|
+
repositoryUrl.password ||
|
|
309
|
+
repositoryUrl.host.toLowerCase() !== providerUrl.host.toLowerCase() ||
|
|
310
|
+
(providerPath !== "" &&
|
|
311
|
+
providerPath !== "/" &&
|
|
312
|
+
!repositoryUrl.pathname.startsWith(`${providerPath}/`))
|
|
313
|
+
) {
|
|
314
|
+
throw new HTTPException(422, {
|
|
315
|
+
message:
|
|
316
|
+
"repositoryUri must be a credential-free HTTPS URL on the registered provider host",
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
if (registration.provider === "github") {
|
|
320
|
+
const installationId = positiveInteger(payload.installationId);
|
|
321
|
+
const repositoryId = positiveInteger(payload.providerRepositoryId);
|
|
322
|
+
if (!installationId || !repositoryId || !registration.appId) {
|
|
323
|
+
throw new HTTPException(422, {
|
|
324
|
+
message: "GitHub repository bindings require App, installation, and repository IDs",
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
const encryptionKey = requirePrReviewEncryptionKey(deps);
|
|
328
|
+
if (!registration.credentialEncrypted) {
|
|
329
|
+
throw new HTTPException(409, {
|
|
330
|
+
message: "PR Review GitHub App credential is unavailable",
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
let allowedRepositories;
|
|
334
|
+
try {
|
|
335
|
+
allowedRepositories = await listGitHubAppRepositoriesWithSigningSettings(
|
|
336
|
+
{
|
|
337
|
+
githubAppId: registration.appId,
|
|
338
|
+
githubAppPrivateKey: decryptVariableSetValue(
|
|
339
|
+
encryptionKey,
|
|
340
|
+
registration.credentialEncrypted,
|
|
341
|
+
),
|
|
342
|
+
},
|
|
343
|
+
{ installationIds: [installationId] },
|
|
344
|
+
);
|
|
345
|
+
} catch {
|
|
346
|
+
throw new HTTPException(502, {
|
|
347
|
+
message: "Could not verify the repository against the registered GitHub App",
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
const allowedRepository = allowedRepositories.find(
|
|
351
|
+
(candidate) =>
|
|
352
|
+
candidate.id === repositoryId &&
|
|
353
|
+
candidate.fullName.toLowerCase() === payload.repositoryFullName.toLowerCase(),
|
|
354
|
+
);
|
|
355
|
+
if (!allowedRepository) {
|
|
356
|
+
throw new HTTPException(403, {
|
|
357
|
+
message: "GitHub repository is not installed for this PR Review App",
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
canonicalRepositoryUri = allowedRepository.cloneUrl;
|
|
361
|
+
canonicalRepositoryFullName = allowedRepository.fullName;
|
|
362
|
+
canonicalProviderRepositoryId = String(allowedRepository.id);
|
|
363
|
+
}
|
|
364
|
+
if (registration.provider !== "github") {
|
|
365
|
+
if (
|
|
366
|
+
registration.accessTokenExpiresAt &&
|
|
367
|
+
Date.parse(registration.accessTokenExpiresAt) <= Date.now()
|
|
368
|
+
) {
|
|
369
|
+
throw new HTTPException(409, {
|
|
370
|
+
message: "PR Review provider credential has expired",
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
const encryptionKey = requirePrReviewEncryptionKey(deps);
|
|
374
|
+
if (!registration.credentialEncrypted) {
|
|
375
|
+
throw new HTTPException(409, {
|
|
376
|
+
message: "PR Review provider credential is unavailable",
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
try {
|
|
380
|
+
const verified = await verifyPrReviewProviderRepository({
|
|
381
|
+
provider: registration.provider,
|
|
382
|
+
providerBaseUrl: registration.providerBaseUrl,
|
|
383
|
+
providerRepositoryId: String(payload.providerRepositoryId),
|
|
384
|
+
...(payload.projectId !== undefined ? { projectId: String(payload.projectId) } : {}),
|
|
385
|
+
token: decryptVariableSetValue(encryptionKey, registration.credentialEncrypted),
|
|
386
|
+
username: registration.webhookUsername,
|
|
387
|
+
settings,
|
|
388
|
+
});
|
|
389
|
+
canonicalRepositoryUri = verified.repositoryUri;
|
|
390
|
+
canonicalRepositoryFullName = verified.repositoryFullName;
|
|
391
|
+
canonicalProviderRepositoryId = verified.providerRepositoryId;
|
|
392
|
+
canonicalProjectId = verified.projectId;
|
|
393
|
+
} catch (error) {
|
|
394
|
+
if (error instanceof PrReviewProviderRepositoryError) {
|
|
395
|
+
const status =
|
|
396
|
+
error.reason === "denied" ? 403 : error.reason === "identity_mismatch" ? 422 : 502;
|
|
397
|
+
throw new HTTPException(status, { message: error.message });
|
|
398
|
+
}
|
|
399
|
+
throw error;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
const catalogSettings = (
|
|
403
|
+
await resolveWorkspaceCatalogSettings(db, deps.settings, {
|
|
404
|
+
accountId: grant.accountId,
|
|
405
|
+
workspaceId,
|
|
406
|
+
})
|
|
407
|
+
).settings;
|
|
408
|
+
const model = payload.model
|
|
409
|
+
? (canonicalConfiguredModel(catalogSettings, payload.model) ?? null)
|
|
410
|
+
: null;
|
|
411
|
+
if (model) await assertWorkspaceModelPolicyAllows(db, catalogSettings, workspaceId, model);
|
|
412
|
+
const beforeCreateCommit = model
|
|
413
|
+
? prReviewCustomModelCommitGuard({
|
|
414
|
+
settings: catalogSettings,
|
|
415
|
+
accountId: grant.accountId,
|
|
416
|
+
workspaceId,
|
|
417
|
+
modelId: model,
|
|
418
|
+
})
|
|
419
|
+
: undefined;
|
|
420
|
+
const template = PR_REVIEW_AUTOMATION_SETUP;
|
|
421
|
+
|
|
422
|
+
const binding = await mapPrReviewUniqueConflict(
|
|
423
|
+
withOrganizationIntegrationAcquisition(db, grant, [integrationKey], async (tx) => {
|
|
424
|
+
await grant.authorizeCommit(tx);
|
|
425
|
+
return createPrReviewRepositoryBinding(tx, {
|
|
426
|
+
accountId: grant.accountId,
|
|
427
|
+
workspaceId,
|
|
428
|
+
registrationId: registration.id,
|
|
429
|
+
provider: registration.provider,
|
|
430
|
+
repositoryUri: canonicalRepositoryUri,
|
|
431
|
+
repositoryFullName: canonicalRepositoryFullName,
|
|
432
|
+
providerRepositoryId: canonicalProviderRepositoryId,
|
|
433
|
+
installationId:
|
|
434
|
+
payload.installationId === undefined ? null : String(payload.installationId),
|
|
435
|
+
projectId: canonicalProjectId,
|
|
436
|
+
model,
|
|
437
|
+
additionalInstructions: payload.additionalInstructions ?? null,
|
|
438
|
+
status: payload.status,
|
|
439
|
+
createdBySubjectId: grant.subjectId,
|
|
440
|
+
|
|
441
|
+
adapterId: template.adapterId,
|
|
442
|
+
eventTypes: template.eventTypes,
|
|
443
|
+
configuration: template.configuration,
|
|
444
|
+
sessionTemplate: template.sessionTemplate,
|
|
445
|
+
...(beforeCreateCommit ? { beforeCreateCommit } : {}),
|
|
446
|
+
});
|
|
447
|
+
}),
|
|
448
|
+
"This repository is already bound to the selected PR Review registration",
|
|
449
|
+
);
|
|
450
|
+
await recordAuditEvent(db, {
|
|
451
|
+
accountId: grant.accountId,
|
|
452
|
+
workspaceId,
|
|
453
|
+
subjectId: grant.subjectId,
|
|
454
|
+
action: "prReview.repository_binding.created",
|
|
455
|
+
targetType: "pr_review_repository_binding",
|
|
456
|
+
targetId: binding.id,
|
|
457
|
+
metadata: {
|
|
458
|
+
provider: binding.provider,
|
|
459
|
+
registrationId: binding.registrationId,
|
|
460
|
+
providerRepositoryId: binding.providerRepositoryId,
|
|
461
|
+
},
|
|
462
|
+
});
|
|
463
|
+
return c.json(PrReviewRepositoryBinding.parse(binding), 201);
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
app.patch("/v1/workspaces/:workspaceId/pr-review/repositories/:bindingId", async (c) => {
|
|
467
|
+
const workspaceId = c.req.param("workspaceId");
|
|
468
|
+
const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:admin");
|
|
469
|
+
|
|
470
|
+
const payload = await parseRequestJson(c, UpdatePrReviewRepositoryBindingRequest);
|
|
471
|
+
const catalogSettings = (
|
|
472
|
+
await resolveWorkspaceCatalogSettings(db, deps.settings, {
|
|
473
|
+
accountId: grant.accountId,
|
|
474
|
+
workspaceId,
|
|
475
|
+
})
|
|
476
|
+
).settings;
|
|
477
|
+
const model =
|
|
478
|
+
payload.model === undefined
|
|
479
|
+
? undefined
|
|
480
|
+
: payload.model === null
|
|
481
|
+
? null
|
|
482
|
+
: (canonicalConfiguredModel(catalogSettings, payload.model) ?? null);
|
|
483
|
+
if (model) await assertWorkspaceModelPolicyAllows(db, catalogSettings, workspaceId, model);
|
|
484
|
+
const beforeUpdateCommit = async (
|
|
485
|
+
tx: ApiRouteDeps["db"],
|
|
486
|
+
context: {
|
|
487
|
+
currentModel: string | null;
|
|
488
|
+
currentStatus: "active" | "disabled";
|
|
489
|
+
nextModel: string | null;
|
|
490
|
+
nextStatus: "active" | "disabled";
|
|
491
|
+
},
|
|
492
|
+
): Promise<void> => {
|
|
493
|
+
const materialExecutionChange =
|
|
494
|
+
payload.model !== undefined ||
|
|
495
|
+
payload.additionalInstructions !== undefined ||
|
|
496
|
+
(context.currentStatus === "disabled" && context.nextStatus === "active");
|
|
497
|
+
if (!materialExecutionChange || !context.nextModel) return;
|
|
498
|
+
await prReviewCustomModelCommitGuard({
|
|
499
|
+
settings: catalogSettings,
|
|
500
|
+
accountId: grant.accountId,
|
|
501
|
+
workspaceId,
|
|
502
|
+
modelId: context.nextModel,
|
|
503
|
+
})?.(tx);
|
|
504
|
+
};
|
|
505
|
+
const binding = await updatePrReviewRepositoryBinding(db, {
|
|
506
|
+
accountId: grant.accountId,
|
|
507
|
+
workspaceId,
|
|
508
|
+
bindingId: c.req.param("bindingId"),
|
|
509
|
+
subjectId: grant.subjectId,
|
|
510
|
+
...(model !== undefined ? { model } : {}),
|
|
511
|
+
...(payload.additionalInstructions !== undefined
|
|
512
|
+
? { additionalInstructions: payload.additionalInstructions }
|
|
513
|
+
: {}),
|
|
514
|
+
...(payload.status !== undefined ? { status: payload.status } : {}),
|
|
515
|
+
beforeUpdateCommit,
|
|
516
|
+
});
|
|
517
|
+
if (!binding)
|
|
518
|
+
throw new HTTPException(404, {
|
|
519
|
+
message: "PR Review repository binding not found",
|
|
520
|
+
});
|
|
521
|
+
await recordAuditEvent(db, {
|
|
522
|
+
accountId: grant.accountId,
|
|
523
|
+
workspaceId,
|
|
524
|
+
subjectId: grant.subjectId,
|
|
525
|
+
action: "prReview.repository_binding.updated",
|
|
526
|
+
targetType: "pr_review_repository_binding",
|
|
527
|
+
targetId: binding.id,
|
|
528
|
+
metadata: { fields: Object.keys(payload) },
|
|
529
|
+
});
|
|
530
|
+
return c.json(PrReviewRepositoryBinding.parse(binding));
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
app.delete("/v1/workspaces/:workspaceId/pr-review/repositories/:bindingId", async (c) => {
|
|
534
|
+
const workspaceId = c.req.param("workspaceId");
|
|
535
|
+
const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:admin");
|
|
536
|
+
const deleted = await deletePrReviewRepositoryBinding(db, {
|
|
537
|
+
accountId: grant.accountId,
|
|
538
|
+
workspaceId,
|
|
539
|
+
bindingId: c.req.param("bindingId"),
|
|
540
|
+
subjectId: grant.subjectId,
|
|
541
|
+
});
|
|
542
|
+
if (!deleted)
|
|
543
|
+
throw new HTTPException(404, {
|
|
544
|
+
message: "PR Review repository binding not found",
|
|
545
|
+
});
|
|
546
|
+
await recordAuditEvent(db, {
|
|
547
|
+
accountId: grant.accountId,
|
|
548
|
+
workspaceId,
|
|
549
|
+
subjectId: grant.subjectId,
|
|
550
|
+
action: "prReview.repository_binding.disabled",
|
|
551
|
+
targetType: "pr_review_repository_binding",
|
|
552
|
+
targetId: c.req.param("bindingId"),
|
|
553
|
+
metadata: {},
|
|
554
|
+
});
|
|
555
|
+
return c.body(null, 204);
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
/** PR Review's server-owned provider, not a repository URL or user label,
|
|
560
|
+
* establishes Lens identity. Other providers have no curated acquisition key. */
|
|
561
|
+
function prReviewIntegrationKey(provider: string): "github-lens" | null {
|
|
562
|
+
return provider === "github" ? "github-lens" : null;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
function prReviewCustomModelCommitGuard(input: {
|
|
566
|
+
settings: ApiRouteDeps["settings"];
|
|
567
|
+
accountId: string;
|
|
568
|
+
workspaceId: string;
|
|
569
|
+
modelId: string;
|
|
570
|
+
}): ((tx: ApiRouteDeps["db"]) => Promise<void>) | undefined {
|
|
571
|
+
const reference = workspaceCustomModelReference(input.settings, input.modelId);
|
|
572
|
+
if (!reference) return undefined;
|
|
573
|
+
return async (tx): Promise<void> => {
|
|
574
|
+
const active = await lockActiveCustomModelForAdmission(tx, {
|
|
575
|
+
accountId: input.accountId,
|
|
576
|
+
workspaceId: input.workspaceId,
|
|
577
|
+
reference,
|
|
578
|
+
});
|
|
579
|
+
if (!active) {
|
|
580
|
+
throw modelUnavailableHttpException(input.modelId);
|
|
581
|
+
}
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
function assertPrReviewSandboxBackend(deps: ApiRouteDeps): void {
|
|
586
|
+
if (deps.settings.sandboxBackend === "selfhosted") {
|
|
587
|
+
throw new HTTPException(409, {
|
|
588
|
+
message:
|
|
589
|
+
"Opengeni Review Bot requires managed compute so it can materialize and verify the exact pull-request head",
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
function requirePrReviewEncryptionKey(deps: ApiRouteDeps): Uint8Array {
|
|
595
|
+
const key = environmentsEncryptionKeyBytes(deps.settings);
|
|
596
|
+
if (!key) {
|
|
597
|
+
throw new HTTPException(503, {
|
|
598
|
+
message: "Opengeni Review Bot requires configured secret encryption",
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
return key;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
async function mapPrReviewUniqueConflict<T>(operation: Promise<T>, message: string): Promise<T> {
|
|
605
|
+
try {
|
|
606
|
+
return await operation;
|
|
607
|
+
} catch (error) {
|
|
608
|
+
if (nestedPostgresSqlState(error) === "23505") {
|
|
609
|
+
throw new HTTPException(409, { message });
|
|
610
|
+
}
|
|
611
|
+
throw error;
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
function positiveInteger(value: unknown): number | null {
|
|
616
|
+
if (typeof value === "number" && Number.isSafeInteger(value) && value > 0) return value;
|
|
617
|
+
if (typeof value === "string" && /^\d+$/.test(value)) {
|
|
618
|
+
const parsed = Number(value);
|
|
619
|
+
return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : null;
|
|
620
|
+
}
|
|
621
|
+
return null;
|
|
622
|
+
}
|