@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,345 @@
1
+ import {
2
+ InsightsCallsResponse,
3
+ InsightsUsageResponse,
4
+ OrganizationInsightsCallsQuery,
5
+ OrganizationInsightsUsageQuery,
6
+ WorkspaceInsightsCallsQuery,
7
+ WorkspaceInsightsUsageQuery,
8
+ } from "@opengeni/contracts/insights-usage";
9
+ import type { AccessContext } from "@opengeni/contracts";
10
+ import {
11
+ accountScopedApiKeyWorkspaceAuthority,
12
+ getInsightsUsage,
13
+ hasPermission,
14
+ listInsightsCalls,
15
+ requireAccessContext,
16
+ requireAccessGrant,
17
+ type ApiRouteDeps,
18
+ type InsightsQueryScope,
19
+ } from "@opengeni/core";
20
+ import {
21
+ currentSessionRlsActorIdentityKey,
22
+ InvalidInsightsCallsCursorError,
23
+ readInsightsResponseCacheFence,
24
+ } from "@opengeni/db";
25
+ import type { Context, Hono } from "hono";
26
+ import { createHash } from "node:crypto";
27
+ import { HTTPException } from "hono/http-exception";
28
+ import { requireSelectedAccount, withBillingUsageActor } from "./billing";
29
+ import { createInFlightCoalescer } from "./insights";
30
+ import {
31
+ createInsightsCredentialPartition,
32
+ createInsightsResponseCache,
33
+ insightsWithFriendlyTimeout,
34
+ } from "./insights-response-cache";
35
+
36
+ /** Keep repeated filters, but reject repeated scalar options in the strict schema. */
37
+ export function insightsQueryParameters(
38
+ query: Record<string, string[]>,
39
+ ): Record<string, string | string[]> {
40
+ return Object.fromEntries(
41
+ Object.entries(query).map(([key, values]) => [key, values.length === 1 ? values[0]! : values]),
42
+ );
43
+ }
44
+
45
+ /** Frozen interim capabilities: a newer additive contract must not silently widen a raw query. */
46
+ export function insightsRawQuerySupported(
47
+ query: Record<string, unknown>,
48
+ organization: boolean,
49
+ calls: boolean,
50
+ ): boolean {
51
+ const keys = new Set([
52
+ "range",
53
+ "provider",
54
+ "model",
55
+ "payer",
56
+ "projectId",
57
+ "person",
58
+ "rootSessionId",
59
+ "scheduleId",
60
+ "limit",
61
+ ...(organization ? ["workspaceId"] : []),
62
+ ...(calls ? ["cursor"] : ["groupBy", "seriesGroups"]),
63
+ ]);
64
+ if (Object.keys(query).some((key) => !keys.has(key))) return false;
65
+ if (
66
+ query.range !== undefined &&
67
+ !new Set(["today", "week", "month", "30d", "90d", "ytd"]).has(String(query.range))
68
+ )
69
+ return false;
70
+ return (
71
+ query.groupBy === undefined ||
72
+ new Set([
73
+ "model",
74
+ "provider",
75
+ "payer",
76
+ "project",
77
+ "rootSession",
78
+ "person",
79
+ "schedule",
80
+ ...(organization ? ["workspace"] : []),
81
+ ]).has(String(query.groupBy))
82
+ );
83
+ }
84
+
85
+ function organizationCacheAuthority(context: AccessContext, accountId: string) {
86
+ const key = accountScopedApiKeyWorkspaceAuthority(context);
87
+ return [
88
+ context.subjectId,
89
+ context.accountGrants
90
+ .filter((g) => g.accountId === accountId)
91
+ .map((g) => [g.subjectId, g.role, [...g.permissions].sort()]),
92
+ context.workspaceGrants
93
+ .filter((g) => g.accountId === accountId)
94
+ .map((g) => [g.workspaceId, g.subjectId, g.permissionMode, [...g.permissions].sort()])
95
+ .sort(),
96
+ key
97
+ ? [key.accountId, key.permissionMode, [...key.permissions].sort(), key.workspaceScope]
98
+ : null,
99
+ ];
100
+ }
101
+
102
+ function rawUsageResponse(response: Awaited<ReturnType<typeof getInsightsUsage>>) {
103
+ const parsed = InsightsUsageResponse.parse(response);
104
+ // A newer contract can supply an additive default. Absence is a capability
105
+ // signal, so this raw implementation must not manufacture source support.
106
+ if (!Object.hasOwn(response.facets, "sources")) Reflect.deleteProperty(parsed.facets, "sources");
107
+ return parsed;
108
+ }
109
+
110
+ /** The actor and its canonical detail authority are part of every sharing key. */
111
+ export function insightsUsageCoalesceKey(
112
+ scope: InsightsQueryScope,
113
+ query: unknown,
114
+ actor: string | null,
115
+ ): string {
116
+ return JSON.stringify([
117
+ scope.accountId,
118
+ scope.workspaceId,
119
+ [...(scope.detailsWorkspaceIds ?? [])].sort(),
120
+ scope.detailsSharedWorkspaces === true,
121
+ query,
122
+ actor,
123
+ ]);
124
+ }
125
+
126
+ /** Reuse canonical read grants, never infer session access from billing authority. */
127
+ export function organizationInsightsScope(
128
+ context: AccessContext,
129
+ accountId: string,
130
+ ): InsightsQueryScope {
131
+ const authority = accountScopedApiKeyWorkspaceAuthority(context);
132
+ if (authority?.accountId === accountId) {
133
+ const readable = hasPermission(
134
+ authority.permissions,
135
+ "sessions:read",
136
+ authority.permissionMode,
137
+ );
138
+ return {
139
+ accountId,
140
+ workspaceId: null,
141
+ detailsWorkspaceIds:
142
+ readable && authority.workspaceScope.kind === "selected"
143
+ ? [...authority.workspaceScope.workspaceIds].sort()
144
+ : [],
145
+ detailsSharedWorkspaces: readable && authority.workspaceScope.kind === "all",
146
+ };
147
+ }
148
+ return {
149
+ accountId,
150
+ workspaceId: null,
151
+ detailsWorkspaceIds: [
152
+ ...new Set(
153
+ context.workspaceGrants
154
+ .filter(
155
+ (grant) =>
156
+ grant.accountId === accountId &&
157
+ grant.subjectId === context.subjectId &&
158
+ hasPermission(grant.permissions, "sessions:read", grant.permissionMode),
159
+ )
160
+ .map((grant) => grant.workspaceId),
161
+ ),
162
+ ].sort(),
163
+ detailsSharedWorkspaces: false,
164
+ };
165
+ }
166
+
167
+ async function callsWithValidation(
168
+ read: () => Promise<Awaited<ReturnType<typeof listInsightsCalls>>>,
169
+ ) {
170
+ try {
171
+ return await read();
172
+ } catch (error) {
173
+ if (error instanceof InvalidInsightsCallsCursorError)
174
+ throw new HTTPException(400, { message: "invalid Insights calls cursor" });
175
+ throw error;
176
+ }
177
+ }
178
+
179
+ export function registerInsightsUsageRoutes(app: Hono, deps: ApiRouteDeps): void {
180
+ const usage = createInFlightCoalescer<InsightsUsageResponse>();
181
+ const calls = createInFlightCoalescer<InsightsCallsResponse>();
182
+ const cache = createInsightsResponseCache();
183
+ const credentialPartition = createInsightsCredentialPartition();
184
+ async function cached<T>(
185
+ c: Context,
186
+ kind: "usage" | "calls",
187
+ scope: InsightsQueryScope,
188
+ query: object,
189
+ authority: unknown,
190
+ coalescer: { run(key: string, work: () => Promise<T>): Promise<T> },
191
+ read: () => Promise<T>,
192
+ ): Promise<T> {
193
+ // This runs only after this request's normal authentication and scope checks.
194
+ const normalized = Object.fromEntries(
195
+ Object.entries(query)
196
+ .sort(([a], [b]) => a.localeCompare(b))
197
+ .map(([key, value]) => [key, Array.isArray(value) ? [...new Set(value)].sort() : value]),
198
+ );
199
+ const key = createHash("sha256")
200
+ .update(
201
+ JSON.stringify([
202
+ kind,
203
+ authority,
204
+ insightsUsageCoalesceKey(scope, normalized, currentSessionRlsActorIdentityKey()),
205
+ credentialPartition(c.req.header("authorization"), c.req.header("cookie")),
206
+ new Date().toISOString().slice(0, 10),
207
+ ]),
208
+ )
209
+ .digest("hex");
210
+ const fence = await readInsightsResponseCacheFence(deps.db, scope);
211
+ if (fence !== null) {
212
+ const hit = cache.get<T>(key, fence);
213
+ if (hit !== null) return hit;
214
+ }
215
+ return await coalescer.run(`${key}:${fence ?? "uncached"}`, async () => {
216
+ const response = await insightsWithFriendlyTimeout(read);
217
+ // Store validated successes only, and only if metadata remained stable.
218
+ if (fence !== null && fence === (await readInsightsResponseCacheFence(deps.db, scope)))
219
+ cache.put(key, fence, response);
220
+ return response;
221
+ });
222
+ }
223
+
224
+ app.get("/v1/workspaces/:workspaceId/insights/usage", async (c) => {
225
+ const workspaceId = c.req.param("workspaceId");
226
+ const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:admin");
227
+ const query = insightsQueryParameters(c.req.queries());
228
+ if (!insightsRawQuerySupported(query, false, false))
229
+ throw new HTTPException(400, { message: "unsupported interim Insights query" });
230
+ const parsed = WorkspaceInsightsUsageQuery.safeParse(query);
231
+ if (!parsed.success) throw new HTTPException(400, { message: "invalid Insights usage query" });
232
+ const scope = {
233
+ accountId: grant.accountId,
234
+ workspaceId,
235
+ detailsWorkspaceIds: hasPermission(grant.permissions, "sessions:read", grant.permissionMode)
236
+ ? [workspaceId]
237
+ : [],
238
+ };
239
+ // The API's workspace middleware already binds/revalidates this grant's RLS actor.
240
+ const response = await cached(
241
+ c,
242
+ "usage",
243
+ scope,
244
+ parsed.data,
245
+ [grant.subjectId, grant.permissionMode, [...grant.permissions].sort()],
246
+ usage,
247
+ async () =>
248
+ rawUsageResponse(await getInsightsUsage(deps.db, { ...scope, query: parsed.data })),
249
+ );
250
+ c.header("cache-control", "private, no-store");
251
+ c.header("x-opengeni-insights-max-staleness-seconds", "60");
252
+ return c.json(response);
253
+ });
254
+
255
+ app.get("/v1/workspaces/:workspaceId/insights/calls", async (c) => {
256
+ const workspaceId = c.req.param("workspaceId");
257
+ const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:admin");
258
+ const query = insightsQueryParameters(c.req.queries());
259
+ if (!insightsRawQuerySupported(query, false, true))
260
+ throw new HTTPException(400, { message: "unsupported interim Insights query" });
261
+ const parsed = WorkspaceInsightsCallsQuery.safeParse(query);
262
+ if (!parsed.success) throw new HTTPException(400, { message: "invalid Insights calls query" });
263
+ const scope = {
264
+ accountId: grant.accountId,
265
+ workspaceId,
266
+ detailsWorkspaceIds: hasPermission(grant.permissions, "sessions:read", grant.permissionMode)
267
+ ? [workspaceId]
268
+ : [],
269
+ };
270
+ const response = await cached(
271
+ c,
272
+ "calls",
273
+ scope,
274
+ parsed.data,
275
+ [grant.subjectId, grant.permissionMode, [...grant.permissions].sort()],
276
+ calls,
277
+ async () =>
278
+ InsightsCallsResponse.parse(
279
+ await callsWithValidation(() =>
280
+ listInsightsCalls(deps.db, { ...scope, query: parsed.data }),
281
+ ),
282
+ ),
283
+ );
284
+ c.header("cache-control", "private, no-store");
285
+ c.header("x-opengeni-insights-max-staleness-seconds", "60");
286
+ return c.json(response);
287
+ });
288
+
289
+ app.get("/v1/organizations/:accountId/insights/usage", async (c) => {
290
+ const context = await requireAccessContext(c, deps);
291
+ const accountId = requireSelectedAccount(context, c.req.param("accountId"), "billing:read");
292
+ const query = insightsQueryParameters(c.req.queries());
293
+ if (!insightsRawQuerySupported(query, true, false))
294
+ throw new HTTPException(400, { message: "unsupported interim Insights query" });
295
+ const parsed = OrganizationInsightsUsageQuery.safeParse(query);
296
+ if (!parsed.success) throw new HTTPException(400, { message: "invalid Insights usage query" });
297
+ const scope = organizationInsightsScope(context, accountId);
298
+ const response = await withBillingUsageActor(deps, context, accountId, () =>
299
+ cached(
300
+ c,
301
+ "usage",
302
+ scope,
303
+ parsed.data,
304
+ organizationCacheAuthority(context, accountId),
305
+ usage,
306
+ async () =>
307
+ rawUsageResponse(await getInsightsUsage(deps.db, { ...scope, query: parsed.data })),
308
+ ),
309
+ );
310
+ c.header("cache-control", "private, no-store");
311
+ c.header("x-opengeni-insights-max-staleness-seconds", "60");
312
+ return c.json(response);
313
+ });
314
+
315
+ app.get("/v1/organizations/:accountId/insights/calls", async (c) => {
316
+ const context = await requireAccessContext(c, deps);
317
+ const accountId = requireSelectedAccount(context, c.req.param("accountId"), "billing:read");
318
+ const query = insightsQueryParameters(c.req.queries());
319
+ if (!insightsRawQuerySupported(query, true, true))
320
+ throw new HTTPException(400, { message: "unsupported interim Insights query" });
321
+ const parsed = OrganizationInsightsCallsQuery.safeParse(query);
322
+ if (!parsed.success) throw new HTTPException(400, { message: "invalid Insights calls query" });
323
+ const scope = organizationInsightsScope(context, accountId);
324
+ // Call readers intersect these canonical grants with current actor visibility.
325
+ const response = await withBillingUsageActor(deps, context, accountId, () =>
326
+ cached(
327
+ c,
328
+ "calls",
329
+ scope,
330
+ parsed.data,
331
+ organizationCacheAuthority(context, accountId),
332
+ calls,
333
+ async () =>
334
+ InsightsCallsResponse.parse(
335
+ await callsWithValidation(() =>
336
+ listInsightsCalls(deps.db, { ...scope, query: parsed.data }),
337
+ ),
338
+ ),
339
+ ),
340
+ );
341
+ c.header("cache-control", "private, no-store");
342
+ c.header("x-opengeni-insights-max-staleness-seconds", "60");
343
+ return c.json(response);
344
+ });
345
+ }
@@ -1,12 +1,17 @@
1
1
  import { InsightsRange, WorkspaceInsightsResponse } from "@opengeni/contracts";
2
2
  import {
3
3
  getWorkspaceInsights,
4
+ measureInsightsPhase,
5
+ workspaceInsightsPhaseMetricObserver,
4
6
  normalizeWorkspaceInsightsFilter,
7
+ normalizeWorkspaceInsightsSessionScope,
5
8
  requireAccessGrant,
9
+ scheduledTaskViewerForGrant,
6
10
  WorkspaceInsightsFilterValidationError,
7
11
  type ApiRouteDeps,
8
12
  type WorkspaceInsightsFilterField,
9
13
  } from "@opengeni/core";
14
+ import { currentSessionRlsActorIdentityKey } from "@opengeni/db";
10
15
  import { workspaceInsightsMetricObserver } from "@opengeni/observability";
11
16
  import type { Hono } from "hono";
12
17
  import { HTTPException } from "hono/http-exception";
@@ -16,7 +21,9 @@ export function normalizeWorkspaceInsightsQueryFilter(
16
21
  field: WorkspaceInsightsFilterField,
17
22
  ): string | null {
18
23
  try {
19
- return normalizeWorkspaceInsightsFilter(value, field);
24
+ return field === "rootSessionId" || field === "sessionId"
25
+ ? normalizeWorkspaceInsightsSessionScope(value, field)
26
+ : normalizeWorkspaceInsightsFilter(value, field);
20
27
  } catch (error) {
21
28
  if (error instanceof WorkspaceInsightsFilterValidationError) {
22
29
  throw new HTTPException(400, { message: error.message });
@@ -25,20 +32,82 @@ export function normalizeWorkspaceInsightsQueryFilter(
25
32
  }
26
33
  }
27
34
 
35
+ /**
36
+ * Share one in-flight computation between identical concurrent callers.
37
+ *
38
+ * A reload, a second tab, or a retried fetch joins the rollup already running
39
+ * instead of starting another multi-second aggregate on the database.
40
+ * Authorization and filter validation still run per request before a caller
41
+ * may join; the map only ever holds running work. The caller supplies the
42
+ * complete sharing key, which must identify everything the result depends on.
43
+ */
44
+ export function createInFlightCoalescer<T>(): {
45
+ run: (key: string, work: () => Promise<T>) => Promise<T>;
46
+ readonly size: number;
47
+ } {
48
+ const inFlight = new Map<string, Promise<T>>();
49
+ return {
50
+ run(key, work) {
51
+ const pending = inFlight.get(key);
52
+ if (pending) return pending;
53
+ const started: Promise<T> = work().finally(() => {
54
+ if (inFlight.get(key) === started) inFlight.delete(key);
55
+ });
56
+ inFlight.set(key, started);
57
+ return started;
58
+ },
59
+ get size() {
60
+ return inFlight.size;
61
+ },
62
+ };
63
+ }
64
+
65
+ /**
66
+ * Insights rows are filtered by the database RLS actor (private sessions are
67
+ * visible only to their owner), so two administrators of one workspace can
68
+ * legitimately receive different responses. The actor identity is part of
69
+ * the key; requests share work only when every visibility input is equal.
70
+ */
71
+ export function workspaceInsightsCoalesceKey(input: {
72
+ workspaceId: string;
73
+ range: string;
74
+ provider: string | null;
75
+ model: string | null;
76
+ rootSessionId?: string | null;
77
+ sessionId?: string | null;
78
+ rlsActor: string | null;
79
+ }): string {
80
+ return JSON.stringify([
81
+ input.workspaceId,
82
+ input.range,
83
+ input.provider,
84
+ input.model,
85
+ input.rootSessionId ?? null,
86
+ input.sessionId ?? null,
87
+ input.rlsActor,
88
+ ]);
89
+ }
90
+
28
91
  export function registerInsightsRoutes(app: Hono, deps: ApiRouteDeps): void {
29
92
  const observeRequest = workspaceInsightsMetricObserver(deps.observability);
93
+ const observePhase = workspaceInsightsPhaseMetricObserver(deps.observability);
94
+ const coalesce = createInFlightCoalescer<Awaited<ReturnType<typeof getWorkspaceInsights>>>();
30
95
  app.get("/v1/workspaces/:workspaceId/insights", async (c) => {
31
96
  const startedAtMs = performance.now();
32
97
  const rangeRaw = c.req.query("range") ?? "week";
33
98
  const providerRaw = c.req.query("provider");
34
99
  const modelRaw = c.req.query("model");
100
+ const rootSessionIdRaw = c.req.query("rootSessionId");
101
+ const sessionIdRaw = c.req.query("sessionId");
35
102
  let provider: string | null = null;
36
103
  let model: string | null = null;
37
104
  let outcome = "failed";
38
105
 
39
106
  try {
40
107
  const workspaceId = c.req.param("workspaceId");
41
- await requireAccessGrant(c, deps, workspaceId, "workspace:admin");
108
+ const grant = await measureInsightsPhase(observePhase, "auth", () =>
109
+ requireAccessGrant(c, deps, workspaceId, "workspace:admin"),
110
+ );
42
111
 
43
112
  const rangeParsed = InsightsRange.safeParse(rangeRaw);
44
113
  if (!rangeParsed.success) {
@@ -48,13 +117,39 @@ export function registerInsightsRoutes(app: Hono, deps: ApiRouteDeps): void {
48
117
  }
49
118
  provider = normalizeWorkspaceInsightsQueryFilter(providerRaw, "provider");
50
119
  model = normalizeWorkspaceInsightsQueryFilter(modelRaw, "model");
120
+ const rootSessionId = normalizeWorkspaceInsightsQueryFilter(
121
+ rootSessionIdRaw,
122
+ "rootSessionId",
123
+ );
124
+ const sessionId = normalizeWorkspaceInsightsQueryFilter(sessionIdRaw, "sessionId");
51
125
 
52
- const response = await getWorkspaceInsights(deps.db, deps.settings, {
53
- workspaceId,
54
- range: rangeParsed.data,
55
- provider,
56
- model,
57
- });
126
+ const response = await coalesce.run(
127
+ workspaceInsightsCoalesceKey({
128
+ workspaceId,
129
+ range: rangeParsed.data,
130
+ provider,
131
+ model,
132
+ rootSessionId,
133
+ sessionId,
134
+ rlsActor: currentSessionRlsActorIdentityKey(),
135
+ }),
136
+ () =>
137
+ getWorkspaceInsights(
138
+ deps.db,
139
+ deps.settings,
140
+ {
141
+ workspaceId,
142
+ range: rangeParsed.data,
143
+ provider,
144
+ model,
145
+ rootSessionId,
146
+ sessionId,
147
+ viewerSubjectId: async () =>
148
+ (await scheduledTaskViewerForGrant(deps.db, grant, deps.settings)).subjectId,
149
+ },
150
+ observePhase,
151
+ ),
152
+ );
58
153
  c.header("cache-control", "private, no-store");
59
154
  const result = c.json(WorkspaceInsightsResponse.parse(response));
60
155
  outcome = "completed";
@@ -158,18 +158,53 @@ function bakedContentType(asset: string): string {
158
158
  // BAKED_DIR is a fixed sibling, so the resolved path cannot escape the dir.
159
159
  async function readBaked(asset: string): Promise<ArrayBuffer | null> {
160
160
  const url = new URL(asset, BAKED_DIR);
161
- try {
162
- const info = await stat(url);
163
- if (!info.isFile()) {
161
+ const runtime =
162
+ /^(?:opengeni-agent-browser|opengeni-computer-native|opengeni-browserd|opengeni-agent)-(.+?)(?:\.(?:sha256|minisig))?$/.exec(
163
+ asset,
164
+ );
165
+ if (runtime) {
166
+ const target = runtime[1]!;
167
+ const cohort = [
168
+ "opengeni-agent",
169
+ "opengeni-browserd",
170
+ "opengeni-agent-browser",
171
+ "opengeni-computer-native",
172
+ ].flatMap((component) =>
173
+ ["", ".sha256", ".minisig"].map((suffix) => `${component}-${target}${suffix}`),
174
+ );
175
+ const members = await Promise.all(
176
+ cohort.map(async (name) => {
177
+ try {
178
+ const info = await stat(new URL(name, BAKED_DIR));
179
+ return info.isFile() && info.size > 0 ? "complete" : "invalid";
180
+ } catch (error) {
181
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") return "absent";
182
+ throw new HTTPException(503, { message: "baked interaction runtime is unavailable" });
183
+ }
184
+ }),
185
+ );
186
+ // A target is either wholly absent or wholly baked. A partial image cannot
187
+ // combine its agent with helpers or verification sidecars from an archive.
188
+ if (members.every((member) => member === "absent")) return null;
189
+ if (members.some((member) => member !== "complete")) {
190
+ throw new HTTPException(503, { message: "baked interaction runtime is incomplete" });
191
+ }
192
+ } else {
193
+ try {
194
+ const info = await stat(url);
195
+ if (!info.isFile()) return null;
196
+ } catch {
164
197
  return null;
165
198
  }
166
- } catch {
167
- return null;
168
199
  }
169
200
  // Return a standalone ArrayBuffer (a valid Response BodyInit). `readFile`'s
170
201
  // Buffer may be a view into a larger pooled allocation, so copy out the exact
171
202
  // byte range with `.slice` rather than handing over the backing store.
172
- const buf = await readFile(url);
203
+ const buf = await readFile(url).catch(() => {
204
+ // Never redirect after selecting a baked cohort, even if a file becomes
205
+ // unreadable between the completeness check and the byte read.
206
+ throw new HTTPException(503, { message: "baked interaction runtime is unavailable" });
207
+ });
173
208
  return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
174
209
  }
175
210
 
@@ -205,7 +240,11 @@ export function registerInstallRoutes(app: Hono, deps: ApiRouteDeps): void {
205
240
  // otherwise 302 to the GitHub Release at `redirectUrl` (mac/windows + any
206
241
  // un-baked asset). The baked path makes the agent the API enrolls against
207
242
  // identical to the API that serves it — no version skew, no extra hop.
208
- async function serveAsset(asset: string, redirectUrl: string): Promise<Response> {
243
+ async function serveAsset(
244
+ asset: string,
245
+ redirectUrl: string,
246
+ allowBaked: boolean,
247
+ ): Promise<Response> {
209
248
  const committed = COMMITTED_BINARY_ASSETS[asset];
210
249
  if (committed) {
211
250
  const buf = await readFile(new URL(committed.file, INSTALL_DIR));
@@ -218,7 +257,7 @@ export function registerInstallRoutes(app: Hono, deps: ApiRouteDeps): void {
218
257
  },
219
258
  });
220
259
  }
221
- const baked = await readBaked(asset);
260
+ const baked = allowBaked ? await readBaked(asset) : null;
222
261
  if (baked !== null) {
223
262
  return new Response(baked, {
224
263
  status: 200,
@@ -251,7 +290,7 @@ export function registerInstallRoutes(app: Hono, deps: ApiRouteDeps): void {
251
290
  if (!ASSET_NAME.test(asset)) {
252
291
  throw new HTTPException(400, { message: "invalid asset name" });
253
292
  }
254
- return serveAsset(asset, `${releasesBase}/download/${stableAgentTag}/${asset}`);
293
+ return serveAsset(asset, `${releasesBase}/download/${stableAgentTag}/${asset}`, true);
255
294
  });
256
295
 
257
296
  // Signed self-update channel manifests. Each deployment exposes its own
@@ -296,7 +335,9 @@ export function registerInstallRoutes(app: Hono, deps: ApiRouteDeps): void {
296
335
  message: "invalid version or asset name",
297
336
  });
298
337
  }
299
- return serveAsset(asset, `${releasesBase}/download/agent-${versionSeg}/${asset}`);
338
+ // A pinned release must never be substituted with this deployment's baked
339
+ // canary, even when its semver happens to match. The archive owns its bytes.
340
+ return serveAsset(asset, `${releasesBase}/download/agent-${versionSeg}/${asset}`, false);
300
341
  });
301
342
  }
302
343