@opengeni/api-router 3.0.1 → 3.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-grant-rls.d.ts +8 -1
- package/dist/admission-trace.d.ts +8 -0
- package/dist/app.d.ts +50 -3
- package/dist/app.js +10 -1
- package/dist/artifact-catalog-cursor.d.ts +1 -0
- package/dist/attached-browser-viewer.d.ts +11 -0
- package/dist/auth/managed-auth-attempt-context.d.ts +2 -0
- package/dist/auth/managed-auth-rate-limits.d.ts +167 -0
- package/dist/auth/managed-auth-session-adapter.d.ts +9 -1
- package/dist/auth/managed-auth.d.ts +72 -5
- package/dist/auth/managed-sign-in-notifications.d.ts +4 -0
- package/dist/auth/new-signups-gate.d.ts +23 -0
- package/dist/auth/signup-funnel-metrics.d.ts +44 -0
- package/dist/azure-live.d.ts +28 -0
- package/dist/browser-action-fences.d.ts +13 -0
- package/dist/browser-controller-authority.d.ts +1 -61
- package/dist/browser-ephemeral.d.ts +5 -0
- package/dist/browser-lost-runtime-end.d.ts +24 -0
- package/dist/browser-state-authority.d.ts +1 -27
- package/dist/chunk-OGQDXVXY.js +18 -0
- package/dist/chunk-OGQDXVXY.js.map +1 -0
- package/dist/{chunk-AJ62T5QN.js → chunk-OT56OY4V.js} +80503 -39869
- package/dist/chunk-OT56OY4V.js.map +1 -0
- package/dist/claude-default-models.d.ts +19 -0
- package/dist/claude-subscription-core.d.ts +50 -0
- package/dist/claude-subscription-oauth.d.ts +36 -0
- package/dist/claude-subscription-profile.d.ts +9 -0
- package/dist/claude-subscription-usage.d.ts +6 -0
- package/dist/claude-workspace-connection.d.ts +15 -0
- package/dist/codemode.d.ts +40 -5
- package/dist/codex-realtime.d.ts +29 -3
- package/dist/codex-session-pointers.d.ts +19 -0
- package/dist/connection-ownership.d.ts +6 -3
- package/dist/controller-data-plane.d.ts +16 -0
- package/dist/credit-promotion-snapshot.d.ts +6 -0
- package/dist/editable-artifact-source-session.d.ts +3 -0
- package/dist/editable-artifact-websocket.d.ts +5 -3
- package/dist/fatal-process-boundary.d.ts +9 -1
- package/dist/github-access.d.ts +7 -1
- package/dist/github-browser-flow.d.ts +1 -1
- package/dist/http/acting-person.d.ts +36 -0
- package/dist/http/api-contract-compat.d.ts +19 -0
- package/dist/http/api-error.d.ts +50 -1
- package/dist/http/auth.d.ts +8 -1
- package/dist/http/cors.d.ts +12 -0
- package/dist/http/deprecation.d.ts +42 -0
- package/dist/http/keyed-admission.d.ts +12 -0
- package/dist/http/local-browser-boundary.d.ts +72 -0
- package/dist/http/metrics-listener.d.ts +22 -0
- package/dist/http/path-identifier.d.ts +17 -0
- package/dist/http/registered-route-label.d.ts +16 -0
- package/dist/http/rejection-telemetry.d.ts +34 -0
- package/dist/http/request-body.d.ts +27 -0
- package/dist/http/request-source.d.ts +41 -3
- package/dist/http/sse.d.ts +12 -1
- package/dist/http/unmatched-route.d.ts +18 -0
- package/dist/http/user-content.d.ts +36 -0
- package/dist/http/variable-sets-removed.d.ts +41 -0
- package/dist/http/websocket-upgrade-dispatch.d.ts +18 -0
- package/dist/index.js +1279 -108
- package/dist/index.js.map +1 -1
- package/dist/integration-connect-metrics.d.ts +35 -0
- package/dist/integration-endpoint-test.d.ts +20 -0
- package/dist/integrations/api-integrations.d.ts +2 -2
- package/dist/integrations/atlassian.d.ts +8 -3
- package/dist/integrations/fiken.d.ts +3 -1
- package/dist/integrations/github-lens-connect.d.ts +37 -66
- package/dist/integrations/google-drive.d.ts +2 -0
- package/dist/integrations/integration-commit-authority.d.ts +13 -0
- package/dist/integrations/marketplace-plugin.d.ts +43 -43
- package/dist/integrations/oauth-client.d.ts +171 -12
- package/dist/integrations/oauth-profiles.d.ts +42 -13
- package/dist/integrations/onepassword-vault-provider.d.ts +9 -0
- package/dist/integrations/slack-bot.d.ts +285 -7
- package/dist/integrations/slack-file-upload-flow.d.ts +62 -0
- package/dist/integrations/slack-interactions.d.ts +89 -10
- package/dist/integrations/slack-mrkdwn.d.ts +41 -0
- package/dist/integrations/slack-routing.d.ts +1 -1
- package/dist/integrations/slack-session-defaults.d.ts +58 -0
- package/dist/integrations/slack-task-file-upload.d.ts +36 -0
- package/dist/integrations/slack-tool-review.d.ts +5 -0
- package/dist/interaction-agent-access.d.ts +13 -8
- package/dist/interaction-agent-version.d.ts +21 -0
- package/dist/interaction-holder-heartbeat.d.ts +5 -0
- package/dist/interaction-metrics.d.ts +27 -2
- package/dist/interaction-route-stages.d.ts +25 -0
- package/dist/interaction-secrets-vault.d.ts +20 -0
- package/dist/interaction-secrets.d.ts +103 -0
- package/dist/mcp/action-catalog-types.d.ts +14 -0
- package/dist/mcp/action-catalog.gen.d.ts +2 -0
- package/dist/mcp/action-descriptions.d.ts +4 -0
- package/dist/mcp/action-schema-imports.gen.d.ts +1 -0
- package/dist/mcp/capability-account-readiness.d.ts +7 -0
- package/dist/mcp/child-read-evidence.d.ts +9 -0
- package/dist/mcp/company-profile-agent-admin.d.ts +12 -0
- package/dist/mcp/contract-input.d.ts +13 -0
- package/dist/mcp/documents.d.ts +2 -0
- package/dist/mcp/first-party-tool-permissions.d.ts +3 -606
- package/dist/mcp/notification-tools.d.ts +26 -0
- package/dist/mcp/orchestration-failure-diagnostic.d.ts +43 -0
- package/dist/mcp/scheduled-task-input.d.ts +1309 -0
- package/dist/mcp/scheduled-task-view.d.ts +217 -3
- package/dist/mcp/secret-tools.d.ts +14 -0
- package/dist/mcp/server.d.ts +108 -5
- package/dist/mcp/session-admin-access-tools.d.ts +33 -0
- package/dist/mcp/session-event-errors.d.ts +28 -0
- package/dist/mcp/session-event-view.d.ts +62 -0
- package/dist/mcp/session-view.d.ts +15 -0
- package/dist/mcp/session-wait.d.ts +18 -0
- package/dist/mcp/site-agent-clamp-tools.d.ts +38 -0
- package/dist/mcp/site-data-tools.d.ts +22 -0
- package/dist/mcp/site-publication-tools.d.ts +19 -0
- package/dist/mcp/site-sql-tools.d.ts +27 -0
- package/dist/mcp-oauth.d.ts +37 -4
- package/dist/model-calls/chat-completions.d.ts +87 -0
- package/dist/model-calls/pending-usage-settlements.d.ts +57 -0
- package/dist/model-calls/service.d.ts +36 -0
- package/dist/model-catalog.d.ts +9 -3
- package/dist/native-push-dispatch.d.ts +69 -0
- package/dist/observability.d.ts +3 -1
- package/dist/organization-mcp.d.ts +82 -0
- package/dist/prepared-mcp-actor.d.ts +77 -0
- package/dist/prepared-mcp-permissions.d.ts +8 -0
- package/dist/routes/analytics-consent.d.ts +26 -0
- package/dist/routes/api-integrations.d.ts +11 -0
- package/dist/routes/api-keys.d.ts +7 -7
- package/dist/routes/automations.d.ts +2 -0
- package/dist/routes/billing.d.ts +59 -0
- package/dist/routes/browser-sessions.d.ts +65 -2
- package/dist/routes/chat-completions.d.ts +11 -0
- package/dist/routes/claude-core-usage.d.ts +20 -0
- package/dist/routes/claude-subscription-accounts.d.ts +3 -0
- package/dist/routes/claude-subscription-oauth.d.ts +3 -0
- package/dist/routes/client-errors.d.ts +182 -0
- package/dist/routes/codex-core.d.ts +401 -0
- package/dist/routes/codex.d.ts +64 -2
- package/dist/routes/computer-sessions.d.ts +6 -1
- package/dist/routes/desktop-distribution.d.ts +32 -0
- package/dist/routes/github-browser-fonts.gen.d.ts +2 -0
- package/dist/routes/github-browser-pages.d.ts +27 -0
- package/dist/routes/inbox.d.ts +13 -0
- package/dist/routes/insights-response-cache.d.ts +10 -0
- package/dist/routes/insights-usage.d.ts +12 -0
- package/dist/routes/insights.d.ts +28 -0
- package/dist/routes/interaction-placement-message.d.ts +7 -0
- package/dist/routes/managed-sign-in-methods.d.ts +6 -0
- package/dist/routes/model-account-choice.d.ts +13 -0
- package/dist/routes/model-account-settings.d.ts +19 -0
- package/dist/routes/native-app-auth.d.ts +12 -0
- package/dist/routes/organization-integration-policy.d.ts +8 -0
- package/dist/routes/organization-integrations.d.ts +6 -0
- package/dist/routes/organization-mcp-connections.d.ts +3 -0
- package/dist/routes/organization-model-defaults.d.ts +9 -0
- package/dist/routes/organization-service-accounts.d.ts +3 -0
- package/dist/routes/personal-api-keys.d.ts +3 -0
- package/dist/routes/session-admin-access.d.ts +3 -0
- package/dist/routes/session-artifact-associations.d.ts +4 -0
- package/dist/routes/session-history-imports.d.ts +20 -0
- package/dist/routes/sessions.d.ts +38 -2
- package/dist/routes/site-data.d.ts +18 -0
- package/dist/routes/site-publishing.d.ts +5 -0
- package/dist/routes/site-runtime.d.ts +31 -0
- package/dist/routes/site-sql.d.ts +16 -0
- package/dist/routes/slack-bot-access.d.ts +3 -0
- package/dist/routes/subscription-account-pools.d.ts +21 -0
- package/dist/routes/subscription-core-http.d.ts +5 -0
- package/dist/routes/subscription-pool-access.d.ts +37 -0
- package/dist/routes/subscription-pool-core.d.ts +153 -0
- package/dist/routes/supergrok.d.ts +6 -6
- package/dist/routes/usage-allowances.d.ts +12 -0
- package/dist/routes/variable-sets-removed.d.ts +2 -0
- package/dist/routes/vault-providers.d.ts +34 -0
- package/dist/routes/vaults.d.ts +3 -0
- package/dist/routes/workspace-integrations.d.ts +35 -0
- package/dist/routes/workspace-model-providers.d.ts +4 -0
- package/dist/routes/workspaces.d.ts +11 -2
- package/dist/sandbox/agent-update.d.ts +64 -0
- package/dist/sandbox/auth-callout.d.ts +8 -0
- package/dist/sandbox/channel-a.d.ts +15 -1
- package/dist/sandbox/enrollment.d.ts +26 -4
- package/dist/sandbox/machine-audience.d.ts +29 -0
- package/dist/sandbox/machines.d.ts +15 -2
- package/dist/sandbox/metrics-ingestion.d.ts +6 -2
- package/dist/sandbox/screen-control.d.ts +85 -0
- package/dist/sandbox/viewer.d.ts +5 -1
- package/dist/sandbox-file-artifacts.d.ts +17 -1
- package/dist/scheduled-task-blockers.d.ts +39 -0
- package/dist/scheduled-task-deletion.d.ts +3 -4
- package/dist/scheduled-task-lifecycle.d.ts +14 -0
- package/dist/secret-answers.d.ts +40 -0
- package/dist/session-create-observability.d.ts +5 -0
- package/dist/session-event-view-36GO3IL7.js +528 -0
- package/dist/session-event-view-36GO3IL7.js.map +1 -0
- package/dist/signed-state-secret.d.ts +18 -0
- package/dist/site-agent-guard.d.ts +53 -0
- package/dist/site-data/operations.d.ts +103 -0
- package/dist/site-data/service.d.ts +203 -0
- package/dist/site-frame-guard.d.ts +32 -0
- package/dist/site-publishing/agent-data-tools.d.ts +84 -0
- package/dist/site-publishing/agent-model.d.ts +58 -0
- package/dist/site-publishing/agent-session.d.ts +16 -0
- package/dist/site-publishing/content-scanner.d.ts +31 -0
- package/dist/site-publishing/edge-sync.d.ts +48 -0
- package/dist/site-publishing/gateway-signature.d.ts +56 -0
- package/dist/site-publishing/limits.d.ts +63 -0
- package/dist/site-publishing/page-tool-authority.d.ts +30 -0
- package/dist/site-publishing/platform-usage.d.ts +113 -0
- package/dist/site-publishing/platform.d.ts +21 -0
- package/dist/site-publishing/readiness.d.ts +62 -0
- package/dist/site-publishing/runtime.d.ts +179 -0
- package/dist/site-publishing/service.d.ts +264 -0
- package/dist/site-publishing/session-events.d.ts +22 -0
- package/dist/site-publishing/session-views.d.ts +36 -0
- package/dist/site-publishing/viewer.d.ts +40 -0
- package/dist/site-session-origin.d.ts +31 -6
- package/dist/site-sql/format.d.ts +47 -0
- package/dist/site-sql/gateway.d.ts +50 -0
- package/dist/site-sql/service.d.ts +213 -0
- package/dist/temporal-schedule-sync.d.ts +26 -0
- package/dist/transcription/billing-refusal.d.ts +8 -0
- package/dist/transcription/normalize.d.ts +23 -0
- package/dist/transcription/providers/azure-mai.d.ts +12 -0
- package/dist/transcription/providers/azure-openai.d.ts +4 -0
- package/dist/transcription/providers/openai.d.ts +16 -0
- package/dist/transcription/providers/subscription-core.d.ts +39 -0
- package/dist/transcription/service.d.ts +10 -1
- package/dist/transcription/wav-duration.d.ts +8 -0
- package/dist/workspace-tool-gateway-attestations.d.ts +37 -0
- package/dist/workspace-tool-gateway-observability.d.ts +16 -0
- package/dist/workspace-tool-gateway-secrets.d.ts +27 -0
- package/dist/workspace-tool-gateway.d.ts +102 -6
- package/dist/workspace-tool-target-fence.d.ts +116 -0
- package/dist/workspace-tool-target.d.ts +225 -0
- package/dist/workspace-webhook-dispatch.d.ts +26 -0
- package/dist/xai-subscription-core.d.ts +60 -0
- package/package.json +25 -20
- package/src/access-grant-rls.ts +64 -14
- package/src/admission-trace.ts +14 -0
- package/src/app.ts +1684 -252
- package/src/artifact-catalog-cursor.ts +1 -0
- package/src/attached-browser-viewer.ts +26 -0
- package/src/auth/managed-auth-attempt-context.ts +9 -0
- package/src/auth/managed-auth-rate-limits.ts +252 -0
- package/src/auth/managed-auth-session-adapter.ts +64 -29
- package/src/auth/managed-auth.ts +303 -35
- package/src/auth/managed-email.ts +18 -1
- package/src/auth/managed-sign-in-notifications.ts +81 -0
- package/src/auth/new-signups-gate.ts +49 -0
- package/src/auth/organization-user-setup.ts +3 -3
- package/src/auth/signup-funnel-metrics.ts +164 -0
- package/src/azure-live.ts +103 -0
- package/src/browser-action-fences.ts +45 -0
- package/src/browser-controller-authority.ts +1 -186
- package/src/browser-ephemeral.ts +39 -0
- package/src/browser-lost-runtime-end.ts +71 -0
- package/src/browser-state-authority.ts +1 -236
- package/src/claude-default-models.ts +37 -0
- package/src/claude-subscription-core.ts +154 -0
- package/src/claude-subscription-oauth.ts +352 -0
- package/src/claude-subscription-profile.ts +73 -0
- package/src/claude-subscription-usage.ts +51 -0
- package/src/claude-workspace-connection.ts +82 -0
- package/src/codemode.ts +236 -39
- package/src/codex-realtime.ts +181 -53
- package/src/codex-session-pointers.ts +80 -0
- package/src/company-brain-okf.ts +1 -1
- package/src/connected-machine-computer-access.ts +2 -1
- package/src/connection-ownership.ts +19 -13
- package/src/controller-data-plane.ts +34 -0
- package/src/credit-promotion-snapshot.ts +36 -0
- package/src/editable-artifact-production.ts +10 -0
- package/src/editable-artifact-source-session.ts +123 -0
- package/src/editable-artifact-websocket.ts +16 -3
- package/src/fatal-process-boundary.ts +67 -3
- package/src/gateway-realtime.ts +12 -8
- package/src/github-access.ts +31 -5
- package/src/github-browser-flow.ts +1 -1
- package/src/http/acting-person.ts +105 -0
- package/src/http/api-contract-compat.ts +49 -0
- package/src/http/api-error.ts +210 -2
- package/src/http/auth.ts +68 -4
- package/src/http/cors.ts +37 -5
- package/src/http/deprecation.ts +118 -0
- package/src/http/keyed-admission.ts +29 -0
- package/src/http/local-browser-boundary.ts +343 -0
- package/src/http/metrics-listener.ts +57 -0
- package/src/http/path-identifier.ts +54 -0
- package/src/http/registered-route-label.ts +34 -0
- package/src/http/rejection-telemetry.ts +120 -0
- package/src/http/request-body.ts +127 -0
- package/src/http/request-source.ts +154 -13
- package/src/http/sse.ts +88 -28
- package/src/http/unmatched-route.ts +60 -0
- package/src/http/user-content.ts +158 -0
- package/src/http/variable-sets-removed.ts +122 -0
- package/src/http/websocket-upgrade-dispatch.ts +29 -0
- package/src/index.ts +107 -57
- package/src/integration-connect-metrics.ts +228 -0
- package/src/integration-endpoint-test.ts +291 -0
- package/src/integrations/api-integrations.ts +81 -7
- package/src/integrations/atlassian.ts +202 -83
- package/src/integrations/fiken.ts +66 -38
- package/src/integrations/github-app-connect.ts +64 -18
- package/src/integrations/github-lens-connect.ts +8 -29
- package/src/integrations/google-drive.ts +448 -152
- package/src/integrations/integration-commit-authority.ts +69 -0
- package/src/integrations/marketplace-plugin.ts +1 -1
- package/src/integrations/oauth-client.ts +733 -193
- package/src/integrations/oauth-profiles.ts +116 -45
- package/src/integrations/onepassword-vault-provider.ts +16 -0
- package/src/integrations/personal-github-repositories.ts +1 -1
- package/src/integrations/personal-github.ts +61 -35
- package/src/integrations/provider-oauth.ts +67 -85
- package/src/integrations/slack-app-home.ts +5 -5
- package/src/integrations/slack-bot.ts +893 -201
- package/src/integrations/slack-file-upload-flow.ts +147 -0
- package/src/integrations/slack-install.ts +7 -7
- package/src/integrations/slack-interactions.ts +1589 -299
- package/src/integrations/slack-mrkdwn.ts +193 -0
- package/src/integrations/slack-routing.ts +2 -2
- package/src/integrations/slack-session-defaults.ts +224 -0
- package/src/integrations/slack-task-file-upload.ts +323 -0
- package/src/integrations/slack-tool-review.ts +65 -0
- package/src/integrations/social-oauth.ts +90 -58
- package/src/interaction-agent-access.ts +40 -20
- package/src/interaction-agent-version.ts +85 -0
- package/src/interaction-holder-heartbeat.ts +24 -8
- package/src/interaction-metrics.ts +164 -2
- package/src/interaction-route-stages.ts +94 -0
- package/src/interaction-secrets-vault.ts +213 -0
- package/src/interaction-secrets.ts +426 -0
- package/src/mcp/action-catalog-types.ts +14 -0
- package/src/mcp/action-catalog.gen.ts +8014 -0
- package/src/mcp/action-descriptions.ts +299 -0
- package/src/mcp/action-schema-imports.gen.ts +304 -0
- package/src/mcp/capability-account-readiness.ts +17 -0
- package/src/mcp/child-read-evidence.ts +19 -0
- package/src/mcp/company-profile-agent-admin.ts +13 -0
- package/src/mcp/contract-input.ts +165 -0
- package/src/mcp/documents.ts +9 -2
- package/src/mcp/editable-artifacts.ts +29 -11
- package/src/mcp/files.ts +5 -1
- package/src/mcp/first-party-tool-permissions.ts +7 -285
- package/src/mcp/knowledge-entries.ts +108 -34
- package/src/mcp/notification-tools.ts +480 -0
- package/src/mcp/orchestration-failure-diagnostic.ts +43 -0
- package/src/mcp/scheduled-task-input.ts +89 -0
- package/src/mcp/scheduled-task-view.ts +63 -3
- package/src/mcp/secret-tools.ts +185 -0
- package/src/mcp/server.ts +2213 -1116
- package/src/mcp/session-admin-access-tools.ts +163 -0
- package/src/mcp/session-event-errors.ts +123 -0
- package/src/mcp/session-event-view.ts +395 -13
- package/src/mcp/session-view.ts +3 -0
- package/src/mcp/session-wait.ts +67 -7
- package/src/mcp/site-agent-clamp-tools.ts +140 -0
- package/src/mcp/site-data-tools.ts +339 -0
- package/src/mcp/site-publication-tools.ts +201 -0
- package/src/mcp/site-sql-tools.ts +427 -0
- package/src/mcp-oauth.ts +635 -45
- package/src/model-calls/chat-completions.ts +352 -0
- package/src/model-calls/pending-usage-settlements.ts +125 -0
- package/src/model-calls/service.ts +694 -0
- package/src/model-catalog.ts +68 -17
- package/src/native-push-dispatch.ts +457 -0
- package/src/observability.ts +15 -1
- package/src/organization-mcp.ts +485 -0
- package/src/prepared-mcp-actor.ts +154 -0
- package/src/prepared-mcp-permissions.ts +38 -0
- package/src/routes/analytics-consent.ts +123 -0
- package/src/routes/api-integrations.ts +268 -9
- package/src/routes/api-keys.ts +164 -25
- package/src/routes/artifact-catalog.ts +111 -0
- package/src/routes/automations.ts +163 -90
- package/src/routes/billing.ts +535 -59
- package/src/routes/browser-sessions.ts +966 -342
- package/src/routes/canonical-human-identities.ts +61 -0
- package/src/routes/capabilities.ts +112 -5
- package/src/routes/channels.ts +4 -3
- package/src/routes/chat-completions.ts +235 -0
- package/src/routes/claude-core-usage.ts +147 -0
- package/src/routes/claude-subscription-accounts.ts +233 -0
- package/src/routes/claude-subscription-oauth.ts +175 -0
- package/src/routes/client-errors.ts +394 -0
- package/src/routes/codex-core.ts +687 -0
- package/src/routes/codex.ts +1277 -1119
- package/src/routes/company-brain.ts +4 -0
- package/src/routes/computer-sessions.ts +319 -85
- package/src/routes/connect.ts +277 -175
- package/src/routes/connections.ts +690 -363
- package/src/routes/desktop-distribution.ts +217 -0
- package/src/routes/documents.ts +13 -7
- package/src/routes/editable-artifacts.ts +74 -4
- package/src/routes/enrollments.ts +110 -16
- package/src/routes/external-identity-links.ts +13 -12
- package/src/routes/files.ts +41 -16
- package/src/routes/github-browser-fonts.gen.ts +12 -0
- package/src/routes/github-browser-pages.ts +258 -0
- package/src/routes/github.ts +200 -75
- package/src/routes/inbox.ts +353 -0
- package/src/routes/insights-response-cache.ts +83 -0
- package/src/routes/insights-usage.ts +345 -0
- package/src/routes/insights.ts +103 -8
- package/src/routes/install.ts +51 -10
- package/src/routes/integration-facets.ts +70 -28
- package/src/routes/interaction-placement-message.ts +12 -0
- package/src/routes/knowledge.ts +136 -27
- package/src/routes/machines.ts +189 -135
- package/src/routes/managed-auth-session-sets.ts +43 -10
- package/src/routes/managed-onboarding.ts +39 -19
- package/src/routes/managed-sign-in-methods.ts +433 -0
- package/src/routes/memory-slack-publications.ts +3 -2
- package/src/routes/model-account-choice.ts +194 -0
- package/src/routes/model-account-settings.ts +235 -0
- package/src/routes/model-connection-access.ts +210 -48
- package/src/routes/native-app-auth.ts +296 -0
- package/src/routes/organization-integration-policy.ts +116 -0
- package/src/routes/organization-integrations.ts +326 -0
- package/src/routes/organization-mcp-connections.ts +183 -0
- package/src/routes/organization-memberships.ts +205 -19
- package/src/routes/organization-model-defaults.ts +110 -0
- package/src/routes/organization-model-providers.ts +74 -3
- package/src/routes/organization-service-accounts.ts +128 -0
- package/src/routes/organization-sessions.ts +21 -5
- package/src/routes/personal-api-keys.ts +184 -0
- package/src/routes/personal-github-git-broker.ts +2 -2
- package/src/routes/personal-github.ts +9 -4
- package/src/routes/plugins.ts +46 -7
- package/src/routes/pr-review-github.ts +105 -118
- package/src/routes/pr-review.ts +88 -82
- package/src/routes/preference-registry.ts +18 -0
- package/src/routes/rigs.ts +48 -13
- package/src/routes/scheduled-tasks.ts +347 -27
- package/src/routes/session-admin-access.ts +271 -0
- package/src/routes/session-artifact-associations.ts +164 -0
- package/src/routes/session-history-imports.ts +305 -0
- package/src/routes/sessions.ts +1682 -363
- package/src/routes/site-data.ts +340 -0
- package/src/routes/site-publishing.ts +584 -0
- package/src/routes/site-runtime.ts +1944 -0
- package/src/routes/site-sql.ts +263 -0
- package/src/routes/skill-content.ts +72 -7
- package/src/routes/skills.ts +5 -4
- package/src/routes/slack-bot-access.ts +108 -0
- package/src/routes/social.ts +27 -15
- package/src/routes/subscription-account-pools.ts +209 -0
- package/src/routes/subscription-core-http.ts +18 -0
- package/src/routes/subscription-pool-access.ts +180 -0
- package/src/routes/subscription-pool-core.ts +552 -0
- package/src/routes/supergrok.ts +174 -655
- package/src/routes/transcription-recordings.ts +71 -4
- package/src/routes/transcriptions.ts +26 -2
- package/src/routes/usage-allowances.ts +381 -0
- package/src/routes/variable-sets-removed.ts +19 -0
- package/src/routes/vault-providers.ts +782 -0
- package/src/routes/vaults.ts +421 -0
- package/src/routes/video-generation.ts +30 -12
- package/src/routes/workspace-artifacts.ts +165 -53
- package/src/routes/workspace-integrations.ts +576 -0
- package/src/routes/workspace-model-providers.ts +148 -0
- package/src/routes/workspace-state.ts +4 -0
- package/src/routes/workspaces.ts +625 -117
- package/src/sandbox/agent-update.ts +315 -0
- package/src/sandbox/auth-callout.ts +104 -21
- package/src/sandbox/channel-a.ts +165 -55
- package/src/sandbox/enrollment.ts +131 -22
- package/src/sandbox/machine-audience.ts +192 -0
- package/src/sandbox/machines.ts +75 -31
- package/src/sandbox/metrics-ingestion.ts +133 -2
- package/src/sandbox/rematerialize.ts +51 -21
- package/src/sandbox/screen-control.ts +289 -0
- package/src/sandbox/viewer.ts +33 -58
- package/src/sandbox-file-artifacts.ts +53 -27
- package/src/scheduled-task-blockers.ts +293 -0
- package/src/scheduled-task-deletion.ts +13 -3
- package/src/scheduled-task-lifecycle.ts +84 -0
- package/src/secret-answers.ts +119 -0
- package/src/session-create-observability.ts +46 -0
- package/src/session-realtime-context.ts +26 -4
- package/src/signed-state-secret.ts +58 -0
- package/src/site-agent-guard.ts +261 -0
- package/src/site-data/operations.ts +777 -0
- package/src/site-data/service.ts +1043 -0
- package/src/site-frame-guard.ts +107 -0
- package/src/site-publishing/agent-data-tools.ts +250 -0
- package/src/site-publishing/agent-model.ts +127 -0
- package/src/site-publishing/agent-session.ts +148 -0
- package/src/site-publishing/content-scanner.ts +93 -0
- package/src/site-publishing/edge-sync.ts +148 -0
- package/src/site-publishing/gateway-signature.ts +198 -0
- package/src/site-publishing/limits.ts +315 -0
- package/src/site-publishing/page-tool-authority.ts +111 -0
- package/src/site-publishing/platform-usage.ts +479 -0
- package/src/site-publishing/platform.ts +98 -0
- package/src/site-publishing/readiness.ts +330 -0
- package/src/site-publishing/runtime.ts +831 -0
- package/src/site-publishing/service.ts +1282 -0
- package/src/site-publishing/session-events.ts +262 -0
- package/src/site-publishing/session-views.ts +262 -0
- package/src/site-publishing/viewer.ts +75 -0
- package/src/site-session-origin.ts +91 -6
- package/src/site-sql/format.ts +134 -0
- package/src/site-sql/gateway.ts +168 -0
- package/src/site-sql/service.ts +1636 -0
- package/src/site-uploads.ts +27 -5
- package/src/temporal-schedule-sync.ts +74 -0
- package/src/transcription/billing-refusal.ts +14 -0
- package/src/transcription/normalize.ts +77 -0
- package/src/transcription/providers/azure-mai.ts +98 -0
- package/src/transcription/providers/azure-openai.ts +16 -7
- package/src/transcription/providers/codex-subscription.ts +190 -67
- package/src/transcription/providers/openai.ts +79 -5
- package/src/transcription/providers/subscription-core.ts +125 -0
- package/src/transcription/providers/xai-subscription.ts +81 -83
- package/src/transcription/segmenter.ts +7 -1
- package/src/transcription/service.ts +239 -10
- package/src/transcription/wav-duration.ts +39 -0
- package/src/workspace-deletion.ts +25 -1
- package/src/workspace-tool-gateway-attestations.ts +133 -0
- package/src/workspace-tool-gateway-observability.ts +64 -0
- package/src/workspace-tool-gateway-secrets.ts +104 -0
- package/src/workspace-tool-gateway.ts +921 -103
- package/src/workspace-tool-target-fence.ts +380 -0
- package/src/workspace-tool-target.ts +554 -0
- package/src/workspace-webhook-dispatch.ts +225 -0
- package/src/xai-realtime.ts +85 -81
- package/src/xai-subscription-core.ts +172 -0
- package/dist/browser-auth-broker.d.ts +0 -20
- package/dist/chunk-AJ62T5QN.js.map +0 -1
- package/dist/connection-authority-owner.d.ts +0 -59
- package/dist/routes/connection-authorities.d.ts +0 -3
- package/dist/routes/environments.d.ts +0 -5
- package/dist/routes/host-mcp-bindings.d.ts +0 -5
- package/dist/routes/host-mcp-resolvers.d.ts +0 -3
- package/dist/routes/packs.d.ts +0 -3
- package/dist/session-event-view-MU3HMNV3.js +0 -264
- package/dist/session-event-view-MU3HMNV3.js.map +0 -1
- package/dist/xai-subscription-auth.d.ts +0 -23
- package/src/browser-auth-broker.ts +0 -155
- package/src/connection-authority-owner.ts +0 -61
- package/src/routes/connection-authorities.ts +0 -139
- package/src/routes/environments.ts +0 -388
- package/src/routes/host-mcp-bindings.ts +0 -122
- package/src/routes/host-mcp-resolvers.ts +0 -41
- package/src/routes/packs.ts +0 -784
- package/src/xai-subscription-auth.ts +0 -139
|
@@ -0,0 +1,782 @@
|
|
|
1
|
+
import type { Context, Hono } from "hono";
|
|
2
|
+
import { HTTPException } from "hono/http-exception";
|
|
3
|
+
import {
|
|
4
|
+
CreateManagedProviderVaultRequest,
|
|
5
|
+
DisconnectOnePasswordResponse,
|
|
6
|
+
InstallOnePasswordRequest,
|
|
7
|
+
InstallOnePasswordResponse,
|
|
8
|
+
LinkProviderVaultRequest,
|
|
9
|
+
ListOnePasswordConnectionsResponse,
|
|
10
|
+
OnePasswordConnectionSummary,
|
|
11
|
+
ProviderVaultMeta,
|
|
12
|
+
ReplaceOnePasswordTokenRequest,
|
|
13
|
+
VAULT_ERROR_HTTP_STATUS,
|
|
14
|
+
type VaultApiError,
|
|
15
|
+
type VaultSummary,
|
|
16
|
+
} from "@opengeni/contracts";
|
|
17
|
+
import {
|
|
18
|
+
ONEPASSWORD_CREDENTIAL_ROLE,
|
|
19
|
+
ONEPASSWORD_PROVIDER_DOMAIN,
|
|
20
|
+
createWorkspaceVaultProviderRegistry,
|
|
21
|
+
externalActorContinuationForAuthorization,
|
|
22
|
+
hasPermission,
|
|
23
|
+
isVaultError,
|
|
24
|
+
providerSecretName,
|
|
25
|
+
requirePermission,
|
|
26
|
+
syncLinkedProviderVault,
|
|
27
|
+
toVaultSummary,
|
|
28
|
+
vaultErrorFromDatabase,
|
|
29
|
+
isOnePasswordConnection,
|
|
30
|
+
loadOnePasswordConnectionToken,
|
|
31
|
+
onePasswordCredentialBundle,
|
|
32
|
+
onePasswordConnectionMetadata,
|
|
33
|
+
requireAccessGrantAuthorization,
|
|
34
|
+
requireEnvironmentEncryption,
|
|
35
|
+
vaultErrorCodeForProvider,
|
|
36
|
+
type AccessGrantAuthorization,
|
|
37
|
+
type ApiRouteDeps,
|
|
38
|
+
type OnePasswordConnectionMetadata,
|
|
39
|
+
type OnePasswordVaultProviderFactory,
|
|
40
|
+
} from "@opengeni/core";
|
|
41
|
+
import {
|
|
42
|
+
createConnection,
|
|
43
|
+
deleteVault,
|
|
44
|
+
encryptEnvironmentValue,
|
|
45
|
+
getConnectionMetadata,
|
|
46
|
+
getVault,
|
|
47
|
+
linkProviderVault,
|
|
48
|
+
listConnectionsMetadata,
|
|
49
|
+
listVaultsForSubject,
|
|
50
|
+
revokeConnection,
|
|
51
|
+
updateConnection,
|
|
52
|
+
type VaultDbContext,
|
|
53
|
+
type VaultRow,
|
|
54
|
+
} from "@opengeni/db";
|
|
55
|
+
import {
|
|
56
|
+
isVaultProviderError,
|
|
57
|
+
VaultProviderError,
|
|
58
|
+
type ProviderVault,
|
|
59
|
+
type VaultProvider,
|
|
60
|
+
type VaultProviderContext,
|
|
61
|
+
type VaultProviderRegistry,
|
|
62
|
+
} from "@opengeni/vaults";
|
|
63
|
+
import { isPersonalConnectionOwnerPrincipal } from "../connection-ownership";
|
|
64
|
+
import { parseRequestJson } from "../http/request-body";
|
|
65
|
+
import { requireConnectOwnerAuthority } from "../integrations/connect-authority";
|
|
66
|
+
import {
|
|
67
|
+
loadOnePasswordModule,
|
|
68
|
+
loadOnePasswordVaultProvider,
|
|
69
|
+
} from "../integrations/onepassword-vault-provider";
|
|
70
|
+
|
|
71
|
+
/** Human-initiated provider calls (install, list, link, sync) are not attempt-budgeted. */
|
|
72
|
+
function routeProviderContext(connectionId: string | null): VaultProviderContext {
|
|
73
|
+
return { connectionId, budget: { take() {} } };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function providerErrorResponse(c: Context, error: unknown, write = false) {
|
|
77
|
+
if (!isVaultProviderError(error)) throw error;
|
|
78
|
+
const code = vaultErrorCodeForProvider(error.code, write ? "write" : "vault");
|
|
79
|
+
const status = VAULT_ERROR_HTTP_STATUS[code] ?? 503;
|
|
80
|
+
if (error.retryAfterMs) c.header("retry-after", String(Math.ceil(error.retryAfterMs / 1000)));
|
|
81
|
+
return c.json(
|
|
82
|
+
{
|
|
83
|
+
error: code,
|
|
84
|
+
message: error.message,
|
|
85
|
+
...(error.retryAfterMs
|
|
86
|
+
? { details: { retryAt: new Date(Date.now() + error.retryAfterMs).toISOString() } }
|
|
87
|
+
: {}),
|
|
88
|
+
},
|
|
89
|
+
status as 401,
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function onePasswordFactoryFor(deps: ApiRouteDeps): OnePasswordVaultProviderFactory {
|
|
94
|
+
if (deps.onePasswordVaultProvider === null) {
|
|
95
|
+
return async () => {
|
|
96
|
+
throw new HTTPException(404, { message: "1Password is not available in this deployment" });
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
return deps.onePasswordVaultProvider ?? loadOnePasswordVaultProvider;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* The 1Password provider for a stored connection the caller can see, plus its
|
|
104
|
+
* metadata. Throws 404 for other connections.
|
|
105
|
+
*/
|
|
106
|
+
export async function onePasswordProviderForConnection(
|
|
107
|
+
deps: ApiRouteDeps,
|
|
108
|
+
input: { workspaceId: string; connectionId: string; subjectId: string | null },
|
|
109
|
+
): Promise<{ provider: VaultProvider; metadata: OnePasswordConnectionMetadata }> {
|
|
110
|
+
const connection = await getConnectionMetadata(
|
|
111
|
+
deps.db,
|
|
112
|
+
input.workspaceId,
|
|
113
|
+
input.connectionId,
|
|
114
|
+
input.subjectId,
|
|
115
|
+
);
|
|
116
|
+
if (!connection || !isOnePasswordConnection(connection)) {
|
|
117
|
+
throw new HTTPException(404, { message: "1Password connection not found" });
|
|
118
|
+
}
|
|
119
|
+
const { token, metadata } = await loadOnePasswordConnectionToken(deps.db, deps.settings, input);
|
|
120
|
+
const provider = await onePasswordFactoryFor(deps)({
|
|
121
|
+
token,
|
|
122
|
+
planTier: metadata.planTier,
|
|
123
|
+
allowFakeTokens: deps.settings.onePasswordFakeTokens,
|
|
124
|
+
});
|
|
125
|
+
return { provider, metadata };
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* The provider registry for one request: 1Password vaults load their
|
|
130
|
+
* connection token for the acting subject in this workspace; host vaults use
|
|
131
|
+
* the embedder's `connectionCredentials.vaultProvider`.
|
|
132
|
+
*/
|
|
133
|
+
export function vaultProviderRegistryFor(
|
|
134
|
+
deps: ApiRouteDeps,
|
|
135
|
+
input: { workspaceId: string; subjectId: string | null },
|
|
136
|
+
): VaultProviderRegistry {
|
|
137
|
+
return createWorkspaceVaultProviderRegistry({
|
|
138
|
+
db: deps.db,
|
|
139
|
+
settings: deps.settings,
|
|
140
|
+
workspaceId: input.workspaceId,
|
|
141
|
+
subjectId: input.subjectId,
|
|
142
|
+
hostVaultProvider: deps.connectionCredentials?.vaultProvider ?? null,
|
|
143
|
+
onePasswordVaultProvider:
|
|
144
|
+
deps.onePasswordVaultProvider === null ? null : onePasswordFactoryFor(deps),
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function vaultContextFor(
|
|
149
|
+
authorization: AccessGrantAuthorization,
|
|
150
|
+
workspaceId: string,
|
|
151
|
+
): VaultDbContext {
|
|
152
|
+
return {
|
|
153
|
+
kind: "subject",
|
|
154
|
+
accountId: authorization.grant.accountId,
|
|
155
|
+
workspaceId,
|
|
156
|
+
subjectId: authorization.grant.subjectId,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function isAccountAdmin(authorization: AccessGrantAuthorization): boolean {
|
|
161
|
+
return authorization.accountGrant?.permissions.includes("account:admin") === true;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
type OnePasswordConnectionRow = NonNullable<Awaited<ReturnType<typeof getConnectionMetadata>>>;
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Whether the caller may link vaults through a 1Password connection, replace
|
|
168
|
+
* its token or disconnect it: the same authority that could have installed it.
|
|
169
|
+
*/
|
|
170
|
+
function canManageOnePasswordConnection(
|
|
171
|
+
authorization: AccessGrantAuthorization,
|
|
172
|
+
connection: OnePasswordConnectionRow,
|
|
173
|
+
metadata: OnePasswordConnectionMetadata,
|
|
174
|
+
): boolean {
|
|
175
|
+
const { grant } = authorization;
|
|
176
|
+
if (!hasPermission(grant.permissions, "connections:write", grant.permissionMode)) return false;
|
|
177
|
+
if (!hasPermission(grant.permissions, "secrets:write", grant.permissionMode)) return false;
|
|
178
|
+
if (connection.subjectId !== null) return connection.subjectId === grant.subjectId;
|
|
179
|
+
if (metadata.ownership === "organization") return isAccountAdmin(authorization);
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function onePasswordConnectionSummary(
|
|
184
|
+
authorization: AccessGrantAuthorization,
|
|
185
|
+
connection: OnePasswordConnectionRow,
|
|
186
|
+
): OnePasswordConnectionSummary {
|
|
187
|
+
const metadata = onePasswordConnectionMetadata(connection.metadata)!;
|
|
188
|
+
return OnePasswordConnectionSummary.parse({
|
|
189
|
+
id: connection.id,
|
|
190
|
+
ownership: connection.subjectId !== null ? "user" : metadata.ownership,
|
|
191
|
+
accountName: metadata.accountName,
|
|
192
|
+
label: metadata.label,
|
|
193
|
+
planTier: metadata.planTier,
|
|
194
|
+
verifiedAt: metadata.verifiedAt || connection.createdAt,
|
|
195
|
+
createdAt: connection.createdAt,
|
|
196
|
+
createdBySubjectId: connection.createdBySubjectId,
|
|
197
|
+
canManage: canManageOnePasswordConnection(authorization, connection, metadata),
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/** A live (not revoked) 1Password connection the caller can see, or 404. */
|
|
202
|
+
async function requireOnePasswordConnection(
|
|
203
|
+
deps: ApiRouteDeps,
|
|
204
|
+
authorization: AccessGrantAuthorization,
|
|
205
|
+
workspaceId: string,
|
|
206
|
+
connectionId: string,
|
|
207
|
+
): Promise<{ connection: OnePasswordConnectionRow; metadata: OnePasswordConnectionMetadata }> {
|
|
208
|
+
const connection = await getConnectionMetadata(
|
|
209
|
+
deps.db,
|
|
210
|
+
workspaceId,
|
|
211
|
+
connectionId,
|
|
212
|
+
authorization.grant.subjectId,
|
|
213
|
+
);
|
|
214
|
+
if (!connection || !isOnePasswordConnection(connection) || connection.status === "revoked") {
|
|
215
|
+
throw new HTTPException(404, { message: "1Password connection not found" });
|
|
216
|
+
}
|
|
217
|
+
return { connection, metadata: onePasswordConnectionMetadata(connection.metadata)! };
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function requireManageOnePasswordConnection(
|
|
221
|
+
authorization: AccessGrantAuthorization,
|
|
222
|
+
connection: OnePasswordConnectionRow,
|
|
223
|
+
metadata: OnePasswordConnectionMetadata,
|
|
224
|
+
): void {
|
|
225
|
+
if (!canManageOnePasswordConnection(authorization, connection, metadata)) {
|
|
226
|
+
throw new HTTPException(403, {
|
|
227
|
+
message:
|
|
228
|
+
metadata.ownership === "organization"
|
|
229
|
+
? "Only an organization admin can change this 1Password connection"
|
|
230
|
+
: "You can't change this 1Password connection",
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
async function vaultSummaryFor(
|
|
236
|
+
deps: ApiRouteDeps,
|
|
237
|
+
authorization: AccessGrantAuthorization,
|
|
238
|
+
workspaceId: string,
|
|
239
|
+
vaultId: string,
|
|
240
|
+
): Promise<VaultSummary> {
|
|
241
|
+
const row = await getVault(deps.db, vaultContextFor(authorization, workspaceId), { vaultId });
|
|
242
|
+
return toVaultSummary(row, { write: true, accountAdmin: isAccountAdmin(authorization) });
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/** Vault and provider errors as `{ error, message, details? }`; anything else rethrows. */
|
|
246
|
+
function vaultRouteError(c: Context, error: unknown, write = false) {
|
|
247
|
+
if (isVaultProviderError(error)) return providerErrorResponse(c, error, write);
|
|
248
|
+
const vaultError = isVaultError(error) ? error : vaultErrorFromDatabase(error);
|
|
249
|
+
if (!vaultError) throw error;
|
|
250
|
+
const body: VaultApiError = {
|
|
251
|
+
error: vaultError.code,
|
|
252
|
+
message: vaultError.message,
|
|
253
|
+
...(vaultError.details ? { details: vaultError.details } : {}),
|
|
254
|
+
};
|
|
255
|
+
return c.json(body, VAULT_ERROR_HTTP_STATUS[vaultError.code] as 401);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function findProviderVault(vaults: ProviderVault[], externalVaultId: string): ProviderVault {
|
|
259
|
+
const found = vaults.find((vault) => vault.externalVaultId === externalVaultId);
|
|
260
|
+
if (!found) {
|
|
261
|
+
throw new VaultProviderError(
|
|
262
|
+
"provider_not_found",
|
|
263
|
+
"that vault does not exist or is not shared with this connection",
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
return found;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export type LinkedVaultLookup = (input: {
|
|
270
|
+
workspaceId: string;
|
|
271
|
+
connectionId: string;
|
|
272
|
+
context: VaultDbContext;
|
|
273
|
+
}) => Promise<ReadonlyMap<string, string>>;
|
|
274
|
+
|
|
275
|
+
export function registerVaultProviderRoutes(
|
|
276
|
+
app: Hono,
|
|
277
|
+
deps: ApiRouteDeps,
|
|
278
|
+
options: { linkedVaults?: LinkedVaultLookup } = {},
|
|
279
|
+
): void {
|
|
280
|
+
const { db, settings } = deps;
|
|
281
|
+
const linkedVaults: LinkedVaultLookup =
|
|
282
|
+
options.linkedVaults ??
|
|
283
|
+
(async ({ workspaceId, connectionId, context }) => {
|
|
284
|
+
const rows = await listVaultsForSubject(db, context, { workspaceId });
|
|
285
|
+
return new Map(
|
|
286
|
+
rows
|
|
287
|
+
.filter(
|
|
288
|
+
(row) =>
|
|
289
|
+
row.source === "onepassword" &&
|
|
290
|
+
row.providerConnectionId === connectionId &&
|
|
291
|
+
row.providerVaultRef,
|
|
292
|
+
)
|
|
293
|
+
.map((row) => [row.providerVaultRef!, row.id]),
|
|
294
|
+
);
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
// Verified paste-a-token install (§10.9): an offline token check, then one
|
|
298
|
+
// `vaults.list` call, then the token enters the encrypted connection store.
|
|
299
|
+
// The response lists the reachable vaults; it never echoes the token.
|
|
300
|
+
app.post("/v1/workspaces/:workspaceId/connections/1password/install", async (c) => {
|
|
301
|
+
const workspaceId = c.req.param("workspaceId");
|
|
302
|
+
const authorization = await requireAccessGrantAuthorization(
|
|
303
|
+
c,
|
|
304
|
+
deps,
|
|
305
|
+
workspaceId,
|
|
306
|
+
"connections:write",
|
|
307
|
+
);
|
|
308
|
+
const grant = authorization.grant;
|
|
309
|
+
const payload = await parseRequestJson(c, InstallOnePasswordRequest);
|
|
310
|
+
if (
|
|
311
|
+
payload.ownership === "organization" &&
|
|
312
|
+
authorization.accountGrant?.permissions.includes("account:admin") !== true
|
|
313
|
+
) {
|
|
314
|
+
throw new HTTPException(403, { message: "missing permission: account:admin" });
|
|
315
|
+
}
|
|
316
|
+
if (payload.ownership === "user" && !isPersonalConnectionOwnerPrincipal(authorization)) {
|
|
317
|
+
throw new HTTPException(403, {
|
|
318
|
+
message: "Only a signed-in person can connect a personal 1Password account",
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
const key = requireEnvironmentEncryption(settings);
|
|
322
|
+
const token = payload.token.trim();
|
|
323
|
+
let accountName: string | null;
|
|
324
|
+
let vaults;
|
|
325
|
+
try {
|
|
326
|
+
const onePassword = await loadOnePasswordModule();
|
|
327
|
+
accountName = onePassword.describeOnePasswordToken(token, {
|
|
328
|
+
allowFakeTokens: settings.onePasswordFakeTokens,
|
|
329
|
+
}).accountName;
|
|
330
|
+
const provider = await onePasswordFactoryFor(deps)({
|
|
331
|
+
token,
|
|
332
|
+
planTier: payload.planTier,
|
|
333
|
+
allowFakeTokens: settings.onePasswordFakeTokens,
|
|
334
|
+
});
|
|
335
|
+
vaults = await provider.listVaults(routeProviderContext(null));
|
|
336
|
+
} catch (error) {
|
|
337
|
+
return providerErrorResponse(c, error);
|
|
338
|
+
}
|
|
339
|
+
const metadata: OnePasswordConnectionMetadata = {
|
|
340
|
+
credentialRole: ONEPASSWORD_CREDENTIAL_ROLE,
|
|
341
|
+
planTier: payload.planTier,
|
|
342
|
+
ownership: payload.ownership,
|
|
343
|
+
accountName,
|
|
344
|
+
label: payload.label ?? null,
|
|
345
|
+
verifiedAt: new Date().toISOString(),
|
|
346
|
+
};
|
|
347
|
+
const credentialEncrypted = encryptEnvironmentValue(
|
|
348
|
+
key,
|
|
349
|
+
JSON.stringify(onePasswordCredentialBundle(token)),
|
|
350
|
+
);
|
|
351
|
+
const continuation = externalActorContinuationForAuthorization(authorization);
|
|
352
|
+
const connection = await db.transaction(async (tx) => {
|
|
353
|
+
await requireConnectOwnerAuthority(tx, {
|
|
354
|
+
accountId: grant.accountId,
|
|
355
|
+
workspaceId,
|
|
356
|
+
subjectId: grant.subjectId,
|
|
357
|
+
personalOwnerVerified: isPersonalConnectionOwnerPrincipal(authorization),
|
|
358
|
+
...(continuation ? { externalContinuation: continuation } : {}),
|
|
359
|
+
});
|
|
360
|
+
return await createConnection(tx, {
|
|
361
|
+
accountId: grant.accountId,
|
|
362
|
+
workspaceId,
|
|
363
|
+
subjectId: payload.ownership === "user" ? grant.subjectId : null,
|
|
364
|
+
providerDomain: ONEPASSWORD_PROVIDER_DOMAIN,
|
|
365
|
+
kind: "api_key",
|
|
366
|
+
credentialEncrypted,
|
|
367
|
+
grantedScopes: [],
|
|
368
|
+
expiresAt: null,
|
|
369
|
+
metadata,
|
|
370
|
+
createdBySubjectId: grant.subjectId,
|
|
371
|
+
});
|
|
372
|
+
});
|
|
373
|
+
return c.json(
|
|
374
|
+
InstallOnePasswordResponse.parse({
|
|
375
|
+
connectionId: connection.id,
|
|
376
|
+
accountName,
|
|
377
|
+
vaults: vaults.map((vault) => ({
|
|
378
|
+
externalVaultId: vault.externalVaultId,
|
|
379
|
+
name: vault.name,
|
|
380
|
+
itemCount: vault.itemCount,
|
|
381
|
+
linkedVaultId: null,
|
|
382
|
+
})),
|
|
383
|
+
}),
|
|
384
|
+
201,
|
|
385
|
+
);
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
// The vaults a stored 1Password connection reaches, with the Opengeni vault
|
|
389
|
+
// each one is linked to (if any). One `vaults.list` request.
|
|
390
|
+
app.get("/v1/workspaces/:workspaceId/connections/:connectionId/provider-vaults", async (c) => {
|
|
391
|
+
const workspaceId = c.req.param("workspaceId");
|
|
392
|
+
const connectionId = c.req.param("connectionId");
|
|
393
|
+
const authorization = await requireAccessGrantAuthorization(
|
|
394
|
+
c,
|
|
395
|
+
deps,
|
|
396
|
+
workspaceId,
|
|
397
|
+
"secrets:list",
|
|
398
|
+
);
|
|
399
|
+
const { grant } = authorization;
|
|
400
|
+
try {
|
|
401
|
+
const { provider } = await onePasswordProviderForConnection(deps, {
|
|
402
|
+
workspaceId,
|
|
403
|
+
connectionId,
|
|
404
|
+
subjectId: grant.subjectId,
|
|
405
|
+
});
|
|
406
|
+
const [vaults, linked] = await Promise.all([
|
|
407
|
+
provider.listVaults(routeProviderContext(connectionId)),
|
|
408
|
+
linkedVaults({
|
|
409
|
+
workspaceId,
|
|
410
|
+
connectionId,
|
|
411
|
+
context: vaultContextFor(authorization, workspaceId),
|
|
412
|
+
}),
|
|
413
|
+
]);
|
|
414
|
+
return c.json({
|
|
415
|
+
vaults: vaults.map((vault) =>
|
|
416
|
+
ProviderVaultMeta.parse({
|
|
417
|
+
externalVaultId: vault.externalVaultId,
|
|
418
|
+
name: vault.name,
|
|
419
|
+
itemCount: vault.itemCount,
|
|
420
|
+
linkedVaultId: linked.get(vault.externalVaultId) ?? null,
|
|
421
|
+
}),
|
|
422
|
+
),
|
|
423
|
+
});
|
|
424
|
+
} catch (error) {
|
|
425
|
+
return vaultRouteError(c, error);
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Link a provider vault as an Opengeni vault, then mirror its metadata.
|
|
431
|
+
* The link stands even if the first sync fails; its status says why.
|
|
432
|
+
*/
|
|
433
|
+
app.post("/v1/workspaces/:workspaceId/vaults/link", async (c) => {
|
|
434
|
+
const workspaceId = c.req.param("workspaceId");
|
|
435
|
+
const authorization = await requireAccessGrantAuthorization(c, deps, workspaceId);
|
|
436
|
+
requirePermission(authorization.grant, "secrets:write");
|
|
437
|
+
const payload = await parseRequestJson(c, LinkProviderVaultRequest);
|
|
438
|
+
if (payload.ownerKind === "organization" && !isAccountAdmin(authorization)) {
|
|
439
|
+
throw new HTTPException(403, { message: "missing permission: account:admin" });
|
|
440
|
+
}
|
|
441
|
+
const context = vaultContextFor(authorization, workspaceId);
|
|
442
|
+
try {
|
|
443
|
+
let provider: VaultProvider;
|
|
444
|
+
if (payload.provider === "onepassword") {
|
|
445
|
+
if (!payload.connectionId) {
|
|
446
|
+
throw new HTTPException(422, { message: "connectionId is required for 1Password" });
|
|
447
|
+
}
|
|
448
|
+
({ provider } = await onePasswordProviderForConnection(deps, {
|
|
449
|
+
workspaceId,
|
|
450
|
+
connectionId: payload.connectionId,
|
|
451
|
+
subjectId: authorization.grant.subjectId,
|
|
452
|
+
}));
|
|
453
|
+
} else {
|
|
454
|
+
const host = deps.connectionCredentials?.vaultProvider;
|
|
455
|
+
if (!host) {
|
|
456
|
+
throw new VaultProviderError(
|
|
457
|
+
"provider_unavailable",
|
|
458
|
+
"this deployment has no host vault provider",
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
provider = host;
|
|
462
|
+
}
|
|
463
|
+
const connectionId = payload.provider === "onepassword" ? payload.connectionId! : null;
|
|
464
|
+
const providerVault = findProviderVault(
|
|
465
|
+
await provider.listVaults(routeProviderContext(connectionId)),
|
|
466
|
+
payload.externalVaultId,
|
|
467
|
+
);
|
|
468
|
+
const row = await linkProviderVault(db, context, {
|
|
469
|
+
ownerKind: payload.ownerKind,
|
|
470
|
+
name: payload.name ?? providerSecretName(providerVault.name, "1Password vault"),
|
|
471
|
+
source: payload.provider,
|
|
472
|
+
providerConnectionId: connectionId,
|
|
473
|
+
providerVaultRef: providerVault.externalVaultId,
|
|
474
|
+
mode: payload.mode,
|
|
475
|
+
...(payload.availability ? { availability: payload.availability } : {}),
|
|
476
|
+
allowOrganization: isAccountAdmin(authorization),
|
|
477
|
+
});
|
|
478
|
+
await syncLinkedProviderVault({
|
|
479
|
+
db,
|
|
480
|
+
context,
|
|
481
|
+
vaultId: row.id,
|
|
482
|
+
providers: vaultProviderRegistryFor(deps, {
|
|
483
|
+
workspaceId,
|
|
484
|
+
subjectId: authorization.grant.subjectId,
|
|
485
|
+
}),
|
|
486
|
+
force: true,
|
|
487
|
+
});
|
|
488
|
+
return c.json(await vaultSummaryFor(deps, authorization, workspaceId, row.id), 201);
|
|
489
|
+
} catch (error) {
|
|
490
|
+
return vaultRouteError(c, error);
|
|
491
|
+
}
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Refresh a linked vault's metadata mirror. Cheap when nothing changed (one
|
|
496
|
+
* `vaults.list`); skipped while the provider's rate limit is in force.
|
|
497
|
+
*/
|
|
498
|
+
app.post("/v1/workspaces/:workspaceId/vaults/:vaultId/sync", async (c) => {
|
|
499
|
+
const workspaceId = c.req.param("workspaceId");
|
|
500
|
+
const vaultId = c.req.param("vaultId");
|
|
501
|
+
const authorization = await requireAccessGrantAuthorization(c, deps, workspaceId);
|
|
502
|
+
requirePermission(authorization.grant, "secrets:write");
|
|
503
|
+
try {
|
|
504
|
+
const result = await syncLinkedProviderVault({
|
|
505
|
+
db,
|
|
506
|
+
context: vaultContextFor(authorization, workspaceId),
|
|
507
|
+
vaultId,
|
|
508
|
+
providers: vaultProviderRegistryFor(deps, {
|
|
509
|
+
workspaceId,
|
|
510
|
+
subjectId: authorization.grant.subjectId,
|
|
511
|
+
}),
|
|
512
|
+
});
|
|
513
|
+
const rateLimitedUntil =
|
|
514
|
+
result.status === "skipped_rate_limited" ||
|
|
515
|
+
(result.status === "failed" && result.rateLimitedUntil)
|
|
516
|
+
? result.rateLimitedUntil
|
|
517
|
+
: null;
|
|
518
|
+
if (rateLimitedUntil) {
|
|
519
|
+
c.header(
|
|
520
|
+
"retry-after",
|
|
521
|
+
String(Math.max(1, Math.ceil((rateLimitedUntil.getTime() - Date.now()) / 1000))),
|
|
522
|
+
);
|
|
523
|
+
}
|
|
524
|
+
return c.json(await vaultSummaryFor(deps, authorization, workspaceId, vaultId));
|
|
525
|
+
} catch (error) {
|
|
526
|
+
return vaultRouteError(c, error);
|
|
527
|
+
}
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* Create a new vault in the connected 1Password account (admins keep
|
|
532
|
+
* access; an optional group grant on TEAMS/BUSINESS) and link it read-write.
|
|
533
|
+
*/
|
|
534
|
+
app.post("/v1/workspaces/:workspaceId/connections/:connectionId/managed-vaults", async (c) => {
|
|
535
|
+
const workspaceId = c.req.param("workspaceId");
|
|
536
|
+
const connectionId = c.req.param("connectionId");
|
|
537
|
+
const authorization = await requireAccessGrantAuthorization(c, deps, workspaceId);
|
|
538
|
+
requirePermission(authorization.grant, "secrets:write");
|
|
539
|
+
const payload = await parseRequestJson(c, CreateManagedProviderVaultRequest);
|
|
540
|
+
if (payload.ownerKind === "organization" && !isAccountAdmin(authorization)) {
|
|
541
|
+
throw new HTTPException(403, { message: "missing permission: account:admin" });
|
|
542
|
+
}
|
|
543
|
+
const context = vaultContextFor(authorization, workspaceId);
|
|
544
|
+
try {
|
|
545
|
+
const { provider } = await onePasswordProviderForConnection(deps, {
|
|
546
|
+
workspaceId,
|
|
547
|
+
connectionId,
|
|
548
|
+
subjectId: authorization.grant.subjectId,
|
|
549
|
+
});
|
|
550
|
+
if (!provider.createVault || !provider.capabilities().createVault) {
|
|
551
|
+
throw new VaultProviderError(
|
|
552
|
+
"provider_unavailable",
|
|
553
|
+
"this 1Password connection cannot create vaults",
|
|
554
|
+
);
|
|
555
|
+
}
|
|
556
|
+
const created = await provider.createVault(routeProviderContext(connectionId), {
|
|
557
|
+
name: payload.name,
|
|
558
|
+
description: "Managed by Opengeni",
|
|
559
|
+
allowAdminsAccess: true,
|
|
560
|
+
...(payload.groupId ? { groupId: payload.groupId } : {}),
|
|
561
|
+
});
|
|
562
|
+
const row = await linkProviderVault(db, context, {
|
|
563
|
+
ownerKind: payload.ownerKind,
|
|
564
|
+
name: payload.name,
|
|
565
|
+
source: "onepassword",
|
|
566
|
+
providerConnectionId: connectionId,
|
|
567
|
+
providerVaultRef: created.externalVaultId,
|
|
568
|
+
mode: "read_write",
|
|
569
|
+
allowOrganization: isAccountAdmin(authorization),
|
|
570
|
+
});
|
|
571
|
+
await syncLinkedProviderVault({
|
|
572
|
+
db,
|
|
573
|
+
context,
|
|
574
|
+
vaultId: row.id,
|
|
575
|
+
providers: vaultProviderRegistryFor(deps, {
|
|
576
|
+
workspaceId,
|
|
577
|
+
subjectId: authorization.grant.subjectId,
|
|
578
|
+
}),
|
|
579
|
+
force: true,
|
|
580
|
+
});
|
|
581
|
+
return c.json(await vaultSummaryFor(deps, authorization, workspaceId, row.id), 201);
|
|
582
|
+
} catch (error) {
|
|
583
|
+
return vaultRouteError(c, error, true);
|
|
584
|
+
}
|
|
585
|
+
});
|
|
586
|
+
|
|
587
|
+
/** The 1Password connections the caller can see, without their tokens. */
|
|
588
|
+
app.get("/v1/workspaces/:workspaceId/connections/1password/service-accounts", async (c) => {
|
|
589
|
+
const workspaceId = c.req.param("workspaceId");
|
|
590
|
+
const authorization = await requireAccessGrantAuthorization(
|
|
591
|
+
c,
|
|
592
|
+
deps,
|
|
593
|
+
workspaceId,
|
|
594
|
+
"secrets:list",
|
|
595
|
+
);
|
|
596
|
+
const rows = await listConnectionsMetadata(db, workspaceId, authorization.grant.subjectId);
|
|
597
|
+
return c.json(
|
|
598
|
+
ListOnePasswordConnectionsResponse.parse({
|
|
599
|
+
connections: rows
|
|
600
|
+
.filter((row) => isOnePasswordConnection(row) && row.status !== "revoked")
|
|
601
|
+
.map((row) => onePasswordConnectionSummary(authorization, row)),
|
|
602
|
+
}),
|
|
603
|
+
);
|
|
604
|
+
});
|
|
605
|
+
|
|
606
|
+
// A new token for an existing connection (rotation, or after it expired).
|
|
607
|
+
// Checked like an install, then stored on the same connection, so every
|
|
608
|
+
// vault linked through it keeps its links and syncs again.
|
|
609
|
+
app.put("/v1/workspaces/:workspaceId/connections/:connectionId/1password/token", async (c) => {
|
|
610
|
+
const workspaceId = c.req.param("workspaceId");
|
|
611
|
+
const connectionId = c.req.param("connectionId");
|
|
612
|
+
const authorization = await requireAccessGrantAuthorization(
|
|
613
|
+
c,
|
|
614
|
+
deps,
|
|
615
|
+
workspaceId,
|
|
616
|
+
"connections:write",
|
|
617
|
+
);
|
|
618
|
+
const grant = authorization.grant;
|
|
619
|
+
const { connection, metadata } = await requireOnePasswordConnection(
|
|
620
|
+
deps,
|
|
621
|
+
authorization,
|
|
622
|
+
workspaceId,
|
|
623
|
+
connectionId,
|
|
624
|
+
);
|
|
625
|
+
requireManageOnePasswordConnection(authorization, connection, metadata);
|
|
626
|
+
if (connection.subjectId !== null && !isPersonalConnectionOwnerPrincipal(authorization)) {
|
|
627
|
+
throw new HTTPException(403, {
|
|
628
|
+
message: "Only a signed-in person can change a personal 1Password connection",
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
const payload = await parseRequestJson(c, ReplaceOnePasswordTokenRequest);
|
|
632
|
+
const key = requireEnvironmentEncryption(settings);
|
|
633
|
+
const token = payload.token.trim();
|
|
634
|
+
const planTier = payload.planTier ?? metadata.planTier;
|
|
635
|
+
let accountName: string | null;
|
|
636
|
+
let vaults;
|
|
637
|
+
try {
|
|
638
|
+
const onePassword = await loadOnePasswordModule();
|
|
639
|
+
accountName = onePassword.describeOnePasswordToken(token, {
|
|
640
|
+
allowFakeTokens: settings.onePasswordFakeTokens,
|
|
641
|
+
}).accountName;
|
|
642
|
+
if (metadata.accountName && accountName && accountName !== metadata.accountName) {
|
|
643
|
+
return c.json(
|
|
644
|
+
{
|
|
645
|
+
error: "provider_conflict",
|
|
646
|
+
message: `This token is for ${accountName}, not ${metadata.accountName}. Connect it as another 1Password account instead.`,
|
|
647
|
+
},
|
|
648
|
+
409,
|
|
649
|
+
);
|
|
650
|
+
}
|
|
651
|
+
const provider = await onePasswordFactoryFor(deps)({
|
|
652
|
+
token,
|
|
653
|
+
planTier,
|
|
654
|
+
allowFakeTokens: settings.onePasswordFakeTokens,
|
|
655
|
+
});
|
|
656
|
+
vaults = await provider.listVaults(routeProviderContext(connectionId));
|
|
657
|
+
} catch (error) {
|
|
658
|
+
return providerErrorResponse(c, error);
|
|
659
|
+
}
|
|
660
|
+
const nextMetadata: OnePasswordConnectionMetadata = {
|
|
661
|
+
...metadata,
|
|
662
|
+
planTier,
|
|
663
|
+
accountName: accountName ?? metadata.accountName,
|
|
664
|
+
verifiedAt: new Date().toISOString(),
|
|
665
|
+
};
|
|
666
|
+
const credentialEncrypted = encryptEnvironmentValue(
|
|
667
|
+
key,
|
|
668
|
+
JSON.stringify(onePasswordCredentialBundle(token)),
|
|
669
|
+
);
|
|
670
|
+
const continuation = externalActorContinuationForAuthorization(authorization);
|
|
671
|
+
const updated = await db.transaction(async (tx) => {
|
|
672
|
+
await requireConnectOwnerAuthority(tx, {
|
|
673
|
+
accountId: grant.accountId,
|
|
674
|
+
workspaceId,
|
|
675
|
+
subjectId: grant.subjectId,
|
|
676
|
+
personalOwnerVerified: isPersonalConnectionOwnerPrincipal(authorization),
|
|
677
|
+
...(continuation ? { externalContinuation: continuation } : {}),
|
|
678
|
+
});
|
|
679
|
+
return await updateConnection(tx, {
|
|
680
|
+
workspaceId,
|
|
681
|
+
connectionId,
|
|
682
|
+
visibleToSubjectId: grant.subjectId,
|
|
683
|
+
expectedVersion: connection.version,
|
|
684
|
+
status: "active",
|
|
685
|
+
credentialEncrypted,
|
|
686
|
+
metadata: { ...connection.metadata, ...nextMetadata },
|
|
687
|
+
updatedBySubjectId: grant.subjectId,
|
|
688
|
+
});
|
|
689
|
+
});
|
|
690
|
+
if (!updated) {
|
|
691
|
+
throw new HTTPException(409, {
|
|
692
|
+
message: "This 1Password connection changed while you were editing it. Try again.",
|
|
693
|
+
});
|
|
694
|
+
}
|
|
695
|
+
// Linked vaults sync with the new token now; each records its own outcome.
|
|
696
|
+
const context = vaultContextFor(authorization, workspaceId);
|
|
697
|
+
const linked = await linkedVaultRows(context, workspaceId, connectionId);
|
|
698
|
+
const providers = vaultProviderRegistryFor(deps, { workspaceId, subjectId: grant.subjectId });
|
|
699
|
+
for (const row of linked) {
|
|
700
|
+
await syncLinkedProviderVault({ db, context, vaultId: row.id, providers, force: true }).catch(
|
|
701
|
+
() => undefined,
|
|
702
|
+
);
|
|
703
|
+
}
|
|
704
|
+
const linkedByRef = new Map(linked.map((row) => [row.providerVaultRef, row.id]));
|
|
705
|
+
return c.json(
|
|
706
|
+
InstallOnePasswordResponse.parse({
|
|
707
|
+
connectionId,
|
|
708
|
+
accountName: nextMetadata.accountName,
|
|
709
|
+
vaults: vaults.map((vault) => ({
|
|
710
|
+
externalVaultId: vault.externalVaultId,
|
|
711
|
+
name: vault.name,
|
|
712
|
+
itemCount: vault.itemCount,
|
|
713
|
+
linkedVaultId: linkedByRef.get(vault.externalVaultId) ?? null,
|
|
714
|
+
})),
|
|
715
|
+
}),
|
|
716
|
+
);
|
|
717
|
+
});
|
|
718
|
+
|
|
719
|
+
// Disconnect: unlink every vault linked through the connection (nothing is
|
|
720
|
+
// deleted in 1Password), then revoke the stored token. Vault removal runs
|
|
721
|
+
// first, so a refusal leaves the connection intact and the request can be
|
|
722
|
+
// retried.
|
|
723
|
+
app.delete("/v1/workspaces/:workspaceId/connections/:connectionId/1password", async (c) => {
|
|
724
|
+
const workspaceId = c.req.param("workspaceId");
|
|
725
|
+
const connectionId = c.req.param("connectionId");
|
|
726
|
+
const authorization = await requireAccessGrantAuthorization(
|
|
727
|
+
c,
|
|
728
|
+
deps,
|
|
729
|
+
workspaceId,
|
|
730
|
+
"connections:write",
|
|
731
|
+
);
|
|
732
|
+
const grant = authorization.grant;
|
|
733
|
+
const { connection, metadata } = await requireOnePasswordConnection(
|
|
734
|
+
deps,
|
|
735
|
+
authorization,
|
|
736
|
+
workspaceId,
|
|
737
|
+
connectionId,
|
|
738
|
+
);
|
|
739
|
+
requireManageOnePasswordConnection(authorization, connection, metadata);
|
|
740
|
+
const context = vaultContextFor(authorization, workspaceId);
|
|
741
|
+
const unlinkedVaultIds: string[] = [];
|
|
742
|
+
try {
|
|
743
|
+
for (const row of await linkedVaultRows(context, workspaceId, connectionId)) {
|
|
744
|
+
await deleteVault(db, context, {
|
|
745
|
+
vaultId: row.id,
|
|
746
|
+
confirmName: row.name,
|
|
747
|
+
allowOrganization: isAccountAdmin(authorization),
|
|
748
|
+
});
|
|
749
|
+
unlinkedVaultIds.push(row.id);
|
|
750
|
+
}
|
|
751
|
+
} catch (error) {
|
|
752
|
+
return vaultRouteError(c, error);
|
|
753
|
+
}
|
|
754
|
+
const revoked = await revokeConnection(
|
|
755
|
+
db,
|
|
756
|
+
workspaceId,
|
|
757
|
+
connectionId,
|
|
758
|
+
grant.subjectId,
|
|
759
|
+
connection.version,
|
|
760
|
+
);
|
|
761
|
+
if (!revoked) {
|
|
762
|
+
throw new HTTPException(409, {
|
|
763
|
+
message: "This 1Password connection changed while you were disconnecting it. Try again.",
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
return c.json(DisconnectOnePasswordResponse.parse({ unlinkedVaultIds }));
|
|
767
|
+
});
|
|
768
|
+
|
|
769
|
+
async function linkedVaultRows(
|
|
770
|
+
context: VaultDbContext,
|
|
771
|
+
workspaceId: string,
|
|
772
|
+
connectionId: string,
|
|
773
|
+
): Promise<(VaultRow & { providerVaultRef: string })[]> {
|
|
774
|
+
const rows = await listVaultsForSubject(db, context, { workspaceId });
|
|
775
|
+
return rows.filter(
|
|
776
|
+
(row): row is VaultRow & { providerVaultRef: string } =>
|
|
777
|
+
row.source === "onepassword" &&
|
|
778
|
+
row.providerConnectionId === connectionId &&
|
|
779
|
+
row.providerVaultRef !== null,
|
|
780
|
+
);
|
|
781
|
+
}
|
|
782
|
+
}
|