@opengeni/api-router 0.30.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (436) hide show
  1. package/dist/access-grant-rls.d.ts +3 -0
  2. package/dist/admission-trace.d.ts +8 -0
  3. package/dist/api-websocket.d.ts +18 -0
  4. package/dist/app.d.ts +50 -2
  5. package/dist/app.js +12 -1
  6. package/dist/artifact-catalog-cursor.d.ts +27 -0
  7. package/dist/auth/managed-auth-attempt-context.d.ts +10 -0
  8. package/dist/auth/managed-auth-rate-limits.d.ts +167 -0
  9. package/dist/auth/managed-auth-session-adapter.d.ts +6 -0
  10. package/dist/auth/managed-auth.d.ts +102 -3
  11. package/dist/auth/managed-email.d.ts +29 -0
  12. package/dist/auth/managed-sign-in-notifications.d.ts +4 -0
  13. package/dist/auth/new-signups-gate.d.ts +23 -0
  14. package/dist/auth/organization-user-setup.d.ts +80 -0
  15. package/dist/auth/signup-funnel-metrics.d.ts +44 -0
  16. package/dist/browser-controller-authority.d.ts +1 -61
  17. package/dist/browser-ephemeral.d.ts +5 -0
  18. package/dist/browser-state-authority.d.ts +1 -27
  19. package/dist/chunk-6TZ5LG3O.js +123948 -0
  20. package/dist/chunk-6TZ5LG3O.js.map +1 -0
  21. package/dist/chunk-OGQDXVXY.js +18 -0
  22. package/dist/chunk-OGQDXVXY.js.map +1 -0
  23. package/dist/claude-subscription-account-conflicts.d.ts +1 -0
  24. package/dist/claude-subscription-account-usage.d.ts +39 -0
  25. package/dist/claude-subscription-oauth.d.ts +25 -0
  26. package/dist/claude-subscription-profile.d.ts +9 -0
  27. package/dist/claude-subscription-usage.d.ts +44 -0
  28. package/dist/claude-workspace-connection.d.ts +15 -0
  29. package/dist/codemode.d.ts +32 -1
  30. package/dist/company-brain-okf.d.ts +24 -0
  31. package/dist/connected-machine-computer-access.d.ts +11 -0
  32. package/dist/connection-ownership.d.ts +54 -0
  33. package/dist/controller-data-plane.d.ts +32 -0
  34. package/dist/editable-artifact-office-import.d.ts +7 -4
  35. package/dist/editable-artifact-source-session.d.ts +3 -0
  36. package/dist/editable-artifact-websocket.d.ts +10 -18
  37. package/dist/editable-artifact-workspace-files.d.ts +1 -1
  38. package/dist/fatal-process-boundary.d.ts +25 -0
  39. package/dist/github-access.d.ts +31 -2
  40. package/dist/http/acting-person.d.ts +24 -0
  41. package/dist/http/api-contract-compat.d.ts +19 -0
  42. package/dist/http/api-error.d.ts +27 -1
  43. package/dist/http/cors.d.ts +17 -0
  44. package/dist/http/deprecation.d.ts +42 -0
  45. package/dist/http/interaction-control-error.d.ts +13 -0
  46. package/dist/http/keyed-admission.d.ts +12 -0
  47. package/dist/http/local-browser-boundary.d.ts +72 -0
  48. package/dist/http/metrics-listener.d.ts +22 -0
  49. package/dist/http/path-identifier.d.ts +17 -0
  50. package/dist/http/registered-route-label.d.ts +16 -0
  51. package/dist/http/request-body.d.ts +27 -0
  52. package/dist/http/request-source.d.ts +52 -0
  53. package/dist/http/sse.d.ts +17 -6
  54. package/dist/http/unmatched-route.d.ts +18 -0
  55. package/dist/http/user-content.d.ts +36 -0
  56. package/dist/http/websocket-upgrade-dispatch.d.ts +18 -0
  57. package/dist/index.d.ts +10 -3
  58. package/dist/index.js +1129 -166
  59. package/dist/index.js.map +1 -1
  60. package/dist/integration-endpoint-test.d.ts +20 -0
  61. package/dist/integrations/api-integrations.d.ts +2 -2
  62. package/dist/integrations/atlassian.d.ts +29 -3
  63. package/dist/integrations/connect-authority.d.ts +1 -0
  64. package/dist/integrations/connect-callback-return.d.ts +6 -0
  65. package/dist/integrations/fiken.d.ts +16 -2
  66. package/dist/integrations/github-app-connect.d.ts +47 -0
  67. package/dist/integrations/github-installation-proof.d.ts +3 -0
  68. package/dist/integrations/github-lens-connect.d.ts +116 -0
  69. package/dist/integrations/github-skill-source.d.ts +1 -5
  70. package/dist/integrations/google-drive.d.ts +25 -0
  71. package/dist/integrations/integration-commit-authority.d.ts +13 -0
  72. package/dist/integrations/marketplace-plugin.d.ts +2691 -0
  73. package/dist/integrations/oauth-client.d.ts +178 -18
  74. package/dist/integrations/oauth-profiles.d.ts +222 -0
  75. package/dist/integrations/oauth-return-path.d.ts +1 -0
  76. package/dist/integrations/personal-github-repositories.d.ts +84 -0
  77. package/dist/integrations/personal-github.d.ts +42 -0
  78. package/dist/integrations/pr-review-provider.d.ts +22 -0
  79. package/dist/integrations/provider-oauth.d.ts +19 -1
  80. package/dist/integrations/slack-app-home.d.ts +24 -0
  81. package/dist/integrations/slack-bot.d.ts +367 -12
  82. package/dist/integrations/slack-file-upload-flow.d.ts +62 -0
  83. package/dist/integrations/slack-install.d.ts +20 -0
  84. package/dist/integrations/slack-interactions.d.ts +113 -10
  85. package/dist/integrations/slack-mrkdwn.d.ts +41 -0
  86. package/dist/integrations/slack-routing.d.ts +120 -0
  87. package/dist/integrations/slack-session-defaults.d.ts +58 -0
  88. package/dist/integrations/slack-task-file-upload.d.ts +36 -0
  89. package/dist/integrations/social-oauth.d.ts +7 -0
  90. package/dist/interaction-agent-access.d.ts +15 -0
  91. package/dist/interaction-frame-proxy.d.ts +68 -0
  92. package/dist/interaction-metrics.d.ts +2 -0
  93. package/dist/mcp/action-catalog-types.d.ts +9 -0
  94. package/dist/mcp/action-catalog.gen.d.ts +2 -0
  95. package/dist/mcp/capability-account-readiness.d.ts +7 -0
  96. package/dist/mcp/child-read-evidence.d.ts +9 -0
  97. package/dist/mcp/command-read.d.ts +24 -0
  98. package/dist/mcp/company-profile-agent-admin.d.ts +44 -0
  99. package/dist/mcp/contract-input.d.ts +11 -0
  100. package/dist/mcp/documents.d.ts +7 -5
  101. package/dist/mcp/files.d.ts +2 -2
  102. package/dist/mcp/first-party-tool-permissions.d.ts +650 -0
  103. package/dist/mcp/knowledge-entries.d.ts +5 -0
  104. package/dist/mcp/orchestration-failure-diagnostic.d.ts +43 -0
  105. package/dist/mcp/receipts.d.ts +9 -0
  106. package/dist/mcp/request-abort.d.ts +19 -0
  107. package/dist/mcp/scheduled-task-input.d.ts +1189 -0
  108. package/dist/mcp/scheduled-task-view.d.ts +22 -4
  109. package/dist/mcp/server.d.ts +255 -3
  110. package/dist/mcp/session-event-view.d.ts +94 -0
  111. package/dist/mcp/session-view.d.ts +66 -2
  112. package/dist/mcp/session-wait.d.ts +174 -0
  113. package/dist/mcp-oauth.d.ts +52 -0
  114. package/dist/model-catalog.d.ts +11 -31
  115. package/dist/observability.d.ts +3 -1
  116. package/dist/organization-mcp.d.ts +52 -0
  117. package/dist/organization-recovery-notifications.d.ts +41 -0
  118. package/dist/routes/analytics-consent.d.ts +26 -0
  119. package/dist/routes/api-integrations.d.ts +25 -0
  120. package/dist/routes/api-keys.d.ts +17 -0
  121. package/dist/routes/artifact-catalog.d.ts +6 -0
  122. package/dist/routes/automations.d.ts +19 -0
  123. package/dist/routes/billing.d.ts +49 -0
  124. package/dist/routes/browser-sessions.d.ts +71 -3
  125. package/dist/routes/claude-subscription-accounts.d.ts +3 -0
  126. package/dist/routes/claude-subscription-oauth.d.ts +3 -0
  127. package/dist/routes/client-errors.d.ts +146 -0
  128. package/dist/routes/codex.d.ts +76 -2
  129. package/dist/routes/company-brain.d.ts +3 -0
  130. package/dist/routes/company-profile.d.ts +2 -1
  131. package/dist/routes/computer-sessions.d.ts +14 -0
  132. package/dist/routes/connect.d.ts +5 -0
  133. package/dist/routes/editable-artifacts.d.ts +2 -0
  134. package/dist/routes/external-identity-links.d.ts +6 -0
  135. package/dist/routes/feedback.d.ts +3 -0
  136. package/dist/routes/files.d.ts +4 -0
  137. package/dist/routes/github-browser-pages.d.ts +12 -0
  138. package/dist/routes/github.d.ts +2 -0
  139. package/dist/routes/insights-response-cache.d.ts +10 -0
  140. package/dist/routes/insights-usage.d.ts +12 -0
  141. package/dist/routes/insights.d.ts +30 -1
  142. package/dist/routes/knowledge.d.ts +3 -0
  143. package/dist/routes/managed-auth-session-sets.d.ts +26 -0
  144. package/dist/routes/managed-onboarding.d.ts +29 -0
  145. package/dist/routes/managed-sign-in-methods.d.ts +6 -0
  146. package/dist/routes/model-connection-access.d.ts +3 -0
  147. package/dist/routes/organization-integration-policy.d.ts +3 -0
  148. package/dist/routes/organization-integrations.d.ts +6 -0
  149. package/dist/routes/organization-mcp-connections.d.ts +3 -0
  150. package/dist/routes/organization-model-providers.d.ts +3 -0
  151. package/dist/routes/organization-recovery.d.ts +19 -0
  152. package/dist/routes/organization-service-accounts.d.ts +3 -0
  153. package/dist/routes/organization-sessions.d.ts +26 -0
  154. package/dist/routes/personal-github-git-broker.d.ts +29 -0
  155. package/dist/routes/personal-github.d.ts +3 -0
  156. package/dist/routes/pr-review-github.d.ts +3 -0
  157. package/dist/routes/pr-review.d.ts +3 -0
  158. package/dist/routes/session-artifact-associations.d.ts +4 -0
  159. package/dist/routes/session-history-imports.d.ts +9 -0
  160. package/dist/routes/sessions.d.ts +44 -6
  161. package/dist/routes/skill-content.d.ts +4 -0
  162. package/dist/routes/skill-install-authority.d.ts +6 -0
  163. package/dist/routes/subscription-account-pools.d.ts +34 -0
  164. package/dist/routes/subscription-pool-access.d.ts +16 -0
  165. package/dist/routes/supergrok.d.ts +6 -1
  166. package/dist/routes/usage-allowances.d.ts +12 -0
  167. package/dist/routes/user-resource-authorities.d.ts +3 -0
  168. package/dist/routes/workspace-artifacts.d.ts +2 -1
  169. package/dist/routes/workspace-capture.d.ts +10 -2
  170. package/dist/routes/workspace-integrations.d.ts +35 -0
  171. package/dist/routes/workspace-learning.d.ts +3 -0
  172. package/dist/routes/workspace-model-providers.d.ts +4 -0
  173. package/dist/routes/workspaces.d.ts +29 -0
  174. package/dist/sandbox/auth-callout.d.ts +8 -0
  175. package/dist/sandbox/channel-a.d.ts +19 -1
  176. package/dist/sandbox/connection-authority.d.ts +3 -0
  177. package/dist/sandbox/enrollment.d.ts +9 -1
  178. package/dist/sandbox/machines.d.ts +5 -2
  179. package/dist/sandbox/metrics-ingestion.d.ts +28 -20
  180. package/dist/sandbox/rematerialize.d.ts +2 -0
  181. package/dist/sandbox/session-attach-variable-sets.d.ts +30 -0
  182. package/dist/sandbox/viewer.d.ts +26 -1
  183. package/dist/sandbox-file-artifacts.d.ts +50 -0
  184. package/dist/scheduled-task-deletion.d.ts +13 -0
  185. package/dist/session-create-observability.d.ts +5 -0
  186. package/dist/session-event-view-MPS2OZD3.js +292 -0
  187. package/dist/session-event-view-MPS2OZD3.js.map +1 -0
  188. package/dist/site-session-origin.d.ts +13 -0
  189. package/dist/site-uploads.d.ts +41 -0
  190. package/dist/slack-reaction-files.d.ts +1 -1
  191. package/dist/temporal-schedule-cleanup.d.ts +1 -0
  192. package/dist/temporal-schedule-sync.d.ts +26 -0
  193. package/dist/transcription/providers/xai-subscription.d.ts +1 -0
  194. package/dist/transcription/service.d.ts +2 -1
  195. package/dist/work-discovery-observability.d.ts +33 -0
  196. package/dist/workspace-artifact-content.d.ts +28 -0
  197. package/dist/workspace-artifact-provenance.d.ts +7 -0
  198. package/dist/workspace-delete-observability.d.ts +10 -0
  199. package/dist/workspace-deletion.d.ts +6 -0
  200. package/dist/workspace-state-projection.d.ts +3 -5
  201. package/dist/workspace-tool-gateway-observability.d.ts +17 -0
  202. package/dist/workspace-tool-gateway.d.ts +123 -0
  203. package/dist/workspace-webhook-dispatch.d.ts +26 -0
  204. package/package.json +23 -19
  205. package/src/access-grant-rls.ts +75 -0
  206. package/src/admission-trace.ts +14 -0
  207. package/src/api-websocket.ts +23 -0
  208. package/src/app.ts +1974 -256
  209. package/src/artifact-catalog-cursor.ts +60 -0
  210. package/src/auth/managed-auth-attempt-context.ts +70 -0
  211. package/src/auth/managed-auth-rate-limits.ts +252 -0
  212. package/src/auth/managed-auth-session-adapter.ts +222 -0
  213. package/src/auth/managed-auth.ts +536 -60
  214. package/src/auth/managed-email.ts +174 -0
  215. package/src/auth/managed-sign-in-notifications.ts +81 -0
  216. package/src/auth/new-signups-gate.ts +49 -0
  217. package/src/auth/organization-user-setup.ts +307 -0
  218. package/src/auth/signup-funnel-metrics.ts +164 -0
  219. package/src/browser-controller-authority.ts +1 -186
  220. package/src/browser-ephemeral.ts +39 -0
  221. package/src/browser-state-authority.ts +1 -236
  222. package/src/claude-subscription-account-conflicts.ts +12 -0
  223. package/src/claude-subscription-account-usage.ts +48 -0
  224. package/src/claude-subscription-oauth.ts +362 -0
  225. package/src/claude-subscription-profile.ts +73 -0
  226. package/src/claude-subscription-usage.ts +97 -0
  227. package/src/claude-workspace-connection.ts +82 -0
  228. package/src/codemode.ts +194 -30
  229. package/src/codex-realtime.ts +8 -2
  230. package/src/company-brain-okf.ts +340 -0
  231. package/src/connected-machine-computer-access.ts +33 -0
  232. package/src/connection-ownership.ts +199 -0
  233. package/src/controller-data-plane.ts +81 -0
  234. package/src/editable-artifact-native-kernel.ts +26 -15
  235. package/src/editable-artifact-office-import.ts +77 -9
  236. package/src/editable-artifact-production.ts +23 -7
  237. package/src/editable-artifact-source-session.ts +123 -0
  238. package/src/editable-artifact-websocket.ts +27 -21
  239. package/src/editable-artifact-workspace-files.ts +31 -6
  240. package/src/fatal-process-boundary.ts +246 -0
  241. package/src/gateway-realtime.ts +1 -1
  242. package/src/github-access.ts +147 -5
  243. package/src/http/acting-person.ts +71 -0
  244. package/src/http/api-contract-compat.ts +49 -0
  245. package/src/http/api-error.ts +115 -1
  246. package/src/http/auth.ts +48 -0
  247. package/src/http/cors.ts +67 -0
  248. package/src/http/deprecation.ts +118 -0
  249. package/src/http/interaction-control-error.ts +164 -0
  250. package/src/http/keyed-admission.ts +29 -0
  251. package/src/http/local-browser-boundary.ts +343 -0
  252. package/src/http/metrics-listener.ts +57 -0
  253. package/src/http/path-identifier.ts +54 -0
  254. package/src/http/registered-route-label.ts +34 -0
  255. package/src/http/request-body.ts +127 -0
  256. package/src/http/request-source.ts +178 -0
  257. package/src/http/sse.ts +486 -132
  258. package/src/http/unmatched-route.ts +60 -0
  259. package/src/http/user-content.ts +158 -0
  260. package/src/http/websocket-upgrade-dispatch.ts +29 -0
  261. package/src/index.ts +157 -52
  262. package/src/integration-endpoint-test.ts +291 -0
  263. package/src/integrations/api-integrations.ts +98 -11
  264. package/src/integrations/atlassian.ts +474 -136
  265. package/src/integrations/connect-authority.ts +2 -0
  266. package/src/integrations/connect-callback-return.ts +86 -0
  267. package/src/integrations/fiken.ts +354 -64
  268. package/src/integrations/github-app-connect.ts +435 -0
  269. package/src/integrations/github-installation-proof.ts +60 -0
  270. package/src/integrations/github-lens-connect.ts +76 -0
  271. package/src/integrations/github-skill-source.ts +2 -142
  272. package/src/integrations/google-drive.ts +820 -222
  273. package/src/integrations/integration-commit-authority.ts +69 -0
  274. package/src/integrations/marketplace-plugin.ts +48 -0
  275. package/src/integrations/oauth-client.ts +1356 -459
  276. package/src/integrations/oauth-profiles.ts +537 -0
  277. package/src/integrations/oauth-return-path.ts +18 -0
  278. package/src/integrations/personal-github-repositories.ts +674 -0
  279. package/src/integrations/personal-github.ts +825 -0
  280. package/src/integrations/pr-review-provider.ts +246 -0
  281. package/src/integrations/provider-oauth.ts +250 -22
  282. package/src/integrations/slack-app-home.ts +300 -0
  283. package/src/integrations/slack-bot.ts +963 -239
  284. package/src/integrations/slack-file-upload-flow.ts +147 -0
  285. package/src/integrations/slack-install.ts +83 -0
  286. package/src/integrations/slack-interactions.ts +3170 -474
  287. package/src/integrations/slack-mrkdwn.ts +193 -0
  288. package/src/integrations/slack-routing.ts +337 -0
  289. package/src/integrations/slack-session-defaults.ts +224 -0
  290. package/src/integrations/slack-task-file-upload.ts +323 -0
  291. package/src/integrations/social-oauth.ts +213 -15
  292. package/src/interaction-agent-access.ts +48 -0
  293. package/src/interaction-frame-proxy.ts +409 -0
  294. package/src/interaction-metrics.ts +30 -0
  295. package/src/mcp/action-catalog-types.ts +9 -0
  296. package/src/mcp/action-catalog.gen.ts +6696 -0
  297. package/src/mcp/capability-account-readiness.ts +17 -0
  298. package/src/mcp/child-read-evidence.ts +19 -0
  299. package/src/mcp/command-read.ts +109 -0
  300. package/src/mcp/company-profile-agent-admin.ts +198 -0
  301. package/src/mcp/contract-input.ts +141 -0
  302. package/src/mcp/documents.ts +65 -377
  303. package/src/mcp/editable-artifacts.ts +12 -6
  304. package/src/mcp/files.ts +80 -38
  305. package/src/mcp/first-party-tool-permissions.ts +305 -0
  306. package/src/mcp/knowledge-entries.ts +322 -0
  307. package/src/mcp/orchestration-failure-diagnostic.ts +43 -0
  308. package/src/mcp/receipts.ts +34 -0
  309. package/src/mcp/request-abort.ts +44 -0
  310. package/src/mcp/scheduled-task-input.ts +76 -0
  311. package/src/mcp/scheduled-task-view.ts +44 -3
  312. package/src/mcp/server.ts +3030 -1267
  313. package/src/mcp/session-event-view.ts +383 -0
  314. package/src/mcp/session-view.ts +84 -3
  315. package/src/mcp/session-wait.ts +665 -0
  316. package/src/mcp-oauth.ts +1123 -0
  317. package/src/model-catalog.ts +91 -333
  318. package/src/observability.ts +15 -1
  319. package/src/organization-mcp.ts +397 -0
  320. package/src/organization-recovery-notifications.ts +103 -0
  321. package/src/routes/analytics-consent.ts +123 -0
  322. package/src/routes/api-integrations.ts +364 -74
  323. package/src/routes/api-keys.ts +336 -10
  324. package/src/routes/artifact-catalog.ts +279 -0
  325. package/src/routes/automations.ts +768 -0
  326. package/src/routes/billing.ts +461 -46
  327. package/src/routes/browser-sessions.ts +839 -131
  328. package/src/routes/canonical-human-identities.ts +90 -14
  329. package/src/routes/capabilities.ts +107 -6
  330. package/src/routes/channels.ts +20 -3
  331. package/src/routes/claude-subscription-accounts.ts +334 -0
  332. package/src/routes/claude-subscription-oauth.ts +142 -0
  333. package/src/routes/client-errors.ts +362 -0
  334. package/src/routes/codex.ts +833 -116
  335. package/src/routes/company-brain.ts +322 -0
  336. package/src/routes/company-profile.ts +65 -1
  337. package/src/routes/computer-sessions.ts +557 -106
  338. package/src/routes/connect.ts +1938 -0
  339. package/src/routes/connections.ts +1040 -349
  340. package/src/routes/documents.ts +488 -287
  341. package/src/routes/editable-artifacts.ts +79 -9
  342. package/src/routes/enrollments.ts +135 -39
  343. package/src/routes/environments.ts +154 -58
  344. package/src/routes/external-identity-links.ts +201 -0
  345. package/src/routes/feedback.ts +113 -0
  346. package/src/routes/files.ts +337 -39
  347. package/src/routes/github-browser-pages.ts +162 -0
  348. package/src/routes/github.ts +446 -144
  349. package/src/routes/insights-response-cache.ts +83 -0
  350. package/src/routes/insights-usage.ts +345 -0
  351. package/src/routes/insights.ts +153 -19
  352. package/src/routes/install.ts +133 -38
  353. package/src/routes/integration-facets.ts +107 -33
  354. package/src/routes/interaction-resources.ts +30 -3
  355. package/src/routes/knowledge.ts +488 -0
  356. package/src/routes/machines.ts +313 -15
  357. package/src/routes/managed-auth-session-sets.ts +1218 -0
  358. package/src/routes/managed-onboarding.ts +337 -0
  359. package/src/routes/managed-sign-in-methods.ts +433 -0
  360. package/src/routes/memory-slack-publications.ts +3 -2
  361. package/src/routes/model-connection-access.ts +208 -0
  362. package/src/routes/organization-integration-policy.ts +116 -0
  363. package/src/routes/organization-integrations.ts +326 -0
  364. package/src/routes/organization-mcp-connections.ts +178 -0
  365. package/src/routes/organization-memberships.ts +1019 -27
  366. package/src/routes/organization-model-providers.ts +293 -0
  367. package/src/routes/organization-recovery.ts +325 -0
  368. package/src/routes/organization-service-accounts.ts +128 -0
  369. package/src/routes/organization-sessions.ts +350 -0
  370. package/src/routes/personal-github-git-broker.ts +785 -0
  371. package/src/routes/personal-github.ts +370 -0
  372. package/src/routes/plugins.ts +251 -22
  373. package/src/routes/pr-review-github.ts +881 -0
  374. package/src/routes/pr-review.ts +622 -0
  375. package/src/routes/preference-registry.ts +12 -93
  376. package/src/routes/rigs.ts +167 -50
  377. package/src/routes/scheduled-tasks.ts +346 -41
  378. package/src/routes/session-artifact-associations.ts +87 -0
  379. package/src/routes/session-history-imports.ts +280 -0
  380. package/src/routes/sessions.ts +2306 -264
  381. package/src/routes/skill-content.ts +297 -0
  382. package/src/routes/skill-install-authority.ts +64 -0
  383. package/src/routes/skills.ts +62 -9
  384. package/src/routes/social.ts +46 -18
  385. package/src/routes/subscription-account-pools.ts +436 -0
  386. package/src/routes/subscription-pool-access.ts +126 -0
  387. package/src/routes/supergrok.ts +219 -303
  388. package/src/routes/transcription-recordings.ts +38 -3
  389. package/src/routes/transcriptions.ts +4 -0
  390. package/src/routes/usage-allowances.ts +378 -0
  391. package/src/routes/user-resource-authorities.ts +138 -0
  392. package/src/routes/video-generation.ts +14 -10
  393. package/src/routes/workspace-artifacts.ts +275 -69
  394. package/src/routes/workspace-capture.ts +21 -0
  395. package/src/routes/workspace-integrations.ts +576 -0
  396. package/src/routes/workspace-learning.ts +159 -0
  397. package/src/routes/workspace-model-providers.ts +148 -0
  398. package/src/routes/workspace-state.ts +38 -25
  399. package/src/routes/workspaces.ts +1004 -127
  400. package/src/sandbox/auth-callout.ts +96 -19
  401. package/src/sandbox/channel-a.ts +323 -24
  402. package/src/sandbox/connection-authority.ts +3 -0
  403. package/src/sandbox/enrollment.ts +81 -6
  404. package/src/sandbox/machines.ts +218 -76
  405. package/src/sandbox/metrics-ingestion.ts +411 -62
  406. package/src/sandbox/rematerialize.ts +121 -19
  407. package/src/sandbox/session-attach-variable-sets.ts +131 -0
  408. package/src/sandbox/viewer.ts +280 -25
  409. package/src/sandbox-file-artifacts.ts +413 -0
  410. package/src/scheduled-task-deletion.ts +138 -0
  411. package/src/session-create-observability.ts +46 -0
  412. package/src/session-realtime-context.ts +6 -3
  413. package/src/site-session-origin.ts +48 -0
  414. package/src/site-uploads.ts +224 -0
  415. package/src/slack-reaction-files.ts +16 -5
  416. package/src/temporal-schedule-cleanup.ts +13 -0
  417. package/src/temporal-schedule-sync.ts +74 -0
  418. package/src/transcription/providers/codex-subscription.ts +2 -0
  419. package/src/transcription/providers/openai.ts +1 -0
  420. package/src/transcription/providers/xai-subscription.ts +49 -3
  421. package/src/transcription/segmenter.ts +8 -2
  422. package/src/transcription/service.ts +43 -6
  423. package/src/work-discovery-observability.ts +121 -0
  424. package/src/workspace-artifact-content.ts +144 -0
  425. package/src/workspace-artifact-provenance.ts +104 -0
  426. package/src/workspace-delete-observability.ts +75 -0
  427. package/src/workspace-deletion.ts +73 -0
  428. package/src/workspace-state-projection.ts +18 -148
  429. package/src/workspace-tool-gateway-observability.ts +100 -0
  430. package/src/workspace-tool-gateway.ts +870 -0
  431. package/src/workspace-webhook-dispatch.ts +190 -0
  432. package/src/xai-subscription-auth.ts +9 -2
  433. package/dist/chunk-2PQMSRCB.js +0 -49759
  434. package/dist/chunk-2PQMSRCB.js.map +0 -1
  435. package/dist/routes/packs.d.ts +0 -3
  436. package/src/routes/packs.ts +0 -729
@@ -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
- DocumentSearchRequest,
9
- DocumentSearchResponse,
10
- KnowledgeMemory,
11
- KnowledgeMemorySearchRequest,
10
+ DocumentDefaultCollectionBackfill,
11
+ DocumentDefaultCollectionBackfillAudit,
12
+ GetDocumentDefaultCollectionBackfillAuditQuery,
13
+ FileAsset,
14
+ FileDownloadUrlResponse,
15
+ ListDocumentAuthorityReclassificationsQuery,
16
+ ListDocumentAuthorityReclassificationsResponse,
17
+ ListDocumentDefaultCollectionBackfillRunsResponse,
18
+ ListDocumentMigrationAuditQuery,
19
+ ListOrganizationDocumentAuthorityReclassificationsResponse,
12
20
  MoveDocumentRequest,
13
- UpdateKnowledgeMemoryRequest,
14
- WorkspaceMemorySearchRequest,
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
- searchEffectiveDocuments,
42
+ reclassifyDocumentAuthority,
43
+ runDocumentDefaultCollectionBackfill,
38
44
  } from "@opengeni/documents";
39
45
  import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
40
- import type { Context, Hono } from "hono";
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
- saveWorkspaceMemoryWithSlackPublication,
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 = CreateDocumentBaseRequest.parse(await c.req.json());
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 = AddDocumentRequest.parse(await c.req.json());
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, { message: "object storage is not configured" });
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
- workspaceId,
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
- app.post("/v1/workspaces/:workspaceId/document-bases/:baseId/search", async (c) => {
279
- const workspaceId = c.req.param("workspaceId");
280
- const grant = await requireAccessGrant(c, deps, workspaceId, "documents:search");
281
- const payload = DocumentSearchRequest.parse(await c.req.json());
282
- const base = await getDocumentBase(db, workspaceId, c.req.param("baseId"));
283
- if (!base) {
284
- throw new HTTPException(404, { message: "document base not found" });
285
- }
286
- return c.json(
287
- DocumentSearchResponse.parse({
288
- results: await searchEffectiveDocuments(
289
- db,
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
- // Knowledge drop: raw text or an uploaded file, no metadata required. Lands
335
- // in the workspace Default base with curationStatus 'pending'; indexing then
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 = CreateKnowledgeDropRequest.parse(await c.req.json());
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: "pending",
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.parse(await c.req.json().catch(() => ({})));
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
- app.get("/v1/workspaces/:workspaceId/knowledge/memories", async (c) => {
505
- const workspaceId = c.req.param("workspaceId");
506
- await requireAccessGrant(c, deps, workspaceId, "documents:search");
507
- const parsed = KnowledgeMemorySearchRequest.safeParse({
508
- query: c.req.query("query") || undefined,
509
- status: c.req.query("status") || undefined,
510
- kind: c.req.query("kind") || undefined,
511
- scope: c.req.query("scope") || undefined,
512
- limit: c.req.query("limit") ? Number(c.req.query("limit")) : undefined,
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
- if (!parsed.success) {
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.post("/v1/workspaces/:workspaceId/knowledge/memories", async (c) => {
770
+ app.all("/v1/workspaces/:workspaceId/mcp/docs", async (c) => {
560
771
  const workspaceId = c.req.param("workspaceId");
561
- const grant = await requireAccessGrant(c, deps, workspaceId, "documents:manage");
562
- const parsedBody = CreateKnowledgeMemoryRequest.safeParse(await c.req.json());
563
- if (!parsedBody.success) {
564
- throw new HTTPException(400, { message: "invalid knowledge memory request" });
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
- const payload = parsedBody.data;
567
- if (payload.status !== "active" && payload.slackPublication) {
568
- throw new HTTPException(400, {
569
- message: "Slack publication is available only for active Workspace Memory writes",
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
- // status `active` (the default) is a memory write → route through the single
573
- // gate (sanitize + embed + dedup). Explicit proposed/approved/rejected keeps
574
- // the legacy curated create.
575
- if (payload.status === "active") {
576
- try {
577
- const result = await saveWorkspaceMemoryWithSlackPublication(
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 c.json(
609
- KnowledgeMemory.parse(
610
- await createKnowledgeMemory(db, {
611
- ...payload,
612
- accountId: grant.accountId,
613
- workspaceId,
614
- }),
615
- ),
616
- 201,
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
- } catch (error) {
645
- throw documentHttpException(error);
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 = error instanceof Error ? error.message : String(error);
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 {