@opengeni/api-router 0.30.3 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-grant-rls.d.ts +3 -0
- package/dist/admission-trace.d.ts +8 -0
- package/dist/api-websocket.d.ts +18 -0
- package/dist/app.d.ts +50 -2
- package/dist/app.js +12 -1
- package/dist/artifact-catalog-cursor.d.ts +27 -0
- package/dist/auth/managed-auth-attempt-context.d.ts +10 -0
- package/dist/auth/managed-auth-rate-limits.d.ts +167 -0
- package/dist/auth/managed-auth-session-adapter.d.ts +6 -0
- package/dist/auth/managed-auth.d.ts +102 -3
- package/dist/auth/managed-email.d.ts +29 -0
- package/dist/auth/managed-sign-in-notifications.d.ts +4 -0
- package/dist/auth/new-signups-gate.d.ts +23 -0
- package/dist/auth/organization-user-setup.d.ts +80 -0
- package/dist/auth/signup-funnel-metrics.d.ts +44 -0
- package/dist/browser-controller-authority.d.ts +1 -61
- package/dist/browser-ephemeral.d.ts +5 -0
- package/dist/browser-state-authority.d.ts +1 -27
- package/dist/chunk-6TZ5LG3O.js +123948 -0
- package/dist/chunk-6TZ5LG3O.js.map +1 -0
- package/dist/chunk-OGQDXVXY.js +18 -0
- package/dist/chunk-OGQDXVXY.js.map +1 -0
- package/dist/claude-subscription-account-conflicts.d.ts +1 -0
- package/dist/claude-subscription-account-usage.d.ts +39 -0
- package/dist/claude-subscription-oauth.d.ts +25 -0
- package/dist/claude-subscription-profile.d.ts +9 -0
- package/dist/claude-subscription-usage.d.ts +44 -0
- package/dist/claude-workspace-connection.d.ts +15 -0
- package/dist/codemode.d.ts +32 -1
- package/dist/company-brain-okf.d.ts +24 -0
- package/dist/connected-machine-computer-access.d.ts +11 -0
- package/dist/connection-ownership.d.ts +54 -0
- package/dist/controller-data-plane.d.ts +32 -0
- package/dist/editable-artifact-source-session.d.ts +3 -0
- package/dist/editable-artifact-websocket.d.ts +10 -18
- package/dist/editable-artifact-workspace-files.d.ts +1 -1
- package/dist/fatal-process-boundary.d.ts +25 -0
- package/dist/github-access.d.ts +31 -2
- package/dist/http/acting-person.d.ts +24 -0
- package/dist/http/api-contract-compat.d.ts +19 -0
- package/dist/http/api-error.d.ts +27 -1
- package/dist/http/cors.d.ts +17 -0
- package/dist/http/deprecation.d.ts +42 -0
- package/dist/http/interaction-control-error.d.ts +13 -0
- package/dist/http/keyed-admission.d.ts +12 -0
- package/dist/http/local-browser-boundary.d.ts +72 -0
- package/dist/http/metrics-listener.d.ts +22 -0
- package/dist/http/path-identifier.d.ts +17 -0
- package/dist/http/registered-route-label.d.ts +16 -0
- package/dist/http/request-body.d.ts +27 -0
- package/dist/http/request-source.d.ts +52 -0
- package/dist/http/sse.d.ts +17 -6
- package/dist/http/unmatched-route.d.ts +18 -0
- package/dist/http/user-content.d.ts +36 -0
- package/dist/http/websocket-upgrade-dispatch.d.ts +18 -0
- package/dist/index.d.ts +10 -3
- package/dist/index.js +1091 -162
- package/dist/index.js.map +1 -1
- package/dist/integration-endpoint-test.d.ts +20 -0
- package/dist/integrations/api-integrations.d.ts +2 -2
- package/dist/integrations/atlassian.d.ts +29 -3
- package/dist/integrations/connect-authority.d.ts +1 -0
- package/dist/integrations/connect-callback-return.d.ts +6 -0
- package/dist/integrations/fiken.d.ts +16 -2
- package/dist/integrations/github-app-connect.d.ts +47 -0
- package/dist/integrations/github-installation-proof.d.ts +3 -0
- package/dist/integrations/github-lens-connect.d.ts +116 -0
- package/dist/integrations/github-skill-source.d.ts +1 -5
- package/dist/integrations/google-drive.d.ts +24 -0
- package/dist/integrations/integration-commit-authority.d.ts +13 -0
- package/dist/integrations/marketplace-plugin.d.ts +2691 -0
- package/dist/integrations/oauth-client.d.ts +178 -18
- package/dist/integrations/oauth-profiles.d.ts +222 -0
- package/dist/integrations/oauth-return-path.d.ts +1 -0
- package/dist/integrations/personal-github-repositories.d.ts +84 -0
- package/dist/integrations/personal-github.d.ts +42 -0
- package/dist/integrations/pr-review-provider.d.ts +22 -0
- package/dist/integrations/provider-oauth.d.ts +19 -1
- package/dist/integrations/slack-app-home.d.ts +24 -0
- package/dist/integrations/slack-bot.d.ts +367 -12
- package/dist/integrations/slack-file-upload-flow.d.ts +62 -0
- package/dist/integrations/slack-install.d.ts +20 -0
- package/dist/integrations/slack-interactions.d.ts +107 -9
- package/dist/integrations/slack-mrkdwn.d.ts +41 -0
- package/dist/integrations/slack-routing.d.ts +120 -0
- package/dist/integrations/slack-session-defaults.d.ts +58 -0
- package/dist/integrations/slack-task-file-upload.d.ts +36 -0
- package/dist/integrations/social-oauth.d.ts +7 -0
- package/dist/interaction-agent-access.d.ts +15 -0
- package/dist/interaction-frame-proxy.d.ts +68 -0
- package/dist/interaction-metrics.d.ts +2 -0
- package/dist/mcp/action-catalog-types.d.ts +9 -0
- package/dist/mcp/action-catalog.gen.d.ts +2 -0
- package/dist/mcp/capability-account-readiness.d.ts +7 -0
- package/dist/mcp/child-read-evidence.d.ts +9 -0
- package/dist/mcp/command-read.d.ts +24 -0
- package/dist/mcp/company-profile-agent-admin.d.ts +44 -0
- package/dist/mcp/contract-input.d.ts +11 -0
- package/dist/mcp/documents.d.ts +7 -5
- package/dist/mcp/files.d.ts +2 -2
- package/dist/mcp/first-party-tool-permissions.d.ts +650 -0
- package/dist/mcp/knowledge-entries.d.ts +5 -0
- package/dist/mcp/orchestration-failure-diagnostic.d.ts +43 -0
- package/dist/mcp/receipts.d.ts +9 -0
- package/dist/mcp/request-abort.d.ts +19 -0
- package/dist/mcp/scheduled-task-input.d.ts +1189 -0
- package/dist/mcp/scheduled-task-view.d.ts +22 -4
- package/dist/mcp/server.d.ts +255 -3
- package/dist/mcp/session-event-view.d.ts +94 -0
- package/dist/mcp/session-view.d.ts +66 -2
- package/dist/mcp/session-wait.d.ts +174 -0
- package/dist/mcp-oauth.d.ts +52 -0
- package/dist/model-catalog.d.ts +11 -31
- package/dist/observability.d.ts +3 -1
- package/dist/organization-mcp.d.ts +52 -0
- package/dist/organization-recovery-notifications.d.ts +41 -0
- package/dist/routes/analytics-consent.d.ts +26 -0
- package/dist/routes/api-integrations.d.ts +25 -0
- package/dist/routes/api-keys.d.ts +17 -0
- package/dist/routes/artifact-catalog.d.ts +6 -0
- package/dist/routes/automations.d.ts +19 -0
- package/dist/routes/billing.d.ts +49 -0
- package/dist/routes/browser-sessions.d.ts +59 -2
- package/dist/routes/claude-subscription-accounts.d.ts +3 -0
- package/dist/routes/claude-subscription-oauth.d.ts +3 -0
- package/dist/routes/client-errors.d.ts +146 -0
- package/dist/routes/codex.d.ts +76 -2
- package/dist/routes/company-brain.d.ts +3 -0
- package/dist/routes/company-profile.d.ts +2 -1
- package/dist/routes/computer-sessions.d.ts +14 -0
- package/dist/routes/connect.d.ts +5 -0
- package/dist/routes/editable-artifacts.d.ts +2 -0
- package/dist/routes/external-identity-links.d.ts +6 -0
- package/dist/routes/feedback.d.ts +3 -0
- package/dist/routes/github-browser-pages.d.ts +12 -0
- package/dist/routes/github.d.ts +2 -0
- package/dist/routes/insights-response-cache.d.ts +10 -0
- package/dist/routes/insights-usage.d.ts +12 -0
- package/dist/routes/insights.d.ts +30 -1
- package/dist/routes/knowledge.d.ts +3 -0
- package/dist/routes/managed-auth-session-sets.d.ts +26 -0
- package/dist/routes/managed-onboarding.d.ts +29 -0
- package/dist/routes/managed-sign-in-methods.d.ts +6 -0
- package/dist/routes/model-connection-access.d.ts +3 -0
- package/dist/routes/organization-integration-policy.d.ts +3 -0
- package/dist/routes/organization-integrations.d.ts +6 -0
- package/dist/routes/organization-mcp-connections.d.ts +3 -0
- package/dist/routes/organization-model-providers.d.ts +3 -0
- package/dist/routes/organization-recovery.d.ts +19 -0
- package/dist/routes/organization-service-accounts.d.ts +3 -0
- package/dist/routes/organization-sessions.d.ts +26 -0
- package/dist/routes/personal-github-git-broker.d.ts +29 -0
- package/dist/routes/personal-github.d.ts +3 -0
- package/dist/routes/pr-review-github.d.ts +3 -0
- package/dist/routes/pr-review.d.ts +3 -0
- package/dist/routes/session-artifact-associations.d.ts +4 -0
- package/dist/routes/session-history-imports.d.ts +9 -0
- package/dist/routes/sessions.d.ts +44 -6
- package/dist/routes/skill-content.d.ts +4 -0
- package/dist/routes/skill-install-authority.d.ts +6 -0
- package/dist/routes/subscription-account-pools.d.ts +34 -0
- package/dist/routes/subscription-pool-access.d.ts +16 -0
- package/dist/routes/supergrok.d.ts +6 -1
- package/dist/routes/usage-allowances.d.ts +12 -0
- package/dist/routes/user-resource-authorities.d.ts +3 -0
- package/dist/routes/workspace-artifacts.d.ts +2 -1
- package/dist/routes/workspace-capture.d.ts +10 -2
- package/dist/routes/workspace-integrations.d.ts +35 -0
- package/dist/routes/workspace-learning.d.ts +3 -0
- package/dist/routes/workspace-model-providers.d.ts +4 -0
- package/dist/routes/workspaces.d.ts +29 -0
- package/dist/sandbox/auth-callout.d.ts +8 -0
- package/dist/sandbox/channel-a.d.ts +19 -1
- package/dist/sandbox/connection-authority.d.ts +3 -0
- package/dist/sandbox/enrollment.d.ts +9 -1
- package/dist/sandbox/machines.d.ts +5 -2
- package/dist/sandbox/metrics-ingestion.d.ts +28 -20
- package/dist/sandbox/rematerialize.d.ts +2 -0
- package/dist/sandbox/session-attach-variable-sets.d.ts +30 -0
- package/dist/sandbox/viewer.d.ts +26 -1
- package/dist/sandbox-file-artifacts.d.ts +50 -0
- package/dist/scheduled-task-deletion.d.ts +13 -0
- package/dist/session-create-observability.d.ts +5 -0
- package/dist/session-event-view-MPS2OZD3.js +292 -0
- package/dist/session-event-view-MPS2OZD3.js.map +1 -0
- package/dist/site-session-origin.d.ts +13 -0
- package/dist/site-uploads.d.ts +41 -0
- package/dist/slack-reaction-files.d.ts +1 -1
- package/dist/temporal-schedule-cleanup.d.ts +1 -0
- package/dist/temporal-schedule-sync.d.ts +26 -0
- package/dist/transcription/providers/xai-subscription.d.ts +1 -0
- package/dist/transcription/service.d.ts +2 -1
- package/dist/work-discovery-observability.d.ts +33 -0
- package/dist/workspace-artifact-content.d.ts +28 -0
- package/dist/workspace-artifact-provenance.d.ts +7 -0
- package/dist/workspace-delete-observability.d.ts +10 -0
- package/dist/workspace-deletion.d.ts +6 -0
- package/dist/workspace-state-projection.d.ts +3 -5
- package/dist/workspace-tool-gateway-observability.d.ts +17 -0
- package/dist/workspace-tool-gateway.d.ts +123 -0
- package/dist/workspace-webhook-dispatch.d.ts +26 -0
- package/package.json +23 -19
- package/src/access-grant-rls.ts +75 -0
- package/src/admission-trace.ts +14 -0
- package/src/api-websocket.ts +23 -0
- package/src/app.ts +1967 -252
- package/src/artifact-catalog-cursor.ts +60 -0
- package/src/auth/managed-auth-attempt-context.ts +70 -0
- package/src/auth/managed-auth-rate-limits.ts +252 -0
- package/src/auth/managed-auth-session-adapter.ts +222 -0
- package/src/auth/managed-auth.ts +536 -60
- package/src/auth/managed-email.ts +174 -0
- package/src/auth/managed-sign-in-notifications.ts +81 -0
- package/src/auth/new-signups-gate.ts +49 -0
- package/src/auth/organization-user-setup.ts +307 -0
- package/src/auth/signup-funnel-metrics.ts +164 -0
- package/src/browser-controller-authority.ts +1 -186
- package/src/browser-ephemeral.ts +39 -0
- package/src/browser-state-authority.ts +1 -236
- package/src/claude-subscription-account-conflicts.ts +12 -0
- package/src/claude-subscription-account-usage.ts +48 -0
- package/src/claude-subscription-oauth.ts +362 -0
- package/src/claude-subscription-profile.ts +73 -0
- package/src/claude-subscription-usage.ts +97 -0
- package/src/claude-workspace-connection.ts +82 -0
- package/src/codemode.ts +194 -30
- package/src/codex-realtime.ts +8 -2
- package/src/company-brain-okf.ts +340 -0
- package/src/connected-machine-computer-access.ts +33 -0
- package/src/connection-ownership.ts +199 -0
- package/src/controller-data-plane.ts +81 -0
- package/src/editable-artifact-native-kernel.ts +26 -15
- package/src/editable-artifact-office-import.ts +28 -3
- package/src/editable-artifact-production.ts +23 -7
- package/src/editable-artifact-source-session.ts +123 -0
- package/src/editable-artifact-websocket.ts +27 -21
- package/src/editable-artifact-workspace-files.ts +31 -6
- package/src/fatal-process-boundary.ts +246 -0
- package/src/gateway-realtime.ts +1 -1
- package/src/github-access.ts +147 -5
- package/src/http/acting-person.ts +71 -0
- package/src/http/api-contract-compat.ts +49 -0
- package/src/http/api-error.ts +115 -1
- package/src/http/auth.ts +48 -0
- package/src/http/cors.ts +67 -0
- package/src/http/deprecation.ts +118 -0
- package/src/http/interaction-control-error.ts +164 -0
- package/src/http/keyed-admission.ts +29 -0
- package/src/http/local-browser-boundary.ts +343 -0
- package/src/http/metrics-listener.ts +57 -0
- package/src/http/path-identifier.ts +54 -0
- package/src/http/registered-route-label.ts +34 -0
- package/src/http/request-body.ts +127 -0
- package/src/http/request-source.ts +178 -0
- package/src/http/sse.ts +486 -132
- package/src/http/unmatched-route.ts +60 -0
- package/src/http/user-content.ts +158 -0
- package/src/http/websocket-upgrade-dispatch.ts +29 -0
- package/src/index.ts +157 -52
- package/src/integration-endpoint-test.ts +291 -0
- package/src/integrations/api-integrations.ts +98 -11
- package/src/integrations/atlassian.ts +474 -136
- package/src/integrations/connect-authority.ts +2 -0
- package/src/integrations/connect-callback-return.ts +86 -0
- package/src/integrations/fiken.ts +354 -64
- package/src/integrations/github-app-connect.ts +435 -0
- package/src/integrations/github-installation-proof.ts +60 -0
- package/src/integrations/github-lens-connect.ts +76 -0
- package/src/integrations/github-skill-source.ts +2 -142
- package/src/integrations/google-drive.ts +717 -225
- package/src/integrations/integration-commit-authority.ts +69 -0
- package/src/integrations/marketplace-plugin.ts +48 -0
- package/src/integrations/oauth-client.ts +1356 -459
- package/src/integrations/oauth-profiles.ts +537 -0
- package/src/integrations/oauth-return-path.ts +18 -0
- package/src/integrations/personal-github-repositories.ts +674 -0
- package/src/integrations/personal-github.ts +825 -0
- package/src/integrations/pr-review-provider.ts +246 -0
- package/src/integrations/provider-oauth.ts +250 -22
- package/src/integrations/slack-app-home.ts +300 -0
- package/src/integrations/slack-bot.ts +963 -239
- package/src/integrations/slack-file-upload-flow.ts +147 -0
- package/src/integrations/slack-install.ts +83 -0
- package/src/integrations/slack-interactions.ts +3167 -474
- package/src/integrations/slack-mrkdwn.ts +193 -0
- package/src/integrations/slack-routing.ts +337 -0
- package/src/integrations/slack-session-defaults.ts +224 -0
- package/src/integrations/slack-task-file-upload.ts +323 -0
- package/src/integrations/social-oauth.ts +213 -15
- package/src/interaction-agent-access.ts +48 -0
- package/src/interaction-frame-proxy.ts +409 -0
- package/src/interaction-metrics.ts +30 -0
- package/src/mcp/action-catalog-types.ts +9 -0
- package/src/mcp/action-catalog.gen.ts +6696 -0
- package/src/mcp/capability-account-readiness.ts +17 -0
- package/src/mcp/child-read-evidence.ts +19 -0
- package/src/mcp/command-read.ts +109 -0
- package/src/mcp/company-profile-agent-admin.ts +198 -0
- package/src/mcp/contract-input.ts +141 -0
- package/src/mcp/documents.ts +65 -377
- package/src/mcp/editable-artifacts.ts +12 -6
- package/src/mcp/files.ts +80 -43
- package/src/mcp/first-party-tool-permissions.ts +305 -0
- package/src/mcp/knowledge-entries.ts +322 -0
- package/src/mcp/orchestration-failure-diagnostic.ts +43 -0
- package/src/mcp/receipts.ts +34 -0
- package/src/mcp/request-abort.ts +44 -0
- package/src/mcp/scheduled-task-input.ts +76 -0
- package/src/mcp/scheduled-task-view.ts +44 -3
- package/src/mcp/server.ts +3030 -1267
- package/src/mcp/session-event-view.ts +383 -0
- package/src/mcp/session-view.ts +84 -3
- package/src/mcp/session-wait.ts +665 -0
- package/src/mcp-oauth.ts +1123 -0
- package/src/model-catalog.ts +91 -333
- package/src/observability.ts +15 -1
- package/src/organization-mcp.ts +397 -0
- package/src/organization-recovery-notifications.ts +103 -0
- package/src/routes/analytics-consent.ts +123 -0
- package/src/routes/api-integrations.ts +364 -74
- package/src/routes/api-keys.ts +336 -10
- package/src/routes/artifact-catalog.ts +279 -0
- package/src/routes/automations.ts +768 -0
- package/src/routes/billing.ts +461 -46
- package/src/routes/browser-sessions.ts +780 -112
- package/src/routes/canonical-human-identities.ts +90 -14
- package/src/routes/capabilities.ts +107 -6
- package/src/routes/channels.ts +20 -3
- package/src/routes/claude-subscription-accounts.ts +334 -0
- package/src/routes/claude-subscription-oauth.ts +142 -0
- package/src/routes/client-errors.ts +362 -0
- package/src/routes/codex.ts +833 -116
- package/src/routes/company-brain.ts +322 -0
- package/src/routes/company-profile.ts +65 -1
- package/src/routes/computer-sessions.ts +557 -106
- package/src/routes/connect.ts +1938 -0
- package/src/routes/connections.ts +1039 -349
- package/src/routes/documents.ts +488 -287
- package/src/routes/editable-artifacts.ts +79 -9
- package/src/routes/enrollments.ts +135 -39
- package/src/routes/environments.ts +154 -58
- package/src/routes/external-identity-links.ts +201 -0
- package/src/routes/feedback.ts +113 -0
- package/src/routes/files.ts +267 -33
- package/src/routes/github-browser-pages.ts +162 -0
- package/src/routes/github.ts +446 -144
- package/src/routes/insights-response-cache.ts +83 -0
- package/src/routes/insights-usage.ts +345 -0
- package/src/routes/insights.ts +153 -19
- package/src/routes/install.ts +133 -38
- package/src/routes/integration-facets.ts +107 -33
- package/src/routes/interaction-resources.ts +30 -3
- package/src/routes/knowledge.ts +488 -0
- package/src/routes/machines.ts +313 -15
- package/src/routes/managed-auth-session-sets.ts +1218 -0
- package/src/routes/managed-onboarding.ts +337 -0
- package/src/routes/managed-sign-in-methods.ts +433 -0
- package/src/routes/memory-slack-publications.ts +3 -2
- package/src/routes/model-connection-access.ts +208 -0
- package/src/routes/organization-integration-policy.ts +116 -0
- package/src/routes/organization-integrations.ts +326 -0
- package/src/routes/organization-mcp-connections.ts +178 -0
- package/src/routes/organization-memberships.ts +1019 -27
- package/src/routes/organization-model-providers.ts +293 -0
- package/src/routes/organization-recovery.ts +325 -0
- package/src/routes/organization-service-accounts.ts +128 -0
- package/src/routes/organization-sessions.ts +350 -0
- package/src/routes/personal-github-git-broker.ts +785 -0
- package/src/routes/personal-github.ts +370 -0
- package/src/routes/plugins.ts +251 -22
- package/src/routes/pr-review-github.ts +881 -0
- package/src/routes/pr-review.ts +622 -0
- package/src/routes/preference-registry.ts +12 -93
- package/src/routes/rigs.ts +167 -50
- package/src/routes/scheduled-tasks.ts +346 -41
- package/src/routes/session-artifact-associations.ts +87 -0
- package/src/routes/session-history-imports.ts +280 -0
- package/src/routes/sessions.ts +2306 -264
- package/src/routes/skill-content.ts +297 -0
- package/src/routes/skill-install-authority.ts +64 -0
- package/src/routes/skills.ts +62 -9
- package/src/routes/social.ts +46 -18
- package/src/routes/subscription-account-pools.ts +436 -0
- package/src/routes/subscription-pool-access.ts +126 -0
- package/src/routes/supergrok.ts +219 -303
- package/src/routes/transcription-recordings.ts +38 -3
- package/src/routes/transcriptions.ts +4 -0
- package/src/routes/usage-allowances.ts +378 -0
- package/src/routes/user-resource-authorities.ts +138 -0
- package/src/routes/video-generation.ts +14 -10
- package/src/routes/workspace-artifacts.ts +275 -69
- package/src/routes/workspace-capture.ts +21 -0
- package/src/routes/workspace-integrations.ts +576 -0
- package/src/routes/workspace-learning.ts +159 -0
- package/src/routes/workspace-model-providers.ts +148 -0
- package/src/routes/workspace-state.ts +38 -25
- package/src/routes/workspaces.ts +1004 -127
- package/src/sandbox/auth-callout.ts +96 -19
- package/src/sandbox/channel-a.ts +323 -24
- package/src/sandbox/connection-authority.ts +3 -0
- package/src/sandbox/enrollment.ts +81 -6
- package/src/sandbox/machines.ts +218 -76
- package/src/sandbox/metrics-ingestion.ts +411 -62
- package/src/sandbox/rematerialize.ts +121 -19
- package/src/sandbox/session-attach-variable-sets.ts +131 -0
- package/src/sandbox/viewer.ts +280 -25
- package/src/sandbox-file-artifacts.ts +413 -0
- package/src/scheduled-task-deletion.ts +138 -0
- package/src/session-create-observability.ts +46 -0
- package/src/session-realtime-context.ts +6 -3
- package/src/site-session-origin.ts +48 -0
- package/src/site-uploads.ts +224 -0
- package/src/slack-reaction-files.ts +16 -5
- package/src/temporal-schedule-cleanup.ts +13 -0
- package/src/temporal-schedule-sync.ts +74 -0
- package/src/transcription/providers/codex-subscription.ts +2 -0
- package/src/transcription/providers/openai.ts +1 -0
- package/src/transcription/providers/xai-subscription.ts +49 -3
- package/src/transcription/segmenter.ts +8 -2
- package/src/transcription/service.ts +43 -6
- package/src/work-discovery-observability.ts +121 -0
- package/src/workspace-artifact-content.ts +144 -0
- package/src/workspace-artifact-provenance.ts +104 -0
- package/src/workspace-delete-observability.ts +75 -0
- package/src/workspace-deletion.ts +73 -0
- package/src/workspace-state-projection.ts +18 -148
- package/src/workspace-tool-gateway-observability.ts +100 -0
- package/src/workspace-tool-gateway.ts +870 -0
- package/src/workspace-webhook-dispatch.ts +190 -0
- package/src/xai-subscription-auth.ts +9 -2
- package/dist/chunk-WCXHI3FF.js +0 -49920
- package/dist/chunk-WCXHI3FF.js.map +0 -1
- package/dist/routes/packs.d.ts +0 -3
- package/src/routes/packs.ts +0 -729
package/src/routes/documents.ts
CHANGED
|
@@ -1,61 +1,101 @@
|
|
|
1
|
+
import { fileOwnerContextForAccess } from "@opengeni/core";
|
|
2
|
+
import { withSessionRlsActorContext } from "@opengeni/db";
|
|
1
3
|
import {
|
|
2
4
|
AddDocumentRequest,
|
|
3
5
|
CreateKnowledgeDropRequest,
|
|
4
|
-
CreateKnowledgeMemoryRequest,
|
|
5
6
|
CreateDocumentBaseRequest,
|
|
6
7
|
Document,
|
|
8
|
+
DocumentAuthorityReclassification,
|
|
7
9
|
DocumentBase,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
DocumentDefaultCollectionBackfill,
|
|
11
|
+
DocumentDefaultCollectionBackfillAudit,
|
|
12
|
+
GetDocumentDefaultCollectionBackfillAuditQuery,
|
|
13
|
+
FileAsset,
|
|
14
|
+
FileDownloadUrlResponse,
|
|
15
|
+
ListDocumentAuthorityReclassificationsQuery,
|
|
16
|
+
ListDocumentAuthorityReclassificationsResponse,
|
|
17
|
+
ListDocumentDefaultCollectionBackfillRunsResponse,
|
|
18
|
+
ListDocumentMigrationAuditQuery,
|
|
19
|
+
ListOrganizationDocumentAuthorityReclassificationsResponse,
|
|
12
20
|
MoveDocumentRequest,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
WorkspaceMemorySearchResponse,
|
|
21
|
+
ReclassifyDocumentAuthorityRequest,
|
|
22
|
+
RunDocumentDefaultCollectionBackfillRequest,
|
|
16
23
|
} from "@opengeni/contracts";
|
|
17
|
-
import {
|
|
18
|
-
completeFileUpload,
|
|
19
|
-
createFileUpload,
|
|
20
|
-
createKnowledgeMemory,
|
|
21
|
-
getKnowledgeMemory,
|
|
22
|
-
listKnowledgeMemories,
|
|
23
|
-
updateKnowledgeMemory,
|
|
24
|
-
searchWorkspaceMemories,
|
|
25
|
-
} from "@opengeni/db";
|
|
24
|
+
import { recordAuditEvent, completeFileUpload, createFileUpload } from "@opengeni/db";
|
|
26
25
|
import {
|
|
27
26
|
addDocumentToBase,
|
|
28
27
|
createDocumentBase,
|
|
29
28
|
deleteDocumentFromBase,
|
|
30
29
|
ensureDefaultBase,
|
|
31
30
|
getDocument,
|
|
31
|
+
getDocumentOriginalFile,
|
|
32
32
|
getDocumentBase,
|
|
33
|
+
getDocumentDefaultCollectionBackfillAudit,
|
|
34
|
+
listAccessibleDocuments,
|
|
35
|
+
listDocumentAuthorityReclassifications,
|
|
36
|
+
listDocumentDefaultCollectionBackfillRuns,
|
|
33
37
|
listDocumentBasesEnsuringDefault,
|
|
34
38
|
listDocuments,
|
|
39
|
+
listOrganizationDocumentAuthorityReclassifications,
|
|
35
40
|
moveDocumentToBase,
|
|
36
41
|
queueDocumentForReindex,
|
|
37
|
-
|
|
42
|
+
reclassifyDocumentAuthority,
|
|
43
|
+
runDocumentDefaultCollectionBackfill,
|
|
38
44
|
} from "@opengeni/documents";
|
|
39
45
|
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
|
|
40
|
-
import type {
|
|
46
|
+
import type { Hono } from "hono";
|
|
41
47
|
import { HTTPException } from "hono/http-exception";
|
|
42
48
|
import {
|
|
43
49
|
requireAccessGrant,
|
|
50
|
+
requireAccountAdminAuthorizationStamp,
|
|
44
51
|
requireAccessGrantAuthorization,
|
|
45
|
-
|
|
52
|
+
knowledgeContextForAccess,
|
|
46
53
|
} from "@opengeni/core";
|
|
47
54
|
import { recordWorkspaceUsage, requireLimit } from "@opengeni/core";
|
|
48
55
|
import type { ApiRouteDeps } from "@opengeni/core";
|
|
49
56
|
import { buildDocumentsMcpServer } from "../mcp/documents";
|
|
57
|
+
import { mcpOAuthAuthenticateHeader, resolveMcpOAuthRouteAccess } from "../mcp-oauth";
|
|
58
|
+
import { withAccessGrantSessionRlsContext } from "../access-grant-rls";
|
|
59
|
+
import {
|
|
60
|
+
buildWorkspaceToolGatewayMcpServer,
|
|
61
|
+
prepareMcpOAuthWorkspaceToolGateway,
|
|
62
|
+
} from "../workspace-tool-gateway";
|
|
50
63
|
import { sanitizeFilename } from "./files";
|
|
64
|
+
import { userContentSignedGetUrlOptions } from "../http/user-content";
|
|
65
|
+
import { parseRequestBody, parseRequestJson } from "../http/request-body";
|
|
51
66
|
|
|
52
67
|
export function registerDocumentRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
53
68
|
const { db, objectStorage, documentIndexer, getDocumentServices } = deps;
|
|
69
|
+
// Document compatibility uploads use the same verified personal file owner as
|
|
70
|
+
// Files and chat uploads. A delegated subject label never becomes an owner.
|
|
71
|
+
for (const path of [
|
|
72
|
+
"/v1/workspaces/:workspaceId/document-bases/*",
|
|
73
|
+
"/v1/workspaces/:workspaceId/documents/*",
|
|
74
|
+
"/v1/workspaces/:workspaceId/knowledge/drops",
|
|
75
|
+
]) {
|
|
76
|
+
app.use(path, async (c, next) => {
|
|
77
|
+
const permission =
|
|
78
|
+
(c.req.method === "GET" && !c.req.path.includes("/authority-reclassifications")) ||
|
|
79
|
+
c.req.path.endsWith("/search")
|
|
80
|
+
? "documents:search"
|
|
81
|
+
: "documents:manage";
|
|
82
|
+
const access = await requireAccessGrantAuthorization(
|
|
83
|
+
c,
|
|
84
|
+
deps,
|
|
85
|
+
c.req.param("workspaceId") ?? "",
|
|
86
|
+
permission,
|
|
87
|
+
);
|
|
88
|
+
return withSessionRlsActorContext(
|
|
89
|
+
await fileOwnerContextForAccess(deps, access, permission),
|
|
90
|
+
next,
|
|
91
|
+
);
|
|
92
|
+
});
|
|
93
|
+
}
|
|
54
94
|
|
|
55
95
|
app.post("/v1/workspaces/:workspaceId/document-bases", async (c) => {
|
|
56
96
|
const workspaceId = c.req.param("workspaceId");
|
|
57
97
|
const grant = await requireAccessGrant(c, deps, workspaceId, "documents:manage");
|
|
58
|
-
const payload =
|
|
98
|
+
const payload = await parseRequestJson(c, CreateDocumentBaseRequest);
|
|
59
99
|
return c.json(
|
|
60
100
|
DocumentBase.parse(
|
|
61
101
|
await createDocumentBase(db, { ...payload, accountId: grant.accountId, workspaceId }),
|
|
@@ -87,6 +127,136 @@ export function registerDocumentRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
87
127
|
return c.json(DocumentBase.parse(base));
|
|
88
128
|
});
|
|
89
129
|
|
|
130
|
+
app.post("/v1/workspaces/:workspaceId/document-default-collection-backfills", async (c) => {
|
|
131
|
+
const workspaceId = c.req.param("workspaceId");
|
|
132
|
+
const authorization = await requireAccessGrantAuthorization(
|
|
133
|
+
c,
|
|
134
|
+
deps,
|
|
135
|
+
workspaceId,
|
|
136
|
+
"documents:manage",
|
|
137
|
+
);
|
|
138
|
+
if (!hasAccountAdminAuthority(authorization)) {
|
|
139
|
+
throw new HTTPException(403, { message: "missing permission: account:admin" });
|
|
140
|
+
}
|
|
141
|
+
const accountAdminAuthorization = requireAccountAdminAuthorizationStamp(authorization);
|
|
142
|
+
const payload = await parseRequestJson(c, RunDocumentDefaultCollectionBackfillRequest);
|
|
143
|
+
try {
|
|
144
|
+
return c.json(
|
|
145
|
+
DocumentDefaultCollectionBackfill.parse(
|
|
146
|
+
await runDocumentDefaultCollectionBackfill(db, {
|
|
147
|
+
...payload,
|
|
148
|
+
accountId: authorization.grant.accountId,
|
|
149
|
+
workspaceId,
|
|
150
|
+
actorSubjectId: authorization.grant.subjectId,
|
|
151
|
+
accountAdminAuthorization,
|
|
152
|
+
}),
|
|
153
|
+
),
|
|
154
|
+
);
|
|
155
|
+
} catch (error) {
|
|
156
|
+
throw documentHttpException(error);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
app.get("/v1/workspaces/:workspaceId/document-default-collection-backfills", async (c) => {
|
|
161
|
+
const workspaceId = c.req.param("workspaceId");
|
|
162
|
+
const authorization = await requireAccessGrantAuthorization(
|
|
163
|
+
c,
|
|
164
|
+
deps,
|
|
165
|
+
workspaceId,
|
|
166
|
+
"documents:manage",
|
|
167
|
+
);
|
|
168
|
+
if (!hasAccountAdminAuthority(authorization)) {
|
|
169
|
+
throw new HTTPException(403, { message: "missing permission: account:admin" });
|
|
170
|
+
}
|
|
171
|
+
const query = ListDocumentMigrationAuditQuery.safeParse(c.req.query());
|
|
172
|
+
if (!query.success) {
|
|
173
|
+
throw new HTTPException(400, { message: "invalid document migration audit query" });
|
|
174
|
+
}
|
|
175
|
+
try {
|
|
176
|
+
return c.json(
|
|
177
|
+
ListDocumentDefaultCollectionBackfillRunsResponse.parse(
|
|
178
|
+
await listDocumentDefaultCollectionBackfillRuns(db, {
|
|
179
|
+
accountId: authorization.grant.accountId,
|
|
180
|
+
workspaceId,
|
|
181
|
+
actorSubjectId: authorization.grant.subjectId,
|
|
182
|
+
accountAdminAuthorization: requireAccountAdminAuthorizationStamp(authorization),
|
|
183
|
+
...query.data,
|
|
184
|
+
}),
|
|
185
|
+
),
|
|
186
|
+
);
|
|
187
|
+
} catch (error) {
|
|
188
|
+
throw documentHttpException(error);
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
app.get("/v1/workspaces/:workspaceId/document-default-collection-backfills/:runId", async (c) => {
|
|
193
|
+
const workspaceId = c.req.param("workspaceId");
|
|
194
|
+
const authorization = await requireAccessGrantAuthorization(
|
|
195
|
+
c,
|
|
196
|
+
deps,
|
|
197
|
+
workspaceId,
|
|
198
|
+
"documents:manage",
|
|
199
|
+
);
|
|
200
|
+
if (!hasAccountAdminAuthority(authorization)) {
|
|
201
|
+
throw new HTTPException(403, { message: "missing permission: account:admin" });
|
|
202
|
+
}
|
|
203
|
+
const runId = RunDocumentDefaultCollectionBackfillRequest.shape.runId.safeParse(
|
|
204
|
+
c.req.param("runId"),
|
|
205
|
+
);
|
|
206
|
+
const query = GetDocumentDefaultCollectionBackfillAuditQuery.safeParse(c.req.query());
|
|
207
|
+
if (!runId.success || !query.success) {
|
|
208
|
+
throw new HTTPException(400, { message: "invalid document migration audit query" });
|
|
209
|
+
}
|
|
210
|
+
try {
|
|
211
|
+
return c.json(
|
|
212
|
+
DocumentDefaultCollectionBackfillAudit.parse(
|
|
213
|
+
await getDocumentDefaultCollectionBackfillAudit(db, {
|
|
214
|
+
accountId: authorization.grant.accountId,
|
|
215
|
+
workspaceId,
|
|
216
|
+
actorSubjectId: authorization.grant.subjectId,
|
|
217
|
+
accountAdminAuthorization: requireAccountAdminAuthorizationStamp(authorization),
|
|
218
|
+
runId: runId.data,
|
|
219
|
+
...query.data,
|
|
220
|
+
}),
|
|
221
|
+
),
|
|
222
|
+
);
|
|
223
|
+
} catch (error) {
|
|
224
|
+
throw documentHttpException(error);
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
app.get("/v1/workspaces/:workspaceId/document-authority-reclassifications", async (c) => {
|
|
229
|
+
const workspaceId = c.req.param("workspaceId");
|
|
230
|
+
const authorization = await requireAccessGrantAuthorization(
|
|
231
|
+
c,
|
|
232
|
+
deps,
|
|
233
|
+
workspaceId,
|
|
234
|
+
"documents:manage",
|
|
235
|
+
);
|
|
236
|
+
if (!hasAccountAdminAuthority(authorization)) {
|
|
237
|
+
throw new HTTPException(403, { message: "missing permission: account:admin" });
|
|
238
|
+
}
|
|
239
|
+
const query = ListDocumentMigrationAuditQuery.safeParse(c.req.query());
|
|
240
|
+
if (!query.success) {
|
|
241
|
+
throw new HTTPException(400, { message: "invalid document migration audit query" });
|
|
242
|
+
}
|
|
243
|
+
try {
|
|
244
|
+
return c.json(
|
|
245
|
+
ListOrganizationDocumentAuthorityReclassificationsResponse.parse(
|
|
246
|
+
await listOrganizationDocumentAuthorityReclassifications(db, {
|
|
247
|
+
accountId: authorization.grant.accountId,
|
|
248
|
+
workspaceId,
|
|
249
|
+
actorSubjectId: authorization.grant.subjectId,
|
|
250
|
+
accountAdminAuthorization: requireAccountAdminAuthorizationStamp(authorization),
|
|
251
|
+
...query.data,
|
|
252
|
+
}),
|
|
253
|
+
),
|
|
254
|
+
);
|
|
255
|
+
} catch (error) {
|
|
256
|
+
throw documentHttpException(error);
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
|
|
90
260
|
app.post("/v1/workspaces/:workspaceId/document-bases/:baseId/documents", async (c) => {
|
|
91
261
|
const workspaceId = c.req.param("workspaceId");
|
|
92
262
|
const access = await requireAccessGrantAuthorization(c, deps, workspaceId, "documents:manage");
|
|
@@ -100,7 +270,7 @@ export function registerDocumentRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
100
270
|
action: "document:index",
|
|
101
271
|
quantity: 0,
|
|
102
272
|
});
|
|
103
|
-
const payload =
|
|
273
|
+
const payload = await parseRequestJson(c, AddDocumentRequest);
|
|
104
274
|
const organizationAuthorityGranted =
|
|
105
275
|
access.accountGrant?.permissions.includes("account:admin") === true;
|
|
106
276
|
if (payload.authorityKind === "organization" && !organizationAuthorityGranted) {
|
|
@@ -130,19 +300,6 @@ export function registerDocumentRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
130
300
|
authorityWorkspaceId: document.authorityWorkspaceId,
|
|
131
301
|
authoritySubjectId: document.authoritySubjectId,
|
|
132
302
|
})) ?? document);
|
|
133
|
-
if (indexed.status === "ready") {
|
|
134
|
-
await recordWorkspaceUsage(deps, {
|
|
135
|
-
accountId: grant.accountId,
|
|
136
|
-
workspaceId,
|
|
137
|
-
subjectId: grant.subjectId,
|
|
138
|
-
eventType: "document.indexed",
|
|
139
|
-
quantity: indexed.chunkCount,
|
|
140
|
-
unit: "chunk",
|
|
141
|
-
sourceResourceType: "document",
|
|
142
|
-
sourceResourceId: indexed.id,
|
|
143
|
-
idempotencyKey: `document.indexed:${workspaceId}:${indexed.id}:${indexed.updatedAt}`,
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
303
|
return c.json(Document.parse(indexed), wasCreated ? 201 : 200);
|
|
147
304
|
} catch (error) {
|
|
148
305
|
throw documentHttpException(error);
|
|
@@ -161,6 +318,151 @@ export function registerDocumentRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
161
318
|
);
|
|
162
319
|
});
|
|
163
320
|
|
|
321
|
+
app.get("/v1/workspaces/:workspaceId/documents", async (c) => {
|
|
322
|
+
const workspaceId = c.req.param("workspaceId");
|
|
323
|
+
const grant = await requireAccessGrant(c, deps, workspaceId, "documents:search");
|
|
324
|
+
return c.json(
|
|
325
|
+
(
|
|
326
|
+
await listAccessibleDocuments(db, workspaceId, {
|
|
327
|
+
viewerSubjectId: grant.subjectId,
|
|
328
|
+
})
|
|
329
|
+
).map((document) => Document.parse(document)),
|
|
330
|
+
);
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
app.post(
|
|
334
|
+
"/v1/workspaces/:workspaceId/documents/:documentId/authority-reclassifications",
|
|
335
|
+
async (c) => {
|
|
336
|
+
const workspaceId = c.req.param("workspaceId");
|
|
337
|
+
const authorization = await requireAccessGrantAuthorization(
|
|
338
|
+
c,
|
|
339
|
+
deps,
|
|
340
|
+
workspaceId,
|
|
341
|
+
"documents:manage",
|
|
342
|
+
);
|
|
343
|
+
const payload = await parseRequestJson(c, ReclassifyDocumentAuthorityRequest);
|
|
344
|
+
const accountAdminAuthorized = hasAccountAdminAuthority(authorization);
|
|
345
|
+
const accountAdminAuthorization = accountAdminAuthorized
|
|
346
|
+
? requireAccountAdminAuthorizationStamp(authorization)
|
|
347
|
+
: null;
|
|
348
|
+
try {
|
|
349
|
+
const document = await getDocument(db, workspaceId, c.req.param("documentId"), {
|
|
350
|
+
viewerSubjectId: authorization.grant.subjectId,
|
|
351
|
+
});
|
|
352
|
+
if (!document) throw new HTTPException(404, { message: "document not found" });
|
|
353
|
+
if (
|
|
354
|
+
(document.authorityKind === "organization" ||
|
|
355
|
+
payload.targetAuthorityKind === "organization") &&
|
|
356
|
+
!accountAdminAuthorization
|
|
357
|
+
) {
|
|
358
|
+
throw new HTTPException(403, { message: "missing permission: account:admin" });
|
|
359
|
+
}
|
|
360
|
+
return c.json(
|
|
361
|
+
DocumentAuthorityReclassification.parse(
|
|
362
|
+
await reclassifyDocumentAuthority(db, {
|
|
363
|
+
...payload,
|
|
364
|
+
accountId: authorization.grant.accountId,
|
|
365
|
+
workspaceId,
|
|
366
|
+
documentId: document.id,
|
|
367
|
+
actorSubjectId: authorization.grant.subjectId,
|
|
368
|
+
accountAdminAuthorization,
|
|
369
|
+
}),
|
|
370
|
+
),
|
|
371
|
+
);
|
|
372
|
+
} catch (error) {
|
|
373
|
+
if (error instanceof HTTPException) throw error;
|
|
374
|
+
throw documentHttpException(error);
|
|
375
|
+
}
|
|
376
|
+
},
|
|
377
|
+
);
|
|
378
|
+
|
|
379
|
+
app.get(
|
|
380
|
+
"/v1/workspaces/:workspaceId/documents/:documentId/authority-reclassifications",
|
|
381
|
+
async (c) => {
|
|
382
|
+
const workspaceId = c.req.param("workspaceId");
|
|
383
|
+
const grant = await requireAccessGrant(c, deps, workspaceId, "documents:manage");
|
|
384
|
+
try {
|
|
385
|
+
const query = ListDocumentAuthorityReclassificationsQuery.parse(c.req.query());
|
|
386
|
+
return c.json(
|
|
387
|
+
ListDocumentAuthorityReclassificationsResponse.parse(
|
|
388
|
+
await listDocumentAuthorityReclassifications(db, {
|
|
389
|
+
accountId: grant.accountId,
|
|
390
|
+
workspaceId,
|
|
391
|
+
documentId: c.req.param("documentId"),
|
|
392
|
+
actorSubjectId: grant.subjectId,
|
|
393
|
+
...query,
|
|
394
|
+
}),
|
|
395
|
+
),
|
|
396
|
+
);
|
|
397
|
+
} catch (error) {
|
|
398
|
+
throw documentHttpException(error);
|
|
399
|
+
}
|
|
400
|
+
},
|
|
401
|
+
);
|
|
402
|
+
|
|
403
|
+
app.get("/v1/workspaces/:workspaceId/documents/:documentId/original-file", async (c) => {
|
|
404
|
+
const workspaceId = c.req.param("workspaceId");
|
|
405
|
+
const grant = await requireAccessGrant(c, deps, workspaceId, "documents:search");
|
|
406
|
+
await requireAccessGrant(c, deps, workspaceId, "files:read");
|
|
407
|
+
const file = await getDocumentOriginalFile(db, {
|
|
408
|
+
accountId: grant.accountId,
|
|
409
|
+
workspaceId,
|
|
410
|
+
documentId: c.req.param("documentId"),
|
|
411
|
+
access: { viewerSubjectId: grant.subjectId },
|
|
412
|
+
});
|
|
413
|
+
if (!file) {
|
|
414
|
+
throw new HTTPException(404, { message: "document file not found" });
|
|
415
|
+
}
|
|
416
|
+
return c.json(FileAsset.parse(file));
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
app.post(
|
|
420
|
+
"/v1/workspaces/:workspaceId/documents/:documentId/original-file/download-url",
|
|
421
|
+
async (c) => {
|
|
422
|
+
const workspaceId = c.req.param("workspaceId");
|
|
423
|
+
const grant = await requireAccessGrant(c, deps, workspaceId, "documents:search");
|
|
424
|
+
await requireAccessGrant(c, deps, workspaceId, "files:read");
|
|
425
|
+
if (!objectStorage) {
|
|
426
|
+
throw new HTTPException(503, { message: "object storage is not configured" });
|
|
427
|
+
}
|
|
428
|
+
const file = await getDocumentOriginalFile(db, {
|
|
429
|
+
accountId: grant.accountId,
|
|
430
|
+
workspaceId,
|
|
431
|
+
documentId: c.req.param("documentId"),
|
|
432
|
+
access: { viewerSubjectId: grant.subjectId },
|
|
433
|
+
});
|
|
434
|
+
if (!file) {
|
|
435
|
+
throw new HTTPException(404, { message: "document file not found" });
|
|
436
|
+
}
|
|
437
|
+
if (file.status !== "ready") {
|
|
438
|
+
throw new HTTPException(409, { message: `file is ${file.status}` });
|
|
439
|
+
}
|
|
440
|
+
const signed = await objectStorage.createGetUrl({
|
|
441
|
+
key: file.objectKey,
|
|
442
|
+
...userContentSignedGetUrlOptions(file.contentType, file.filename),
|
|
443
|
+
});
|
|
444
|
+
await recordAuditEvent(db, {
|
|
445
|
+
accountId: grant.accountId,
|
|
446
|
+
workspaceId,
|
|
447
|
+
subjectId: grant.subjectId,
|
|
448
|
+
action: "file.signed_url.issued",
|
|
449
|
+
targetType: "workspace_document",
|
|
450
|
+
targetId: c.req.param("documentId"),
|
|
451
|
+
metadata: {
|
|
452
|
+
fileId: file.id,
|
|
453
|
+
kind: "document_original",
|
|
454
|
+
expiresAt: signed.expiresAt.toISOString(),
|
|
455
|
+
},
|
|
456
|
+
});
|
|
457
|
+
return c.json(
|
|
458
|
+
FileDownloadUrlResponse.parse({
|
|
459
|
+
url: signed.url,
|
|
460
|
+
expiresAt: signed.expiresAt.toISOString(),
|
|
461
|
+
}),
|
|
462
|
+
);
|
|
463
|
+
},
|
|
464
|
+
);
|
|
465
|
+
|
|
164
466
|
app.delete(
|
|
165
467
|
"/v1/workspaces/:workspaceId/document-bases/:baseId/documents/:documentId",
|
|
166
468
|
async (c) => {
|
|
@@ -212,7 +514,9 @@ export function registerDocumentRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
212
514
|
const { grant } = authorization;
|
|
213
515
|
const organizationAuthorityGranted = hasAccountAdminAuthority(authorization);
|
|
214
516
|
if (!objectStorage) {
|
|
215
|
-
throw new HTTPException(503, {
|
|
517
|
+
throw new HTTPException(503, {
|
|
518
|
+
message: "object storage is not configured",
|
|
519
|
+
});
|
|
216
520
|
}
|
|
217
521
|
await requireLimit(deps, {
|
|
218
522
|
accountId: grant.accountId,
|
|
@@ -246,25 +550,14 @@ export function registerDocumentRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
246
550
|
const indexed =
|
|
247
551
|
(await documentIndexer.indexDocument({
|
|
248
552
|
accountId: grant.accountId,
|
|
249
|
-
|
|
553
|
+
// The requested workspace authorizes the human operation; the
|
|
554
|
+
// immutable ingestion workspace remains the indexing authority.
|
|
555
|
+
workspaceId: queued.workspaceId,
|
|
250
556
|
documentId: document.id,
|
|
251
557
|
authorityKind: document.authorityKind,
|
|
252
558
|
authorityWorkspaceId: document.authorityWorkspaceId,
|
|
253
559
|
authoritySubjectId: document.authoritySubjectId,
|
|
254
560
|
})) ?? queued;
|
|
255
|
-
if (indexed.status === "ready") {
|
|
256
|
-
await recordWorkspaceUsage(deps, {
|
|
257
|
-
accountId: grant.accountId,
|
|
258
|
-
workspaceId,
|
|
259
|
-
subjectId: grant.subjectId,
|
|
260
|
-
eventType: "document.indexed",
|
|
261
|
-
quantity: indexed.chunkCount,
|
|
262
|
-
unit: "chunk",
|
|
263
|
-
sourceResourceType: "document",
|
|
264
|
-
sourceResourceId: indexed.id,
|
|
265
|
-
idempotencyKey: `document.indexed:${workspaceId}:${indexed.id}:${indexed.updatedAt}`,
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
561
|
return c.json(Document.parse(indexed));
|
|
269
562
|
} catch (error) {
|
|
270
563
|
if (error instanceof HTTPException) {
|
|
@@ -275,66 +568,21 @@ export function registerDocumentRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
275
568
|
},
|
|
276
569
|
);
|
|
277
570
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
throw new HTTPException(
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
{
|
|
291
|
-
accountId: grant.accountId,
|
|
292
|
-
workspaceId,
|
|
293
|
-
baseIds: [base.id],
|
|
294
|
-
query: payload.query,
|
|
295
|
-
limit: payload.limit,
|
|
296
|
-
mode: payload.mode,
|
|
297
|
-
sourceKinds: payload.sourceKinds,
|
|
298
|
-
aclTags: payload.aclTags,
|
|
299
|
-
initiatingSubjectId: grant.subjectId,
|
|
300
|
-
surface: "human",
|
|
301
|
-
},
|
|
302
|
-
getDocumentServices(),
|
|
303
|
-
),
|
|
304
|
-
}),
|
|
305
|
-
);
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
app.post("/v1/workspaces/:workspaceId/knowledge/search", async (c) => {
|
|
309
|
-
const workspaceId = c.req.param("workspaceId");
|
|
310
|
-
const grant = await requireAccessGrant(c, deps, workspaceId, "documents:search");
|
|
311
|
-
const payload = await parseDocumentSearchRequest(c, "invalid knowledge search request");
|
|
312
|
-
return c.json(
|
|
313
|
-
DocumentSearchResponse.parse({
|
|
314
|
-
results: await searchEffectiveDocuments(
|
|
315
|
-
db,
|
|
316
|
-
{
|
|
317
|
-
accountId: grant.accountId,
|
|
318
|
-
workspaceId,
|
|
319
|
-
query: payload.query,
|
|
320
|
-
baseIds: payload.baseIds,
|
|
321
|
-
limit: payload.limit,
|
|
322
|
-
mode: payload.mode,
|
|
323
|
-
sourceKinds: payload.sourceKinds,
|
|
324
|
-
aclTags: payload.aclTags,
|
|
325
|
-
initiatingSubjectId: grant.subjectId,
|
|
326
|
-
surface: "human",
|
|
327
|
-
},
|
|
328
|
-
getDocumentServices(),
|
|
329
|
-
),
|
|
330
|
-
}),
|
|
331
|
-
);
|
|
332
|
-
});
|
|
571
|
+
for (const path of [
|
|
572
|
+
"/v1/workspaces/:workspaceId/document-bases/:baseId/search",
|
|
573
|
+
"/v1/workspaces/:workspaceId/knowledge/search",
|
|
574
|
+
]) {
|
|
575
|
+
app.post(path, async (c) => {
|
|
576
|
+
await requireAccessGrant(c, deps, c.req.param("workspaceId")!, "documents:search");
|
|
577
|
+
throw new HTTPException(410, {
|
|
578
|
+
message:
|
|
579
|
+
"Document search moved to /knowledge/entries/search. Pending Knowledge is available through its review view.",
|
|
580
|
+
});
|
|
581
|
+
});
|
|
582
|
+
}
|
|
333
583
|
|
|
334
|
-
//
|
|
335
|
-
//
|
|
336
|
-
// applies the configured curation provider, or leaves it as 'none' when
|
|
337
|
-
// curation is disabled.
|
|
584
|
+
// Compatibility upload endpoint. Retained originals and extracted text now
|
|
585
|
+
// enter canonical Knowledge. Agent findings use ordinary accepted turns.
|
|
338
586
|
app.post("/v1/workspaces/:workspaceId/knowledge/drops", async (c) => {
|
|
339
587
|
const workspaceId = c.req.param("workspaceId");
|
|
340
588
|
const access = await requireAccessGrantAuthorization(c, deps, workspaceId, "documents:manage");
|
|
@@ -348,7 +596,16 @@ export function registerDocumentRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
348
596
|
action: "document:index",
|
|
349
597
|
quantity: 0,
|
|
350
598
|
});
|
|
351
|
-
const payload =
|
|
599
|
+
const payload = await parseRequestJson(c, CreateKnowledgeDropRequest);
|
|
600
|
+
const personalFileOwner =
|
|
601
|
+
payload.authorityKind === "personal"
|
|
602
|
+
? (await fileOwnerContextForAccess(deps, access, "documents:manage"))
|
|
603
|
+
.privateFileOwnerSubjectId
|
|
604
|
+
: null;
|
|
605
|
+
if (payload.authorityKind === "personal" && !personalFileOwner)
|
|
606
|
+
throw new HTTPException(403, {
|
|
607
|
+
message: "Personal source retention requires verified ownership",
|
|
608
|
+
});
|
|
352
609
|
const organizationAuthorityGranted =
|
|
353
610
|
access.accountGrant?.permissions.includes("account:admin") === true;
|
|
354
611
|
if (payload.authorityKind === "organization" && !organizationAuthorityGranted) {
|
|
@@ -377,6 +634,7 @@ export function registerDocumentRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
377
634
|
accountId: grant.accountId,
|
|
378
635
|
workspaceId,
|
|
379
636
|
fileId: newFileId,
|
|
637
|
+
privateOwnerSubjectId: personalFileOwner ?? null,
|
|
380
638
|
filename,
|
|
381
639
|
safeFilename,
|
|
382
640
|
contentType: "text/plain; charset=utf-8",
|
|
@@ -423,7 +681,7 @@ export function registerDocumentRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
423
681
|
createdBy: grant.subjectId,
|
|
424
682
|
initiatingSubjectId: grant.subjectId,
|
|
425
683
|
organizationAuthorityGranted,
|
|
426
|
-
curationStatus: "
|
|
684
|
+
curationStatus: "none",
|
|
427
685
|
access: { viewerSubjectId: grant.subjectId },
|
|
428
686
|
});
|
|
429
687
|
const wasCreated =
|
|
@@ -439,19 +697,6 @@ export function registerDocumentRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
439
697
|
authorityWorkspaceId: document.authorityWorkspaceId,
|
|
440
698
|
authoritySubjectId: document.authoritySubjectId,
|
|
441
699
|
})) ?? document);
|
|
442
|
-
if (indexed.status === "ready") {
|
|
443
|
-
await recordWorkspaceUsage(deps, {
|
|
444
|
-
accountId: grant.accountId,
|
|
445
|
-
workspaceId,
|
|
446
|
-
subjectId: grant.subjectId,
|
|
447
|
-
eventType: "document.indexed",
|
|
448
|
-
quantity: indexed.chunkCount,
|
|
449
|
-
unit: "chunk",
|
|
450
|
-
sourceResourceType: "document",
|
|
451
|
-
sourceResourceId: indexed.id,
|
|
452
|
-
idempotencyKey: `document.indexed:${workspaceId}:${indexed.id}:${indexed.updatedAt}`,
|
|
453
|
-
});
|
|
454
|
-
}
|
|
455
700
|
return c.json(Document.parse(indexed), wasCreated ? 201 : 200);
|
|
456
701
|
} catch (error) {
|
|
457
702
|
if (error instanceof HTTPException) {
|
|
@@ -472,7 +717,7 @@ export function registerDocumentRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
472
717
|
);
|
|
473
718
|
const { grant } = authorization;
|
|
474
719
|
const organizationAuthorityGranted = hasAccountAdminAuthority(authorization);
|
|
475
|
-
const payload = MoveDocumentRequest
|
|
720
|
+
const payload = parseRequestBody(MoveDocumentRequest, await c.req.json().catch(() => ({})));
|
|
476
721
|
try {
|
|
477
722
|
const document = await getDocument(db, workspaceId, c.req.param("documentId"), {
|
|
478
723
|
viewerSubjectId: grant.subjectId,
|
|
@@ -501,180 +746,92 @@ export function registerDocumentRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
501
746
|
}
|
|
502
747
|
});
|
|
503
748
|
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
749
|
+
// Old clients get an explicit cutover response instead of writing to an
|
|
750
|
+
// invisible second Knowledge store. Historical Memory IDs are entry IDs now.
|
|
751
|
+
for (const path of [
|
|
752
|
+
"/v1/workspaces/:workspaceId/knowledge/memories",
|
|
753
|
+
"/v1/workspaces/:workspaceId/knowledge/memories/*",
|
|
754
|
+
]) {
|
|
755
|
+
app.all(path, async (c) => {
|
|
756
|
+
await requireAccessGrant(c, deps, c.req.param("workspaceId")!, "documents:search");
|
|
757
|
+
return c.json(
|
|
758
|
+
{
|
|
759
|
+
error: {
|
|
760
|
+
code: "memory_replaced",
|
|
761
|
+
message:
|
|
762
|
+
"Memory has been replaced by Knowledge entries. Use /knowledge/entries and the current SDK Knowledge methods.",
|
|
763
|
+
},
|
|
764
|
+
},
|
|
765
|
+
410,
|
|
766
|
+
);
|
|
513
767
|
});
|
|
514
|
-
|
|
515
|
-
throw new HTTPException(400, { message: "invalid knowledge memory query parameters" });
|
|
516
|
-
}
|
|
517
|
-
return c.json(
|
|
518
|
-
(await listKnowledgeMemories(db, workspaceId, parsed.data)).map((memory) =>
|
|
519
|
-
KnowledgeMemory.parse(memory),
|
|
520
|
-
),
|
|
521
|
-
);
|
|
522
|
-
});
|
|
523
|
-
|
|
524
|
-
app.get("/v1/workspaces/:workspaceId/knowledge/memories/:memoryId", async (c) => {
|
|
525
|
-
const workspaceId = c.req.param("workspaceId");
|
|
526
|
-
await requireAccessGrant(c, deps, workspaceId, "documents:search");
|
|
527
|
-
const memory = await getKnowledgeMemory(db, workspaceId, c.req.param("memoryId"));
|
|
528
|
-
if (!memory) {
|
|
529
|
-
throw new HTTPException(404, { message: "knowledge memory not found" });
|
|
530
|
-
}
|
|
531
|
-
return c.json(KnowledgeMemory.parse(memory));
|
|
532
|
-
});
|
|
533
|
-
|
|
534
|
-
// Hybrid search over the workspace's agent-visible memory (active ∪ approved).
|
|
535
|
-
// Available regardless of the workspace memory setting (human/audit lane).
|
|
536
|
-
app.post("/v1/workspaces/:workspaceId/knowledge/memories/search", async (c) => {
|
|
537
|
-
const workspaceId = c.req.param("workspaceId");
|
|
538
|
-
await requireAccessGrant(c, deps, workspaceId, "documents:search");
|
|
539
|
-
const parsed = WorkspaceMemorySearchRequest.safeParse(await c.req.json());
|
|
540
|
-
if (!parsed.success) {
|
|
541
|
-
throw new HTTPException(400, { message: "invalid workspace memory search request" });
|
|
542
|
-
}
|
|
543
|
-
const results = await searchWorkspaceMemories(
|
|
544
|
-
db,
|
|
545
|
-
workspaceId,
|
|
546
|
-
parsed.data,
|
|
547
|
-
getDocumentServices().embedder,
|
|
548
|
-
);
|
|
549
|
-
return c.json(
|
|
550
|
-
WorkspaceMemorySearchResponse.parse({
|
|
551
|
-
results: results.map((result) => ({
|
|
552
|
-
...result,
|
|
553
|
-
memory: KnowledgeMemory.parse(result.memory),
|
|
554
|
-
})),
|
|
555
|
-
}),
|
|
556
|
-
);
|
|
557
|
-
});
|
|
768
|
+
}
|
|
558
769
|
|
|
559
|
-
app.
|
|
770
|
+
app.all("/v1/workspaces/:workspaceId/mcp/docs", async (c) => {
|
|
560
771
|
const workspaceId = c.req.param("workspaceId");
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
772
|
+
let oauthAccess: Awaited<ReturnType<typeof resolveMcpOAuthRouteAccess>>;
|
|
773
|
+
try {
|
|
774
|
+
oauthAccess = await resolveMcpOAuthRouteAccess(deps, c.req.raw, workspaceId);
|
|
775
|
+
} catch (error) {
|
|
776
|
+
if (error instanceof HTTPException && error.status === 401) {
|
|
777
|
+
c.header("www-authenticate", mcpOAuthAuthenticateHeader(deps, new URL(c.req.url).pathname));
|
|
778
|
+
}
|
|
779
|
+
throw error;
|
|
565
780
|
}
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
781
|
+
if (oauthAccess) {
|
|
782
|
+
return await withAccessGrantSessionRlsContext(deps, oauthAccess.grant, async () => {
|
|
783
|
+
const prepared = await prepareMcpOAuthWorkspaceToolGateway(
|
|
784
|
+
deps,
|
|
785
|
+
oauthAccess.grant,
|
|
786
|
+
oauthAccess.allowedToolIdentities,
|
|
787
|
+
);
|
|
788
|
+
const transport = new WebStandardStreamableHTTPServerTransport({
|
|
789
|
+
enableJsonResponse: true,
|
|
790
|
+
});
|
|
791
|
+
const server = buildWorkspaceToolGatewayMcpServer(
|
|
792
|
+
prepared,
|
|
793
|
+
oauthAccess.grant,
|
|
794
|
+
deps.observability,
|
|
795
|
+
);
|
|
796
|
+
try {
|
|
797
|
+
await server.connect(transport);
|
|
798
|
+
return await transport.handleRequest(c.req.raw);
|
|
799
|
+
} finally {
|
|
800
|
+
await Promise.allSettled([server.close(), prepared.close()]);
|
|
801
|
+
}
|
|
570
802
|
});
|
|
571
803
|
}
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
db,
|
|
579
|
-
{
|
|
580
|
-
accountId: grant.accountId,
|
|
581
|
-
workspaceId,
|
|
582
|
-
text: payload.text,
|
|
583
|
-
kind: payload.kind,
|
|
584
|
-
confidence: payload.confidence,
|
|
585
|
-
pinned: payload.pinned,
|
|
586
|
-
replacesId: payload.replacesId ?? null,
|
|
587
|
-
metadata: payload.metadata,
|
|
588
|
-
origin: "human",
|
|
589
|
-
},
|
|
590
|
-
payload.slackPublication
|
|
591
|
-
? {
|
|
592
|
-
distribution: payload.slackPublication,
|
|
593
|
-
actor: {
|
|
594
|
-
kind: "human",
|
|
595
|
-
subjectId: grant.subjectId,
|
|
596
|
-
initiatingHumanSubjectId: grant.subjectId,
|
|
597
|
-
},
|
|
598
|
-
ownerLabel: grant.subjectLabel ?? null,
|
|
599
|
-
}
|
|
600
|
-
: null,
|
|
601
|
-
getDocumentServices().embedder,
|
|
602
|
-
);
|
|
603
|
-
return c.json(KnowledgeMemory.parse(result.memory), 201);
|
|
604
|
-
} catch (error) {
|
|
605
|
-
throw documentHttpException(error);
|
|
804
|
+
let grant: Awaited<ReturnType<typeof requireAccessGrant>>;
|
|
805
|
+
try {
|
|
806
|
+
grant = await requireAccessGrant(c, deps, workspaceId, "documents:search");
|
|
807
|
+
} catch (error) {
|
|
808
|
+
if (deps.settings.mcpOauthEnabled && error instanceof HTTPException && error.status === 401) {
|
|
809
|
+
c.header("www-authenticate", mcpOAuthAuthenticateHeader(deps, new URL(c.req.url).pathname));
|
|
606
810
|
}
|
|
811
|
+
throw error;
|
|
607
812
|
}
|
|
608
|
-
return
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
app.patch("/v1/workspaces/:workspaceId/knowledge/memories/:memoryId", async (c) => {
|
|
621
|
-
const workspaceId = c.req.param("workspaceId");
|
|
622
|
-
const grant = await requireAccessGrant(c, deps, workspaceId, "documents:manage");
|
|
623
|
-
const payload = UpdateKnowledgeMemoryRequest.parse(await c.req.json());
|
|
624
|
-
const reviewedBy =
|
|
625
|
-
payload.reviewedBy ??
|
|
626
|
-
(payload.status === "approved" || payload.status === "rejected"
|
|
627
|
-
? (grant.subjectLabel ?? grant.subjectId)
|
|
628
|
-
: undefined);
|
|
629
|
-
try {
|
|
630
|
-
return c.json(
|
|
631
|
-
KnowledgeMemory.parse(
|
|
632
|
-
await updateKnowledgeMemory(
|
|
633
|
-
db,
|
|
634
|
-
workspaceId,
|
|
635
|
-
c.req.param("memoryId"),
|
|
636
|
-
{
|
|
637
|
-
...payload,
|
|
638
|
-
...(reviewedBy ? { reviewedBy } : {}),
|
|
639
|
-
},
|
|
640
|
-
getDocumentServices().embedder,
|
|
813
|
+
return await withAccessGrantSessionRlsContext(deps, grant, async () => {
|
|
814
|
+
const transport = new WebStandardStreamableHTTPServerTransport({ enableJsonResponse: true });
|
|
815
|
+
const server = buildDocumentsMcpServer(
|
|
816
|
+
db,
|
|
817
|
+
grant.accountId,
|
|
818
|
+
workspaceId,
|
|
819
|
+
getDocumentServices(),
|
|
820
|
+
{
|
|
821
|
+
knowledge: await knowledgeContextForAccess(
|
|
822
|
+
deps,
|
|
823
|
+
await requireAccessGrantAuthorization(c, deps, workspaceId, "documents:search"),
|
|
824
|
+
"documents:search",
|
|
641
825
|
),
|
|
642
|
-
|
|
826
|
+
settings: deps.settings,
|
|
827
|
+
},
|
|
643
828
|
);
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
}
|
|
647
|
-
});
|
|
648
|
-
|
|
649
|
-
app.all("/v1/workspaces/:workspaceId/mcp/docs", async (c) => {
|
|
650
|
-
const workspaceId = c.req.param("workspaceId");
|
|
651
|
-
const grant = await requireAccessGrant(c, deps, workspaceId, "documents:search");
|
|
652
|
-
const sessionId =
|
|
653
|
-
typeof grant.metadata?.sessionId === "string" ? grant.metadata.sessionId : undefined;
|
|
654
|
-
const transport = new WebStandardStreamableHTTPServerTransport({ enableJsonResponse: true });
|
|
655
|
-
const server = buildDocumentsMcpServer(
|
|
656
|
-
db,
|
|
657
|
-
grant.accountId,
|
|
658
|
-
workspaceId,
|
|
659
|
-
getDocumentServices(),
|
|
660
|
-
{ createdBySessionId: sessionId, initiatingSubjectId: grant.subjectId },
|
|
661
|
-
);
|
|
662
|
-
await server.connect(transport);
|
|
663
|
-
return await transport.handleRequest(c.req.raw);
|
|
829
|
+
await server.connect(transport);
|
|
830
|
+
return await transport.handleRequest(c.req.raw);
|
|
831
|
+
});
|
|
664
832
|
});
|
|
665
833
|
}
|
|
666
834
|
|
|
667
|
-
async function parseDocumentSearchRequest(
|
|
668
|
-
context: Context,
|
|
669
|
-
message: string,
|
|
670
|
-
): Promise<DocumentSearchRequest> {
|
|
671
|
-
const parsed = DocumentSearchRequest.safeParse(await context.req.json().catch(() => null));
|
|
672
|
-
if (!parsed.success) {
|
|
673
|
-
throw new HTTPException(422, { message });
|
|
674
|
-
}
|
|
675
|
-
return parsed.data;
|
|
676
|
-
}
|
|
677
|
-
|
|
678
835
|
/** Derive a .txt filename for a raw-text drop from its optional title/filename. */
|
|
679
836
|
function dropFilename(preferred: string | undefined): string {
|
|
680
837
|
const stem = (preferred ?? "").trim() || `note-${new Date().toISOString().slice(0, 10)}`;
|
|
@@ -682,16 +839,47 @@ function dropFilename(preferred: string | undefined): string {
|
|
|
682
839
|
}
|
|
683
840
|
|
|
684
841
|
function documentHttpException(error: unknown): HTTPException {
|
|
685
|
-
const message =
|
|
842
|
+
const message = documentDomainErrorMessage(error);
|
|
686
843
|
if (message.includes("organization document") && message.includes("exact account authority")) {
|
|
687
844
|
return new HTTPException(403, { message: "missing permission: account:admin" });
|
|
688
845
|
}
|
|
689
846
|
if (message.includes("not found")) {
|
|
690
847
|
return new HTTPException(404, { message });
|
|
691
848
|
}
|
|
849
|
+
if (message.includes("document Default collection backfill audit run is unavailable")) {
|
|
850
|
+
return new HTTPException(404, { message });
|
|
851
|
+
}
|
|
692
852
|
if (message.includes("already exists")) {
|
|
693
853
|
return new HTTPException(409, { message });
|
|
694
854
|
}
|
|
855
|
+
if (
|
|
856
|
+
message.includes("operation id was reused") ||
|
|
857
|
+
message.includes("authority changed before reclassification") ||
|
|
858
|
+
message.includes("run identity mismatch")
|
|
859
|
+
) {
|
|
860
|
+
return new HTTPException(409, { message });
|
|
861
|
+
}
|
|
862
|
+
if (
|
|
863
|
+
message.includes("reclassification requires") ||
|
|
864
|
+
message.includes("backfill requires organization administration") ||
|
|
865
|
+
message.includes("document migration audit requires organization administration") ||
|
|
866
|
+
message.includes("document migration audit scope is invalid")
|
|
867
|
+
) {
|
|
868
|
+
return new HTTPException(403, { message });
|
|
869
|
+
}
|
|
870
|
+
if (
|
|
871
|
+
message.includes("reclassification input is invalid") ||
|
|
872
|
+
message.includes("reclassification authority is invalid") ||
|
|
873
|
+
message.includes("invalid document authority receipt cursor") ||
|
|
874
|
+
message.includes("document authority receipt limit") ||
|
|
875
|
+
message.includes("invalid document migration audit cursor") ||
|
|
876
|
+
message.includes("document migration audit cursor is invalid") ||
|
|
877
|
+
message.includes("document migration audit limit") ||
|
|
878
|
+
message.includes("document migration audit authority is incomplete") ||
|
|
879
|
+
message.includes("document Default collection backfill audit run id is required")
|
|
880
|
+
) {
|
|
881
|
+
return new HTTPException(400, { message });
|
|
882
|
+
}
|
|
695
883
|
if (message.includes("no suggested base")) {
|
|
696
884
|
return new HTTPException(422, { message });
|
|
697
885
|
}
|
|
@@ -711,6 +899,19 @@ function documentHttpException(error: unknown): HTTPException {
|
|
|
711
899
|
return new HTTPException(500, { message });
|
|
712
900
|
}
|
|
713
901
|
|
|
902
|
+
function documentDomainErrorMessage(error: unknown): string {
|
|
903
|
+
let current: unknown = error;
|
|
904
|
+
let message = error instanceof Error ? error.message : String(error);
|
|
905
|
+
const seen = new Set<unknown>();
|
|
906
|
+
while (current && typeof current === "object" && !seen.has(current) && seen.size < 8) {
|
|
907
|
+
seen.add(current);
|
|
908
|
+
const record = current as { cause?: unknown; message?: unknown };
|
|
909
|
+
if (typeof record.message === "string") message = record.message;
|
|
910
|
+
current = record.cause;
|
|
911
|
+
}
|
|
912
|
+
return message;
|
|
913
|
+
}
|
|
914
|
+
|
|
714
915
|
function hasAccountAdminAuthority(
|
|
715
916
|
authorization: Awaited<ReturnType<typeof requireAccessGrantAuthorization>>,
|
|
716
917
|
): boolean {
|