@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
@@ -1,5 +1,8 @@
1
- import { canonicalPublicOrigin, type Settings } from "@opengeni/config";
1
+ import { canonicalPublicOrigin, managedUserEmailAllowed, type Settings } from "@opengeni/config";
2
+ import { MANAGED_AUTH_NEW_SIGNUPS_PAUSED_CODE } from "@opengeni/contracts";
2
3
  import {
4
+ configureManagedUserAdmission,
5
+ recordManagedAuthLoggedFailure,
3
6
  type ManagedAuth,
4
7
  type ManagedEmailMessage,
5
8
  type ManagedEmailTransport,
@@ -12,20 +15,37 @@ import {
12
15
  getCanonicalHumanExactLoginBindingForAuthUser,
13
16
  synchronizeCanonicalHumanLoginBindings,
14
17
  } from "@opengeni/db/canonical-human-identities";
18
+ import type { Observability } from "@opengeni/observability";
15
19
  import { betterAuth } from "better-auth";
16
- import { createEmailVerificationToken } from "better-auth/api";
17
- import { hashPassword } from "better-auth/crypto";
20
+ import { APIError, createEmailVerificationToken } from "better-auth/api";
21
+ import { hashPassword, verifyPassword } from "better-auth/crypto";
18
22
  import { sql } from "drizzle-orm";
19
- import { Pool } from "pg";
23
+ import { Pool, type PoolConfig } from "pg";
20
24
 
25
+ import { TRUSTED_CLIENT_ADDRESS_HEADER } from "../http/request-source";
21
26
  import { decideCanonicalHumanSessionAdmission } from "./canonical-human-session-admission";
27
+ import {
28
+ createManagedAuthEmailThrottleHook,
29
+ MANAGED_AUTH_CLIENT_RATE_LIMIT_RULES,
30
+ } from "./managed-auth-rate-limits";
31
+ import { deliverManagedSignInNotification } from "./managed-sign-in-notifications";
32
+ import {
33
+ createManagedAuthNewSignupsGate,
34
+ type ManagedAuthNewSignupsGate,
35
+ } from "./new-signups-gate";
36
+ import { createSignupFunnelMetrics } from "./signup-funnel-metrics";
22
37
  import {
23
38
  currentManagedAuthProviderId,
24
39
  currentManagedAuthAttemptId,
25
40
  recordCurrentManagedAuthSession,
26
41
  shouldDiscardCurrentManagedAuthProviderSession,
42
+ currentManagedSignInConnectIntent,
27
43
  } from "./managed-auth-attempt-context";
28
44
 
45
+ // Only used when no Better Auth secret is configured (local development);
46
+ // the email throttle key is a content-free digest either way.
47
+ const MANAGED_AUTH_EMAIL_THROTTLE_FALLBACK_KEY = "opengeni:managed-auth:email-throttle:local";
48
+
29
49
  // `ManagedAuth` (the Better Auth `Auth<any>` alias) is owned by @opengeni/core
30
50
  // (`managed-auth-type.ts`) — `dependencies.ts`/`access` reference it as a
31
51
  // type-only slot. We re-export it from this construction site so existing
@@ -33,26 +53,61 @@ import {
33
53
  export type { ManagedAuth };
34
54
 
35
55
  export function managedAuthRequiresEmailVerification(
36
- settings: Pick<Settings, "environment">,
56
+ settings: Pick<Settings, "environment" | "managedAuthRequireEmailVerification">,
37
57
  ): boolean {
38
- return settings.environment !== "local";
58
+ return settings.managedAuthRequireEmailVerification ?? settings.environment !== "local";
39
59
  }
40
60
 
41
61
  export function managedAuthUserCreateOverride(
42
- settings: Pick<Settings, "environment">,
62
+ settings: Pick<Settings, "environment" | "managedAuthRequireEmailVerification">,
43
63
  user: { emailVerified: boolean } & Record<string, unknown>,
44
64
  ): { data: typeof user } | undefined {
45
65
  if (managedAuthRequiresEmailVerification(settings)) return undefined;
46
66
  return { data: { ...user, emailVerified: true } };
47
67
  }
48
68
 
69
+ export const MANAGED_AUTH_NEW_SIGNUPS_PAUSED_MESSAGE =
70
+ "We're at capacity for new accounts right now. Please try again later.";
71
+
72
+ /**
73
+ * Typed refusal for a new account while the deployment has paused sign-ups.
74
+ * Existing accounts are unaffected; the body mirrors Better Auth's
75
+ * `{ code, message }` error shape so browser and SDK callers parse it alike.
76
+ */
77
+ export function managedAuthNewSignupsPausedResponse(): Response {
78
+ return Response.json(
79
+ {
80
+ code: MANAGED_AUTH_NEW_SIGNUPS_PAUSED_CODE,
81
+ message: MANAGED_AUTH_NEW_SIGNUPS_PAUSED_MESSAGE,
82
+ },
83
+ { status: 403, headers: { "cache-control": "no-store" } },
84
+ );
85
+ }
86
+
87
+ /**
88
+ * Thrown from the user-create hook while the runtime switch has paused new
89
+ * sign-ups. Better Auth returns it as `403 { code: "NEW_SIGNUPS_PAUSED" }` on
90
+ * email sign-up, and its OAuth callback turns the message into the
91
+ * `error=signup_disabled` redirect it also uses for a static provider refusal.
92
+ */
93
+ export class ManagedAuthNewSignupsPausedError extends APIError {
94
+ constructor() {
95
+ super("FORBIDDEN", { code: MANAGED_AUTH_NEW_SIGNUPS_PAUSED_CODE, message: "signup disabled" });
96
+ }
97
+ }
98
+
49
99
  export function managedAuthUserCreateAdmission(
50
- settings: Pick<Settings, "environment">,
100
+ settings: Pick<Settings, "environment" | "allowedUserEmails"> &
101
+ Partial<Pick<Settings, "managedAuthNewSignupsEnabled" | "managedAuthRequireEmailVerification">>,
51
102
  user: { emailVerified: boolean } & Record<string, unknown>,
52
103
  providerId: string,
53
104
  ): { data: typeof user } | false | undefined {
105
+ // Backstop for every Better Auth user-create path. Invited-user account
106
+ // setup does not create users through Better Auth, so it is unaffected.
107
+ if (settings.managedAuthNewSignupsEnabled === false) return false;
108
+ if (!managedUserEmailAllowed(settings.allowedUserEmails, user.email)) return false;
54
109
  if (
55
- managedAuthRequiresEmailVerification(settings) &&
110
+ (settings.environment !== "local" || managedAuthRequiresEmailVerification(settings)) &&
56
111
  providerId !== "credential" &&
57
112
  !user.emailVerified
58
113
  ) {
@@ -61,29 +116,168 @@ export function managedAuthUserCreateAdmission(
61
116
  return managedAuthUserCreateOverride(settings, user);
62
117
  }
63
118
 
119
+ /**
120
+ * Per-provider Better Auth options while sign-ups are paused. A social sign-in
121
+ * for an existing human still signs in (and may link a verified provider);
122
+ * an unknown human is redirected back with `error=signup_disabled`.
123
+ * `disableSignUp` is the hard switch: `disableImplicitSignUp` alone can be
124
+ * overridden by a client-supplied `requestSignUp`.
125
+ */
126
+ export function managedAuthSocialSignupOptions(
127
+ settings: Pick<Settings, "managedAuthNewSignupsEnabled">,
128
+ ): { disableImplicitSignUp?: true; disableSignUp?: true } {
129
+ return settings.managedAuthNewSignupsEnabled
130
+ ? {}
131
+ : { disableImplicitSignUp: true, disableSignUp: true };
132
+ }
133
+
64
134
  /** Keep Better Auth password policy and storage format behind this boundary. */
65
135
  export async function hashManagedAuthPassword(password: string): Promise<string> {
66
136
  return await hashPassword(password);
67
137
  }
68
138
 
139
+ export async function verifyManagedAuthPassword(password: string, hash: string): Promise<boolean> {
140
+ return await verifyPassword({ password, hash });
141
+ }
142
+
143
+ type ManagedAuthPoolObservability = Pick<Observability, "warn" | "incrementCounter">;
144
+
145
+ /**
146
+ * Better Auth's default console output, plus handing logged failures to the
147
+ * session-lookup boundary so a lost database connection behind its generic
148
+ * INTERNAL_SERVER_ERROR stays recognizable (see `withManagedAuthSessionLookup`).
149
+ */
150
+ function logBetterAuthMessage(
151
+ level: "debug" | "info" | "warn" | "error",
152
+ message: string,
153
+ ...args: unknown[]
154
+ ): void {
155
+ if (level === "error") recordManagedAuthLoggedFailure(args);
156
+ const line = `${new Date().toISOString()} ${level.toUpperCase()} [Better Auth]: ${message}`;
157
+ if (level === "error") console.error(line, ...args);
158
+ else if (level === "warn") console.warn(line, ...args);
159
+ else console.log(line, ...args);
160
+ }
161
+
162
+ /**
163
+ * Bounded pool settings for Better Auth's dedicated `pg` pool. A connection
164
+ * attempt fails after 10 s instead of queueing requests indefinitely while the
165
+ * database is unreachable, and connections recycle like the main postgres-js
166
+ * pool so a pooler- or failover-replaced backend is not held forever.
167
+ */
168
+ export const MANAGED_AUTH_DATABASE_POOL_OPTIONS = {
169
+ max: 10,
170
+ connectionTimeoutMillis: 10_000,
171
+ idleTimeoutMillis: 30_000,
172
+ maxLifetimeSeconds: 1_800,
173
+ keepAlive: true,
174
+ } as const satisfies PoolConfig;
175
+
176
+ /**
177
+ * Better Auth's `pg` pool. When the server closes a connection (a restart,
178
+ * failover, or maintenance window) `pg` emits `error`: on the pool for an idle
179
+ * client, and on the client itself for one checked out by Better Auth's query
180
+ * layer. Without listeners either becomes an uncaught exception and the API's
181
+ * fatal process boundary exits. Both listeners record one content-free signal
182
+ * and keep serving. The pool has already discarded a failed idle client and
183
+ * opens a fresh connection for the next checkout; a checked-out client's
184
+ * in-flight query already rejects to its caller, and the pool discards the
185
+ * dead client on release. An idle client's error also reaches its own
186
+ * listener, so that listener records only while the client is checked out,
187
+ * and at most once per checkout.
188
+ */
189
+ export function createManagedAuthDatabasePool(
190
+ databaseUrl: string,
191
+ observability?: ManagedAuthPoolObservability,
192
+ ): Pool {
193
+ const pool = new Pool({ connectionString: databaseUrl, ...MANAGED_AUTH_DATABASE_POOL_OPTIONS });
194
+ const checkedOut = new WeakSet<object>();
195
+ pool.on("acquire", (client) => checkedOut.add(client));
196
+ pool.on("release", (_error, client) => checkedOut.delete(client));
197
+ pool.on("connect", (client) => {
198
+ client.on("error", () => {
199
+ // One lost connection can emit twice (the server's termination
200
+ // message, then the socket end), so count it once.
201
+ if (checkedOut.delete(client)) {
202
+ recordManagedAuthPoolError(observability, "checked_out_connection_failed");
203
+ }
204
+ });
205
+ });
206
+ pool.on("error", () => recordManagedAuthPoolError(observability, "idle_connection_discarded"));
207
+ return pool;
208
+ }
209
+
210
+ export const MANAGED_AUTH_DATABASE_POOL_ERRORS_METRIC = {
211
+ name: "opengeni_managed_auth_database_pool_errors_total",
212
+ help: "Managed-auth database connections the server closed or lost, by pool state.",
213
+ } as const;
214
+
215
+ function recordManagedAuthPoolError(
216
+ observability: ManagedAuthPoolObservability | undefined,
217
+ outcome: "idle_connection_discarded" | "checked_out_connection_failed",
218
+ ): void {
219
+ try {
220
+ observability?.incrementCounter({
221
+ ...MANAGED_AUTH_DATABASE_POOL_ERRORS_METRIC,
222
+ labels: { outcome },
223
+ });
224
+ observability?.warn("Managed auth database connection failed", {
225
+ dependency: "managed_auth_database",
226
+ outcome,
227
+ });
228
+ } catch {
229
+ // An observer failure must not turn a recovered pool error into a crash.
230
+ }
231
+ }
232
+
69
233
  export function createManagedAuth(
70
234
  settings: Settings,
71
235
  db: Database,
72
236
  managedEmailTransport: ManagedEmailTransport,
237
+ options: {
238
+ observability?: ManagedAuthPoolObservability;
239
+ newSignupsGate?: ManagedAuthNewSignupsGate;
240
+ } = {},
73
241
  ): ManagedAuth | null {
74
242
  if (settings.productAccessMode !== "managed") {
75
243
  return null;
76
244
  }
245
+ // Content-free sign-up funnel counters; recording never fails an auth flow.
246
+ const funnel = options.observability
247
+ ? createSignupFunnelMetrics(options.observability)
248
+ : undefined;
77
249
  const requireEmailVerification = managedAuthRequiresEmailVerification(settings);
78
- const pool = new Pool({ connectionString: settings.databaseUrl });
79
- return betterAuth({
80
- appName: "OpenGeni",
250
+ const pool = createManagedAuthDatabasePool(settings.databaseUrl, options.observability);
251
+ // The deployment ceiling is static Better Auth configuration; the runtime
252
+ // switch is checked per user create in the hook below.
253
+ const newSignupsSocialProviderOptions = managedAuthSocialSignupOptions(settings);
254
+ const newSignupsGate =
255
+ options.newSignupsGate ??
256
+ createManagedAuthNewSignupsGate({ db, settings, observability: options.observability });
257
+ const auth = betterAuth({
258
+ appName: "Opengeni",
81
259
  baseURL: betterAuthBaseUrl(settings),
82
260
  basePath: "/v1/auth",
83
261
  secret: settings.betterAuthSecret,
84
262
  database: pool,
85
263
  trustedOrigins: betterAuthTrustedOrigins(settings),
264
+ logger: { log: logBetterAuthMessage },
265
+ hooks: {
266
+ before: createManagedAuthEmailThrottleHook(
267
+ db,
268
+ settings.betterAuthSecret ?? MANAGED_AUTH_EMAIL_THROTTLE_FALLBACK_KEY,
269
+ ),
270
+ },
86
271
  advanced: {
272
+ // Better Auth reads client addresses only from request headers. The API
273
+ // strips this header from every inbound request and re-stamps it on
274
+ // managed-auth routes with the trusted source address (transport peer,
275
+ // or the forwarded client when OPENGENI_API_TRUSTED_PROXY_HOPS declares
276
+ // a proxy chain), so callers cannot choose their rate-limit bucket or
277
+ // recorded session address.
278
+ ipAddress: {
279
+ ipAddressHeaders: [TRUSTED_CLIENT_ADDRESS_HEADER],
280
+ },
87
281
  useSecureCookies: settings.publicBaseUrl?.startsWith("https://") ?? false,
88
282
  ...(settings.betterAuthCookieDomain
89
283
  ? {
@@ -104,6 +298,7 @@ export function createManagedAuth(
104
298
  fields: {
105
299
  lastRequest: "last_request",
106
300
  },
301
+ customRules: MANAGED_AUTH_CLIENT_RATE_LIMIT_RULES,
107
302
  },
108
303
  user: {
109
304
  modelName: "auth_users",
@@ -180,7 +375,18 @@ export function createManagedAuth(
180
375
  updatedAt: "updated_at",
181
376
  },
182
377
  accountLinking: {
183
- enabled: false,
378
+ enabled: true,
379
+ requireLocalEmailVerified: true,
380
+ trustedProviders: [],
381
+ allowDifferentEmails: false,
382
+ },
383
+ additionalFields: {
384
+ managedLinkIntentId: {
385
+ type: "string",
386
+ fieldName: "managed_link_intent_id",
387
+ input: false,
388
+ returned: false,
389
+ },
184
390
  },
185
391
  encryptOAuthTokens: true,
186
392
  storeStateStrategy: "database",
@@ -192,6 +398,7 @@ export function createManagedAuth(
192
398
  clientId: settings.managedAuthGoogleClientId,
193
399
  clientSecret: settings.managedAuthGoogleClientSecret,
194
400
  prompt: "select_account" as const,
401
+ ...newSignupsSocialProviderOptions,
195
402
  },
196
403
  }
197
404
  : {}),
@@ -200,6 +407,7 @@ export function createManagedAuth(
200
407
  github: {
201
408
  clientId: settings.managedAuthGithubClientId,
202
409
  clientSecret: settings.managedAuthGithubClientSecret,
410
+ ...newSignupsSocialProviderOptions,
203
411
  },
204
412
  }
205
413
  : {}),
@@ -215,45 +423,48 @@ export function createManagedAuth(
215
423
  },
216
424
  emailAndPassword: {
217
425
  enabled: true,
426
+ // Sign-in, password reset, and verification stay enabled; only new
427
+ // account creation is refused while sign-ups are paused.
428
+ disableSignUp: !settings.managedAuthNewSignupsEnabled,
218
429
  // Local managed mode exists so the complete human/org tenancy flow can
219
430
  // be exercised without first configuring a transactional-email vendor.
220
- // Every non-local deployment retains the verified-email boundary.
431
+ // Non-local deployments require verification unless explicitly overridden.
221
432
  requireEmailVerification,
222
433
  revokeSessionsOnPasswordReset: true,
223
434
  onExistingUserSignUp: async ({ user }) => {
224
435
  if (requireEmailVerification && !user.emailVerified) {
225
436
  const url = await verificationUrl(settings, user.email);
226
- await sendManagedAuthEmail(managedEmailTransport, {
227
- kind: "email_verification",
228
- to: user.email,
229
- subject: "Verify your OpenGeni email",
230
- text: `Verify your OpenGeni email: ${url}`,
231
- html: `<p>Verify your OpenGeni email:</p><p><a href="${escapeHtml(url)}">Verify email</a></p>`,
232
- });
437
+ await sendManagedAuthEmail(
438
+ managedEmailTransport,
439
+ emailVerificationMessage(user.email, url),
440
+ );
233
441
  }
234
442
  },
235
443
  sendResetPassword: async ({ user, url }) => {
236
444
  await sendManagedAuthEmail(managedEmailTransport, {
237
445
  kind: "password_reset",
238
446
  to: user.email,
239
- subject: "Reset your OpenGeni password",
240
- text: `Reset your OpenGeni password: ${url}`,
241
- html: `<p>Reset your OpenGeni password:</p><p><a href="${escapeHtml(url)}">Reset password</a></p>`,
447
+ subject: "Reset your Opengeni password",
448
+ text: `Reset your Opengeni password: ${url}`,
449
+ html: `<p>Reset your Opengeni password:</p><p><a href="${escapeHtml(url)}">Reset password</a></p>`,
242
450
  });
243
451
  },
244
452
  },
245
453
  emailVerification: {
246
454
  sendOnSignUp: requireEmailVerification,
455
+ // The first successful verification link click signs the user in (a
456
+ // reused link creates no session). Only legacy mode: session-set modes
457
+ // bind sign-in to an isolated browser transaction, and the provider
458
+ // session this would create is discarded there by design.
459
+ autoSignInAfterVerification: settings.managedAuthSessionSetMode === "legacy",
247
460
  sendVerificationEmail: async ({ user, url }) => {
248
- await sendManagedAuthEmail(managedEmailTransport, {
249
- kind: "email_verification",
250
- to: user.email,
251
- subject: "Verify your OpenGeni email",
252
- text: `Verify your OpenGeni email: ${url}`,
253
- html: `<p>Verify your OpenGeni email:</p><p><a href="${escapeHtml(url)}">Verify email</a></p>`,
254
- });
461
+ await sendManagedAuthEmail(
462
+ managedEmailTransport,
463
+ emailVerificationMessage(user.email, url),
464
+ );
255
465
  },
256
466
  afterEmailVerification: async (user) => {
467
+ funnel?.recordEmailVerified();
257
468
  await ensureManagedAccessForUser(db, {
258
469
  userId: user.id,
259
470
  email: user.email,
@@ -264,9 +475,41 @@ export function createManagedAuth(
264
475
  },
265
476
  },
266
477
  databaseHooks: {
478
+ account: {
479
+ create: {
480
+ before: async (account) => ({
481
+ data: {
482
+ ...account,
483
+ ...(currentManagedSignInConnectIntent()
484
+ ? { managedLinkIntentId: currentManagedSignInConnectIntent() }
485
+ : {}),
486
+ },
487
+ }),
488
+ after: async (account) => {
489
+ if (
490
+ !["google", "github"].includes(account.providerId) ||
491
+ currentManagedSignInConnectIntent()
492
+ )
493
+ return;
494
+ await deliverManagedSignInNotification(db, managedEmailTransport, account.id);
495
+ },
496
+ },
497
+ },
267
498
  session: {
268
499
  create: {
269
500
  before: async (session) => {
501
+ if (settings.allowedUserEmails !== undefined) {
502
+ const result = await pool.query<{ email: string; email_verified: boolean }>(
503
+ "select email, email_verified from auth_users where id = $1",
504
+ [session.userId],
505
+ );
506
+ const user = result.rows[0];
507
+ if (
508
+ !user?.email_verified ||
509
+ !managedUserEmailAllowed(settings.allowedUserEmails, user.email)
510
+ )
511
+ return false;
512
+ }
270
513
  const providerId = currentManagedAuthProviderId();
271
514
  await ensureCanonicalHumanIdentityForAuthUser(db, session.userId);
272
515
  const preflightProjection = await getCanonicalHumanIdentityProjection(
@@ -357,6 +600,7 @@ export function createManagedAuth(
357
600
  };
358
601
  },
359
602
  after: async (session) => {
603
+ funnel?.recordSignIn();
360
604
  recordCurrentManagedAuthSession(session.id);
361
605
  if (!shouldDiscardCurrentManagedAuthProviderSession()) return;
362
606
  await db.execute(sql`delete from auth_sessions where id = ${session.id}`);
@@ -365,9 +609,18 @@ export function createManagedAuth(
365
609
  },
366
610
  user: {
367
611
  create: {
368
- before: async (user) =>
369
- managedAuthUserCreateAdmission(settings, user, currentManagedAuthProviderId()),
370
- after: async (user) => {
612
+ before: async (user) => {
613
+ const admission = managedAuthUserCreateAdmission(
614
+ settings,
615
+ user,
616
+ currentManagedAuthProviderId(),
617
+ );
618
+ if (admission === false) return false;
619
+ if (!(await newSignupsGate.signupsOpen())) throw new ManagedAuthNewSignupsPausedError();
620
+ return admission;
621
+ },
622
+ after: async (user, context) => {
623
+ await funnel?.recordSignUp(context);
371
624
  if (!user.emailVerified) return;
372
625
  await ensureManagedAccessForUser(db, {
373
626
  userId: user.id,
@@ -381,6 +634,8 @@ export function createManagedAuth(
381
634
  },
382
635
  },
383
636
  }) as ManagedAuth;
637
+ configureManagedUserAdmission(auth, settings.allowedUserEmails);
638
+ return auth;
384
639
  }
385
640
 
386
641
  export type ManagedAuthOAuthAttempt = {
@@ -393,7 +648,7 @@ export type ManagedAuthOAuthAttempt = {
393
648
  };
394
649
 
395
650
  /**
396
- * Resolve OpenGeni's server-only login transaction proof from Better Auth's
651
+ * Resolve Opengeni's server-only login transaction proof from Better Auth's
397
652
  * database-backed OAuth state before the provider callback consumes it.
398
653
  */
399
654
  export async function resolveManagedAuthOAuthAttempt(
@@ -533,6 +788,19 @@ export async function sendManagedAuthEmail(
533
788
  if (result.status !== "sent") throw new Error(`managed email ${result.status}`);
534
789
  }
535
790
 
791
+ // Verification can sign the clicker in (autoSignInAfterVerification), so an
792
+ // unsolicited verification email must say plainly that it can be ignored.
793
+ function emailVerificationMessage(to: string, url: string): Omit<ManagedEmailMessage, "from"> {
794
+ const ignore = "If you did not create an Opengeni account, ignore this email.";
795
+ return {
796
+ kind: "email_verification",
797
+ to,
798
+ subject: "Verify your Opengeni email",
799
+ text: `Verify your Opengeni email: ${url}\n\n${ignore}`,
800
+ html: `<p>Verify your Opengeni email:</p><p><a href="${escapeHtml(url)}">Verify email</a></p><p>${ignore}</p>`,
801
+ };
802
+ }
803
+
536
804
  async function verificationUrl(settings: Settings, email: string): Promise<string> {
537
805
  if (!settings.betterAuthSecret) {
538
806
  throw new Error(
@@ -33,7 +33,7 @@ export class InMemoryManagedEmailTransport implements ManagedEmailTransport {
33
33
  idempotency?: ManagedEmailTransport["idempotency"];
34
34
  } = {},
35
35
  ) {
36
- this.sender = options.sender ?? "OpenGeni <auth@mail.opengeni.ai>";
36
+ this.sender = options.sender ?? "Opengeni <auth@mail.opengeni.ai>";
37
37
  this.idempotency = options.idempotency ?? {
38
38
  scope: "opengeni-in-memory-v1",
39
39
  retentionSeconds: 86_400,
@@ -88,6 +88,20 @@ class UnconfiguredManagedEmailTransport implements ManagedEmailTransport {
88
88
  }
89
89
  }
90
90
 
91
+ /** Operator-selected OPENGENI_MANAGED_EMAIL_DELIVERY=disabled: never contacts a provider. */
92
+ class DisabledManagedEmailTransport implements ManagedEmailTransport {
93
+ readonly idempotency = {
94
+ scope: "opengeni-disabled-v1",
95
+ retentionSeconds: 0,
96
+ } as const;
97
+
98
+ constructor(readonly sender: string) {}
99
+
100
+ async send(): Promise<ManagedEmailDeliveryResult> {
101
+ return { status: "failed", errorClass: "delivery_disabled" };
102
+ }
103
+ }
104
+
91
105
  class ResendManagedEmailTransport implements ManagedEmailTransport {
92
106
  private readonly client: Resend;
93
107
  readonly idempotency: ManagedEmailTransport["idempotency"];
@@ -144,6 +158,9 @@ class ResendManagedEmailTransport implements ManagedEmailTransport {
144
158
  }
145
159
 
146
160
  export function createManagedEmailTransport(settings: Settings): ManagedEmailTransport {
161
+ if (settings.managedEmailDelivery === "disabled") {
162
+ return new DisabledManagedEmailTransport(settings.emailFrom);
163
+ }
147
164
  if (settings.resendApiKey) {
148
165
  if (!settings.betterAuthSecret) {
149
166
  throw new Error("OPENGENI_BETTER_AUTH_SECRET is required for managed email delivery");
@@ -0,0 +1,81 @@
1
+ import type { ManagedEmailTransport } from "@opengeni/core";
2
+ import type { Database } from "@opengeni/db";
3
+ import { sql } from "drizzle-orm";
4
+ import { z } from "zod";
5
+
6
+ const Claim = z.object({
7
+ operationId: z.string().uuid(),
8
+ leaseId: z.string().uuid(),
9
+ email: z.string().email(),
10
+ provider: z.enum(["password", "google", "github"]),
11
+ sender: z.string(),
12
+ });
13
+ const started = new WeakSet<object>();
14
+
15
+ export async function deliverManagedSignInNotification(
16
+ db: Database,
17
+ transport: ManagedEmailTransport,
18
+ operationId: string | null = null,
19
+ ): Promise<"sent" | "failed" | "outcome_unknown"> {
20
+ try {
21
+ const result = await db.execute(
22
+ sql`select claim_managed_sign_in_notification(${operationId}::uuid,${transport.sender},${transport.idempotency.scope},${transport.idempotency.retentionSeconds}::integer) as claim`,
23
+ );
24
+ const row = (Array.isArray(result) ? result : result.rows)[0] as { claim: unknown } | undefined;
25
+ if (!row?.claim) return "outcome_unknown";
26
+ const claim = Claim.parse(row.claim);
27
+ let status: "sent" | "failed" | "outcome_unknown" = "outcome_unknown";
28
+ let timer: ReturnType<typeof setTimeout> | undefined;
29
+ try {
30
+ const response = await Promise.race([
31
+ transport.send({
32
+ kind: "sign_in_method_changed",
33
+ from: claim.sender,
34
+ to: claim.email,
35
+ idempotencyKey: `sign-in-method:${claim.operationId}`,
36
+ subject: "Your Opengeni sign-in methods changed",
37
+ text: `Your Opengeni ${claim.provider} sign-in method changed. If this was not you, reset your password and contact your administrator.`,
38
+ html: `<p>Your Opengeni ${claim.provider} sign-in method changed. If this was not you, reset your password and contact your administrator.</p>`,
39
+ }),
40
+ new Promise<{ status: "outcome_unknown" }>((resolve) => {
41
+ timer = setTimeout(() => resolve({ status: "outcome_unknown" }), 5_000);
42
+ }),
43
+ ]);
44
+ status = response.status;
45
+ } catch {
46
+ /* Retain the durable unknown claim for idempotent retry. */
47
+ } finally {
48
+ if (timer) clearTimeout(timer);
49
+ }
50
+ await db.execute(
51
+ sql`select settle_managed_sign_in_notification(${claim.operationId}::uuid,${claim.leaseId}::uuid,${status})`,
52
+ );
53
+ return status;
54
+ } catch {
55
+ // Security state is already committed. A failed claim/ack must never be
56
+ // reported as a failed method change; its durable obligation remains live.
57
+ return "outcome_unknown";
58
+ }
59
+ }
60
+
61
+ export function startManagedSignInNotificationDelivery(
62
+ db: Database,
63
+ transport: ManagedEmailTransport,
64
+ ): void {
65
+ if (started.has(db as object)) return;
66
+ started.add(db as object);
67
+ let active = false;
68
+ const drain = async () => {
69
+ if (active) return;
70
+ active = true;
71
+ try {
72
+ for (let count = 0; count < 10; count++)
73
+ if ((await deliverManagedSignInNotification(db, transport)) === "outcome_unknown") break;
74
+ } finally {
75
+ active = false;
76
+ }
77
+ };
78
+ const timer = setInterval(() => void drain(), 60_000);
79
+ (timer as ReturnType<typeof setInterval> & { unref?: () => void }).unref?.();
80
+ void drain();
81
+ }
@@ -0,0 +1,49 @@
1
+ import type { Settings } from "@opengeni/config";
2
+ import { readManagedAuthNewSignupsSwitch, type Database } from "@opengeni/db";
3
+ import type { Observability } from "@opengeni/observability";
4
+
5
+ /**
6
+ * Decides whether a new managed account may be created right now.
7
+ *
8
+ * `OPENGENI_MANAGED_AUTH_NEW_SIGNUPS_ENABLED` is the deployment ceiling (read at
9
+ * startup). While it allows sign-ups, the newest revision of the operator
10
+ * runtime switch (migration 0585) decides, read on every call so a flip
11
+ * applies to the next request on every API replica without a restart.
12
+ *
13
+ * Fail-safe: if the read fails, the last value this process observed wins;
14
+ * before any successful read, the deployment ceiling wins. A missing revision
15
+ * (pre-0585 schema) also follows the ceiling.
16
+ */
17
+ export type ManagedAuthNewSignupsGate = {
18
+ signupsOpen(): Promise<boolean>;
19
+ };
20
+
21
+ export function createManagedAuthNewSignupsGate(input: {
22
+ db: Database;
23
+ settings: Pick<Settings, "managedAuthNewSignupsEnabled">;
24
+ observability?: Pick<Observability, "warn"> | undefined;
25
+ }): ManagedAuthNewSignupsGate {
26
+ const ceiling = input.settings.managedAuthNewSignupsEnabled !== false;
27
+ let lastKnown: boolean | null = null;
28
+ return {
29
+ async signupsOpen() {
30
+ if (!ceiling) return false;
31
+ try {
32
+ const current = await readManagedAuthNewSignupsSwitch(input.db);
33
+ lastKnown = current ? current.signupsEnabled : true;
34
+ return lastKnown;
35
+ } catch (error) {
36
+ try {
37
+ input.observability?.warn("Managed auth new signups switch read failed", {
38
+ dependency: "managed_auth_new_signups_switch",
39
+ fallback: lastKnown === null ? "deployment_ceiling" : "last_known",
40
+ errorClass: error instanceof Error ? error.name : "UnknownError",
41
+ });
42
+ } catch {
43
+ // An observer failure must not decide a sign-up.
44
+ }
45
+ return lastKnown ?? ceiling;
46
+ }
47
+ },
48
+ };
49
+ }