@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
@@ -2,11 +2,13 @@ import {
2
2
  GitHubActionPoliciesResponse,
3
3
  GitHubActionPolicyActorState,
4
4
  GitHubAppManifestCreate,
5
+ OrganizationIntegrationDeniedError,
5
6
  UpdateGitHubActionPolicyRequest,
6
7
  type AccessGrant,
7
8
  type GitHubInstallationBindingCandidate,
8
9
  } from "@opengeni/contracts";
9
10
  import { PersonalGitHubConnectionMetadata } from "@opengeni/contracts/personal-github";
11
+ import { withOrganizationIntegrationAcquisition } from "@opengeni/db/organization-integration-policy";
10
12
  import {
11
13
  ListGitHubRepositoryBranchesQuery,
12
14
  VerifyPublicGitHubRepositoryRefRequest,
@@ -31,6 +33,7 @@ import {
31
33
  GitHubPublicRepositoryVerificationError,
32
34
  githubAppMissingSettings,
33
35
  githubOAuthAuthorizeUrl,
36
+ inspectSignedState,
34
37
  organizationAppManifestUrl,
35
38
  personalAppManifestUrl,
36
39
  readSignedState,
@@ -39,9 +42,10 @@ import {
39
42
  type GitHubSignedStatePayload,
40
43
  verifySignedState,
41
44
  } from "@opengeni/github";
42
- import type { Context, Hono } from "hono";
45
+ import type { Context, Hono, MiddlewareHandler } from "hono";
43
46
  import { deleteCookie, setCookie } from "hono/cookie";
44
47
  import { HTTPException } from "hono/http-exception";
48
+ import type { ContentfulStatusCode } from "hono/utils/http-status";
45
49
  import {
46
50
  githubAppActionPolicyActor,
47
51
  hasPermission,
@@ -71,22 +75,90 @@ import {
71
75
  assertPersonalConnectionOwnerPrincipal,
72
76
  requireLegacyOAuthActor,
73
77
  } from "../connection-ownership";
78
+ import { workspaceIntegrationsPathForUntrusted } from "../integrations/oauth-client";
74
79
  import { listPersonalGitHubConnections } from "../integrations/personal-github";
80
+ import {
81
+ integrationCommitGrant,
82
+ type IntegrationCommitGrant,
83
+ } from "../integrations/integration-commit-authority";
75
84
  import {
76
85
  isConsistentGitHubBindingCandidates,
77
86
  isConsistentGitHubBindingProof,
78
87
  } from "../integrations/github-installation-proof";
88
+ import {
89
+ githubConnectFailureHtml,
90
+ githubInstallationChooserHtml,
91
+ githubSetupPendingHtml,
92
+ githubOwnerApprovedHtml,
93
+ githubSetupSuccessHtml,
94
+ githubSuccessHtml,
95
+ type GitHubConnectFailure,
96
+ } from "./github-browser-pages";
79
97
  import {
80
98
  completeGitHubAppConnect,
81
99
  isGitHubAppConnectState,
82
100
  } from "../integrations/github-app-connect";
101
+ import { parseRequestJson } from "../http/request-body";
83
102
 
84
103
  const githubStateCookie = "opengeni_github_state";
85
104
  const githubBindingStateMaxAgeSeconds = 10 * 60;
86
105
  const legacyInstallationChooserDisabledMessage =
87
106
  "The legacy repository-admin GitHub installation chooser is disabled; use the GitHub owner-consent connect flow";
107
+ /**
108
+ * GitHub routes a browser navigates to (not the JSON API). A page-load link
109
+ * opened after it expired, GitHub's Cancel button, or a non-owner all land on
110
+ * one of these, so their failures render a readable page instead of JSON.
111
+ */
112
+ const GITHUB_BROWSER_ROUTES = [
113
+ "/v1/workspaces/:workspaceId/github/connect",
114
+ "/v1/workspaces/:workspaceId/github/installations/select",
115
+ "/v1/workspaces/:workspaceId/github/installations/:installationId/configure",
116
+ "/v1/github/app-manifest/callback",
117
+ "/v1/github/setup",
118
+ "/v1/github/install/callback",
119
+ "/v1/github/oauth/callback",
120
+ ] as const;
121
+
122
+ /** An HTTP failure that already knows which browser page explains it. */
123
+ class GitHubBrowserFailure extends HTTPException {
124
+ constructor(
125
+ status: 400 | 403,
126
+ message: string,
127
+ readonly failure: GitHubConnectFailure,
128
+ ) {
129
+ super(status, { message });
130
+ this.name = "GitHubBrowserFailure";
131
+ }
132
+ }
133
+
88
134
  export function registerGitHubRoutes(app: Hono, deps: ApiRouteDeps): void {
89
135
  const { db, settings, githubStateSecret } = deps;
136
+ // Registered before the routes so it wraps them. The status code is kept, so
137
+ // automation still sees the same outcome; only the body becomes a page. Every
138
+ // failure is rendered, not only HTTP ones: an organization policy denial or an
139
+ // unexpected fault must not reach the browser as the JSON error envelope.
140
+ const browserFailurePage: MiddlewareHandler = async (c, next) => {
141
+ let failure: unknown;
142
+ let handledStatus: number | undefined;
143
+ try {
144
+ await next();
145
+ if (!c.error) return;
146
+ failure = c.error;
147
+ // The app error handler has already answered this failure.
148
+ handledStatus = c.res.status;
149
+ } catch (error) {
150
+ failure = error;
151
+ }
152
+ c.res = c.html(
153
+ githubConnectFailureHtml(
154
+ githubBrowserFailureKind(failure),
155
+ githubFailureReturnUrl(deps, c),
156
+ githubBrowserFailureDetail(failure),
157
+ ),
158
+ githubBrowserFailureStatus(failure, handledStatus) as ContentfulStatusCode,
159
+ );
160
+ };
161
+ for (const path of GITHUB_BROWSER_ROUTES) app.use(path, browserFailurePage);
90
162
 
91
163
  app.get("/v1/workspaces/:workspaceId/github/app", async (c) => {
92
164
  const workspaceId = c.req.param("workspaceId");
@@ -174,7 +246,7 @@ export function registerGitHubRoutes(app: Hono, deps: ApiRouteDeps): void {
174
246
 
175
247
  app.patch("/v1/workspaces/:workspaceId/github/action-policies", async (c) => {
176
248
  const workspaceId = c.req.param("workspaceId");
177
- const payload = UpdateGitHubActionPolicyRequest.parse(await c.req.json());
249
+ const payload = await parseRequestJson(c, UpdateGitHubActionPolicyRequest);
178
250
  const actor = payload.actor;
179
251
  if (actor.kind === "workspace_app") {
180
252
  const grant = await requireAccessGrant(c, deps, workspaceId, "github:manage");
@@ -228,7 +300,7 @@ export function registerGitHubRoutes(app: Hono, deps: ApiRouteDeps): void {
228
300
 
229
301
  // Start with user authorization, not GitHub's install/configure selector.
230
302
  // This lets an owner link an already-installed App without relying on
231
- // GitHub's Configure page to preserve or return OpenGeni state.
303
+ // GitHub's Configure page to preserve or return Opengeni state.
232
304
  app.get("/v1/workspaces/:workspaceId/github/connect", async (c) => {
233
305
  const workspaceId = c.req.param("workspaceId");
234
306
  const state = c.req.query("state");
@@ -308,7 +380,7 @@ export function registerGitHubRoutes(app: Hono, deps: ApiRouteDeps): void {
308
380
  const workspaceId = c.req.param("workspaceId");
309
381
  const grant = await requireAccessGrant(c, deps, workspaceId);
310
382
  requirePublicGitHubRepositoryVerificationPermission(grant);
311
- const request = VerifyPublicGitHubRepositoryRefRequest.parse(await c.req.json());
383
+ const request = await parseRequestJson(c, VerifyPublicGitHubRepositoryRefRequest);
312
384
  let repository: ReturnType<typeof parseCanonicalGitHubRepositoryUrl>;
313
385
  try {
314
386
  repository = parseCanonicalGitHubRepositoryUrl(request.url);
@@ -431,7 +503,7 @@ export function registerGitHubRoutes(app: Hono, deps: ApiRouteDeps): void {
431
503
  const access = await requireAccessGrantAuthorization(c, deps, workspaceId, "github:manage");
432
504
  requireLegacyOAuthActor(access);
433
505
  const grant = access.grant;
434
- const payload = GitHubAppManifestCreate.parse(await c.req.json());
506
+ const payload = await parseRequestJson(c, GitHubAppManifestCreate);
435
507
  const baseUrl = (settings.githubAppManifestBaseUrl ?? new URL(c.req.url).origin).replace(
436
508
  /\/+$/,
437
509
  "",
@@ -441,7 +513,7 @@ export function registerGitHubRoutes(app: Hono, deps: ApiRouteDeps): void {
441
513
  workspaceId: grant.workspaceId,
442
514
  });
443
515
  setGitHubStateCookie(c, deps, state);
444
- const appName = payload.appName?.trim() || "OpenGeni";
516
+ const appName = payload.appName?.trim() || "Opengeni";
445
517
  const manifest = buildGitHubAppManifest({
446
518
  appName,
447
519
  baseUrl,
@@ -498,6 +570,16 @@ export function registerGitHubRoutes(app: Hono, deps: ApiRouteDeps): void {
498
570
  );
499
571
  });
500
572
  if (!state) {
573
+ // An organization owner approving a member's request (or installing
574
+ // straight from GitHub) arrives with no Opengeni state. Nothing names a
575
+ // workspace, so nothing is connected: explain the remaining step instead
576
+ // of an "expired link" error. No provider or database call happens here.
577
+ if (
578
+ c.req.query("setup_action") === "install" &&
579
+ parsePositiveInteger(c.req.query("installation_id")) !== null
580
+ ) {
581
+ return c.html(githubOwnerApprovedHtml(githubFailureReturnUrl(deps, c)));
582
+ }
501
583
  throw new HTTPException(400, { message: "missing GitHub installation state" });
502
584
  }
503
585
  const statePayload = readSignedState(state, githubStateSecret);
@@ -519,7 +601,17 @@ export function registerGitHubRoutes(app: Hono, deps: ApiRouteDeps): void {
519
601
  }
520
602
  const setupAction = c.req.query("setup_action");
521
603
  if (setupAction === "request") {
522
- return c.html(githubSetupPendingHtml());
604
+ return c.html(
605
+ githubSetupPendingHtml(
606
+ openGeniReturnUrl(
607
+ settings,
608
+ c,
609
+ grant.workspaceId,
610
+ typeof statePayload.returnPath === "string" ? statePayload.returnPath : null,
611
+ "requested",
612
+ ),
613
+ ),
614
+ );
523
615
  }
524
616
  if (setupAction !== "install" && setupAction !== "update") {
525
617
  throw new HTTPException(400, { message: "unsupported GitHub setup action" });
@@ -575,6 +667,9 @@ export function registerGitHubRoutes(app: Hono, deps: ApiRouteDeps): void {
575
667
  });
576
668
  const code = c.req.query("code");
577
669
  const state = c.req.query("state");
670
+ if (c.req.query("error") === "access_denied") {
671
+ throw new GitHubBrowserFailure(400, "GitHub authorization was cancelled", "cancelled");
672
+ }
578
673
  if (!code) {
579
674
  throw new HTTPException(400, { message: "missing GitHub OAuth code" });
580
675
  }
@@ -598,6 +693,7 @@ export function registerGitHubRoutes(app: Hono, deps: ApiRouteDeps): void {
598
693
  message: "GitHub OAuth state does not match this workspace",
599
694
  });
600
695
  }
696
+ await withOrganizationIntegrationAcquisition(db, grant, ["github-app"], async () => {});
601
697
  let candidates: GitHubInstallationBindingCandidate[] | null;
602
698
  try {
603
699
  candidates = deps.githubAppApi?.discoverInstallationBindingCandidates
@@ -652,6 +748,7 @@ export function registerGitHubRoutes(app: Hono, deps: ApiRouteDeps): void {
652
748
  message: "GitHub OAuth state does not match this workspace",
653
749
  });
654
750
  }
751
+ await withOrganizationIntegrationAcquisition(db, grant, ["github-app"], async () => {});
655
752
  let proof;
656
753
  try {
657
754
  proof = deps.githubAppApi?.authorizeInstallationBinding
@@ -681,22 +778,30 @@ export function registerGitHubRoutes(app: Hono, deps: ApiRouteDeps): void {
681
778
  const expiresAt = new Date((statePayload.iat + githubBindingStateMaxAgeSeconds) * 1_000);
682
779
  let bound;
683
780
  try {
684
- bound = await bindAuthorizedGitHubInstallationRepositories(db, {
685
- accountId: grant.accountId,
686
- workspaceId: grant.workspaceId,
687
- installationId,
688
- githubAccountId: proof.installation.accountId,
689
- accountLogin: proof.installation.accountLogin,
690
- accountType: proof.installation.accountType,
691
- linkedBySubjectId: grant.subjectId,
692
- githubActorId: proof.actorId,
693
- githubActorLogin: proof.actorLogin,
694
- authorityKind: proof.authorityKind,
695
- authorityCheckedAt,
696
- authorityExpiresAt: expiresAt,
697
- authorityNonce: statePayload.nonce,
698
- repositoryIds,
699
- });
781
+ bound = await withOrganizationIntegrationAcquisition(
782
+ db,
783
+ grant,
784
+ ["github-app"],
785
+ async (tx) => {
786
+ await grant.authorizeCommit(tx);
787
+ return bindAuthorizedGitHubInstallationRepositories(tx, {
788
+ accountId: grant.accountId,
789
+ workspaceId: grant.workspaceId,
790
+ installationId,
791
+ githubAccountId: proof.installation.accountId,
792
+ accountLogin: proof.installation.accountLogin,
793
+ accountType: proof.installation.accountType,
794
+ linkedBySubjectId: grant.subjectId,
795
+ githubActorId: proof.actorId,
796
+ githubActorLogin: proof.actorLogin,
797
+ authorityKind: proof.authorityKind,
798
+ authorityCheckedAt,
799
+ authorityExpiresAt: expiresAt,
800
+ authorityNonce: statePayload.nonce,
801
+ repositoryIds,
802
+ });
803
+ },
804
+ );
700
805
  } catch (error) {
701
806
  if (error instanceof GitHubInstallationAuthorityCommitError) {
702
807
  throw new HTTPException(409, { message: error.message });
@@ -913,18 +1018,32 @@ async function requireGitHubManageGrant(
913
1018
  deps: ApiRouteDeps,
914
1019
  workspaceId: string,
915
1020
  expectedState: GitHubSignedStatePayload,
916
- ): Promise<AccessGrant> {
1021
+ ): Promise<IntegrationCommitGrant> {
917
1022
  try {
918
1023
  const access = await requireAccessGrantAuthorization(c, deps, workspaceId, "github:manage");
919
1024
  requireLegacyOAuthActor(access);
920
- return access.grant;
1025
+ return integrationCommitGrant(access, ["github:manage"], {
1026
+ settings: deps.settings,
1027
+ authorizationHeader: c.req.header("authorization"),
1028
+ });
921
1029
  } catch (error) {
922
1030
  if (!(error instanceof HTTPException) || error.status !== 401) {
923
1031
  throw error;
924
1032
  }
925
1033
  const grant = githubBrowserGrantFromState(deps.settings, expectedState, workspaceId);
926
1034
  if (grant) {
927
- return grant;
1035
+ return {
1036
+ ...grant,
1037
+ authorizeCommit: async () => {
1038
+ const current = githubBrowserGrantFromState(deps.settings, expectedState, workspaceId);
1039
+ if (
1040
+ !current ||
1041
+ current.accountId !== grant.accountId ||
1042
+ current.subjectId !== grant.subjectId
1043
+ )
1044
+ throw new HTTPException(403, { message: "GitHub browser handoff expired or changed" });
1045
+ },
1046
+ };
928
1047
  }
929
1048
  throw error;
930
1049
  }
@@ -952,7 +1071,7 @@ function githubAuthorityHttpError(error: unknown): HTTPException {
952
1071
  }
953
1072
  if (error instanceof GitHubInstallationAuthorityError) {
954
1073
  if (error.reason === "authority_denied") {
955
- return new HTTPException(403, { message: error.message });
1074
+ return new GitHubBrowserFailure(403, error.message, "not_owner");
956
1075
  }
957
1076
  if (error.reason === "installation_missing") {
958
1077
  return new HTTPException(404, { message: error.message });
@@ -1022,39 +1141,6 @@ function isSecureRequest(c: Context, deps: ApiRouteDeps): boolean {
1022
1141
  );
1023
1142
  }
1024
1143
 
1025
- function githubSuccessHtml(envLines: string[]): string {
1026
- const envText = envLines.join("\n");
1027
- const escaped = escapeHtml(envText);
1028
- return `<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>GitHub App Created</title><style>body{font-family:system-ui,sans-serif;margin:0;min-height:100vh;display:grid;place-items:center;background:#0b0b0d;color:#f4f4f5}main{width:min(760px,calc(100vw - 32px));border:1px solid #27272a;border-radius:8px;padding:28px;background:#111114}h1{margin:0 0 10px;font-size:24px;line-height:1.2}p{margin:0 0 18px;color:#d4d4d8}.env-header{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:22px 0 8px}.env-header h2{margin:0;font-size:13px;line-height:1.2;text-transform:uppercase;letter-spacing:.08em;color:#a1a1aa}pre{white-space:pre-wrap;word-break:break-word;max-height:380px;overflow:auto;background:#09090b;border:1px solid #27272a;border-radius:8px;padding:16px;font-size:13px;line-height:1.5}button{display:inline-flex;align-items:center;justify-content:center;min-height:36px;border-radius:6px;border:1px solid #3f3f46;padding:0 12px;background:#f4f4f5;color:#09090b;font:600 14px system-ui,sans-serif;cursor:pointer}button:disabled{cursor:not-allowed;opacity:.7}</style></head><body><main><h1>GitHub App created</h1><p>Add these values to .env, then restart API and worker.</p><div class="env-header"><h2>Environment variables</h2><button id="copy-env" type="button">Copy env</button></div><pre id="env-lines">${escaped}</pre><script>(()=>{const button=document.getElementById("copy-env");const env=document.getElementById("env-lines");async function copyText(text){if(navigator.clipboard&&window.isSecureContext){await navigator.clipboard.writeText(text);return;}const area=document.createElement("textarea");area.value=text;area.setAttribute("readonly","");area.style.position="fixed";area.style.inset="-9999px";document.body.append(area);area.select();document.execCommand("copy");area.remove();}button?.addEventListener("click",async()=>{try{await copyText(env?.textContent||"");button.textContent="Copied";setTimeout(()=>button.textContent="Copy env",1600);}catch{button.textContent="Copy failed";setTimeout(()=>button.textContent="Copy env",2200);}});})();</script></main></body></html>`;
1029
- }
1030
-
1031
- function githubSetupSuccessHtml(account: string, returnUrl: string): string {
1032
- return `<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>GitHub App Connected</title><style>body{font-family:system-ui,sans-serif;margin:0;min-height:100vh;display:grid;place-items:center;background:#0b0b0d;color:#f4f4f5}main{width:min(640px,calc(100vw - 32px));border:1px solid #27272a;border-radius:8px;padding:28px;background:#111114}h1{margin:0 0 10px;font-size:24px;line-height:1.2}p{margin:0 0 18px;color:#d4d4d8}.button{display:inline-flex;align-items:center;justify-content:center;min-height:36px;border-radius:6px;border:1px solid #3f3f46;padding:0 12px;background:#f4f4f5;color:#09090b;font:600 14px system-ui,sans-serif;text-decoration:none}</style></head><body><main><h1>GitHub App connected</h1><p>${escapeHtml(account)} is now available to this OpenGeni workspace through an explicit repository allowlist.</p><a class="button" href="${escapeHtml(returnUrl)}">Back to OpenGeni</a></main></body></html>`;
1033
- }
1034
-
1035
- function githubInstallationChooserHtml(
1036
- candidates: GitHubInstallationBindingCandidate[],
1037
- state: string,
1038
- workspaceId: string,
1039
- baseUrl: string,
1040
- ): string {
1041
- const action = `${baseUrl}/v1/workspaces/${encodeURIComponent(workspaceId)}/github/installations/select`;
1042
- const options = candidates
1043
- .map(({ installation, authorityKind }, index) => {
1044
- const account = escapeHtml(
1045
- installation.accountLogin ?? `installation ${installation.installationId}`,
1046
- );
1047
- const label = authorityKind === "personal_owner" ? "Personal account" : "Organization owner";
1048
- return `<label class="option"><input type="radio" name="installation_id" value="${installation.installationId}" required${candidates.length === 1 && index === 0 ? " checked" : ""}><span><strong>${account}</strong><small>${label}</small></span></label>`;
1049
- })
1050
- .join("");
1051
- return `<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Choose GitHub installation</title><style>body{font-family:system-ui,sans-serif;margin:0;min-height:100vh;display:grid;place-items:center;background:#0b0b0d;color:#f4f4f5}main{width:min(640px,calc(100vw - 32px));border:1px solid #27272a;border-radius:12px;padding:28px;background:#111114}h1{margin:0 0 10px;font-size:24px}p{margin:0 0 18px;color:#d4d4d8}.options{display:grid;gap:8px;margin-bottom:18px}.option{display:flex;align-items:center;gap:12px;border:1px solid #3f3f46;border-radius:8px;padding:12px;cursor:pointer}.option span{display:grid;gap:2px}.option small{color:#a1a1aa}button{min-height:38px;border-radius:7px;border:1px solid #3f3f46;padding:0 14px;background:#f4f4f5;color:#09090b;font:600 14px system-ui,sans-serif;cursor:pointer}.secondary{margin-left:8px;background:transparent;color:#f4f4f5}</style></head><body><main><h1>Choose a GitHub account</h1><p>These accounts already have the OpenGeni GitHub App installed and GitHub proved you are the personal owner or an active organization owner.</p><form method="get" action="${escapeHtml(action)}"><input type="hidden" name="state" value="${escapeHtml(state)}"><div class="options">${options}</div><button type="submit">Connect selected</button><button class="secondary" type="submit" name="installation_id" value="new" formnovalidate>Install on another account</button></form></main></body></html>`;
1052
- }
1053
-
1054
- function githubSetupPendingHtml(): string {
1055
- return `<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>GitHub App Requested</title><style>body{font-family:system-ui,sans-serif;margin:0;min-height:100vh;display:grid;place-items:center;background:#0b0b0d;color:#f4f4f5}main{width:min(640px,calc(100vw - 32px));border:1px solid #27272a;border-radius:8px;padding:28px;background:#111114}h1{margin:0 0 10px;font-size:24px;line-height:1.2}p{margin:0;color:#d4d4d8}</style></head><body><main><h1>GitHub App request sent</h1><p>A GitHub organization owner must approve the installation. OpenGeni has not created a workspace binding.</p></main></body></html>`;
1056
- }
1057
-
1058
1144
  function parsePositiveInteger(value: string | undefined | null): number | null {
1059
1145
  if (!value || !/^\d+$/.test(value)) {
1060
1146
  return null;
@@ -1068,32 +1154,19 @@ function isFreshGitHubBindingState(payload: GitHubSignedStatePayload): boolean {
1068
1154
  return age >= 0 && age < githubBindingStateMaxAgeSeconds;
1069
1155
  }
1070
1156
 
1071
- function escapeHtml(value: string): string {
1072
- return value.replace(
1073
- /[&<>"']/g,
1074
- (char) =>
1075
- ({
1076
- "&": "&amp;",
1077
- "<": "&lt;",
1078
- ">": "&gt;",
1079
- '"': "&quot;",
1080
- "'": "&#39;",
1081
- })[char] ?? char,
1082
- );
1083
- }
1084
-
1085
1157
  function openGeniReturnUrl(
1086
1158
  settings: ApiRouteDeps["settings"],
1087
1159
  c: Context,
1088
1160
  workspaceId: string,
1089
1161
  returnPath: string | null = null,
1162
+ outcome: "connected" | "requested" = "connected",
1090
1163
  ): string {
1091
1164
  const baseUrl = openGeniBaseUrl(settings, c) || new URL(c.req.url).origin;
1092
1165
  const safeReturnPath = githubSessionReturnPath(returnPath, workspaceId);
1093
1166
  const url = safeReturnPath ? new URL(safeReturnPath, `${baseUrl}/`) : new URL(baseUrl);
1094
1167
  if (safeReturnPath) {
1095
1168
  url.searchParams.delete("capability_auth");
1096
- url.searchParams.set("github", "connected");
1169
+ url.searchParams.set("github", outcome);
1097
1170
  return url.toString();
1098
1171
  }
1099
1172
  url.searchParams.set("workspaceId", workspaceId);
@@ -1103,3 +1176,55 @@ function openGeniReturnUrl(
1103
1176
  function openGeniBaseUrl(settings: ApiRouteDeps["settings"], c: Context): string {
1104
1177
  return githubBrowserBaseUrl(settings, new URL(c.req.url).origin);
1105
1178
  }
1179
+
1180
+ /** The status the app error handler gives this failure; the page keeps it. */
1181
+ function githubBrowserFailureStatus(error: unknown, handledStatus: number | undefined): number {
1182
+ if (error instanceof HTTPException) return error.status;
1183
+ if (error instanceof OrganizationIntegrationDeniedError) return 403;
1184
+ // An unexpected fault keeps whatever the error handler answered (500 by default).
1185
+ return handledStatus ?? 500;
1186
+ }
1187
+
1188
+ function githubBrowserFailureKind(error: unknown): GitHubConnectFailure {
1189
+ if (error instanceof OrganizationIntegrationDeniedError) return "policy_denied";
1190
+ if (!(error instanceof HTTPException)) return "failed";
1191
+ if (error instanceof GitHubBrowserFailure) return error.failure;
1192
+ if (error.status === 401) return "signed_out";
1193
+ if (error.status === 403) return "forbidden";
1194
+ // Every signed-state rejection names its state; they all mean "start again".
1195
+ if (error.status === 400 && /\bstate\b/iu.test(error.message)) return "expired";
1196
+ return "failed";
1197
+ }
1198
+
1199
+ /**
1200
+ * Human-authored HTTP messages only; configuration errors carry a JSON
1201
+ * envelope. Anything else (an unexpected fault) shows no detail.
1202
+ */
1203
+ function githubBrowserFailureDetail(error: unknown): string | null {
1204
+ if (!(error instanceof HTTPException)) return null;
1205
+ if (error instanceof GitHubBrowserFailure && error.failure === "cancelled") return null;
1206
+ try {
1207
+ const parsed = JSON.parse(error.message) as { message?: unknown };
1208
+ return typeof parsed?.message === "string" ? parsed.message : null;
1209
+ } catch {
1210
+ return error.message || null;
1211
+ }
1212
+ }
1213
+
1214
+ /**
1215
+ * The failure page links back to the workspace integrations page when the
1216
+ * request names a workspace (its path, or a correctly signed state even if it
1217
+ * aged out); otherwise to the Opengeni home. This is only a link target, so an
1218
+ * expired state is acceptable evidence of where the user came from.
1219
+ */
1220
+ function githubFailureReturnUrl(deps: ApiRouteDeps, c: Context): string {
1221
+ const baseUrl = (
1222
+ deps.settings.webBaseUrl ??
1223
+ (openGeniBaseUrl(deps.settings, c) || new URL(c.req.url).origin)
1224
+ ).replace(/\/+$/u, "");
1225
+ const rawState = c.req.query("state");
1226
+ const candidate =
1227
+ c.req.param("workspaceId") ??
1228
+ (rawState ? inspectSignedState(rawState, deps.githubStateSecret)?.workspaceId : undefined);
1229
+ return `${baseUrl}${workspaceIntegrationsPathForUntrusted(candidate) ?? "/"}`;
1230
+ }