@opengeni/api-router 3.0.1 → 3.0.2-canary.38894290271001

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 (546) hide show
  1. package/dist/access-grant-rls.d.ts +8 -1
  2. package/dist/admission-trace.d.ts +8 -0
  3. package/dist/app.d.ts +50 -3
  4. package/dist/app.js +10 -1
  5. package/dist/artifact-catalog-cursor.d.ts +1 -0
  6. package/dist/attached-browser-viewer.d.ts +11 -0
  7. package/dist/auth/managed-auth-attempt-context.d.ts +2 -0
  8. package/dist/auth/managed-auth-rate-limits.d.ts +167 -0
  9. package/dist/auth/managed-auth-session-adapter.d.ts +9 -1
  10. package/dist/auth/managed-auth.d.ts +72 -5
  11. package/dist/auth/managed-sign-in-notifications.d.ts +4 -0
  12. package/dist/auth/new-signups-gate.d.ts +23 -0
  13. package/dist/auth/signup-funnel-metrics.d.ts +44 -0
  14. package/dist/azure-live.d.ts +28 -0
  15. package/dist/browser-action-fences.d.ts +13 -0
  16. package/dist/browser-controller-authority.d.ts +1 -61
  17. package/dist/browser-ephemeral.d.ts +5 -0
  18. package/dist/browser-lost-runtime-end.d.ts +24 -0
  19. package/dist/browser-state-authority.d.ts +1 -27
  20. package/dist/{chunk-AJ62T5QN.js → chunk-GBUJ2DYZ.js} +80507 -39878
  21. package/dist/chunk-GBUJ2DYZ.js.map +1 -0
  22. package/dist/chunk-OGQDXVXY.js +18 -0
  23. package/dist/chunk-OGQDXVXY.js.map +1 -0
  24. package/dist/claude-default-models.d.ts +19 -0
  25. package/dist/claude-subscription-core.d.ts +50 -0
  26. package/dist/claude-subscription-oauth.d.ts +36 -0
  27. package/dist/claude-subscription-profile.d.ts +9 -0
  28. package/dist/claude-subscription-usage.d.ts +6 -0
  29. package/dist/claude-workspace-connection.d.ts +15 -0
  30. package/dist/codemode.d.ts +40 -5
  31. package/dist/codex-realtime.d.ts +29 -3
  32. package/dist/codex-session-pointers.d.ts +19 -0
  33. package/dist/connection-ownership.d.ts +6 -3
  34. package/dist/controller-data-plane.d.ts +16 -0
  35. package/dist/credit-promotion-snapshot.d.ts +6 -0
  36. package/dist/editable-artifact-source-session.d.ts +3 -0
  37. package/dist/editable-artifact-websocket.d.ts +5 -3
  38. package/dist/fatal-process-boundary.d.ts +9 -1
  39. package/dist/github-access.d.ts +7 -1
  40. package/dist/github-browser-flow.d.ts +1 -1
  41. package/dist/http/acting-person.d.ts +36 -0
  42. package/dist/http/api-contract-compat.d.ts +19 -0
  43. package/dist/http/api-error.d.ts +50 -1
  44. package/dist/http/auth.d.ts +8 -1
  45. package/dist/http/cors.d.ts +12 -0
  46. package/dist/http/deprecation.d.ts +42 -0
  47. package/dist/http/keyed-admission.d.ts +12 -0
  48. package/dist/http/local-browser-boundary.d.ts +72 -0
  49. package/dist/http/metrics-listener.d.ts +22 -0
  50. package/dist/http/path-identifier.d.ts +17 -0
  51. package/dist/http/registered-route-label.d.ts +16 -0
  52. package/dist/http/rejection-telemetry.d.ts +34 -0
  53. package/dist/http/request-body.d.ts +27 -0
  54. package/dist/http/request-source.d.ts +41 -3
  55. package/dist/http/sse.d.ts +12 -1
  56. package/dist/http/unmatched-route.d.ts +18 -0
  57. package/dist/http/user-content.d.ts +36 -0
  58. package/dist/http/variable-sets-removed.d.ts +41 -0
  59. package/dist/http/websocket-upgrade-dispatch.d.ts +18 -0
  60. package/dist/index.js +1279 -108
  61. package/dist/index.js.map +1 -1
  62. package/dist/integration-connect-metrics.d.ts +35 -0
  63. package/dist/integration-endpoint-test.d.ts +20 -0
  64. package/dist/integrations/api-integrations.d.ts +2 -2
  65. package/dist/integrations/atlassian.d.ts +8 -3
  66. package/dist/integrations/fiken.d.ts +3 -1
  67. package/dist/integrations/github-lens-connect.d.ts +37 -66
  68. package/dist/integrations/google-drive.d.ts +2 -0
  69. package/dist/integrations/integration-commit-authority.d.ts +13 -0
  70. package/dist/integrations/marketplace-plugin.d.ts +43 -43
  71. package/dist/integrations/oauth-client.d.ts +171 -12
  72. package/dist/integrations/oauth-profiles.d.ts +42 -13
  73. package/dist/integrations/onepassword-vault-provider.d.ts +9 -0
  74. package/dist/integrations/slack-bot.d.ts +285 -7
  75. package/dist/integrations/slack-file-upload-flow.d.ts +62 -0
  76. package/dist/integrations/slack-interactions.d.ts +89 -10
  77. package/dist/integrations/slack-mrkdwn.d.ts +41 -0
  78. package/dist/integrations/slack-routing.d.ts +1 -1
  79. package/dist/integrations/slack-session-defaults.d.ts +58 -0
  80. package/dist/integrations/slack-task-file-upload.d.ts +36 -0
  81. package/dist/integrations/slack-tool-review.d.ts +5 -0
  82. package/dist/interaction-agent-access.d.ts +13 -8
  83. package/dist/interaction-agent-version.d.ts +21 -0
  84. package/dist/interaction-holder-heartbeat.d.ts +5 -0
  85. package/dist/interaction-metrics.d.ts +27 -2
  86. package/dist/interaction-route-stages.d.ts +25 -0
  87. package/dist/interaction-secrets-vault.d.ts +20 -0
  88. package/dist/interaction-secrets.d.ts +103 -0
  89. package/dist/mcp/action-catalog-types.d.ts +14 -0
  90. package/dist/mcp/action-catalog.gen.d.ts +2 -0
  91. package/dist/mcp/action-descriptions.d.ts +4 -0
  92. package/dist/mcp/action-schema-imports.gen.d.ts +1 -0
  93. package/dist/mcp/capability-account-readiness.d.ts +7 -0
  94. package/dist/mcp/child-read-evidence.d.ts +9 -0
  95. package/dist/mcp/company-profile-agent-admin.d.ts +12 -0
  96. package/dist/mcp/contract-input.d.ts +13 -0
  97. package/dist/mcp/documents.d.ts +2 -0
  98. package/dist/mcp/first-party-tool-permissions.d.ts +3 -606
  99. package/dist/mcp/notification-tools.d.ts +26 -0
  100. package/dist/mcp/orchestration-failure-diagnostic.d.ts +43 -0
  101. package/dist/mcp/scheduled-task-input.d.ts +1309 -0
  102. package/dist/mcp/scheduled-task-view.d.ts +217 -3
  103. package/dist/mcp/secret-tools.d.ts +14 -0
  104. package/dist/mcp/server.d.ts +108 -5
  105. package/dist/mcp/session-admin-access-tools.d.ts +33 -0
  106. package/dist/mcp/session-event-errors.d.ts +28 -0
  107. package/dist/mcp/session-event-view.d.ts +62 -0
  108. package/dist/mcp/session-view.d.ts +15 -0
  109. package/dist/mcp/session-wait.d.ts +18 -0
  110. package/dist/mcp/site-agent-clamp-tools.d.ts +38 -0
  111. package/dist/mcp/site-data-tools.d.ts +22 -0
  112. package/dist/mcp/site-publication-tools.d.ts +19 -0
  113. package/dist/mcp/site-sql-tools.d.ts +27 -0
  114. package/dist/mcp-oauth.d.ts +37 -4
  115. package/dist/model-calls/chat-completions.d.ts +87 -0
  116. package/dist/model-calls/pending-usage-settlements.d.ts +57 -0
  117. package/dist/model-calls/service.d.ts +36 -0
  118. package/dist/model-catalog.d.ts +9 -3
  119. package/dist/native-push-dispatch.d.ts +69 -0
  120. package/dist/observability.d.ts +3 -1
  121. package/dist/organization-mcp.d.ts +82 -0
  122. package/dist/prepared-mcp-actor.d.ts +77 -0
  123. package/dist/prepared-mcp-permissions.d.ts +8 -0
  124. package/dist/routes/analytics-consent.d.ts +26 -0
  125. package/dist/routes/api-integrations.d.ts +11 -0
  126. package/dist/routes/api-keys.d.ts +7 -7
  127. package/dist/routes/automations.d.ts +2 -0
  128. package/dist/routes/billing.d.ts +59 -0
  129. package/dist/routes/browser-sessions.d.ts +65 -2
  130. package/dist/routes/chat-completions.d.ts +11 -0
  131. package/dist/routes/claude-core-usage.d.ts +20 -0
  132. package/dist/routes/claude-subscription-accounts.d.ts +3 -0
  133. package/dist/routes/claude-subscription-oauth.d.ts +3 -0
  134. package/dist/routes/client-errors.d.ts +182 -0
  135. package/dist/routes/codex-core.d.ts +401 -0
  136. package/dist/routes/codex.d.ts +64 -2
  137. package/dist/routes/computer-sessions.d.ts +6 -1
  138. package/dist/routes/desktop-distribution.d.ts +32 -0
  139. package/dist/routes/github-browser-fonts.gen.d.ts +2 -0
  140. package/dist/routes/github-browser-pages.d.ts +27 -0
  141. package/dist/routes/inbox.d.ts +13 -0
  142. package/dist/routes/insights-response-cache.d.ts +10 -0
  143. package/dist/routes/insights-usage.d.ts +12 -0
  144. package/dist/routes/insights.d.ts +28 -0
  145. package/dist/routes/interaction-placement-message.d.ts +7 -0
  146. package/dist/routes/managed-sign-in-methods.d.ts +6 -0
  147. package/dist/routes/model-account-choice.d.ts +13 -0
  148. package/dist/routes/model-account-settings.d.ts +19 -0
  149. package/dist/routes/native-app-auth.d.ts +12 -0
  150. package/dist/routes/organization-integration-policy.d.ts +8 -0
  151. package/dist/routes/organization-integrations.d.ts +6 -0
  152. package/dist/routes/organization-mcp-connections.d.ts +3 -0
  153. package/dist/routes/organization-model-defaults.d.ts +9 -0
  154. package/dist/routes/organization-service-accounts.d.ts +3 -0
  155. package/dist/routes/personal-api-keys.d.ts +3 -0
  156. package/dist/routes/session-admin-access.d.ts +3 -0
  157. package/dist/routes/session-artifact-associations.d.ts +4 -0
  158. package/dist/routes/session-history-imports.d.ts +20 -0
  159. package/dist/routes/sessions.d.ts +38 -2
  160. package/dist/routes/site-data.d.ts +18 -0
  161. package/dist/routes/site-publishing.d.ts +5 -0
  162. package/dist/routes/site-runtime.d.ts +31 -0
  163. package/dist/routes/site-sql.d.ts +16 -0
  164. package/dist/routes/slack-bot-access.d.ts +3 -0
  165. package/dist/routes/subscription-account-pools.d.ts +21 -0
  166. package/dist/routes/subscription-core-http.d.ts +5 -0
  167. package/dist/routes/subscription-pool-access.d.ts +37 -0
  168. package/dist/routes/subscription-pool-core.d.ts +153 -0
  169. package/dist/routes/supergrok.d.ts +6 -6
  170. package/dist/routes/usage-allowances.d.ts +12 -0
  171. package/dist/routes/variable-sets-removed.d.ts +2 -0
  172. package/dist/routes/vault-providers.d.ts +34 -0
  173. package/dist/routes/vaults.d.ts +3 -0
  174. package/dist/routes/workspace-integrations.d.ts +35 -0
  175. package/dist/routes/workspace-model-providers.d.ts +4 -0
  176. package/dist/routes/workspaces.d.ts +11 -2
  177. package/dist/sandbox/agent-update.d.ts +64 -0
  178. package/dist/sandbox/auth-callout.d.ts +8 -0
  179. package/dist/sandbox/channel-a.d.ts +15 -1
  180. package/dist/sandbox/enrollment.d.ts +26 -4
  181. package/dist/sandbox/machine-audience.d.ts +29 -0
  182. package/dist/sandbox/machines.d.ts +15 -2
  183. package/dist/sandbox/metrics-ingestion.d.ts +6 -2
  184. package/dist/sandbox/screen-control.d.ts +85 -0
  185. package/dist/sandbox/viewer.d.ts +5 -1
  186. package/dist/sandbox-file-artifacts.d.ts +17 -1
  187. package/dist/scheduled-task-blockers.d.ts +39 -0
  188. package/dist/scheduled-task-deletion.d.ts +3 -4
  189. package/dist/scheduled-task-lifecycle.d.ts +14 -0
  190. package/dist/secret-answers.d.ts +40 -0
  191. package/dist/session-create-observability.d.ts +5 -0
  192. package/dist/session-event-view-36GO3IL7.js +528 -0
  193. package/dist/session-event-view-36GO3IL7.js.map +1 -0
  194. package/dist/signed-state-secret.d.ts +18 -0
  195. package/dist/site-agent-guard.d.ts +53 -0
  196. package/dist/site-data/operations.d.ts +103 -0
  197. package/dist/site-data/service.d.ts +203 -0
  198. package/dist/site-frame-guard.d.ts +32 -0
  199. package/dist/site-publishing/agent-data-tools.d.ts +84 -0
  200. package/dist/site-publishing/agent-model.d.ts +58 -0
  201. package/dist/site-publishing/agent-session.d.ts +16 -0
  202. package/dist/site-publishing/content-scanner.d.ts +31 -0
  203. package/dist/site-publishing/edge-sync.d.ts +48 -0
  204. package/dist/site-publishing/gateway-signature.d.ts +56 -0
  205. package/dist/site-publishing/limits.d.ts +63 -0
  206. package/dist/site-publishing/page-tool-authority.d.ts +30 -0
  207. package/dist/site-publishing/platform-usage.d.ts +113 -0
  208. package/dist/site-publishing/platform.d.ts +21 -0
  209. package/dist/site-publishing/readiness.d.ts +62 -0
  210. package/dist/site-publishing/runtime.d.ts +179 -0
  211. package/dist/site-publishing/service.d.ts +264 -0
  212. package/dist/site-publishing/session-events.d.ts +22 -0
  213. package/dist/site-publishing/session-views.d.ts +36 -0
  214. package/dist/site-publishing/viewer.d.ts +40 -0
  215. package/dist/site-session-origin.d.ts +31 -6
  216. package/dist/site-sql/format.d.ts +47 -0
  217. package/dist/site-sql/gateway.d.ts +50 -0
  218. package/dist/site-sql/service.d.ts +213 -0
  219. package/dist/temporal-schedule-sync.d.ts +26 -0
  220. package/dist/transcription/billing-refusal.d.ts +8 -0
  221. package/dist/transcription/normalize.d.ts +23 -0
  222. package/dist/transcription/providers/azure-mai.d.ts +12 -0
  223. package/dist/transcription/providers/azure-openai.d.ts +4 -0
  224. package/dist/transcription/providers/openai.d.ts +16 -0
  225. package/dist/transcription/providers/subscription-core.d.ts +39 -0
  226. package/dist/transcription/service.d.ts +10 -1
  227. package/dist/transcription/wav-duration.d.ts +8 -0
  228. package/dist/workspace-tool-gateway-attestations.d.ts +37 -0
  229. package/dist/workspace-tool-gateway-observability.d.ts +16 -0
  230. package/dist/workspace-tool-gateway-secrets.d.ts +27 -0
  231. package/dist/workspace-tool-gateway.d.ts +102 -6
  232. package/dist/workspace-tool-target-fence.d.ts +116 -0
  233. package/dist/workspace-tool-target.d.ts +225 -0
  234. package/dist/workspace-webhook-dispatch.d.ts +26 -0
  235. package/dist/xai-subscription-core.d.ts +60 -0
  236. package/package.json +25 -20
  237. package/src/access-grant-rls.ts +64 -14
  238. package/src/admission-trace.ts +14 -0
  239. package/src/app.ts +1684 -252
  240. package/src/artifact-catalog-cursor.ts +1 -0
  241. package/src/attached-browser-viewer.ts +26 -0
  242. package/src/auth/managed-auth-attempt-context.ts +9 -0
  243. package/src/auth/managed-auth-rate-limits.ts +252 -0
  244. package/src/auth/managed-auth-session-adapter.ts +64 -29
  245. package/src/auth/managed-auth.ts +303 -35
  246. package/src/auth/managed-email.ts +18 -1
  247. package/src/auth/managed-sign-in-notifications.ts +81 -0
  248. package/src/auth/new-signups-gate.ts +49 -0
  249. package/src/auth/organization-user-setup.ts +3 -3
  250. package/src/auth/signup-funnel-metrics.ts +164 -0
  251. package/src/azure-live.ts +103 -0
  252. package/src/browser-action-fences.ts +45 -0
  253. package/src/browser-controller-authority.ts +1 -186
  254. package/src/browser-ephemeral.ts +39 -0
  255. package/src/browser-lost-runtime-end.ts +71 -0
  256. package/src/browser-state-authority.ts +1 -236
  257. package/src/claude-default-models.ts +37 -0
  258. package/src/claude-subscription-core.ts +154 -0
  259. package/src/claude-subscription-oauth.ts +352 -0
  260. package/src/claude-subscription-profile.ts +73 -0
  261. package/src/claude-subscription-usage.ts +51 -0
  262. package/src/claude-workspace-connection.ts +82 -0
  263. package/src/codemode.ts +236 -39
  264. package/src/codex-realtime.ts +181 -53
  265. package/src/codex-session-pointers.ts +80 -0
  266. package/src/company-brain-okf.ts +1 -1
  267. package/src/connected-machine-computer-access.ts +2 -1
  268. package/src/connection-ownership.ts +19 -13
  269. package/src/controller-data-plane.ts +34 -0
  270. package/src/credit-promotion-snapshot.ts +36 -0
  271. package/src/editable-artifact-production.ts +10 -0
  272. package/src/editable-artifact-source-session.ts +123 -0
  273. package/src/editable-artifact-websocket.ts +16 -3
  274. package/src/fatal-process-boundary.ts +67 -3
  275. package/src/gateway-realtime.ts +12 -8
  276. package/src/github-access.ts +31 -5
  277. package/src/github-browser-flow.ts +1 -1
  278. package/src/http/acting-person.ts +105 -0
  279. package/src/http/api-contract-compat.ts +49 -0
  280. package/src/http/api-error.ts +210 -2
  281. package/src/http/auth.ts +68 -4
  282. package/src/http/cors.ts +37 -5
  283. package/src/http/deprecation.ts +118 -0
  284. package/src/http/keyed-admission.ts +29 -0
  285. package/src/http/local-browser-boundary.ts +343 -0
  286. package/src/http/metrics-listener.ts +57 -0
  287. package/src/http/path-identifier.ts +54 -0
  288. package/src/http/registered-route-label.ts +34 -0
  289. package/src/http/rejection-telemetry.ts +120 -0
  290. package/src/http/request-body.ts +127 -0
  291. package/src/http/request-source.ts +154 -13
  292. package/src/http/sse.ts +88 -28
  293. package/src/http/unmatched-route.ts +60 -0
  294. package/src/http/user-content.ts +158 -0
  295. package/src/http/variable-sets-removed.ts +122 -0
  296. package/src/http/websocket-upgrade-dispatch.ts +29 -0
  297. package/src/index.ts +107 -57
  298. package/src/integration-connect-metrics.ts +228 -0
  299. package/src/integration-endpoint-test.ts +291 -0
  300. package/src/integrations/api-integrations.ts +81 -7
  301. package/src/integrations/atlassian.ts +202 -83
  302. package/src/integrations/fiken.ts +66 -38
  303. package/src/integrations/github-app-connect.ts +64 -18
  304. package/src/integrations/github-lens-connect.ts +8 -29
  305. package/src/integrations/google-drive.ts +448 -152
  306. package/src/integrations/integration-commit-authority.ts +69 -0
  307. package/src/integrations/marketplace-plugin.ts +1 -1
  308. package/src/integrations/oauth-client.ts +733 -193
  309. package/src/integrations/oauth-profiles.ts +116 -45
  310. package/src/integrations/onepassword-vault-provider.ts +16 -0
  311. package/src/integrations/personal-github-repositories.ts +1 -1
  312. package/src/integrations/personal-github.ts +61 -35
  313. package/src/integrations/provider-oauth.ts +67 -85
  314. package/src/integrations/slack-app-home.ts +5 -5
  315. package/src/integrations/slack-bot.ts +893 -201
  316. package/src/integrations/slack-file-upload-flow.ts +147 -0
  317. package/src/integrations/slack-install.ts +7 -7
  318. package/src/integrations/slack-interactions.ts +1589 -299
  319. package/src/integrations/slack-mrkdwn.ts +193 -0
  320. package/src/integrations/slack-routing.ts +2 -2
  321. package/src/integrations/slack-session-defaults.ts +224 -0
  322. package/src/integrations/slack-task-file-upload.ts +323 -0
  323. package/src/integrations/slack-tool-review.ts +65 -0
  324. package/src/integrations/social-oauth.ts +90 -58
  325. package/src/interaction-agent-access.ts +40 -20
  326. package/src/interaction-agent-version.ts +85 -0
  327. package/src/interaction-holder-heartbeat.ts +24 -8
  328. package/src/interaction-metrics.ts +164 -2
  329. package/src/interaction-route-stages.ts +94 -0
  330. package/src/interaction-secrets-vault.ts +213 -0
  331. package/src/interaction-secrets.ts +426 -0
  332. package/src/mcp/action-catalog-types.ts +14 -0
  333. package/src/mcp/action-catalog.gen.ts +8014 -0
  334. package/src/mcp/action-descriptions.ts +299 -0
  335. package/src/mcp/action-schema-imports.gen.ts +304 -0
  336. package/src/mcp/capability-account-readiness.ts +17 -0
  337. package/src/mcp/child-read-evidence.ts +19 -0
  338. package/src/mcp/company-profile-agent-admin.ts +13 -0
  339. package/src/mcp/contract-input.ts +165 -0
  340. package/src/mcp/documents.ts +9 -2
  341. package/src/mcp/editable-artifacts.ts +29 -11
  342. package/src/mcp/files.ts +5 -1
  343. package/src/mcp/first-party-tool-permissions.ts +7 -285
  344. package/src/mcp/knowledge-entries.ts +108 -34
  345. package/src/mcp/notification-tools.ts +480 -0
  346. package/src/mcp/orchestration-failure-diagnostic.ts +43 -0
  347. package/src/mcp/scheduled-task-input.ts +89 -0
  348. package/src/mcp/scheduled-task-view.ts +63 -3
  349. package/src/mcp/secret-tools.ts +185 -0
  350. package/src/mcp/server.ts +2213 -1116
  351. package/src/mcp/session-admin-access-tools.ts +163 -0
  352. package/src/mcp/session-event-errors.ts +123 -0
  353. package/src/mcp/session-event-view.ts +395 -13
  354. package/src/mcp/session-view.ts +3 -0
  355. package/src/mcp/session-wait.ts +67 -7
  356. package/src/mcp/site-agent-clamp-tools.ts +140 -0
  357. package/src/mcp/site-data-tools.ts +339 -0
  358. package/src/mcp/site-publication-tools.ts +201 -0
  359. package/src/mcp/site-sql-tools.ts +427 -0
  360. package/src/mcp-oauth.ts +635 -45
  361. package/src/model-calls/chat-completions.ts +352 -0
  362. package/src/model-calls/pending-usage-settlements.ts +125 -0
  363. package/src/model-calls/service.ts +694 -0
  364. package/src/model-catalog.ts +68 -17
  365. package/src/native-push-dispatch.ts +457 -0
  366. package/src/observability.ts +15 -1
  367. package/src/organization-mcp.ts +485 -0
  368. package/src/prepared-mcp-actor.ts +154 -0
  369. package/src/prepared-mcp-permissions.ts +38 -0
  370. package/src/routes/analytics-consent.ts +123 -0
  371. package/src/routes/api-integrations.ts +268 -9
  372. package/src/routes/api-keys.ts +164 -25
  373. package/src/routes/artifact-catalog.ts +111 -0
  374. package/src/routes/automations.ts +163 -90
  375. package/src/routes/billing.ts +535 -59
  376. package/src/routes/browser-sessions.ts +966 -342
  377. package/src/routes/canonical-human-identities.ts +61 -0
  378. package/src/routes/capabilities.ts +112 -5
  379. package/src/routes/channels.ts +4 -3
  380. package/src/routes/chat-completions.ts +235 -0
  381. package/src/routes/claude-core-usage.ts +147 -0
  382. package/src/routes/claude-subscription-accounts.ts +233 -0
  383. package/src/routes/claude-subscription-oauth.ts +175 -0
  384. package/src/routes/client-errors.ts +394 -0
  385. package/src/routes/codex-core.ts +687 -0
  386. package/src/routes/codex.ts +1277 -1119
  387. package/src/routes/company-brain.ts +4 -0
  388. package/src/routes/computer-sessions.ts +319 -85
  389. package/src/routes/connect.ts +277 -175
  390. package/src/routes/connections.ts +690 -363
  391. package/src/routes/desktop-distribution.ts +217 -0
  392. package/src/routes/documents.ts +13 -7
  393. package/src/routes/editable-artifacts.ts +74 -4
  394. package/src/routes/enrollments.ts +110 -16
  395. package/src/routes/external-identity-links.ts +13 -12
  396. package/src/routes/files.ts +41 -16
  397. package/src/routes/github-browser-fonts.gen.ts +12 -0
  398. package/src/routes/github-browser-pages.ts +258 -0
  399. package/src/routes/github.ts +200 -75
  400. package/src/routes/inbox.ts +353 -0
  401. package/src/routes/insights-response-cache.ts +83 -0
  402. package/src/routes/insights-usage.ts +345 -0
  403. package/src/routes/insights.ts +103 -8
  404. package/src/routes/install.ts +51 -10
  405. package/src/routes/integration-facets.ts +70 -28
  406. package/src/routes/interaction-placement-message.ts +12 -0
  407. package/src/routes/knowledge.ts +136 -27
  408. package/src/routes/machines.ts +189 -135
  409. package/src/routes/managed-auth-session-sets.ts +43 -10
  410. package/src/routes/managed-onboarding.ts +39 -19
  411. package/src/routes/managed-sign-in-methods.ts +433 -0
  412. package/src/routes/memory-slack-publications.ts +3 -2
  413. package/src/routes/model-account-choice.ts +194 -0
  414. package/src/routes/model-account-settings.ts +235 -0
  415. package/src/routes/model-connection-access.ts +210 -48
  416. package/src/routes/native-app-auth.ts +296 -0
  417. package/src/routes/organization-integration-policy.ts +116 -0
  418. package/src/routes/organization-integrations.ts +326 -0
  419. package/src/routes/organization-mcp-connections.ts +183 -0
  420. package/src/routes/organization-memberships.ts +205 -19
  421. package/src/routes/organization-model-defaults.ts +110 -0
  422. package/src/routes/organization-model-providers.ts +74 -3
  423. package/src/routes/organization-service-accounts.ts +128 -0
  424. package/src/routes/organization-sessions.ts +21 -5
  425. package/src/routes/personal-api-keys.ts +184 -0
  426. package/src/routes/personal-github-git-broker.ts +2 -2
  427. package/src/routes/personal-github.ts +9 -4
  428. package/src/routes/plugins.ts +46 -7
  429. package/src/routes/pr-review-github.ts +105 -118
  430. package/src/routes/pr-review.ts +88 -82
  431. package/src/routes/preference-registry.ts +18 -0
  432. package/src/routes/rigs.ts +48 -13
  433. package/src/routes/scheduled-tasks.ts +347 -27
  434. package/src/routes/session-admin-access.ts +271 -0
  435. package/src/routes/session-artifact-associations.ts +164 -0
  436. package/src/routes/session-history-imports.ts +305 -0
  437. package/src/routes/sessions.ts +1682 -363
  438. package/src/routes/site-data.ts +340 -0
  439. package/src/routes/site-publishing.ts +584 -0
  440. package/src/routes/site-runtime.ts +1944 -0
  441. package/src/routes/site-sql.ts +263 -0
  442. package/src/routes/skill-content.ts +72 -7
  443. package/src/routes/skills.ts +5 -4
  444. package/src/routes/slack-bot-access.ts +108 -0
  445. package/src/routes/social.ts +27 -15
  446. package/src/routes/subscription-account-pools.ts +209 -0
  447. package/src/routes/subscription-core-http.ts +18 -0
  448. package/src/routes/subscription-pool-access.ts +180 -0
  449. package/src/routes/subscription-pool-core.ts +552 -0
  450. package/src/routes/supergrok.ts +174 -655
  451. package/src/routes/transcription-recordings.ts +71 -4
  452. package/src/routes/transcriptions.ts +26 -2
  453. package/src/routes/usage-allowances.ts +381 -0
  454. package/src/routes/variable-sets-removed.ts +19 -0
  455. package/src/routes/vault-providers.ts +782 -0
  456. package/src/routes/vaults.ts +421 -0
  457. package/src/routes/video-generation.ts +30 -12
  458. package/src/routes/workspace-artifacts.ts +165 -53
  459. package/src/routes/workspace-integrations.ts +576 -0
  460. package/src/routes/workspace-model-providers.ts +148 -0
  461. package/src/routes/workspace-state.ts +4 -0
  462. package/src/routes/workspaces.ts +625 -117
  463. package/src/sandbox/agent-update.ts +315 -0
  464. package/src/sandbox/auth-callout.ts +104 -21
  465. package/src/sandbox/channel-a.ts +150 -49
  466. package/src/sandbox/enrollment.ts +131 -22
  467. package/src/sandbox/machine-audience.ts +192 -0
  468. package/src/sandbox/machines.ts +75 -31
  469. package/src/sandbox/metrics-ingestion.ts +133 -2
  470. package/src/sandbox/rematerialize.ts +51 -21
  471. package/src/sandbox/screen-control.ts +289 -0
  472. package/src/sandbox/viewer.ts +33 -58
  473. package/src/sandbox-file-artifacts.ts +53 -27
  474. package/src/scheduled-task-blockers.ts +293 -0
  475. package/src/scheduled-task-deletion.ts +13 -3
  476. package/src/scheduled-task-lifecycle.ts +84 -0
  477. package/src/secret-answers.ts +119 -0
  478. package/src/session-create-observability.ts +46 -0
  479. package/src/session-realtime-context.ts +26 -4
  480. package/src/signed-state-secret.ts +58 -0
  481. package/src/site-agent-guard.ts +261 -0
  482. package/src/site-data/operations.ts +777 -0
  483. package/src/site-data/service.ts +1043 -0
  484. package/src/site-frame-guard.ts +107 -0
  485. package/src/site-publishing/agent-data-tools.ts +250 -0
  486. package/src/site-publishing/agent-model.ts +127 -0
  487. package/src/site-publishing/agent-session.ts +148 -0
  488. package/src/site-publishing/content-scanner.ts +93 -0
  489. package/src/site-publishing/edge-sync.ts +148 -0
  490. package/src/site-publishing/gateway-signature.ts +198 -0
  491. package/src/site-publishing/limits.ts +315 -0
  492. package/src/site-publishing/page-tool-authority.ts +111 -0
  493. package/src/site-publishing/platform-usage.ts +479 -0
  494. package/src/site-publishing/platform.ts +98 -0
  495. package/src/site-publishing/readiness.ts +330 -0
  496. package/src/site-publishing/runtime.ts +831 -0
  497. package/src/site-publishing/service.ts +1282 -0
  498. package/src/site-publishing/session-events.ts +262 -0
  499. package/src/site-publishing/session-views.ts +262 -0
  500. package/src/site-publishing/viewer.ts +75 -0
  501. package/src/site-session-origin.ts +91 -6
  502. package/src/site-sql/format.ts +134 -0
  503. package/src/site-sql/gateway.ts +168 -0
  504. package/src/site-sql/service.ts +1636 -0
  505. package/src/site-uploads.ts +27 -5
  506. package/src/temporal-schedule-sync.ts +74 -0
  507. package/src/transcription/billing-refusal.ts +14 -0
  508. package/src/transcription/normalize.ts +77 -0
  509. package/src/transcription/providers/azure-mai.ts +98 -0
  510. package/src/transcription/providers/azure-openai.ts +16 -7
  511. package/src/transcription/providers/codex-subscription.ts +190 -67
  512. package/src/transcription/providers/openai.ts +79 -5
  513. package/src/transcription/providers/subscription-core.ts +125 -0
  514. package/src/transcription/providers/xai-subscription.ts +81 -83
  515. package/src/transcription/segmenter.ts +7 -1
  516. package/src/transcription/service.ts +239 -10
  517. package/src/transcription/wav-duration.ts +39 -0
  518. package/src/workspace-deletion.ts +25 -1
  519. package/src/workspace-tool-gateway-attestations.ts +133 -0
  520. package/src/workspace-tool-gateway-observability.ts +64 -0
  521. package/src/workspace-tool-gateway-secrets.ts +104 -0
  522. package/src/workspace-tool-gateway.ts +921 -103
  523. package/src/workspace-tool-target-fence.ts +380 -0
  524. package/src/workspace-tool-target.ts +554 -0
  525. package/src/workspace-webhook-dispatch.ts +225 -0
  526. package/src/xai-realtime.ts +85 -81
  527. package/src/xai-subscription-core.ts +172 -0
  528. package/dist/browser-auth-broker.d.ts +0 -20
  529. package/dist/chunk-AJ62T5QN.js.map +0 -1
  530. package/dist/connection-authority-owner.d.ts +0 -59
  531. package/dist/routes/connection-authorities.d.ts +0 -3
  532. package/dist/routes/environments.d.ts +0 -5
  533. package/dist/routes/host-mcp-bindings.d.ts +0 -5
  534. package/dist/routes/host-mcp-resolvers.d.ts +0 -3
  535. package/dist/routes/packs.d.ts +0 -3
  536. package/dist/session-event-view-MU3HMNV3.js +0 -264
  537. package/dist/session-event-view-MU3HMNV3.js.map +0 -1
  538. package/dist/xai-subscription-auth.d.ts +0 -23
  539. package/src/browser-auth-broker.ts +0 -155
  540. package/src/connection-authority-owner.ts +0 -61
  541. package/src/routes/connection-authorities.ts +0 -139
  542. package/src/routes/environments.ts +0 -388
  543. package/src/routes/host-mcp-bindings.ts +0 -122
  544. package/src/routes/host-mcp-resolvers.ts +0 -41
  545. package/src/routes/packs.ts +0 -784
  546. package/src/xai-subscription-auth.ts +0 -139
@@ -0,0 +1,80 @@
1
+ // The legacy Codex session pointers (`codexPinnedCredentialId`,
2
+ // `codexLastCredentialId`, and `codexCurrentSelection` when the Session
3
+ // carries it) of every Session a response returns, by the organization's
4
+ // Codex cutover disposition (M3 PR 2b; current selection M3 PR 3):
5
+ // - core (enabled row): the session's core binding (explicit choice and bound
6
+ // connection) and the active Codex turn's live core lease (or explicit
7
+ // choice while it waits); a session without a Codex binding shows nulls;
8
+ // - maintenance (missing or disabled row): nulls, never the legacy ids.
9
+ // A session read never fails because of Codex state: if the disposition or the
10
+ // bindings cannot be read, the pointers show nulls.
11
+ import {
12
+ getSubscriptionCoreCodexCurrentSelections,
13
+ getSubscriptionCoreCodexSessionPointers,
14
+ readCodexCutoverDisposition,
15
+ type Database,
16
+ } from "@opengeni/db";
17
+
18
+ type CodexPointerFields = {
19
+ id: string;
20
+ accountId: string;
21
+ codexPinnedCredentialId: string | null;
22
+ codexLastCredentialId: string | null;
23
+ codexCurrentSelection?: { credentialId: string | null; waiting: boolean } | null | undefined;
24
+ };
25
+
26
+ /** Projects one Session's public Codex pointer fields from the core. */
27
+ export type CodexSessionPointerProjection = <T extends CodexPointerFields>(session: T) => T;
28
+
29
+ const unchanged: CodexSessionPointerProjection = (session) => session;
30
+
31
+ /**
32
+ * Load the projection once for every Session a response returns (all from one
33
+ * workspace). Missing cutover state is maintenance, not historical fallback.
34
+ */
35
+ export async function loadCodexSessionPointerProjection(
36
+ db: Database,
37
+ workspaceId: string,
38
+ sessions: readonly CodexPointerFields[],
39
+ ): Promise<CodexSessionPointerProjection> {
40
+ const accountId = sessions[0]?.accountId;
41
+ if (!accountId) return unchanged;
42
+ let pointers: Map<string, { pinnedCredentialId: string | null; lastCredentialId: string | null }>;
43
+ let selections: Map<string, { credentialId: string | null; waiting: boolean }>;
44
+ try {
45
+ const disposition = await readCodexCutoverDisposition(db, accountId, workspaceId);
46
+ const sessionIds = sessions.map((session) => session.id);
47
+ [pointers, selections] =
48
+ disposition === "core"
49
+ ? await Promise.all([
50
+ getSubscriptionCoreCodexSessionPointers(db, { accountId, workspaceId, sessionIds }),
51
+ sessions.some((session) => session.codexCurrentSelection !== undefined)
52
+ ? getSubscriptionCoreCodexCurrentSelections(db, {
53
+ accountId,
54
+ workspaceId,
55
+ sessionIds,
56
+ })
57
+ : Promise.resolve(new Map()),
58
+ ])
59
+ : [new Map(), new Map()];
60
+ } catch (error) {
61
+ console.warn("Codex session pointers unavailable; showing none", {
62
+ workspaceId,
63
+ error: error instanceof Error ? error.name : typeof error,
64
+ });
65
+ pointers = new Map();
66
+ selections = new Map();
67
+ }
68
+ return <T extends CodexPointerFields>(session: T): T => {
69
+ const pointer = pointers.get(session.id);
70
+ return {
71
+ ...session,
72
+ codexPinnedCredentialId: pointer?.pinnedCredentialId ?? null,
73
+ codexLastCredentialId: pointer?.lastCredentialId ?? null,
74
+ // A field the Session does not carry stays absent.
75
+ ...(session.codexCurrentSelection === undefined
76
+ ? {}
77
+ : { codexCurrentSelection: selections.get(session.id) ?? null }),
78
+ };
79
+ };
80
+ }
@@ -316,7 +316,7 @@ export function serializeCompanyBrainOkf(value: CompanyBrainOkfPackageType): str
316
316
  const parsed = CompanyBrainOkfPackage.parse(value);
317
317
  return [
318
318
  OKF_MARKER,
319
- "# OpenGeni Company Brain",
319
+ "# Opengeni Company Brain",
320
320
  "",
321
321
  "This permission-filtered package is portable evidence. Postgres remains canonical.",
322
322
  "",
@@ -26,7 +26,8 @@ export function connectedMachineComputerAccessError(
26
26
  if (requiresControl && !state.allowScreenControl) {
27
27
  return {
28
28
  status: 403,
29
- message: "Screen control is not enabled for this Connected Machine.",
29
+ message:
30
+ "Screen control is not enabled for this Connected Machine. Turn it on in place with connected_machine_enable_screen_control (no reconnect or human click needed), then retry.",
30
31
  };
31
32
  }
32
33
  return null;
@@ -1,14 +1,27 @@
1
1
  import type { ConnectionOwnership } from "@opengeni/contracts";
2
2
  import {
3
3
  externalActorContinuationForAuthorization,
4
+ isVerifiedDelegatedHumanAuthorization,
4
5
  type AccessGrantAuthorization,
5
6
  } from "@opengeni/core";
6
7
  import { HTTPException } from "hono/http-exception";
7
8
 
9
+ /** Signing in to a third-party provider is the person's own step in the
10
+ * browser; an agent acting as them through the organization MCP server is told
11
+ * to finish it there. */
12
+ export function requireProviderConsentInBrowser(access: AccessGrantAuthorization): void {
13
+ if (isVerifiedDelegatedHumanAuthorization(access))
14
+ throw new HTTPException(403, {
15
+ message:
16
+ "Signing in to a provider has to be done by the person in the Opengeni app in a browser.",
17
+ });
18
+ }
19
+
8
20
  /** A verified external actor must not enter a native callback that has no
9
21
  * corresponding key/identity reauthorization proof. Remove at an entry point
10
22
  * only when that provider's signed continuation and commit fence are wired. */
11
23
  export function requireLegacyOAuthActor(access: AccessGrantAuthorization): void {
24
+ requireProviderConsentInBrowser(access);
12
25
  if (externalActorContinuationForAuthorization(access))
13
26
  throw new HTTPException(422, {
14
27
  message: "This provider does not yet support external-user OAuth continuation",
@@ -37,9 +50,9 @@ export function requireLegacyOAuthActor(access: AccessGrantAuthorization): void
37
50
  */
38
51
 
39
52
  /**
40
- * Subject namespaces OpenGeni itself mints for machines. This is deliberately
53
+ * Subject namespaces Opengeni itself mints for machines. This is deliberately
41
54
  * NOT an allow-list of human subjects: `docs/embedding.md` states that
42
- * `subjectId` "remains opaque to OpenGeni" and that the kind must not be
55
+ * `subjectId` "remains opaque to Opengeni" and that the kind must not be
43
56
  * inferred from a subject-id prefix "because the host owns that namespace", so
44
57
  * a trusted embedding host legitimately signs `human_session` over an opaque
45
58
  * subject that is not `user:`-prefixed. Restricting personal ownership to
@@ -49,7 +62,7 @@ export function requireLegacyOAuthActor(access: AccessGrantAuthorization): void
49
62
  * The allow-list that actually decides is `principalKind === "human_session"`.
50
63
  * This list is defence-in-depth against exactly one residual threat: a holder
51
64
  * of the first-party delegation secret signing a human claim over an
52
- * OpenGeni-minted machine subject.
65
+ * Opengeni-minted machine subject.
53
66
  *
54
67
  * `connection-ownership.test.ts` asserts that every machine subject named in
55
68
  * its list is rejected. Note what that does and does not buy: it catches a
@@ -85,13 +98,7 @@ const RESERVED_MACHINE_SUBJECT_NAMESPACES = [
85
98
  export function isPersonalConnectionOwnerPrincipal(access: AccessGrantAuthorization): boolean {
86
99
  const { grant } = access;
87
100
  return (
88
- // The anti-substitution invariant `requireConnectionAuthorityOwner` uses for
89
- // the same question: every context grant agrees on principal kind, delegated
90
- // flag and service flags, and the selected grant's account resolves to
91
- // exactly one matching account grant. Without it a grant whose account has
92
- // no matching account grant (a surviving membership row in an organization
93
- // where the membership is no longer active) could mint a personal
94
- // Connection that the sibling helper would refuse.
101
+ // Every context grant must agree on the authenticated principal and account.
95
102
  access.contextIntegrity &&
96
103
  access.authenticatedSubjectId === grant.subjectId &&
97
104
  grant.principalKind === "human_session" &&
@@ -101,7 +108,7 @@ export function isPersonalConnectionOwnerPrincipal(access: AccessGrantAuthorizat
101
108
  );
102
109
  }
103
110
 
104
- /** Rejects an OpenGeni-minted machine subject; see the namespace list's rationale. */
111
+ /** Rejects an Opengeni-minted machine subject; see the namespace list's rationale. */
105
112
  export function isPersonalConnectionOwnerSubject(subjectId: string): boolean {
106
113
  const separator = subjectId.indexOf(":");
107
114
  if (separator < 0) {
@@ -132,8 +139,7 @@ export function personalOnlyConnectionPrincipalMessage(label: string): string {
132
139
  * rejects every reserved machine-subject namespace as defence-in-depth. The
133
140
  * sibling guards a self-service authority surface where the caller claims to
134
141
  * *be* the owner (403 "not you"), while this one rejects an ownership *value*
135
- * that is unavailable to the caller, alongside `assertOwnershipAllowed`'s
136
- * existing 422 convention.
142
+ * that is unavailable to the caller (422).
137
143
  */
138
144
  export function assertPersonalConnectionOwnerPrincipal(
139
145
  access: AccessGrantAuthorization,
@@ -6,6 +6,8 @@ import {
6
6
  parseOpenSandboxSignedUriPath,
7
7
  signedEndpointNeedsRefresh,
8
8
  } from "@opengeni/runtime/sandbox";
9
+ import type { InteractionPlacement } from "@opengeni/contracts";
10
+ import type { ChannelAOperation } from "./sandbox/channel-a";
9
11
 
10
12
  /** Modal/Daytona/Blaxel tunnels serve browserd at `/`, so a cached
11
13
  * controller-only session can host-fetch JSON. OpenSandbox's lifecycle proxy
@@ -80,3 +82,35 @@ export function isRetryableControllerTransport(error: unknown): boolean {
80
82
  (error instanceof BrowserControlRequestError && error.retryable)
81
83
  );
82
84
  }
85
+
86
+ /** A stopped sidecar needs provisioning on its original, fenced placement.
87
+ * Only reads and journaled actions may recover, once across provider retries.
88
+ * Revalidate controller authority before starting the sidecar. */
89
+ export async function withControllerTransportRecovery<T>(options: {
90
+ channelOperation: ChannelAOperation;
91
+ placementKind: InteractionPlacement["kind"];
92
+ recoveryState: { attempted: boolean };
93
+ transportAlreadyFailed: boolean;
94
+ use: () => Promise<T>;
95
+ admitRecovery: () => Promise<void>;
96
+ recover: () => Promise<T>;
97
+ }): Promise<T> {
98
+ if (
99
+ (options.channelOperation !== "browser.read" &&
100
+ options.channelOperation !== "browser.action") ||
101
+ options.placementKind !== "sandbox_group" ||
102
+ options.recoveryState.attempted
103
+ ) {
104
+ return await options.use();
105
+ }
106
+ if (!options.transportAlreadyFailed) {
107
+ try {
108
+ return await options.use();
109
+ } catch (error) {
110
+ if (!isRetryableControllerTransport(error)) throw error;
111
+ }
112
+ }
113
+ options.recoveryState.attempted = true;
114
+ await options.admitRecovery();
115
+ return await options.recover();
116
+ }
@@ -0,0 +1,36 @@
1
+ import { PromotionalCreditScope } from "@opengeni/contracts";
2
+
3
+ const prefix = "opengeni_credit_scope_";
4
+ const countKey = `${prefix}v1`;
5
+
6
+ /** Preserve scoped status and fallback eligibility; runtime policy can update coverage.
7
+ * Stripe metadata values are limited to 500 characters. Keep each chunk below that. */
8
+ export function creditScopeMetadata(scope?: PromotionalCreditScope): Record<string, string> {
9
+ if (!scope) return {};
10
+ const encoded = JSON.stringify(PromotionalCreditScope.parse(scope));
11
+ const chunks = encoded.match(/[\s\S]{1,400}/g)!;
12
+ if (chunks.length > 24)
13
+ throw new Error("Promotional credit policy exceeds checkout metadata limits");
14
+ return Object.fromEntries([
15
+ [countKey, String(chunks.length)],
16
+ ...chunks.map((chunk, index) => [`${prefix}${index}`, chunk]),
17
+ ]);
18
+ }
19
+
20
+ /** Missing metadata is a legacy checkout; incomplete metadata must never become unrestricted. */
21
+ export function creditScopeFromMetadata(
22
+ metadata: Record<string, string> | null | undefined,
23
+ ): PromotionalCreditScope | undefined {
24
+ if (!metadata || !Object.keys(metadata).some((key) => key.startsWith(prefix))) return undefined;
25
+ const count = Number(metadata[countKey]);
26
+ if (!Number.isInteger(count) || count < 1 || count > 24) {
27
+ throw new Error("Invalid promotional credit snapshot");
28
+ }
29
+ let encoded = "";
30
+ for (let index = 0; index < count; index++) {
31
+ const chunk = metadata[`${prefix}${index}`];
32
+ if (!chunk) throw new Error("Incomplete promotional credit snapshot");
33
+ encoded += chunk;
34
+ }
35
+ return PromotionalCreditScope.parse(JSON.parse(encoded));
36
+ }
@@ -6,6 +6,7 @@ import {
6
6
  import {
7
7
  EditableArtifactDurableExportService,
8
8
  EditableArtifactAgentApplication,
9
+ EDITABLE_ARTIFACT_EXPORT_FORMATS,
9
10
  EDITABLE_ARTIFACT_EXPORT_MAX_DOWNLOAD_BYTES,
10
11
  EditableArtifactCompactionPipeline,
11
12
  EditableArtifactGenesisPipeline,
@@ -47,6 +48,7 @@ import {
47
48
  PostgresEditableArtifactStore,
48
49
  listEditableArtifactIdsForSession,
49
50
  touchEditableArtifactSessionLink,
51
+ recordNativeDocumentInspection,
50
52
  dbSql,
51
53
  withRlsContext,
52
54
  type Database,
@@ -167,6 +169,11 @@ export async function createStandaloneEditableArtifactApplication(input: {
167
169
  await touchEditableArtifactSessionLink(input.db, scope, sessionId, artifactId),
168
170
  } satisfies EditableArtifactAgentAssociationPort),
169
171
  inspector: kernel,
172
+ recordInspection: async (inspection) => {
173
+ if (inspection.actor.kind !== "agent")
174
+ throw new Error("Inspection proof requires an agent attempt");
175
+ return recordNativeDocumentInspection(input.db, { ...inspection, actor: inspection.actor });
176
+ },
170
177
  officeImports,
171
178
  workspaceFiles: new EditableArtifactWorkspaceFileAdapter({
172
179
  db: input.db,
@@ -353,10 +360,13 @@ function materializationProfiles(
353
360
  }
354
361
  const codecVersion = capabilities.codecVersions["opengeni.xlsx"];
355
362
  return Object.freeze({
363
+ supportedFormats: EDITABLE_ARTIFACT_EXPORT_FORMATS,
356
364
  async resolve(input: Parameters<EditableArtifactMaterializationProfilePort["resolve"]>[0]) {
365
+ // EDITABLE_ARTIFACT_EXPORT_FORMATS is what agents are told exists.
357
366
  if (
358
367
  input.modality !== "spreadsheet" ||
359
368
  input.format !== "xlsx" ||
369
+ !EDITABLE_ARTIFACT_EXPORT_FORMATS[input.modality].includes(input.format) ||
360
370
  Object.keys(input.options).length !== 0
361
371
  ) {
362
372
  return null;
@@ -0,0 +1,123 @@
1
+ import {
2
+ hasPermission,
3
+ requireExternalContinuationAuthority,
4
+ requireSessionAuthorization,
5
+ type ApiRouteDeps,
6
+ type OpenEditableArtifactLiveInput,
7
+ } from "@opengeni/core";
8
+ import {
9
+ findActiveWorkspaceApiKeyById,
10
+ getSession,
11
+ getWorkspaceGrant,
12
+ hasEditableArtifactSessionLink,
13
+ lockExternalWorkspaceMembershipLifecycle,
14
+ withRlsContext,
15
+ } from "@opengeni/db";
16
+ import { withAccessGrantSessionRlsContext } from "./access-grant-rls";
17
+ import { sql } from "drizzle-orm";
18
+
19
+ /** Supplied by the API adapter, so mounted hosts use their canonical live port. */
20
+ export function editableArtifactSourceSessionAuthorizer(
21
+ deps: ApiRouteDeps,
22
+ ): NonNullable<OpenEditableArtifactLiveInput["authorizeSourceSession"]> {
23
+ return async (ticket, permission, transaction, signal) => {
24
+ signal?.throwIfAborted();
25
+ const authority = ticket.sourceSessionAuthority;
26
+ if (!authority) return true;
27
+ const { grant } = authority;
28
+ const required = permission === "edit" ? "artifacts:publish" : "artifacts:read";
29
+ if (
30
+ !hasPermission(grant.permissions, required) ||
31
+ !hasPermission(grant.permissions, "sessions:read")
32
+ ) {
33
+ return false;
34
+ }
35
+ // An external audit shape without the verified continuation is not authority.
36
+ if (grant.metadata?.externalActor && !authority.externalContinuation) return false;
37
+ try {
38
+ const scopedDeps = transaction ? { ...deps, db: transaction } : deps;
39
+ // Source-bound stores invoke us before their tenancy/aggregate locks.
40
+ // Match lifecycle writers' organization -> tenancy -> session prefix.
41
+ if (transaction) {
42
+ await lockExternalWorkspaceMembershipLifecycle(transaction, ticket.scope.accountId);
43
+ signal?.throwIfAborted();
44
+ // Tenancy writers acquire this fence before source session rows.
45
+ await transaction.execute(sql`select pg_advisory_xact_lock_shared(
46
+ hashtextextended(${`session-tenancy:${ticket.scope.workspaceId}`}, 0))`);
47
+ signal?.throwIfAborted();
48
+ }
49
+ return await withAccessGrantSessionRlsContext(scopedDeps, grant, async () => {
50
+ return await withRlsContext(scopedDeps.db, ticket.scope, async (tx) => {
51
+ if (authority.externalContinuation) {
52
+ await requireExternalContinuationAuthority(
53
+ tx,
54
+ authority.externalContinuation,
55
+ { ...ticket.scope, subjectId: grant.subjectId },
56
+ ["sessions:read", required],
57
+ );
58
+ signal?.throwIfAborted();
59
+ } else if (transaction) {
60
+ // The authenticated ticket grant is a ceiling, not proof that
61
+ // source-read permission still exists at the commit boundary.
62
+ const actor = ticket.actor;
63
+ if (
64
+ actor.kind === "human" ||
65
+ (actor.kind === "service" && actor.service === "configured_key")
66
+ ) {
67
+ await tx.execute(sql`select subject_id from workspace_memberships
68
+ where account_id = ${ticket.scope.accountId}::uuid
69
+ and workspace_id = ${ticket.scope.workspaceId}::uuid
70
+ and subject_id = ${grant.subjectId} for share`);
71
+ const live = await getWorkspaceGrant(tx, grant.subjectId, ticket.scope.workspaceId);
72
+ if (!live || !hasPermission(live.permissions, "sessions:read")) return false;
73
+ } else if (actor.kind === "service" && actor.service === "api_key") {
74
+ await tx.execute(sql`select id from api_keys
75
+ where account_id = ${ticket.scope.accountId}::uuid
76
+ and id::text = ${grant.subjectId.slice("api_key:".length)}
77
+ for share`);
78
+ const live = await findActiveWorkspaceApiKeyById(tx, {
79
+ ...ticket.scope,
80
+ apiKeyId: grant.subjectId.slice("api_key:".length),
81
+ });
82
+ if (!live || !hasPermission(live.permissions, "sessions:read")) return false;
83
+ } else if (actor.kind === "agent") {
84
+ const live = await getSession(tx, ticket.scope.workspaceId, actor.sessionId);
85
+ if (
86
+ !live ||
87
+ (live.firstPartyMcpPermissions !== null &&
88
+ !hasPermission(live.firstPartyMcpPermissions, "sessions:read"))
89
+ ) {
90
+ return false;
91
+ }
92
+ } else {
93
+ return false;
94
+ }
95
+ signal?.throwIfAborted();
96
+ }
97
+ // Locks protect visibility and removal of the exact association
98
+ // until the enclosing mutation transaction commits.
99
+ const linked = await hasEditableArtifactSessionLink(
100
+ tx,
101
+ ticket.scope,
102
+ authority.sessionId,
103
+ ticket.artifactId,
104
+ { lockForCommit: transaction !== undefined },
105
+ );
106
+ signal?.throwIfAborted();
107
+ if (!linked) return false;
108
+ await requireSessionAuthorization({ ...scopedDeps, db: tx }, grant, {
109
+ sessionId: authority.sessionId,
110
+ operation: "session.read",
111
+ surface: "http",
112
+ });
113
+ signal?.throwIfAborted();
114
+ return true;
115
+ });
116
+ });
117
+ } catch {
118
+ // Denial or an unavailable authority must stop data/writes, never fall
119
+ // back to artifact-only scope. The live loop closes denied readers.
120
+ return false;
121
+ }
122
+ };
123
+ }
@@ -8,6 +8,7 @@ import {
8
8
  type EditableArtifactLiveServerFrame,
9
9
  type EditableArtifactLiveSession,
10
10
  type EditableArtifactLiveSinkPort,
11
+ type OpenEditableArtifactLiveInput,
11
12
  } from "@opengeni/core";
12
13
  import type {
13
14
  ApiWebSocketConnection,
@@ -35,7 +36,10 @@ export type EditableArtifactWebSocketHandler = Readonly<{
35
36
  export class EditableArtifactWebSocketTransport {
36
37
  readonly websocket: EditableArtifactWebSocketHandler;
37
38
 
38
- constructor(private readonly application: EditableArtifactApplicationPort | undefined) {
39
+ constructor(
40
+ private readonly application: EditableArtifactApplicationPort | undefined,
41
+ private readonly authorizeSourceSession?: OpenEditableArtifactLiveInput["authorizeSourceSession"],
42
+ ) {
39
43
  this.websocket = Object.freeze({
40
44
  open: (socket) => socket.data.attach(socket),
41
45
  message: (socket, message) => socket.data.receive(message),
@@ -60,7 +64,10 @@ export class EditableArtifactWebSocketTransport {
60
64
  if (!offeredProtocol(request.headers.get("sec-websocket-protocol"))) {
61
65
  return new Response("WebSocket protocol required", { status: 426 });
62
66
  }
63
- const connection = new EditableArtifactWebSocketConnection(this.application);
67
+ const connection = new EditableArtifactWebSocketConnection(
68
+ this.application,
69
+ this.authorizeSourceSession,
70
+ );
64
71
  const upgraded = server.upgrade(request, {
65
72
  data: connection,
66
73
  headers: {
@@ -82,7 +89,10 @@ export class EditableArtifactWebSocketConnection
82
89
  private queuedBytes = 0;
83
90
  private terminal = false;
84
91
 
85
- constructor(private readonly application: EditableArtifactApplicationPort) {}
92
+ constructor(
93
+ private readonly application: EditableArtifactApplicationPort,
94
+ private readonly authorizeSourceSession?: OpenEditableArtifactLiveInput["authorizeSourceSession"],
95
+ ) {}
86
96
 
87
97
  attach(socket: EditableArtifactWebSocketLike): void {
88
98
  if (this.socket || this.terminal) {
@@ -177,6 +187,9 @@ export class EditableArtifactWebSocketConnection
177
187
  protocolVersion: frame.protocolVersion,
178
188
  resume: frame.resume,
179
189
  sink: this,
190
+ ...(this.authorizeSourceSession
191
+ ? { authorizeSourceSession: this.authorizeSourceSession }
192
+ : {}),
180
193
  });
181
194
  if (this.terminal) {
182
195
  await session.close("transport_error");
@@ -1,4 +1,5 @@
1
1
  import { randomUUID } from "node:crypto";
2
+ import { isDatabaseConnectionLoss } from "@opengeni/db";
2
3
  import type { Attributes, Observability, Span } from "@opengeni/observability";
3
4
 
4
5
  export type ApiFatalEvent = "startup_failure" | "unhandled_rejection" | "uncaught_exception";
@@ -15,7 +16,8 @@ export type ApiFatalReasonKind =
15
16
  | "symbol"
16
17
  | "undefined";
17
18
 
18
- type ApiFatalObservability = Pick<Observability, "error" | "flush" | "startSpan">;
19
+ type ApiFatalObservability = Pick<Observability, "error" | "flush" | "startSpan"> &
20
+ Partial<Pick<Observability, "recordFailureDiagnostic" | "warn" | "incrementCounter">>;
19
21
 
20
22
  type ApiFatalProcess = {
21
23
  on: (
@@ -35,6 +37,14 @@ export type ApiFatalProcessBoundaryOptions = {
35
37
  flushTimeoutMs?: number;
36
38
  correlationId?: () => string;
37
39
  fallbackLog?: (message: string) => void;
40
+ /**
41
+ * Classifies an unhandled rejection that leaves no process state behind and
42
+ * is therefore survivable once the API is serving. Defaults to a lost
43
+ * database connection (deploy drain, failover, restart): the rejected query
44
+ * held only a pooled connection the driver has already discarded, and every
45
+ * durable loop retries its claim on the next tick.
46
+ */
47
+ isRecoverableRejection?: (reason: unknown) => boolean;
38
48
  };
39
49
 
40
50
  export type ApiFatalProcessBoundary = {
@@ -60,19 +70,72 @@ export function installApiFatalProcessBoundary(
60
70
  const flushTimeoutMs = options.flushTimeoutMs ?? API_FATAL_FLUSH_TIMEOUT_MS;
61
71
  const correlationId = options.correlationId ?? (() => `api-fatal.${randomUUID()}`);
62
72
  const fallbackLog = options.fallbackLog ?? ((message: string) => console.error(message));
73
+ const isRecoverableRejection = options.isRecoverableRejection ?? isDatabaseConnectionLoss;
63
74
  let observability = options.observability;
64
75
  let phase: ApiFatalPhase = "startup";
65
76
  let reporting = false;
66
77
 
78
+ const recover = (reason: unknown): boolean => {
79
+ if (phase !== "running" || reporting) return false;
80
+ let recoverable = false;
81
+ try {
82
+ recoverable = isRecoverableRejection(reason);
83
+ } catch {
84
+ return false;
85
+ }
86
+ if (!recoverable) return false;
87
+ const attributes = {
88
+ errorClass: "ApiRecoveredRejection",
89
+ errorCode: "api_unhandled_database_connection_loss",
90
+ origin: "api",
91
+ reasonKind: apiFatalReasonKind(reason),
92
+ };
93
+ try {
94
+ if (observability?.warn) {
95
+ observability.warn(
96
+ "Opengeni API recovered an unhandled database connection loss",
97
+ attributes,
98
+ );
99
+ } else {
100
+ safeFallbackLog(
101
+ fallbackLog,
102
+ "Opengeni API recovered an unhandled database connection loss (api_unhandled_database_connection_loss)",
103
+ );
104
+ }
105
+ observability?.incrementCounter?.({
106
+ name: "opengeni_api_recovered_rejections_total",
107
+ help: "Unhandled rejections the API survived because they only reported a lost database connection.",
108
+ labels: { code: "api_unhandled_database_connection_loss" },
109
+ });
110
+ } catch {
111
+ // Recovery never depends on the observer.
112
+ }
113
+ return true;
114
+ };
115
+
67
116
  const report = async (event: ApiFatalEvent, reason: unknown): Promise<void> => {
68
117
  if (reporting) return;
69
118
  reporting = true;
70
119
 
71
120
  const diagnostic = apiFatalDiagnostic(event, phase, reason, correlationId);
72
- const message = apiFatalMessage(diagnostic);
121
+ let message = apiFatalMessage(diagnostic);
73
122
  const activeObservability = observability;
74
123
  try {
75
124
  if (activeObservability) {
125
+ try {
126
+ const diagnosticId = activeObservability.recordFailureDiagnostic?.({
127
+ code: FATAL_ERROR_CODES[event],
128
+ stage: phase,
129
+ retryDecision: "not_retryable",
130
+ error: reason,
131
+ });
132
+ if (diagnosticId) {
133
+ diagnostic.correlationId = diagnosticId;
134
+ message = apiFatalMessage(diagnostic);
135
+ }
136
+ } catch {
137
+ // Never replace the required fatal exit with an observer failure.
138
+ }
76
139
  let logged = false;
77
140
  try {
78
141
  activeObservability.error(message, diagnostic);
@@ -99,6 +162,7 @@ export function installApiFatalProcessBoundary(
99
162
  };
100
163
 
101
164
  const onUnhandledRejection = (reason: unknown): void => {
165
+ if (recover(reason)) return;
102
166
  void report("unhandled_rejection", reason);
103
167
  };
104
168
  const onUncaughtException = (reason: unknown): void => {
@@ -169,7 +233,7 @@ function apiFatalReasonKind(reason: unknown): ApiFatalReasonKind {
169
233
 
170
234
  function apiFatalMessage(diagnostic: ReturnType<typeof apiFatalDiagnostic>): string {
171
235
  return (
172
- `OpenGeni API fatal process failure (${diagnostic.errorCode}; ` +
236
+ `Opengeni API fatal process failure (${diagnostic.errorCode}; ` +
173
237
  `phase=${diagnostic.phase}; reason_kind=${diagnostic.reasonKind}; ` +
174
238
  `correlation_id=${diagnostic.correlationId})`
175
239
  );
@@ -62,7 +62,7 @@ export async function createGatewayRealtimeConnectionSecret(input: {
62
62
  throw new GatewayRealtimeBrokerError(
63
63
  "credential_unavailable",
64
64
  resolved.source === "managed"
65
- ? "OpenGeni Gateway voice is not configured"
65
+ ? "Opengeni Gateway voice is not configured"
66
66
  : "The workspace AI Gateway connection is unavailable",
67
67
  );
68
68
  }
@@ -72,6 +72,7 @@ export async function createGatewayRealtimeConnectionSecret(input: {
72
72
  getSessionRealtimeContinuityEntries(input.db, input.workspaceId, input.sessionId),
73
73
  mintGatewayClientSecret({
74
74
  apiKey,
75
+ source: resolved.source,
75
76
  upstreamModelId: resolved.upstreamModelId,
76
77
  fetchImpl: input.fetchImpl ?? fetch,
77
78
  }),
@@ -86,6 +87,7 @@ export async function createGatewayRealtimeConnectionSecret(input: {
86
87
 
87
88
  async function mintGatewayClientSecret(input: {
88
89
  apiKey: string;
90
+ source: "managed" | "workspace";
89
91
  upstreamModelId: string;
90
92
  fetchImpl: typeof fetch;
91
93
  }): Promise<{ token: string; url: string; expiresAt: number | null }> {
@@ -105,17 +107,19 @@ async function mintGatewayClientSecret(input: {
105
107
  } catch {
106
108
  throw new GatewayRealtimeBrokerError(
107
109
  "provider_error",
108
- "AI Gateway realtime token request failed",
110
+ "The voice provider could not be reached. Try again.",
109
111
  );
110
112
  }
111
113
  if (!response.ok) {
114
+ const rejected = response.status === 401 || response.status === 403;
115
+ // User-facing: say what to do, never which deployment credential failed.
112
116
  throw new GatewayRealtimeBrokerError(
113
- response.status === 401 || response.status === 403
114
- ? "credential_unavailable"
115
- : "provider_error",
116
- response.status === 401 || response.status === 403
117
- ? "AI Gateway credentials were rejected"
118
- : "AI Gateway realtime token request failed",
117
+ rejected ? "credential_unavailable" : "provider_error",
118
+ rejected
119
+ ? input.source === "managed"
120
+ ? "Opengeni voice is temporarily unavailable. Try another voice model."
121
+ : "Your AI Gateway key was rejected. Update it in workspace settings."
122
+ : "The voice provider could not start a call. Try again.",
119
123
  response.status,
120
124
  );
121
125
  }