@opengeni/api-router 3.0.1 → 3.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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-OGQDXVXY.js +18 -0
  21. package/dist/chunk-OGQDXVXY.js.map +1 -0
  22. package/dist/{chunk-AJ62T5QN.js → chunk-OT56OY4V.js} +80503 -39869
  23. package/dist/chunk-OT56OY4V.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 +165 -55
  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
@@ -1,69 +1,55 @@
1
+ import { registerSubscriptionAccountPoolRoutes } from "./subscription-account-pools";
2
+ import {
3
+ coreConnectRefused,
4
+ deliverPoolCoreWake,
5
+ requireSubscriptionCoreRoute,
6
+ type SubscriptionPoolCore,
7
+ } from "./subscription-pool-core";
8
+ import {
9
+ managedCookieHuman,
10
+ requireSameOriginBrowserMutation,
11
+ requireSubscriptionScopeMutation,
12
+ } from "./subscription-pool-access";
13
+ export { managedCookieHuman } from "./subscription-pool-access";
1
14
  import { requireOrganizationCodexHuman } from "./codex";
2
15
  import {
3
- listOrganizationXaiSubscriptions,
4
- upsertOrganizationXaiSubscription,
5
- updateOrganizationXaiSubscription,
6
- updateOrganizationXaiRotation,
16
+ connectSubscriptionCoreXaiConnection,
17
+ getSubscriptionCoreXaiOrganizationProjection,
18
+ getSubscriptionCoreXaiWorkspaceProjection,
19
+ SUBSCRIPTION_CORE_XAI,
20
+ encryptEnvironmentValue,
21
+ decryptEnvironmentValue,
22
+ type XaiSubscriptionAccountMetadata,
7
23
  } from "@opengeni/db";
8
24
  import {
9
25
  configuredModels,
10
26
  environmentsEncryptionKeyBytes,
11
27
  withXaiSubscriptionCatalogProvider,
12
28
  } from "@opengeni/config";
13
- import {
14
- WORKSPACE_XAI_PROVIDER_ACCOUNT_AUTHORITY_SNAPSHOT_V1,
15
- type XaiProviderAccountAuthoritySnapshotV1,
16
- } from "@opengeni/contracts";
17
- import {
18
- disconnectXaiSubscriptionCredentialAndRepick,
19
- ensureXaiRotationSettings,
20
- getXaiRotationSettings,
21
- getXaiSubscriptionAccountAuthoritySnapshot,
22
- listXaiSubscriptionAccountsMetadata,
23
- materializeXaiCredentialForRun,
24
- refreshXaiSubscriptionCredentialSerialized,
25
- renameXaiSubscriptionAccount,
26
- resolveXaiProviderAccountAuthoritySnapshotForAcceptance,
27
- setActiveXaiCredential,
28
- setInitialActiveXaiCredential,
29
- updateXaiAllocatorEligibility,
30
- updateXaiRotationSettings,
31
- upsertXaiSubscriptionCredential,
32
- wakeXaiCapacityWaiters,
33
- encryptEnvironmentValue,
34
- decryptEnvironmentValue,
35
- getWorkspaceGrant,
36
- type XaiSubscriptionAccountMetadata,
37
- } from "@opengeni/db";
29
+ import { SubscriptionConnectPollRequest, SupergrokConnectStartRequest } from "@opengeni/contracts";
38
30
  import { createSignedState, readSignedState } from "@opengeni/github";
39
31
  import {
40
- getManagedSession,
41
32
  requireAccessGrant,
42
33
  requireAccessGrantAuthorization,
43
34
  externalActorContinuationForAuthorization,
44
35
  type ApiRouteDeps,
45
36
  } from "@opengeni/core";
46
37
  import {
47
- XAI_CLIENT_VERSION,
48
38
  XaiSubscriptionError,
49
- fetchXaiSubscriptionModels,
50
39
  pollXaiDeviceCode,
51
- refreshXaiToken,
52
40
  requestXaiDeviceCode,
53
41
  xaiAccessTokenExpiry,
54
42
  xaiIdentityFromDeviceTokens,
55
43
  type XaiFetch,
56
- type XaiProxyAuthContext,
57
44
  } from "@opengeni/xai-subscription";
58
45
  import type { Context, Hono } from "hono";
59
46
  import { HTTPException } from "hono/http-exception";
60
- import * as z from "zod/v4";
61
47
  import { projectClientModel } from "../model-catalog";
48
+ import { readXaiCoreStatus } from "../xai-subscription-core";
62
49
  import { ExternalActorContinuation } from "@opengeni/contracts/external-identities";
63
50
  import { requireConnectOwnerAuthority } from "../integrations/connect-authority";
64
-
65
- type XaiAuthoritySnapshot = XaiProviderAccountAuthoritySnapshotV1;
66
- type ManagedCookieHuman = { subjectId: string };
51
+ import { databaseUnavailableHttpError } from "../http/api-error";
52
+ import { requirePrivateSubscriptionHuman } from "./subscription-pool-access";
67
53
 
68
54
  type SuperGrokConnectState = {
69
55
  externalContinuationEncrypted?: string;
@@ -76,59 +62,20 @@ type SuperGrokConnectState = {
76
62
  iat: number;
77
63
  };
78
64
 
79
- const connectStartBody = z.object({
80
- scope: z.enum(["workspace", "user"]).default("workspace"),
81
- });
82
- const connectPollBody = z.object({ state: z.string().min(1).max(16_384) });
83
- const allocatorBody = z.object({
84
- enabled: z.boolean(),
85
- expectedVersion: z.number().int().positive(),
86
- });
87
- const settingsBody = z.object({ rotationEnabled: z.boolean() });
88
- const renameBody = z.object({ label: z.string().trim().max(200).nullable() });
89
-
90
- export async function managedCookieHuman(
91
- c: Context,
92
- deps: ApiRouteDeps,
93
- ): Promise<ManagedCookieHuman | null> {
94
- if (
95
- deps.settings.productAccessMode !== "managed" ||
96
- !deps.managedAuth ||
97
- !c.req.header("cookie") ||
98
- c.req.header("authorization")
99
- ) {
100
- return null;
101
- }
102
- const session = await getManagedSession(c, deps.managedAuth, {
103
- db: deps.db,
104
- sessionAdapter: deps.managedAuthSessionAdapter,
105
- sessionSetMode: deps.settings.managedAuthSessionSetMode,
106
- });
107
- return session?.user?.id ? { subjectId: `user:${session.user.id}` } : null;
108
- }
65
+ const connectStartBody = SupergrokConnectStartRequest;
109
66
 
110
- function requireSameOriginBrowserMutation(c: Context, deps: ApiRouteDeps): void {
111
- const contentType = c.req.header("content-type")?.split(";", 1)[0]?.trim().toLowerCase();
112
- if (contentType !== "application/json") {
113
- throw new HTTPException(403, { message: "JSON browser request required" });
114
- }
115
- if (!deps.settings.publicBaseUrl) {
116
- throw new HTTPException(503, {
117
- message: "managed browser origin is not configured",
118
- });
119
- }
120
- const expectedOrigin = new URL(deps.settings.publicBaseUrl).origin;
121
- if (c.req.header("origin") !== expectedOrigin) {
122
- throw new HTTPException(403, {
123
- message: "same-origin browser request required",
124
- });
125
- }
126
- if (c.req.header("sec-fetch-site")?.toLowerCase() !== "same-origin") {
127
- throw new HTTPException(403, {
128
- message: "same-origin fetch metadata required",
129
- });
130
- }
131
- }
67
+ /**
68
+ * SuperGrok on the shared subscription core (provider id `xai`), its only
69
+ * runtime: the legacy pool runtime was deleted after the SuperGrok cutover.
70
+ */
71
+ const SUPERGROK_CORE: SubscriptionPoolCore = {
72
+ binding: SUBSCRIPTION_CORE_XAI,
73
+ workspaceProjection: getSubscriptionCoreXaiWorkspaceProjection,
74
+ organizationProjection: getSubscriptionCoreXaiOrganizationProjection,
75
+ };
76
+ const supergrokRoute = (deps: ApiRouteDeps, accountId: () => Promise<string>) =>
77
+ requireSubscriptionCoreRoute(deps, "xai", "SuperGrok", accountId);
78
+ const connectPollBody = SubscriptionConnectPollRequest;
132
79
 
133
80
  function requireEnabled(deps: ApiRouteDeps): void {
134
81
  if (!deps.settings.supergrokSubscriptionEnabled) {
@@ -138,100 +85,43 @@ function requireEnabled(deps: ApiRouteDeps): void {
138
85
  }
139
86
  }
140
87
 
141
- async function requirePrivateHuman(
142
- c: Context,
143
- deps: ApiRouteDeps,
144
- workspaceId: string,
145
- ): Promise<{ accountId: string; subjectId: string }> {
146
- if (c.req.header("authorization")) {
147
- const authorization = await requireAccessGrantAuthorization(
148
- c,
149
- deps,
150
- workspaceId,
151
- "connections:write",
152
- );
153
- const external = externalActorContinuationForAuthorization(authorization);
154
- if (
155
- external &&
156
- authorization.contextIntegrity &&
157
- external.actor.effectiveSubjectId === authorization.grant.subjectId
158
- ) {
159
- // The existing xAI user-pool domain requires an ordinary workspace
160
- // membership, not just the synthetic Personal-workspace owner grant.
161
- if (!(await getWorkspaceGrant(deps.db, authorization.grant.subjectId, workspaceId)))
162
- throw new HTTPException(409, {
163
- message: "Private SuperGrok accounts require membership in an ordinary workspace",
164
- });
165
- return { accountId: authorization.grant.accountId, subjectId: authorization.grant.subjectId };
166
- }
167
- throw new HTTPException(403, {
168
- message: "Private SuperGrok accounts require a verified owning user",
169
- });
170
- }
171
- const human = await managedCookieHuman(c, deps);
172
- if (!human) {
173
- throw new HTTPException(401, {
174
- message: "managed browser session required",
175
- });
176
- }
177
- const grant = await requireAccessGrant(c, deps, workspaceId, "connections:write");
178
- if (grant.subjectId !== human.subjectId) {
179
- throw new HTTPException(403, {
180
- message: "managed browser identity mismatch",
181
- });
182
- }
183
- if (!(await getWorkspaceGrant(deps.db, grant.subjectId, workspaceId)))
184
- throw new HTTPException(409, {
185
- message: "Private SuperGrok accounts require membership in an ordinary workspace",
186
- });
187
- return { accountId: grant.accountId, subjectId: grant.subjectId };
188
- }
189
-
190
- export async function requireScopeMutation(
88
+ /**
89
+ * The legacy scope check; on the shared core a private (`user`) account is
90
+ * managed only from its owner's Personal workspace.
91
+ */
92
+ export const requireScopeMutation = (
191
93
  c: Context,
192
94
  deps: ApiRouteDeps,
193
95
  workspaceId: string,
194
96
  scope: "workspace" | "user" | "organization",
195
- ): Promise<{ accountId: string; subjectId: string }> {
196
- if (scope === "organization")
197
- throw new HTTPException(409, { message: "Manage this subscription in organization settings" });
198
- if (scope === "user") {
199
- // Server-side external-user assertions do not use browser cookies. Ordinary
200
- // bearers remain rejected by requirePrivateHuman; native CSRF is unchanged.
201
- if (!c.req.header("authorization")) requireSameOriginBrowserMutation(c, deps);
202
- return await requirePrivateHuman(c, deps, workspaceId);
203
- }
204
- const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:admin");
205
- return { accountId: grant.accountId, subjectId: grant.subjectId };
206
- }
207
-
208
- async function resolveReadAuthority(
209
- c: Context,
210
- deps: ApiRouteDeps,
211
- workspaceId: string,
212
- ): Promise<{
213
- accountId: string;
214
- subjectId: string;
215
- snapshot: XaiAuthoritySnapshot;
216
- }> {
217
- const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:read");
218
- const snapshot = await resolveXaiProviderAccountAuthoritySnapshotForAcceptance(deps.db, {
97
+ runtime: "legacy" | "core" = "legacy",
98
+ ) =>
99
+ requireSubscriptionScopeMutation(
100
+ c,
101
+ deps,
219
102
  workspaceId,
220
- subjectId: grant.subjectId,
221
- });
222
- if (snapshot.scope !== "user") {
223
- return { accountId: grant.accountId, subjectId: grant.subjectId, snapshot };
224
- }
225
- const human = await requirePrivateHuman(c, deps, workspaceId);
226
- if (human.subjectId !== grant.subjectId) {
227
- throw new HTTPException(403, {
228
- message: "managed browser identity mismatch",
229
- });
230
- }
231
- return { accountId: human.accountId, subjectId: human.subjectId, snapshot };
232
- }
103
+ scope,
104
+ "SuperGrok",
105
+ runtime === "core" ? "personal_workspace" : "ordinary_workspace",
106
+ );
107
+
108
+ /**
109
+ * The runtime serving a workspace route. With the receipt the switch row is
110
+ * read for the caller's organization, which a workspace grant names first,
111
+ * so an unauthenticated caller learns nothing about it.
112
+ */
113
+ const workspaceRuntime = (c: Context, deps: ApiRouteDeps, workspaceId: string) =>
114
+ supergrokRoute(
115
+ deps,
116
+ async () => (await requireAccessGrant(c, deps, workspaceId, "workspace:read")).accountId,
117
+ );
233
118
 
234
119
  function xaiHttpError(error: unknown, fallback: string): HTTPException {
120
+ // A connect poll can lose its database connection after provider login or
121
+ // persistence. Preserve retryability and unknown mutation outcome instead
122
+ // of misclassifying the outage as a provider 502.
123
+ const databaseError = databaseUnavailableHttpError(error, "POST");
124
+ if (databaseError) return databaseError;
235
125
  if (error instanceof HTTPException) return error;
236
126
  if (error instanceof XaiSubscriptionError) {
237
127
  const status =
@@ -271,119 +161,62 @@ function accountJson(row: XaiSubscriptionAccountMetadata, activeCredentialId: st
271
161
  };
272
162
  }
273
163
 
274
- async function materializedAuthContext(
164
+ /**
165
+ * Persist a finished SuperGrok device sign-in on the shared core: a personal
166
+ * connection for a `user` scope (only in the person's Personal workspace),
167
+ * else a shared one through the neutral writer. Returns the connection id.
168
+ */
169
+ async function coreSuperGrokConnected(
170
+ c: Context,
275
171
  deps: ApiRouteDeps,
276
172
  input: {
277
173
  accountId: string;
278
- workspaceId: string;
174
+ workspaceId: string | null;
279
175
  subjectId: string;
280
- credentialId: string;
281
- authoritySnapshot: XaiAuthoritySnapshot;
176
+ personal?: boolean;
177
+ encryptionKey: Uint8Array;
178
+ tokens: { accessToken: string; refreshToken?: string | null; expiresInSeconds: number };
179
+ identity: ReturnType<typeof xaiIdentityFromDeviceTokens>;
282
180
  },
283
- ): Promise<{
284
- context: XaiProxyAuthContext;
285
- account: XaiSubscriptionAccountMetadata;
286
- }> {
287
- const encryptionKey = environmentsEncryptionKeyBytes(deps.settings);
288
- if (!encryptionKey) {
289
- throw new HTTPException(500, {
290
- message: "OPENGENI_ENVIRONMENTS_ENCRYPTION_KEY is not configured",
291
- });
292
- }
293
- let credential = await materializeXaiCredentialForRun(deps.db, {
294
- ...input,
295
- encryptionKey,
296
- });
297
- const tokenSnapshot = () => {
298
- if (!credential.secret.accessToken || !credential.providerAccountId) {
299
- throw new XaiSubscriptionError(
300
- "relogin_required",
301
- "The SuperGrok connection is missing an access token or verified identity",
302
- );
303
- }
304
- return {
305
- accessToken: credential.secret.accessToken,
306
- userId: credential.providerAccountId,
307
- };
308
- };
309
- return {
310
- account: credential,
311
- context: {
312
- clientVersion: XAI_CLIENT_VERSION,
313
- getToken: async () => tokenSnapshot(),
314
- refresh: async () => {
315
- const observedAccessToken = credential.secret.accessToken;
316
- const observedRefreshToken = credential.secret.refreshToken;
317
- if (!observedRefreshToken) {
318
- throw new XaiSubscriptionError(
319
- "relogin_required",
320
- "The SuperGrok connection cannot be refreshed",
321
- );
322
- }
323
- const result = await refreshXaiSubscriptionCredentialSerialized(deps.db, {
324
- accountId: input.accountId,
325
- workspaceId: input.workspaceId,
326
- subjectId: input.subjectId,
327
- credentialId: input.credentialId,
328
- authoritySnapshot: input.authoritySnapshot,
329
- encryptionKey,
330
- observedAccessToken,
331
- observedRefreshToken,
332
- refresh: async (current) => {
333
- const refreshToken = current.secret.refreshToken;
334
- if (!refreshToken) {
335
- throw new XaiSubscriptionError(
336
- "relogin_required",
337
- "The SuperGrok connection cannot be refreshed",
338
- );
339
- }
340
- const tokens = await refreshXaiToken(refreshToken, {
341
- fetch: (deps.xaiFetch ?? fetch) as XaiFetch,
342
- });
343
- return {
344
- secret: {
345
- version: 1,
346
- accessToken: tokens.accessToken,
347
- refreshToken: tokens.refreshToken,
348
- },
349
- expiresAt:
350
- xaiAccessTokenExpiry(tokens.accessToken) ??
351
- new Date(Date.now() + tokens.expiresInSeconds * 1_000),
352
- };
353
- },
354
- });
355
- credential = result.credential;
356
- return tokenSnapshot();
357
- },
181
+ ): Promise<string> {
182
+ const result = await connectSubscriptionCoreXaiConnection(deps.db, {
183
+ accountId: input.accountId,
184
+ workspaceId: input.workspaceId,
185
+ subjectId: input.subjectId,
186
+ ...(input.personal ? { personal: true } : {}),
187
+ encryptionKey: input.encryptionKey,
188
+ tokens: {
189
+ accessToken: input.tokens.accessToken,
190
+ refreshToken: input.tokens.refreshToken || null,
358
191
  },
359
- };
360
- }
361
-
362
- async function authorityForAccountMutation(
363
- c: Context,
364
- deps: ApiRouteDeps,
365
- workspaceId: string,
366
- credentialId: string,
367
- ): Promise<{
368
- accountId: string;
369
- subjectId: string;
370
- snapshot: XaiAuthoritySnapshot;
371
- }> {
372
- const readGrant = await requireAccessGrant(c, deps, workspaceId, "workspace:read");
373
- const snapshot = await getXaiSubscriptionAccountAuthoritySnapshot(deps.db, {
374
- workspaceId,
375
- subjectId: readGrant.subjectId,
376
- credentialId,
192
+ identitySubject: input.identity.subject,
193
+ accountEmail: input.identity.email,
194
+ label: input.identity.name ?? input.identity.email ?? input.identity.subject,
195
+ expiresAt:
196
+ xaiAccessTokenExpiry(input.tokens.accessToken) ??
197
+ new Date(Date.now() + input.tokens.expiresInSeconds * 1_000),
198
+ connectedBySubjectId: (await managedCookieHuman(c, deps))?.subjectId ?? null,
377
199
  });
378
- if (!snapshot) throw new HTTPException(404, { message: "SuperGrok account not found" });
379
- const mutation = await requireScopeMutation(c, deps, workspaceId, snapshot.scope);
380
- return { ...mutation, snapshot };
200
+ if (result.kind === "refused")
201
+ throw coreConnectRefused(result.reason, "SuperGrok", input.personal === true);
202
+ await deliverPoolCoreWake(deps, SUPERGROK_CORE, result.wake);
203
+ return result.id;
381
204
  }
382
205
 
383
206
  export function registerSuperGrokRoutes(app: Hono, deps: ApiRouteDeps): void {
207
+ registerSubscriptionAccountPoolRoutes(app, deps, {
208
+ provider: "xai",
209
+ route: "supergrok",
210
+ displayName: "SuperGrok",
211
+ enabled: () => deps.settings.supergrokSubscriptionEnabled,
212
+ accountJson,
213
+ core: SUPERGROK_CORE,
214
+ });
384
215
  const { db } = deps;
385
216
 
386
217
  const organizationPath = "/v1/organizations/:organizationId/supergrok";
218
+ // Device sign-in (start/poll) accepts an agent acting as an admin: the agent
219
+ // relays the short code, and the person still approves at xAI themselves.
387
220
  const organizationActor = async (c: Context, mutation = false) => {
388
221
  requireEnabled(deps);
389
222
  if (mutation) requireSameOriginBrowserMutation(c, deps);
@@ -391,24 +224,10 @@ export function registerSuperGrokRoutes(app: Hono, deps: ApiRouteDeps): void {
391
224
  const human = await requireOrganizationCodexHuman(c, deps, organizationId);
392
225
  return { organizationId, actorSubjectId: human.subjectId };
393
226
  };
394
- app.get(`${organizationPath}/accounts`, async (c) => {
395
- const actor = await organizationActor(c);
396
- const { accounts, rotation } = await listOrganizationXaiSubscriptions(db, actor);
397
- const activeAccountId = rotation?.activeCredentialId ?? null;
398
- return c.json({
399
- accounts: accounts.map((account) => accountJson(account, activeAccountId)),
400
- activeAccountId,
401
- source: "organization",
402
- organizationId: actor.organizationId,
403
- settings: {
404
- rotationEnabled: rotation?.rotationEnabled ?? false,
405
- rotationStrategy: "sharded",
406
- activeCredentialId: activeAccountId,
407
- },
408
- });
409
- });
410
227
  app.post(`${organizationPath}/connect/start`, async (c) => {
411
228
  const actor = await organizationActor(c, true);
229
+ // A sign-in that could not be saved is never started (maintenance fails closed).
230
+ await supergrokRoute(deps, async () => actor.organizationId);
412
231
  try {
413
232
  const start = await requestXaiDeviceCode({ fetch: (deps.xaiFetch ?? fetch) as XaiFetch });
414
233
  const expiresAt = Math.floor(Date.now() / 1000) + start.expiresInSeconds;
@@ -429,6 +248,7 @@ export function registerSuperGrokRoutes(app: Hono, deps: ApiRouteDeps): void {
429
248
  });
430
249
  app.post(`${organizationPath}/connect/poll`, async (c) => {
431
250
  const actor = await organizationActor(c, true);
251
+ await supergrokRoute(deps, async () => actor.organizationId);
432
252
  const parsed = connectPollBody.safeParse(await c.req.json().catch(() => null));
433
253
  if (!parsed.success) throw new HTTPException(400, { message: "SuperGrok state is required" });
434
254
  const state = readSignedState(parsed.data.state, deps.githubStateSecret) as {
@@ -459,94 +279,38 @@ export function registerSuperGrokRoutes(app: Hono, deps: ApiRouteDeps): void {
459
279
  const encryptionKey = environmentsEncryptionKeyBytes(deps.settings);
460
280
  if (!encryptionKey)
461
281
  throw new HTTPException(500, { message: "Connection encryption is not configured" });
462
- const connected = await upsertOrganizationXaiSubscription(db, {
463
- ...actor,
282
+ const id = await coreSuperGrokConnected(c, deps, {
283
+ accountId: actor.organizationId,
284
+ workspaceId: null,
285
+ subjectId: actor.actorSubjectId,
464
286
  encryptionKey,
465
- secret: {
466
- version: 1,
467
- accessToken: poll.tokens.accessToken,
468
- refreshToken: poll.tokens.refreshToken,
469
- },
470
- providerAccountId: identity.subject,
471
- label: identity.name ?? identity.email ?? identity.subject,
472
- accountEmail: identity.email,
473
- expiresAt:
474
- xaiAccessTokenExpiry(poll.tokens.accessToken) ??
475
- new Date(Date.now() + poll.tokens.expiresInSeconds * 1000),
287
+ tokens: poll.tokens,
288
+ identity,
289
+ });
290
+ const { activeCredentialId } = await getSubscriptionCoreXaiOrganizationProjection(db, {
291
+ organizationId: actor.organizationId,
292
+ subjectId: actor.actorSubjectId,
476
293
  });
477
294
  return c.json({
478
295
  status: "connected",
479
- accountId: connected.account.id,
296
+ accountId: id,
480
297
  scope: "organization",
481
- isActive: connected.isActive,
298
+ isActive: activeCredentialId === id,
482
299
  email: identity.email,
483
300
  });
484
301
  } catch (error) {
485
302
  throw xaiHttpError(error, "SuperGrok device login failed");
486
303
  }
487
304
  });
488
- app.patch(`${organizationPath}/settings`, async (c) => {
489
- const actor = await organizationActor(c, true);
490
- const parsed = settingsBody.safeParse(await c.req.json().catch(() => null));
491
- if (!parsed.success) throw new HTTPException(400, { message: "rotationEnabled is required" });
492
- const rotation = await updateOrganizationXaiRotation(db, { ...actor, ...parsed.data });
493
- return c.json({
494
- rotationEnabled: rotation.rotationEnabled,
495
- rotationStrategy: "sharded",
496
- activeCredentialId: rotation.activeCredentialId,
497
- });
498
- });
499
- const updateOrganizationAccount = async (
500
- c: Context,
501
- changes: Omit<
502
- Parameters<typeof updateOrganizationXaiSubscription>[1],
503
- "organizationId" | "actorSubjectId" | "credentialId"
504
- >,
505
- ) => {
506
- const actor = await organizationActor(c, true);
507
- try {
508
- const result = await updateOrganizationXaiSubscription(db, {
509
- ...actor,
510
- credentialId: c.req.param("accountId")!,
511
- ...changes,
512
- });
513
- if (!result) throw new HTTPException(404, { message: "SuperGrok account not found" });
514
- return c.json(result);
515
- } catch (error) {
516
- if (error instanceof HTTPException) throw error;
517
- throw new HTTPException(409, {
518
- message:
519
- error instanceof Error ? error.message : "SuperGrok subscription could not be updated",
520
- });
521
- }
522
- };
523
- app.post(`${organizationPath}/accounts/:accountId/activate`, (c) =>
524
- updateOrganizationAccount(c, { activate: true }),
525
- );
526
- app.delete(`${organizationPath}/accounts/:accountId`, (c) =>
527
- updateOrganizationAccount(c, { disconnect: true }),
528
- );
529
- app.patch(`${organizationPath}/accounts/:accountId`, async (c) => {
530
- const parsed = renameBody.safeParse(await c.req.json().catch(() => null));
531
- if (!parsed.success) throw new HTTPException(400, { message: "label is invalid" });
532
- return updateOrganizationAccount(c, { label: parsed.data.label || null });
533
- });
534
- app.patch(`${organizationPath}/accounts/:accountId/allocator`, async (c) => {
535
- const parsed = allocatorBody.safeParse(await c.req.json().catch(() => null));
536
- if (!parsed.success)
537
- throw new HTTPException(400, { message: "enabled and expectedVersion are required" });
538
- return updateOrganizationAccount(c, {
539
- allocatorEnabled: parsed.data.enabled,
540
- expectedAllocatorVersion: parsed.data.expectedVersion,
541
- });
542
- });
543
-
544
305
  app.post("/v1/workspaces/:workspaceId/supergrok/connect/start", async (c) => {
545
306
  requireEnabled(deps);
546
307
  const workspaceId = c.req.param("workspaceId");
547
308
  const parsed = connectStartBody.safeParse(await c.req.json().catch(() => ({})));
548
309
  if (!parsed.success) throw new HTTPException(400, { message: "invalid SuperGrok scope" });
549
- const authority = await requireScopeMutation(c, deps, workspaceId, parsed.data.scope);
310
+ // On the core a private account is connected only from the person's own
311
+ // Personal workspace: refused here, before the xAI sign-in, elsewhere.
312
+ const runtime = await workspaceRuntime(c, deps, workspaceId);
313
+ const authority = await requireScopeMutation(c, deps, workspaceId, parsed.data.scope, runtime);
550
314
  const authorization = await requireAccessGrantAuthorization(
551
315
  c,
552
316
  deps,
@@ -613,7 +377,8 @@ export function registerSuperGrokRoutes(app: Hono, deps: ApiRouteDeps): void {
613
377
  message: "SuperGrok connect state is invalid or expired",
614
378
  });
615
379
  }
616
- const authority = await requireScopeMutation(c, deps, workspaceId, state.scope);
380
+ const runtime = await workspaceRuntime(c, deps, workspaceId);
381
+ const authority = await requireScopeMutation(c, deps, workspaceId, state.scope, runtime);
617
382
  if (authority.subjectId !== state.subjectId) {
618
383
  throw new HTTPException(403, {
619
384
  message: "SuperGrok connect identity changed",
@@ -660,7 +425,7 @@ export function registerSuperGrokRoutes(app: Hono, deps: ApiRouteDeps): void {
660
425
  const identity = xaiIdentityFromDeviceTokens(poll.tokens);
661
426
  phase = "credential_persist";
662
427
  await requireOrigin();
663
- const liveAuthority = await requireScopeMutation(c, deps, workspaceId, state.scope);
428
+ const liveAuthority = await requireScopeMutation(c, deps, workspaceId, state.scope, runtime);
664
429
  if (
665
430
  liveAuthority.accountId !== authority.accountId ||
666
431
  liveAuthority.subjectId !== authority.subjectId
@@ -672,51 +437,25 @@ export function registerSuperGrokRoutes(app: Hono, deps: ApiRouteDeps): void {
672
437
  message: "OPENGENI_ENVIRONMENTS_ENCRYPTION_KEY is not configured",
673
438
  });
674
439
  }
675
- const upserted = await upsertXaiSubscriptionCredential(deps.db, {
440
+ const id = await coreSuperGrokConnected(c, deps, {
676
441
  accountId: authority.accountId,
677
442
  workspaceId,
678
443
  subjectId: authority.subjectId,
679
- scope: state.scope,
444
+ personal: state.scope === "user",
680
445
  encryptionKey,
681
- secret: {
682
- version: 1,
683
- accessToken: poll.tokens.accessToken,
684
- refreshToken: poll.tokens.refreshToken,
685
- },
686
- providerAccountId: identity.subject,
687
- label: identity.name ?? identity.email ?? identity.subject,
688
- accountEmail: identity.email,
689
- expiresAt:
690
- xaiAccessTokenExpiry(poll.tokens.accessToken) ??
691
- new Date(Date.now() + poll.tokens.expiresInSeconds * 1_000),
446
+ tokens: poll.tokens,
447
+ identity,
692
448
  });
693
- const rotation = await ensureXaiRotationSettings(deps.db, {
449
+ const { activeCredentialId } = await getSubscriptionCoreXaiWorkspaceProjection(deps.db, {
694
450
  accountId: authority.accountId,
695
451
  workspaceId,
696
- subjectId: authority.subjectId,
697
- authoritySnapshot: upserted.authoritySnapshot,
698
- });
699
- let isActive = rotation.activeCredentialId === upserted.account.id;
700
- if (!isActive && rotation.activeCredentialId === null) {
701
- isActive = await setInitialActiveXaiCredential(deps.db, {
702
- accountId: authority.accountId,
703
- workspaceId,
704
- subjectId: authority.subjectId,
705
- authoritySnapshot: upserted.authoritySnapshot,
706
- credentialId: upserted.account.id,
707
- });
708
- }
709
- await wakeXaiCapacityWaiters(deps.db, {
710
- workspaceId,
711
- subjectId: authority.subjectId,
712
- authoritySnapshot: upserted.authoritySnapshot,
713
- reason: "xai_credential_connected",
452
+ viewerSubjectId: authority.subjectId,
714
453
  });
715
454
  return c.json({
716
455
  status: "connected" as const,
717
- accountId: upserted.account.id,
456
+ accountId: id,
718
457
  scope: state.scope,
719
- isActive,
458
+ isActive: activeCredentialId === id,
720
459
  email: identity.email,
721
460
  });
722
461
  } catch (error) {
@@ -742,265 +481,45 @@ export function registerSuperGrokRoutes(app: Hono, deps: ApiRouteDeps): void {
742
481
  }
743
482
  });
744
483
 
745
- app.get("/v1/workspaces/:workspaceId/supergrok/accounts", async (c) => {
746
- requireEnabled(deps);
747
- const workspaceId = c.req.param("workspaceId");
748
- const authority = await resolveReadAuthority(c, deps, workspaceId);
749
- const [accounts, settings] = await Promise.all([
750
- listXaiSubscriptionAccountsMetadata(deps.db, {
751
- workspaceId,
752
- subjectId: authority.subjectId,
753
- }),
754
- getXaiRotationSettings(deps.db, {
755
- workspaceId,
756
- subjectId: authority.subjectId,
757
- authoritySnapshot: authority.snapshot,
758
- }),
759
- ]);
760
- const activeCredentialId = settings?.activeCredentialId ?? null;
761
- return c.json({
762
- source: authority.snapshot.scope,
763
- organizationId: authority.accountId,
764
- accounts: accounts
765
- .filter((account) =>
766
- authority.snapshot.scope === "organization"
767
- ? account.scope === "organization"
768
- : account.scope !== "organization",
769
- )
770
- .map((account) => accountJson(account, activeCredentialId)),
771
- activeAccountId: activeCredentialId,
772
- settings: {
773
- rotationEnabled: settings?.rotationEnabled ?? true,
774
- rotationStrategy: "sharded" as const,
775
- activeCredentialId,
776
- },
777
- });
778
- });
779
-
780
484
  app.get("/v1/workspaces/:workspaceId/supergrok/status", async (c) => {
781
485
  requireEnabled(deps);
782
486
  const workspaceId = c.req.param("workspaceId");
783
- const authority = await resolveReadAuthority(c, deps, workspaceId);
784
- const [accounts, settings] = await Promise.all([
785
- listXaiSubscriptionAccountsMetadata(deps.db, {
786
- workspaceId,
787
- subjectId: authority.subjectId,
788
- }),
789
- getXaiRotationSettings(deps.db, {
790
- workspaceId,
791
- subjectId: authority.subjectId,
792
- authoritySnapshot: authority.snapshot,
793
- }),
794
- ]);
795
- const active = accounts.find((account) => account.id === settings?.activeCredentialId) ?? null;
796
- if (!active || !settings?.activeCredentialId) {
797
- return c.json({
798
- connected: accounts.length > 0,
799
- valid: false,
800
- accountCount: accounts.length,
801
- });
802
- }
803
- let valid = false;
804
- try {
805
- const auth = await materializedAuthContext(deps, {
806
- accountId: authority.accountId,
487
+ const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:read");
488
+ const supergrokModels = async () =>
489
+ configuredModels(
490
+ withXaiSubscriptionCatalogProvider((await deps.resolveCatalogSettings()).settings),
491
+ )
492
+ .filter(
493
+ (model) =>
494
+ model.credentialSource.kind === "connected_subscription" &&
495
+ model.credentialSource.provider === "xai",
496
+ )
497
+ .map(projectClientModel);
498
+ return c.json(
499
+ await readXaiCoreStatus(deps, {
500
+ accountId: grant.accountId,
807
501
  workspaceId,
808
- subjectId: authority.subjectId,
809
- credentialId: active.id,
810
- authoritySnapshot: authority.snapshot,
811
- });
812
- await fetchXaiSubscriptionModels({
813
- context: auth.context,
502
+ subjectId: grant.subjectId,
503
+ models: supergrokModels,
504
+ // Only the verified owner in their Personal workspace may make a
505
+ // live personal-account usage request; other viewers get stored status.
506
+ ownerVerified: async () => {
507
+ try {
508
+ const owner = await requirePrivateSubscriptionHuman(
509
+ c,
510
+ deps,
511
+ workspaceId,
512
+ "SuperGrok",
513
+ "personal_workspace",
514
+ );
515
+ return owner.accountId === grant.accountId && owner.subjectId === grant.subjectId;
516
+ } catch (error) {
517
+ if (error instanceof HTTPException) return false;
518
+ throw error;
519
+ }
520
+ },
814
521
  ...(deps.xaiFetch ? { fetch: deps.xaiFetch } : {}),
815
- });
816
- valid = true;
817
- } catch {
818
- valid = false;
819
- }
820
- const catalogSettings = valid ? (await deps.resolveCatalogSettings()).settings : null;
821
- const catalog = catalogSettings
822
- ? configuredModels(withXaiSubscriptionCatalogProvider(catalogSettings))
823
- .filter(
824
- (model) =>
825
- model.credentialSource.kind === "connected_subscription" &&
826
- model.credentialSource.provider === "xai",
827
- )
828
- .map(projectClientModel)
829
- : [];
830
- return c.json({
831
- connected: true,
832
- valid,
833
- accountCount: accounts.length,
834
- models: catalog,
835
- activeAccount: {
836
- id: active.id,
837
- label: active.label,
838
- subject: active.providerAccountId,
839
- scope: active.scope,
840
- },
841
- });
842
- });
843
-
844
- app.post("/v1/workspaces/:workspaceId/supergrok/accounts/:accountId/activate", async (c) => {
845
- requireEnabled(deps);
846
- const workspaceId = c.req.param("workspaceId");
847
- const credentialId = c.req.param("accountId");
848
- const authority = await authorityForAccountMutation(c, deps, workspaceId, credentialId);
849
- const activated = await setActiveXaiCredential(deps.db, {
850
- accountId: authority.accountId,
851
- workspaceId,
852
- subjectId: authority.subjectId,
853
- authoritySnapshot: authority.snapshot,
854
- credentialId,
855
- });
856
- if (!activated)
857
- throw new HTTPException(409, {
858
- message: "SuperGrok account requires relogin",
859
- });
860
- await wakeXaiCapacityWaiters(deps.db, {
861
- workspaceId,
862
- subjectId: authority.subjectId,
863
- authoritySnapshot: authority.snapshot,
864
- reason: "xai_active_credential_changed",
865
- });
866
- return c.json({ activated: true, accountId: credentialId });
867
- });
868
-
869
- app.patch("/v1/workspaces/:workspaceId/supergrok/settings", async (c) => {
870
- requireEnabled(deps);
871
- const workspaceId = c.req.param("workspaceId");
872
- const parsed = settingsBody.safeParse(await c.req.json().catch(() => null));
873
- if (!parsed.success) throw new HTTPException(400, { message: "rotationEnabled is required" });
874
- const readAuthority = await resolveReadAuthority(c, deps, workspaceId);
875
- const authority = await requireScopeMutation(
876
- c,
877
- deps,
878
- workspaceId,
879
- readAuthority.snapshot.scope,
522
+ }),
880
523
  );
881
- const current = await ensureXaiRotationSettings(deps.db, {
882
- accountId: authority.accountId,
883
- workspaceId,
884
- subjectId: authority.subjectId,
885
- authoritySnapshot: readAuthority.snapshot,
886
- });
887
- const updated = await updateXaiRotationSettings(deps.db, {
888
- workspaceId,
889
- subjectId: authority.subjectId,
890
- authoritySnapshot: readAuthority.snapshot,
891
- expectedVersion: current.version,
892
- rotationEnabled: parsed.data.rotationEnabled,
893
- }).catch(() => null);
894
- if (!updated) throw new HTTPException(409, { message: "SuperGrok settings changed" });
895
- await wakeXaiCapacityWaiters(deps.db, {
896
- workspaceId,
897
- subjectId: authority.subjectId,
898
- authoritySnapshot: readAuthority.snapshot,
899
- reason: "xai_rotation_settings_changed",
900
- });
901
- return c.json({
902
- rotationEnabled: updated.rotationEnabled,
903
- rotationStrategy: "sharded" as const,
904
- activeCredentialId: updated.activeCredentialId,
905
- });
906
- });
907
-
908
- app.patch("/v1/workspaces/:workspaceId/supergrok/accounts/:accountId/allocator", async (c) => {
909
- requireEnabled(deps);
910
- const workspaceId = c.req.param("workspaceId");
911
- const credentialId = c.req.param("accountId");
912
- const authority = await authorityForAccountMutation(c, deps, workspaceId, credentialId);
913
- const parsed = allocatorBody.safeParse(await c.req.json().catch(() => null));
914
- if (!parsed.success) {
915
- throw new HTTPException(400, {
916
- message: "enabled and expectedVersion are required",
917
- });
918
- }
919
- const result = await updateXaiAllocatorEligibility(deps.db, {
920
- workspaceId,
921
- subjectId: authority.subjectId,
922
- credentialId,
923
- enabled: parsed.data.enabled,
924
- expectedVersion: parsed.data.expectedVersion,
925
- });
926
- if (result.kind === "not_found") {
927
- throw new HTTPException(404, {
928
- message: "SuperGrok account not found",
929
- });
930
- }
931
- const response = {
932
- allocatorEnabled: result.allocatorEnabled,
933
- allocatorVersion: result.allocatorVersion,
934
- allocatorUpdatedAt: result.allocatorUpdatedAt?.toISOString() ?? null,
935
- changed: result.kind === "updated",
936
- };
937
- if (result.kind === "updated") {
938
- await wakeXaiCapacityWaiters(deps.db, {
939
- workspaceId,
940
- subjectId: authority.subjectId,
941
- authoritySnapshot: authority.snapshot,
942
- reason: "xai_allocator_eligibility_changed",
943
- });
944
- }
945
- return result.kind === "conflict" ? c.json(response, 409) : c.json(response);
946
- });
947
-
948
- app.patch("/v1/workspaces/:workspaceId/supergrok/accounts/:accountId", async (c) => {
949
- requireEnabled(deps);
950
- const workspaceId = c.req.param("workspaceId");
951
- const credentialId = c.req.param("accountId");
952
- const authority = await authorityForAccountMutation(c, deps, workspaceId, credentialId);
953
- const parsed = renameBody.safeParse(await c.req.json().catch(() => null));
954
- if (!parsed.success) throw new HTTPException(400, { message: "label is invalid" });
955
- const account = await renameXaiSubscriptionAccount(deps.db, {
956
- workspaceId,
957
- subjectId: authority.subjectId,
958
- credentialId,
959
- label: parsed.data.label || null,
960
- });
961
- if (!account)
962
- throw new HTTPException(404, {
963
- message: "SuperGrok account not found",
964
- });
965
- const settings = await getXaiRotationSettings(deps.db, {
966
- workspaceId,
967
- subjectId: authority.subjectId,
968
- authoritySnapshot: authority.snapshot,
969
- });
970
- return c.json(accountJson(account, settings?.activeCredentialId ?? null));
971
- });
972
-
973
- app.delete("/v1/workspaces/:workspaceId/supergrok/accounts/:accountId", async (c) => {
974
- requireEnabled(deps);
975
- const workspaceId = c.req.param("workspaceId");
976
- const credentialId = c.req.param("accountId");
977
- const authority = await authorityForAccountMutation(c, deps, workspaceId, credentialId);
978
- if (authority.snapshot.scope === "user") {
979
- await wakeXaiCapacityWaiters(deps.db, {
980
- workspaceId,
981
- subjectId: authority.subjectId,
982
- authoritySnapshot: authority.snapshot,
983
- reason: "xai_credential_disconnecting",
984
- });
985
- }
986
- const result = await disconnectXaiSubscriptionCredentialAndRepick(deps.db, {
987
- accountId: authority.accountId,
988
- workspaceId,
989
- subjectId: authority.subjectId,
990
- credentialId,
991
- authoritySnapshot: authority.snapshot,
992
- });
993
- if (result.disconnected && authority.snapshot.scope === "workspace") {
994
- await wakeXaiCapacityWaiters(deps.db, {
995
- workspaceId,
996
- subjectId: authority.subjectId,
997
- authoritySnapshot: WORKSPACE_XAI_PROVIDER_ACCOUNT_AUTHORITY_SNAPSHOT_V1,
998
- reason: "xai_credential_disconnected",
999
- });
1000
- }
1001
- return c.json({
1002
- disconnected: result.disconnected,
1003
- newActiveId: result.newActiveCredentialId,
1004
- });
1005
524
  });
1006
525
  }