@opengeni/api-router 0.30.1 → 1.0.0

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 (436) hide show
  1. package/dist/access-grant-rls.d.ts +3 -0
  2. package/dist/admission-trace.d.ts +8 -0
  3. package/dist/api-websocket.d.ts +18 -0
  4. package/dist/app.d.ts +50 -2
  5. package/dist/app.js +12 -1
  6. package/dist/artifact-catalog-cursor.d.ts +27 -0
  7. package/dist/auth/managed-auth-attempt-context.d.ts +10 -0
  8. package/dist/auth/managed-auth-rate-limits.d.ts +167 -0
  9. package/dist/auth/managed-auth-session-adapter.d.ts +6 -0
  10. package/dist/auth/managed-auth.d.ts +102 -3
  11. package/dist/auth/managed-email.d.ts +29 -0
  12. package/dist/auth/managed-sign-in-notifications.d.ts +4 -0
  13. package/dist/auth/new-signups-gate.d.ts +23 -0
  14. package/dist/auth/organization-user-setup.d.ts +80 -0
  15. package/dist/auth/signup-funnel-metrics.d.ts +44 -0
  16. package/dist/browser-controller-authority.d.ts +1 -61
  17. package/dist/browser-ephemeral.d.ts +5 -0
  18. package/dist/browser-state-authority.d.ts +1 -27
  19. package/dist/chunk-6TZ5LG3O.js +123948 -0
  20. package/dist/chunk-6TZ5LG3O.js.map +1 -0
  21. package/dist/chunk-OGQDXVXY.js +18 -0
  22. package/dist/chunk-OGQDXVXY.js.map +1 -0
  23. package/dist/claude-subscription-account-conflicts.d.ts +1 -0
  24. package/dist/claude-subscription-account-usage.d.ts +39 -0
  25. package/dist/claude-subscription-oauth.d.ts +25 -0
  26. package/dist/claude-subscription-profile.d.ts +9 -0
  27. package/dist/claude-subscription-usage.d.ts +44 -0
  28. package/dist/claude-workspace-connection.d.ts +15 -0
  29. package/dist/codemode.d.ts +32 -1
  30. package/dist/company-brain-okf.d.ts +24 -0
  31. package/dist/connected-machine-computer-access.d.ts +11 -0
  32. package/dist/connection-ownership.d.ts +54 -0
  33. package/dist/controller-data-plane.d.ts +32 -0
  34. package/dist/editable-artifact-office-import.d.ts +7 -4
  35. package/dist/editable-artifact-source-session.d.ts +3 -0
  36. package/dist/editable-artifact-websocket.d.ts +10 -18
  37. package/dist/editable-artifact-workspace-files.d.ts +1 -1
  38. package/dist/fatal-process-boundary.d.ts +25 -0
  39. package/dist/github-access.d.ts +31 -2
  40. package/dist/http/acting-person.d.ts +24 -0
  41. package/dist/http/api-contract-compat.d.ts +19 -0
  42. package/dist/http/api-error.d.ts +27 -1
  43. package/dist/http/cors.d.ts +17 -0
  44. package/dist/http/deprecation.d.ts +42 -0
  45. package/dist/http/interaction-control-error.d.ts +13 -0
  46. package/dist/http/keyed-admission.d.ts +12 -0
  47. package/dist/http/local-browser-boundary.d.ts +72 -0
  48. package/dist/http/metrics-listener.d.ts +22 -0
  49. package/dist/http/path-identifier.d.ts +17 -0
  50. package/dist/http/registered-route-label.d.ts +16 -0
  51. package/dist/http/request-body.d.ts +27 -0
  52. package/dist/http/request-source.d.ts +52 -0
  53. package/dist/http/sse.d.ts +17 -6
  54. package/dist/http/unmatched-route.d.ts +18 -0
  55. package/dist/http/user-content.d.ts +36 -0
  56. package/dist/http/websocket-upgrade-dispatch.d.ts +18 -0
  57. package/dist/index.d.ts +10 -3
  58. package/dist/index.js +1129 -166
  59. package/dist/index.js.map +1 -1
  60. package/dist/integration-endpoint-test.d.ts +20 -0
  61. package/dist/integrations/api-integrations.d.ts +2 -2
  62. package/dist/integrations/atlassian.d.ts +29 -3
  63. package/dist/integrations/connect-authority.d.ts +1 -0
  64. package/dist/integrations/connect-callback-return.d.ts +6 -0
  65. package/dist/integrations/fiken.d.ts +16 -2
  66. package/dist/integrations/github-app-connect.d.ts +47 -0
  67. package/dist/integrations/github-installation-proof.d.ts +3 -0
  68. package/dist/integrations/github-lens-connect.d.ts +116 -0
  69. package/dist/integrations/github-skill-source.d.ts +1 -5
  70. package/dist/integrations/google-drive.d.ts +25 -0
  71. package/dist/integrations/integration-commit-authority.d.ts +13 -0
  72. package/dist/integrations/marketplace-plugin.d.ts +2691 -0
  73. package/dist/integrations/oauth-client.d.ts +178 -18
  74. package/dist/integrations/oauth-profiles.d.ts +222 -0
  75. package/dist/integrations/oauth-return-path.d.ts +1 -0
  76. package/dist/integrations/personal-github-repositories.d.ts +84 -0
  77. package/dist/integrations/personal-github.d.ts +42 -0
  78. package/dist/integrations/pr-review-provider.d.ts +22 -0
  79. package/dist/integrations/provider-oauth.d.ts +19 -1
  80. package/dist/integrations/slack-app-home.d.ts +24 -0
  81. package/dist/integrations/slack-bot.d.ts +367 -12
  82. package/dist/integrations/slack-file-upload-flow.d.ts +62 -0
  83. package/dist/integrations/slack-install.d.ts +20 -0
  84. package/dist/integrations/slack-interactions.d.ts +113 -10
  85. package/dist/integrations/slack-mrkdwn.d.ts +41 -0
  86. package/dist/integrations/slack-routing.d.ts +120 -0
  87. package/dist/integrations/slack-session-defaults.d.ts +58 -0
  88. package/dist/integrations/slack-task-file-upload.d.ts +36 -0
  89. package/dist/integrations/social-oauth.d.ts +7 -0
  90. package/dist/interaction-agent-access.d.ts +15 -0
  91. package/dist/interaction-frame-proxy.d.ts +68 -0
  92. package/dist/interaction-metrics.d.ts +2 -0
  93. package/dist/mcp/action-catalog-types.d.ts +9 -0
  94. package/dist/mcp/action-catalog.gen.d.ts +2 -0
  95. package/dist/mcp/capability-account-readiness.d.ts +7 -0
  96. package/dist/mcp/child-read-evidence.d.ts +9 -0
  97. package/dist/mcp/command-read.d.ts +24 -0
  98. package/dist/mcp/company-profile-agent-admin.d.ts +44 -0
  99. package/dist/mcp/contract-input.d.ts +11 -0
  100. package/dist/mcp/documents.d.ts +7 -5
  101. package/dist/mcp/files.d.ts +2 -2
  102. package/dist/mcp/first-party-tool-permissions.d.ts +650 -0
  103. package/dist/mcp/knowledge-entries.d.ts +5 -0
  104. package/dist/mcp/orchestration-failure-diagnostic.d.ts +43 -0
  105. package/dist/mcp/receipts.d.ts +9 -0
  106. package/dist/mcp/request-abort.d.ts +19 -0
  107. package/dist/mcp/scheduled-task-input.d.ts +1189 -0
  108. package/dist/mcp/scheduled-task-view.d.ts +22 -4
  109. package/dist/mcp/server.d.ts +255 -3
  110. package/dist/mcp/session-event-view.d.ts +94 -0
  111. package/dist/mcp/session-view.d.ts +66 -2
  112. package/dist/mcp/session-wait.d.ts +174 -0
  113. package/dist/mcp-oauth.d.ts +52 -0
  114. package/dist/model-catalog.d.ts +11 -31
  115. package/dist/observability.d.ts +3 -1
  116. package/dist/organization-mcp.d.ts +52 -0
  117. package/dist/organization-recovery-notifications.d.ts +41 -0
  118. package/dist/routes/analytics-consent.d.ts +26 -0
  119. package/dist/routes/api-integrations.d.ts +25 -0
  120. package/dist/routes/api-keys.d.ts +17 -0
  121. package/dist/routes/artifact-catalog.d.ts +6 -0
  122. package/dist/routes/automations.d.ts +19 -0
  123. package/dist/routes/billing.d.ts +49 -0
  124. package/dist/routes/browser-sessions.d.ts +71 -3
  125. package/dist/routes/claude-subscription-accounts.d.ts +3 -0
  126. package/dist/routes/claude-subscription-oauth.d.ts +3 -0
  127. package/dist/routes/client-errors.d.ts +146 -0
  128. package/dist/routes/codex.d.ts +76 -2
  129. package/dist/routes/company-brain.d.ts +3 -0
  130. package/dist/routes/company-profile.d.ts +2 -1
  131. package/dist/routes/computer-sessions.d.ts +14 -0
  132. package/dist/routes/connect.d.ts +5 -0
  133. package/dist/routes/editable-artifacts.d.ts +2 -0
  134. package/dist/routes/external-identity-links.d.ts +6 -0
  135. package/dist/routes/feedback.d.ts +3 -0
  136. package/dist/routes/files.d.ts +4 -0
  137. package/dist/routes/github-browser-pages.d.ts +12 -0
  138. package/dist/routes/github.d.ts +2 -0
  139. package/dist/routes/insights-response-cache.d.ts +10 -0
  140. package/dist/routes/insights-usage.d.ts +12 -0
  141. package/dist/routes/insights.d.ts +30 -1
  142. package/dist/routes/knowledge.d.ts +3 -0
  143. package/dist/routes/managed-auth-session-sets.d.ts +26 -0
  144. package/dist/routes/managed-onboarding.d.ts +29 -0
  145. package/dist/routes/managed-sign-in-methods.d.ts +6 -0
  146. package/dist/routes/model-connection-access.d.ts +3 -0
  147. package/dist/routes/organization-integration-policy.d.ts +3 -0
  148. package/dist/routes/organization-integrations.d.ts +6 -0
  149. package/dist/routes/organization-mcp-connections.d.ts +3 -0
  150. package/dist/routes/organization-model-providers.d.ts +3 -0
  151. package/dist/routes/organization-recovery.d.ts +19 -0
  152. package/dist/routes/organization-service-accounts.d.ts +3 -0
  153. package/dist/routes/organization-sessions.d.ts +26 -0
  154. package/dist/routes/personal-github-git-broker.d.ts +29 -0
  155. package/dist/routes/personal-github.d.ts +3 -0
  156. package/dist/routes/pr-review-github.d.ts +3 -0
  157. package/dist/routes/pr-review.d.ts +3 -0
  158. package/dist/routes/session-artifact-associations.d.ts +4 -0
  159. package/dist/routes/session-history-imports.d.ts +9 -0
  160. package/dist/routes/sessions.d.ts +44 -6
  161. package/dist/routes/skill-content.d.ts +4 -0
  162. package/dist/routes/skill-install-authority.d.ts +6 -0
  163. package/dist/routes/subscription-account-pools.d.ts +34 -0
  164. package/dist/routes/subscription-pool-access.d.ts +16 -0
  165. package/dist/routes/supergrok.d.ts +6 -1
  166. package/dist/routes/usage-allowances.d.ts +12 -0
  167. package/dist/routes/user-resource-authorities.d.ts +3 -0
  168. package/dist/routes/workspace-artifacts.d.ts +2 -1
  169. package/dist/routes/workspace-capture.d.ts +10 -2
  170. package/dist/routes/workspace-integrations.d.ts +35 -0
  171. package/dist/routes/workspace-learning.d.ts +3 -0
  172. package/dist/routes/workspace-model-providers.d.ts +4 -0
  173. package/dist/routes/workspaces.d.ts +29 -0
  174. package/dist/sandbox/auth-callout.d.ts +8 -0
  175. package/dist/sandbox/channel-a.d.ts +19 -1
  176. package/dist/sandbox/connection-authority.d.ts +3 -0
  177. package/dist/sandbox/enrollment.d.ts +9 -1
  178. package/dist/sandbox/machines.d.ts +5 -2
  179. package/dist/sandbox/metrics-ingestion.d.ts +28 -20
  180. package/dist/sandbox/rematerialize.d.ts +2 -0
  181. package/dist/sandbox/session-attach-variable-sets.d.ts +30 -0
  182. package/dist/sandbox/viewer.d.ts +26 -1
  183. package/dist/sandbox-file-artifacts.d.ts +50 -0
  184. package/dist/scheduled-task-deletion.d.ts +13 -0
  185. package/dist/session-create-observability.d.ts +5 -0
  186. package/dist/session-event-view-MPS2OZD3.js +292 -0
  187. package/dist/session-event-view-MPS2OZD3.js.map +1 -0
  188. package/dist/site-session-origin.d.ts +13 -0
  189. package/dist/site-uploads.d.ts +41 -0
  190. package/dist/slack-reaction-files.d.ts +1 -1
  191. package/dist/temporal-schedule-cleanup.d.ts +1 -0
  192. package/dist/temporal-schedule-sync.d.ts +26 -0
  193. package/dist/transcription/providers/xai-subscription.d.ts +1 -0
  194. package/dist/transcription/service.d.ts +2 -1
  195. package/dist/work-discovery-observability.d.ts +33 -0
  196. package/dist/workspace-artifact-content.d.ts +28 -0
  197. package/dist/workspace-artifact-provenance.d.ts +7 -0
  198. package/dist/workspace-delete-observability.d.ts +10 -0
  199. package/dist/workspace-deletion.d.ts +6 -0
  200. package/dist/workspace-state-projection.d.ts +3 -5
  201. package/dist/workspace-tool-gateway-observability.d.ts +17 -0
  202. package/dist/workspace-tool-gateway.d.ts +123 -0
  203. package/dist/workspace-webhook-dispatch.d.ts +26 -0
  204. package/package.json +23 -19
  205. package/src/access-grant-rls.ts +75 -0
  206. package/src/admission-trace.ts +14 -0
  207. package/src/api-websocket.ts +23 -0
  208. package/src/app.ts +1974 -256
  209. package/src/artifact-catalog-cursor.ts +60 -0
  210. package/src/auth/managed-auth-attempt-context.ts +70 -0
  211. package/src/auth/managed-auth-rate-limits.ts +252 -0
  212. package/src/auth/managed-auth-session-adapter.ts +222 -0
  213. package/src/auth/managed-auth.ts +536 -60
  214. package/src/auth/managed-email.ts +174 -0
  215. package/src/auth/managed-sign-in-notifications.ts +81 -0
  216. package/src/auth/new-signups-gate.ts +49 -0
  217. package/src/auth/organization-user-setup.ts +307 -0
  218. package/src/auth/signup-funnel-metrics.ts +164 -0
  219. package/src/browser-controller-authority.ts +1 -186
  220. package/src/browser-ephemeral.ts +39 -0
  221. package/src/browser-state-authority.ts +1 -236
  222. package/src/claude-subscription-account-conflicts.ts +12 -0
  223. package/src/claude-subscription-account-usage.ts +48 -0
  224. package/src/claude-subscription-oauth.ts +362 -0
  225. package/src/claude-subscription-profile.ts +73 -0
  226. package/src/claude-subscription-usage.ts +97 -0
  227. package/src/claude-workspace-connection.ts +82 -0
  228. package/src/codemode.ts +194 -30
  229. package/src/codex-realtime.ts +8 -2
  230. package/src/company-brain-okf.ts +340 -0
  231. package/src/connected-machine-computer-access.ts +33 -0
  232. package/src/connection-ownership.ts +199 -0
  233. package/src/controller-data-plane.ts +81 -0
  234. package/src/editable-artifact-native-kernel.ts +26 -15
  235. package/src/editable-artifact-office-import.ts +77 -9
  236. package/src/editable-artifact-production.ts +23 -7
  237. package/src/editable-artifact-source-session.ts +123 -0
  238. package/src/editable-artifact-websocket.ts +27 -21
  239. package/src/editable-artifact-workspace-files.ts +31 -6
  240. package/src/fatal-process-boundary.ts +246 -0
  241. package/src/gateway-realtime.ts +1 -1
  242. package/src/github-access.ts +147 -5
  243. package/src/http/acting-person.ts +71 -0
  244. package/src/http/api-contract-compat.ts +49 -0
  245. package/src/http/api-error.ts +115 -1
  246. package/src/http/auth.ts +48 -0
  247. package/src/http/cors.ts +67 -0
  248. package/src/http/deprecation.ts +118 -0
  249. package/src/http/interaction-control-error.ts +164 -0
  250. package/src/http/keyed-admission.ts +29 -0
  251. package/src/http/local-browser-boundary.ts +343 -0
  252. package/src/http/metrics-listener.ts +57 -0
  253. package/src/http/path-identifier.ts +54 -0
  254. package/src/http/registered-route-label.ts +34 -0
  255. package/src/http/request-body.ts +127 -0
  256. package/src/http/request-source.ts +178 -0
  257. package/src/http/sse.ts +486 -132
  258. package/src/http/unmatched-route.ts +60 -0
  259. package/src/http/user-content.ts +158 -0
  260. package/src/http/websocket-upgrade-dispatch.ts +29 -0
  261. package/src/index.ts +157 -52
  262. package/src/integration-endpoint-test.ts +291 -0
  263. package/src/integrations/api-integrations.ts +98 -11
  264. package/src/integrations/atlassian.ts +474 -136
  265. package/src/integrations/connect-authority.ts +2 -0
  266. package/src/integrations/connect-callback-return.ts +86 -0
  267. package/src/integrations/fiken.ts +354 -64
  268. package/src/integrations/github-app-connect.ts +435 -0
  269. package/src/integrations/github-installation-proof.ts +60 -0
  270. package/src/integrations/github-lens-connect.ts +76 -0
  271. package/src/integrations/github-skill-source.ts +2 -142
  272. package/src/integrations/google-drive.ts +820 -222
  273. package/src/integrations/integration-commit-authority.ts +69 -0
  274. package/src/integrations/marketplace-plugin.ts +48 -0
  275. package/src/integrations/oauth-client.ts +1356 -459
  276. package/src/integrations/oauth-profiles.ts +537 -0
  277. package/src/integrations/oauth-return-path.ts +18 -0
  278. package/src/integrations/personal-github-repositories.ts +674 -0
  279. package/src/integrations/personal-github.ts +825 -0
  280. package/src/integrations/pr-review-provider.ts +246 -0
  281. package/src/integrations/provider-oauth.ts +250 -22
  282. package/src/integrations/slack-app-home.ts +300 -0
  283. package/src/integrations/slack-bot.ts +963 -239
  284. package/src/integrations/slack-file-upload-flow.ts +147 -0
  285. package/src/integrations/slack-install.ts +83 -0
  286. package/src/integrations/slack-interactions.ts +3170 -474
  287. package/src/integrations/slack-mrkdwn.ts +193 -0
  288. package/src/integrations/slack-routing.ts +337 -0
  289. package/src/integrations/slack-session-defaults.ts +224 -0
  290. package/src/integrations/slack-task-file-upload.ts +323 -0
  291. package/src/integrations/social-oauth.ts +213 -15
  292. package/src/interaction-agent-access.ts +48 -0
  293. package/src/interaction-frame-proxy.ts +409 -0
  294. package/src/interaction-metrics.ts +30 -0
  295. package/src/mcp/action-catalog-types.ts +9 -0
  296. package/src/mcp/action-catalog.gen.ts +6696 -0
  297. package/src/mcp/capability-account-readiness.ts +17 -0
  298. package/src/mcp/child-read-evidence.ts +19 -0
  299. package/src/mcp/command-read.ts +109 -0
  300. package/src/mcp/company-profile-agent-admin.ts +198 -0
  301. package/src/mcp/contract-input.ts +141 -0
  302. package/src/mcp/documents.ts +65 -377
  303. package/src/mcp/editable-artifacts.ts +12 -6
  304. package/src/mcp/files.ts +80 -38
  305. package/src/mcp/first-party-tool-permissions.ts +305 -0
  306. package/src/mcp/knowledge-entries.ts +322 -0
  307. package/src/mcp/orchestration-failure-diagnostic.ts +43 -0
  308. package/src/mcp/receipts.ts +34 -0
  309. package/src/mcp/request-abort.ts +44 -0
  310. package/src/mcp/scheduled-task-input.ts +76 -0
  311. package/src/mcp/scheduled-task-view.ts +44 -3
  312. package/src/mcp/server.ts +3030 -1267
  313. package/src/mcp/session-event-view.ts +383 -0
  314. package/src/mcp/session-view.ts +84 -3
  315. package/src/mcp/session-wait.ts +665 -0
  316. package/src/mcp-oauth.ts +1123 -0
  317. package/src/model-catalog.ts +91 -333
  318. package/src/observability.ts +15 -1
  319. package/src/organization-mcp.ts +397 -0
  320. package/src/organization-recovery-notifications.ts +103 -0
  321. package/src/routes/analytics-consent.ts +123 -0
  322. package/src/routes/api-integrations.ts +364 -74
  323. package/src/routes/api-keys.ts +336 -10
  324. package/src/routes/artifact-catalog.ts +279 -0
  325. package/src/routes/automations.ts +768 -0
  326. package/src/routes/billing.ts +461 -46
  327. package/src/routes/browser-sessions.ts +839 -131
  328. package/src/routes/canonical-human-identities.ts +90 -14
  329. package/src/routes/capabilities.ts +107 -6
  330. package/src/routes/channels.ts +20 -3
  331. package/src/routes/claude-subscription-accounts.ts +334 -0
  332. package/src/routes/claude-subscription-oauth.ts +142 -0
  333. package/src/routes/client-errors.ts +362 -0
  334. package/src/routes/codex.ts +833 -116
  335. package/src/routes/company-brain.ts +322 -0
  336. package/src/routes/company-profile.ts +65 -1
  337. package/src/routes/computer-sessions.ts +557 -106
  338. package/src/routes/connect.ts +1938 -0
  339. package/src/routes/connections.ts +1040 -349
  340. package/src/routes/documents.ts +488 -287
  341. package/src/routes/editable-artifacts.ts +79 -9
  342. package/src/routes/enrollments.ts +135 -39
  343. package/src/routes/environments.ts +154 -58
  344. package/src/routes/external-identity-links.ts +201 -0
  345. package/src/routes/feedback.ts +113 -0
  346. package/src/routes/files.ts +337 -39
  347. package/src/routes/github-browser-pages.ts +162 -0
  348. package/src/routes/github.ts +446 -144
  349. package/src/routes/insights-response-cache.ts +83 -0
  350. package/src/routes/insights-usage.ts +345 -0
  351. package/src/routes/insights.ts +153 -19
  352. package/src/routes/install.ts +133 -38
  353. package/src/routes/integration-facets.ts +107 -33
  354. package/src/routes/interaction-resources.ts +30 -3
  355. package/src/routes/knowledge.ts +488 -0
  356. package/src/routes/machines.ts +313 -15
  357. package/src/routes/managed-auth-session-sets.ts +1218 -0
  358. package/src/routes/managed-onboarding.ts +337 -0
  359. package/src/routes/managed-sign-in-methods.ts +433 -0
  360. package/src/routes/memory-slack-publications.ts +3 -2
  361. package/src/routes/model-connection-access.ts +208 -0
  362. package/src/routes/organization-integration-policy.ts +116 -0
  363. package/src/routes/organization-integrations.ts +326 -0
  364. package/src/routes/organization-mcp-connections.ts +178 -0
  365. package/src/routes/organization-memberships.ts +1019 -27
  366. package/src/routes/organization-model-providers.ts +293 -0
  367. package/src/routes/organization-recovery.ts +325 -0
  368. package/src/routes/organization-service-accounts.ts +128 -0
  369. package/src/routes/organization-sessions.ts +350 -0
  370. package/src/routes/personal-github-git-broker.ts +785 -0
  371. package/src/routes/personal-github.ts +370 -0
  372. package/src/routes/plugins.ts +251 -22
  373. package/src/routes/pr-review-github.ts +881 -0
  374. package/src/routes/pr-review.ts +622 -0
  375. package/src/routes/preference-registry.ts +12 -93
  376. package/src/routes/rigs.ts +167 -50
  377. package/src/routes/scheduled-tasks.ts +346 -41
  378. package/src/routes/session-artifact-associations.ts +87 -0
  379. package/src/routes/session-history-imports.ts +280 -0
  380. package/src/routes/sessions.ts +2306 -264
  381. package/src/routes/skill-content.ts +297 -0
  382. package/src/routes/skill-install-authority.ts +64 -0
  383. package/src/routes/skills.ts +62 -9
  384. package/src/routes/social.ts +46 -18
  385. package/src/routes/subscription-account-pools.ts +436 -0
  386. package/src/routes/subscription-pool-access.ts +126 -0
  387. package/src/routes/supergrok.ts +219 -303
  388. package/src/routes/transcription-recordings.ts +38 -3
  389. package/src/routes/transcriptions.ts +4 -0
  390. package/src/routes/usage-allowances.ts +378 -0
  391. package/src/routes/user-resource-authorities.ts +138 -0
  392. package/src/routes/video-generation.ts +14 -10
  393. package/src/routes/workspace-artifacts.ts +275 -69
  394. package/src/routes/workspace-capture.ts +21 -0
  395. package/src/routes/workspace-integrations.ts +576 -0
  396. package/src/routes/workspace-learning.ts +159 -0
  397. package/src/routes/workspace-model-providers.ts +148 -0
  398. package/src/routes/workspace-state.ts +38 -25
  399. package/src/routes/workspaces.ts +1004 -127
  400. package/src/sandbox/auth-callout.ts +96 -19
  401. package/src/sandbox/channel-a.ts +323 -24
  402. package/src/sandbox/connection-authority.ts +3 -0
  403. package/src/sandbox/enrollment.ts +81 -6
  404. package/src/sandbox/machines.ts +218 -76
  405. package/src/sandbox/metrics-ingestion.ts +411 -62
  406. package/src/sandbox/rematerialize.ts +121 -19
  407. package/src/sandbox/session-attach-variable-sets.ts +131 -0
  408. package/src/sandbox/viewer.ts +280 -25
  409. package/src/sandbox-file-artifacts.ts +413 -0
  410. package/src/scheduled-task-deletion.ts +138 -0
  411. package/src/session-create-observability.ts +46 -0
  412. package/src/session-realtime-context.ts +6 -3
  413. package/src/site-session-origin.ts +48 -0
  414. package/src/site-uploads.ts +224 -0
  415. package/src/slack-reaction-files.ts +16 -5
  416. package/src/temporal-schedule-cleanup.ts +13 -0
  417. package/src/temporal-schedule-sync.ts +74 -0
  418. package/src/transcription/providers/codex-subscription.ts +2 -0
  419. package/src/transcription/providers/openai.ts +1 -0
  420. package/src/transcription/providers/xai-subscription.ts +49 -3
  421. package/src/transcription/segmenter.ts +8 -2
  422. package/src/transcription/service.ts +43 -6
  423. package/src/work-discovery-observability.ts +121 -0
  424. package/src/workspace-artifact-content.ts +144 -0
  425. package/src/workspace-artifact-provenance.ts +104 -0
  426. package/src/workspace-delete-observability.ts +75 -0
  427. package/src/workspace-deletion.ts +73 -0
  428. package/src/workspace-state-projection.ts +18 -148
  429. package/src/workspace-tool-gateway-observability.ts +100 -0
  430. package/src/workspace-tool-gateway.ts +870 -0
  431. package/src/workspace-webhook-dispatch.ts +190 -0
  432. package/src/xai-subscription-auth.ts +9 -2
  433. package/dist/chunk-2PQMSRCB.js +0 -49759
  434. package/dist/chunk-2PQMSRCB.js.map +0 -1
  435. package/dist/routes/packs.d.ts +0 -3
  436. package/src/routes/packs.ts +0 -729
@@ -0,0 +1,622 @@
1
+ import { environmentsEncryptionKeyBytes } from "@opengeni/config";
2
+ import { withOrganizationIntegrationAcquisition } from "@opengeni/db/organization-integration-policy";
3
+ import {
4
+ CreatePrReviewAppRegistrationRequest,
5
+ CreatePrReviewRepositoryBindingRequest,
6
+ PrReviewAppRegistration,
7
+ PrReviewRepositoryBinding,
8
+ UpdatePrReviewAppRegistrationRequest,
9
+ UpdatePrReviewRepositoryBindingRequest,
10
+ } from "@opengeni/contracts";
11
+ import {
12
+ assertWorkspaceModelPolicyAllows,
13
+ canonicalConfiguredModel,
14
+ defaultPrReviewProviderBaseUrl,
15
+ workspaceCustomModelReference,
16
+ lockActiveCustomModelForAdmission,
17
+ modelUnavailableHttpException,
18
+ prReviewWebhookAuthKind,
19
+ normalizePrReviewProviderBaseUrl,
20
+ requireAccessGrant,
21
+ requireAccessGrantAuthorization,
22
+ requirePermission,
23
+ resolveWorkspaceCatalogSettings,
24
+ type ApiRouteDeps,
25
+ PR_REVIEW_AUTOMATION_SETUP,
26
+ } from "@opengeni/core";
27
+ import {
28
+ createPrReviewAppRegistration,
29
+ createPrReviewRepositoryBinding,
30
+ deletePrReviewAppRegistration,
31
+ deletePrReviewRepositoryBinding,
32
+ decryptVariableSetValue,
33
+ encryptVariableSetValue,
34
+ getPrReviewAppRegistrationSecret,
35
+ listPrReviewAppRegistrations,
36
+ listPrReviewRepositoryBindings,
37
+ nestedPostgresSqlState,
38
+ recordAuditEvent,
39
+ updatePrReviewAppRegistration,
40
+ updatePrReviewRepositoryBinding,
41
+ } from "@opengeni/db";
42
+ import { listGitHubAppRepositoriesWithSigningSettings } from "@opengeni/github";
43
+ import type { Hono } from "hono";
44
+ import { HTTPException } from "hono/http-exception";
45
+ import {
46
+ PrReviewProviderRepositoryError,
47
+ verifyPrReviewProviderRepository,
48
+ } from "../integrations/pr-review-provider";
49
+ import { registerPrReviewGitHubRoutes } from "./pr-review-github";
50
+ import { integrationCommitGrant } from "../integrations/integration-commit-authority";
51
+ import { parseRequestJson } from "../http/request-body";
52
+
53
+ export function registerPrReviewRoutes(app: Hono, deps: ApiRouteDeps): void {
54
+ const { db, settings } = deps;
55
+ registerPrReviewGitHubRoutes(app, deps);
56
+
57
+ app.get("/v1/workspaces/:workspaceId/pr-review/registrations", async (c) => {
58
+ const workspaceId = c.req.param("workspaceId");
59
+ const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:read");
60
+
61
+ return c.json({
62
+ registrations: await listPrReviewAppRegistrations(db, grant.accountId, workspaceId),
63
+ repositories: await listPrReviewRepositoryBindings(db, grant.accountId, workspaceId),
64
+ });
65
+ });
66
+
67
+ app.post("/v1/workspaces/:workspaceId/pr-review/registrations", async (c) => {
68
+ const workspaceId = c.req.param("workspaceId");
69
+ const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:admin");
70
+ requirePermission(grant, "secrets:write");
71
+
72
+ assertPrReviewSandboxBackend(deps);
73
+ const payload = await parseRequestJson(c, CreatePrReviewAppRegistrationRequest);
74
+ const encryptionKey = requirePrReviewEncryptionKey(deps);
75
+ let providerBaseUrl: string;
76
+ try {
77
+ providerBaseUrl = normalizePrReviewProviderBaseUrl(
78
+ payload.provider,
79
+ payload.providerBaseUrl ?? defaultPrReviewProviderBaseUrl(payload.provider),
80
+ );
81
+ } catch (error) {
82
+ throw new HTTPException(422, {
83
+ message:
84
+ error instanceof Error
85
+ ? error.message
86
+ : "PR Review providerBaseUrl must be a credential-free HTTPS origin or path",
87
+ });
88
+ }
89
+ if (
90
+ payload.provider === "azure_devops" &&
91
+ new URL(providerBaseUrl).pathname.split("/").filter(Boolean).length === 0
92
+ ) {
93
+ throw new HTTPException(422, {
94
+ message: "Azure DevOps PR Review providerBaseUrl must include the organization path",
95
+ });
96
+ }
97
+ const registration = await mapPrReviewUniqueConflict(
98
+ withOrganizationIntegrationAcquisition(
99
+ db,
100
+ grant,
101
+ [prReviewIntegrationKey(payload.provider)],
102
+ (tx) =>
103
+ createPrReviewAppRegistration(tx, {
104
+ accountId: grant.accountId,
105
+ workspaceId,
106
+ name: payload.name,
107
+ provider: payload.provider,
108
+ providerBaseUrl,
109
+ appId: payload.appId ?? null,
110
+ credentialKind: payload.credentialKind,
111
+ credentialEncrypted: encryptVariableSetValue(
112
+ encryptionKey,
113
+ payload.privateKey ?? payload.accessToken!,
114
+ ),
115
+ accessTokenExpiresAt: payload.accessTokenExpiresAt
116
+ ? new Date(payload.accessTokenExpiresAt)
117
+ : null,
118
+ webhookAuthKind: prReviewWebhookAuthKind(payload.provider),
119
+ webhookSecretEncrypted: encryptVariableSetValue(encryptionKey, payload.webhookSecret),
120
+ webhookUsername: payload.webhookUsername ?? null,
121
+ createdBySubjectId: grant.subjectId,
122
+ }),
123
+ ),
124
+ "A PR Review registration with this provider and name already exists",
125
+ );
126
+ await recordAuditEvent(db, {
127
+ accountId: grant.accountId,
128
+ workspaceId,
129
+ subjectId: grant.subjectId,
130
+ action: "prReview.app_registration.created",
131
+ targetType: "pr_review_app_registration",
132
+ targetId: registration.id,
133
+ metadata: {
134
+ provider: registration.provider,
135
+ credentialKind: registration.credentialKind,
136
+ webhookAuthKind: registration.webhookAuthKind,
137
+ },
138
+ });
139
+ return c.json(PrReviewAppRegistration.parse(registration), 201);
140
+ });
141
+
142
+ app.patch("/v1/workspaces/:workspaceId/pr-review/registrations/:registrationId", async (c) => {
143
+ const workspaceId = c.req.param("workspaceId");
144
+ const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:admin");
145
+ requirePermission(grant, "secrets:write");
146
+
147
+ const payload = await parseRequestJson(c, UpdatePrReviewAppRegistrationRequest);
148
+ const existing = await getPrReviewAppRegistrationSecret(db, {
149
+ accountId: grant.accountId,
150
+ workspaceId,
151
+ registrationId: c.req.param("registrationId"),
152
+ });
153
+ if (!existing)
154
+ throw new HTTPException(404, {
155
+ message: "PR Review app registration not found",
156
+ });
157
+ if (existing.credentialKind === "managed_github_app") {
158
+ if (
159
+ payload.accessToken !== undefined ||
160
+ payload.privateKey !== undefined ||
161
+ payload.webhookSecret !== undefined ||
162
+ payload.webhookUsername !== undefined ||
163
+ payload.accessTokenExpiresAt !== undefined
164
+ ) {
165
+ throw new HTTPException(422, {
166
+ message: "Opengeni Lens credentials are managed by the deployment",
167
+ });
168
+ }
169
+ if (payload.status === "active") {
170
+ throw new HTTPException(409, {
171
+ message: "Reconnect Opengeni Lens to reactivate and resync its repositories",
172
+ });
173
+ }
174
+ }
175
+ if (payload.accessToken && existing.credentialKind !== "provider_token") {
176
+ throw new HTTPException(422, {
177
+ message: "GitHub App registrations accept private keys, not access tokens",
178
+ });
179
+ }
180
+ if (payload.privateKey && existing.credentialKind !== "github_app") {
181
+ throw new HTTPException(422, {
182
+ message: "Provider-token registrations do not accept GitHub private keys",
183
+ });
184
+ }
185
+ if (
186
+ payload.accessTokenExpiresAt !== undefined &&
187
+ existing.credentialKind !== "provider_token"
188
+ ) {
189
+ throw new HTTPException(422, {
190
+ message: "GitHub App registrations do not accept access-token expiry",
191
+ });
192
+ }
193
+ const encryptionKey =
194
+ payload.privateKey || payload.accessToken || payload.webhookSecret
195
+ ? requirePrReviewEncryptionKey(deps)
196
+ : null;
197
+ const updated = await mapPrReviewUniqueConflict(
198
+ updatePrReviewAppRegistration(db, {
199
+ accountId: grant.accountId,
200
+ workspaceId,
201
+ registrationId: existing.id,
202
+ ...(payload.name !== undefined ? { name: payload.name } : {}),
203
+ ...(payload.accessToken !== undefined
204
+ ? {
205
+ credentialEncrypted: encryptVariableSetValue(encryptionKey!, payload.accessToken),
206
+ }
207
+ : {}),
208
+ ...(payload.privateKey !== undefined
209
+ ? {
210
+ credentialEncrypted: encryptVariableSetValue(encryptionKey!, payload.privateKey),
211
+ }
212
+ : {}),
213
+ ...(payload.accessTokenExpiresAt !== undefined
214
+ ? {
215
+ accessTokenExpiresAt: payload.accessTokenExpiresAt
216
+ ? new Date(payload.accessTokenExpiresAt)
217
+ : null,
218
+ }
219
+ : {}),
220
+ ...(payload.webhookSecret !== undefined
221
+ ? {
222
+ webhookSecretEncrypted: encryptVariableSetValue(
223
+ encryptionKey!,
224
+ payload.webhookSecret,
225
+ ),
226
+ }
227
+ : {}),
228
+ ...(payload.webhookUsername !== undefined
229
+ ? { webhookUsername: payload.webhookUsername }
230
+ : {}),
231
+ ...(payload.status !== undefined ? { status: payload.status } : {}),
232
+ }),
233
+ "A PR Review registration with this provider and name already exists",
234
+ );
235
+ await recordAuditEvent(db, {
236
+ accountId: grant.accountId,
237
+ workspaceId,
238
+ subjectId: grant.subjectId,
239
+ action: "prReview.app_registration.updated",
240
+ targetType: "pr_review_app_registration",
241
+ targetId: existing.id,
242
+ metadata: {
243
+ fields: Object.keys(payload).filter(
244
+ (field) => field !== "accessToken" && field !== "privateKey" && field !== "webhookSecret",
245
+ ),
246
+ credentialRotated: payload.accessToken !== undefined || payload.privateKey !== undefined,
247
+ webhookSecretRotated: payload.webhookSecret !== undefined,
248
+ },
249
+ });
250
+ return c.json(PrReviewAppRegistration.parse(updated));
251
+ });
252
+
253
+ app.delete("/v1/workspaces/:workspaceId/pr-review/registrations/:registrationId", async (c) => {
254
+ const workspaceId = c.req.param("workspaceId");
255
+ const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:admin");
256
+ requirePermission(grant, "secrets:write");
257
+ const deleted = await deletePrReviewAppRegistration(db, {
258
+ accountId: grant.accountId,
259
+ workspaceId,
260
+ registrationId: c.req.param("registrationId"),
261
+ });
262
+ if (!deleted)
263
+ throw new HTTPException(404, {
264
+ message: "PR Review app registration not found",
265
+ });
266
+ await recordAuditEvent(db, {
267
+ accountId: grant.accountId,
268
+ workspaceId,
269
+ subjectId: grant.subjectId,
270
+ action: "prReview.app_registration.disabled",
271
+ targetType: "pr_review_app_registration",
272
+ targetId: c.req.param("registrationId"),
273
+ metadata: {},
274
+ });
275
+ return c.body(null, 204);
276
+ });
277
+
278
+ app.post("/v1/workspaces/:workspaceId/pr-review/repositories", async (c) => {
279
+ const workspaceId = c.req.param("workspaceId");
280
+ const grant = await integrationCommitGrant(
281
+ await requireAccessGrantAuthorization(c, deps, workspaceId, "workspace:admin"),
282
+ ["workspace:admin"],
283
+ { settings: deps.settings, authorizationHeader: c.req.header("authorization") },
284
+ );
285
+
286
+ const payload = await parseRequestJson(c, CreatePrReviewRepositoryBindingRequest);
287
+ const registration = await getPrReviewAppRegistrationSecret(db, {
288
+ accountId: grant.accountId,
289
+ workspaceId,
290
+ registrationId: payload.registrationId,
291
+ });
292
+ if (!registration)
293
+ throw new HTTPException(404, {
294
+ message: "PR Review app registration not found",
295
+ });
296
+ const integrationKey = prReviewIntegrationKey(registration.provider);
297
+ await withOrganizationIntegrationAcquisition(db, grant, [integrationKey], async () => {});
298
+ const repositoryUrl = new URL(payload.repositoryUri);
299
+ let canonicalRepositoryUri = repositoryUrl.href;
300
+ let canonicalRepositoryFullName = payload.repositoryFullName;
301
+ let canonicalProviderRepositoryId = String(payload.providerRepositoryId);
302
+ let canonicalProjectId = payload.projectId === undefined ? null : String(payload.projectId);
303
+ const providerUrl = new URL(registration.providerBaseUrl);
304
+ const providerPath = providerUrl.pathname.replace(/\/$/, "");
305
+ if (
306
+ repositoryUrl.protocol !== "https:" ||
307
+ repositoryUrl.username ||
308
+ repositoryUrl.password ||
309
+ repositoryUrl.host.toLowerCase() !== providerUrl.host.toLowerCase() ||
310
+ (providerPath !== "" &&
311
+ providerPath !== "/" &&
312
+ !repositoryUrl.pathname.startsWith(`${providerPath}/`))
313
+ ) {
314
+ throw new HTTPException(422, {
315
+ message:
316
+ "repositoryUri must be a credential-free HTTPS URL on the registered provider host",
317
+ });
318
+ }
319
+ if (registration.provider === "github") {
320
+ const installationId = positiveInteger(payload.installationId);
321
+ const repositoryId = positiveInteger(payload.providerRepositoryId);
322
+ if (!installationId || !repositoryId || !registration.appId) {
323
+ throw new HTTPException(422, {
324
+ message: "GitHub repository bindings require App, installation, and repository IDs",
325
+ });
326
+ }
327
+ const encryptionKey = requirePrReviewEncryptionKey(deps);
328
+ if (!registration.credentialEncrypted) {
329
+ throw new HTTPException(409, {
330
+ message: "PR Review GitHub App credential is unavailable",
331
+ });
332
+ }
333
+ let allowedRepositories;
334
+ try {
335
+ allowedRepositories = await listGitHubAppRepositoriesWithSigningSettings(
336
+ {
337
+ githubAppId: registration.appId,
338
+ githubAppPrivateKey: decryptVariableSetValue(
339
+ encryptionKey,
340
+ registration.credentialEncrypted,
341
+ ),
342
+ },
343
+ { installationIds: [installationId] },
344
+ );
345
+ } catch {
346
+ throw new HTTPException(502, {
347
+ message: "Could not verify the repository against the registered GitHub App",
348
+ });
349
+ }
350
+ const allowedRepository = allowedRepositories.find(
351
+ (candidate) =>
352
+ candidate.id === repositoryId &&
353
+ candidate.fullName.toLowerCase() === payload.repositoryFullName.toLowerCase(),
354
+ );
355
+ if (!allowedRepository) {
356
+ throw new HTTPException(403, {
357
+ message: "GitHub repository is not installed for this PR Review App",
358
+ });
359
+ }
360
+ canonicalRepositoryUri = allowedRepository.cloneUrl;
361
+ canonicalRepositoryFullName = allowedRepository.fullName;
362
+ canonicalProviderRepositoryId = String(allowedRepository.id);
363
+ }
364
+ if (registration.provider !== "github") {
365
+ if (
366
+ registration.accessTokenExpiresAt &&
367
+ Date.parse(registration.accessTokenExpiresAt) <= Date.now()
368
+ ) {
369
+ throw new HTTPException(409, {
370
+ message: "PR Review provider credential has expired",
371
+ });
372
+ }
373
+ const encryptionKey = requirePrReviewEncryptionKey(deps);
374
+ if (!registration.credentialEncrypted) {
375
+ throw new HTTPException(409, {
376
+ message: "PR Review provider credential is unavailable",
377
+ });
378
+ }
379
+ try {
380
+ const verified = await verifyPrReviewProviderRepository({
381
+ provider: registration.provider,
382
+ providerBaseUrl: registration.providerBaseUrl,
383
+ providerRepositoryId: String(payload.providerRepositoryId),
384
+ ...(payload.projectId !== undefined ? { projectId: String(payload.projectId) } : {}),
385
+ token: decryptVariableSetValue(encryptionKey, registration.credentialEncrypted),
386
+ username: registration.webhookUsername,
387
+ settings,
388
+ });
389
+ canonicalRepositoryUri = verified.repositoryUri;
390
+ canonicalRepositoryFullName = verified.repositoryFullName;
391
+ canonicalProviderRepositoryId = verified.providerRepositoryId;
392
+ canonicalProjectId = verified.projectId;
393
+ } catch (error) {
394
+ if (error instanceof PrReviewProviderRepositoryError) {
395
+ const status =
396
+ error.reason === "denied" ? 403 : error.reason === "identity_mismatch" ? 422 : 502;
397
+ throw new HTTPException(status, { message: error.message });
398
+ }
399
+ throw error;
400
+ }
401
+ }
402
+ const catalogSettings = (
403
+ await resolveWorkspaceCatalogSettings(db, deps.settings, {
404
+ accountId: grant.accountId,
405
+ workspaceId,
406
+ })
407
+ ).settings;
408
+ const model = payload.model
409
+ ? (canonicalConfiguredModel(catalogSettings, payload.model) ?? null)
410
+ : null;
411
+ if (model) await assertWorkspaceModelPolicyAllows(db, catalogSettings, workspaceId, model);
412
+ const beforeCreateCommit = model
413
+ ? prReviewCustomModelCommitGuard({
414
+ settings: catalogSettings,
415
+ accountId: grant.accountId,
416
+ workspaceId,
417
+ modelId: model,
418
+ })
419
+ : undefined;
420
+ const template = PR_REVIEW_AUTOMATION_SETUP;
421
+
422
+ const binding = await mapPrReviewUniqueConflict(
423
+ withOrganizationIntegrationAcquisition(db, grant, [integrationKey], async (tx) => {
424
+ await grant.authorizeCommit(tx);
425
+ return createPrReviewRepositoryBinding(tx, {
426
+ accountId: grant.accountId,
427
+ workspaceId,
428
+ registrationId: registration.id,
429
+ provider: registration.provider,
430
+ repositoryUri: canonicalRepositoryUri,
431
+ repositoryFullName: canonicalRepositoryFullName,
432
+ providerRepositoryId: canonicalProviderRepositoryId,
433
+ installationId:
434
+ payload.installationId === undefined ? null : String(payload.installationId),
435
+ projectId: canonicalProjectId,
436
+ model,
437
+ additionalInstructions: payload.additionalInstructions ?? null,
438
+ status: payload.status,
439
+ createdBySubjectId: grant.subjectId,
440
+
441
+ adapterId: template.adapterId,
442
+ eventTypes: template.eventTypes,
443
+ configuration: template.configuration,
444
+ sessionTemplate: template.sessionTemplate,
445
+ ...(beforeCreateCommit ? { beforeCreateCommit } : {}),
446
+ });
447
+ }),
448
+ "This repository is already bound to the selected PR Review registration",
449
+ );
450
+ await recordAuditEvent(db, {
451
+ accountId: grant.accountId,
452
+ workspaceId,
453
+ subjectId: grant.subjectId,
454
+ action: "prReview.repository_binding.created",
455
+ targetType: "pr_review_repository_binding",
456
+ targetId: binding.id,
457
+ metadata: {
458
+ provider: binding.provider,
459
+ registrationId: binding.registrationId,
460
+ providerRepositoryId: binding.providerRepositoryId,
461
+ },
462
+ });
463
+ return c.json(PrReviewRepositoryBinding.parse(binding), 201);
464
+ });
465
+
466
+ app.patch("/v1/workspaces/:workspaceId/pr-review/repositories/:bindingId", async (c) => {
467
+ const workspaceId = c.req.param("workspaceId");
468
+ const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:admin");
469
+
470
+ const payload = await parseRequestJson(c, UpdatePrReviewRepositoryBindingRequest);
471
+ const catalogSettings = (
472
+ await resolveWorkspaceCatalogSettings(db, deps.settings, {
473
+ accountId: grant.accountId,
474
+ workspaceId,
475
+ })
476
+ ).settings;
477
+ const model =
478
+ payload.model === undefined
479
+ ? undefined
480
+ : payload.model === null
481
+ ? null
482
+ : (canonicalConfiguredModel(catalogSettings, payload.model) ?? null);
483
+ if (model) await assertWorkspaceModelPolicyAllows(db, catalogSettings, workspaceId, model);
484
+ const beforeUpdateCommit = async (
485
+ tx: ApiRouteDeps["db"],
486
+ context: {
487
+ currentModel: string | null;
488
+ currentStatus: "active" | "disabled";
489
+ nextModel: string | null;
490
+ nextStatus: "active" | "disabled";
491
+ },
492
+ ): Promise<void> => {
493
+ const materialExecutionChange =
494
+ payload.model !== undefined ||
495
+ payload.additionalInstructions !== undefined ||
496
+ (context.currentStatus === "disabled" && context.nextStatus === "active");
497
+ if (!materialExecutionChange || !context.nextModel) return;
498
+ await prReviewCustomModelCommitGuard({
499
+ settings: catalogSettings,
500
+ accountId: grant.accountId,
501
+ workspaceId,
502
+ modelId: context.nextModel,
503
+ })?.(tx);
504
+ };
505
+ const binding = await updatePrReviewRepositoryBinding(db, {
506
+ accountId: grant.accountId,
507
+ workspaceId,
508
+ bindingId: c.req.param("bindingId"),
509
+ subjectId: grant.subjectId,
510
+ ...(model !== undefined ? { model } : {}),
511
+ ...(payload.additionalInstructions !== undefined
512
+ ? { additionalInstructions: payload.additionalInstructions }
513
+ : {}),
514
+ ...(payload.status !== undefined ? { status: payload.status } : {}),
515
+ beforeUpdateCommit,
516
+ });
517
+ if (!binding)
518
+ throw new HTTPException(404, {
519
+ message: "PR Review repository binding not found",
520
+ });
521
+ await recordAuditEvent(db, {
522
+ accountId: grant.accountId,
523
+ workspaceId,
524
+ subjectId: grant.subjectId,
525
+ action: "prReview.repository_binding.updated",
526
+ targetType: "pr_review_repository_binding",
527
+ targetId: binding.id,
528
+ metadata: { fields: Object.keys(payload) },
529
+ });
530
+ return c.json(PrReviewRepositoryBinding.parse(binding));
531
+ });
532
+
533
+ app.delete("/v1/workspaces/:workspaceId/pr-review/repositories/:bindingId", async (c) => {
534
+ const workspaceId = c.req.param("workspaceId");
535
+ const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:admin");
536
+ const deleted = await deletePrReviewRepositoryBinding(db, {
537
+ accountId: grant.accountId,
538
+ workspaceId,
539
+ bindingId: c.req.param("bindingId"),
540
+ subjectId: grant.subjectId,
541
+ });
542
+ if (!deleted)
543
+ throw new HTTPException(404, {
544
+ message: "PR Review repository binding not found",
545
+ });
546
+ await recordAuditEvent(db, {
547
+ accountId: grant.accountId,
548
+ workspaceId,
549
+ subjectId: grant.subjectId,
550
+ action: "prReview.repository_binding.disabled",
551
+ targetType: "pr_review_repository_binding",
552
+ targetId: c.req.param("bindingId"),
553
+ metadata: {},
554
+ });
555
+ return c.body(null, 204);
556
+ });
557
+ }
558
+
559
+ /** PR Review's server-owned provider, not a repository URL or user label,
560
+ * establishes Lens identity. Other providers have no curated acquisition key. */
561
+ function prReviewIntegrationKey(provider: string): "github-lens" | null {
562
+ return provider === "github" ? "github-lens" : null;
563
+ }
564
+
565
+ function prReviewCustomModelCommitGuard(input: {
566
+ settings: ApiRouteDeps["settings"];
567
+ accountId: string;
568
+ workspaceId: string;
569
+ modelId: string;
570
+ }): ((tx: ApiRouteDeps["db"]) => Promise<void>) | undefined {
571
+ const reference = workspaceCustomModelReference(input.settings, input.modelId);
572
+ if (!reference) return undefined;
573
+ return async (tx): Promise<void> => {
574
+ const active = await lockActiveCustomModelForAdmission(tx, {
575
+ accountId: input.accountId,
576
+ workspaceId: input.workspaceId,
577
+ reference,
578
+ });
579
+ if (!active) {
580
+ throw modelUnavailableHttpException(input.modelId);
581
+ }
582
+ };
583
+ }
584
+
585
+ function assertPrReviewSandboxBackend(deps: ApiRouteDeps): void {
586
+ if (deps.settings.sandboxBackend === "selfhosted") {
587
+ throw new HTTPException(409, {
588
+ message:
589
+ "Opengeni Review Bot requires managed compute so it can materialize and verify the exact pull-request head",
590
+ });
591
+ }
592
+ }
593
+
594
+ function requirePrReviewEncryptionKey(deps: ApiRouteDeps): Uint8Array {
595
+ const key = environmentsEncryptionKeyBytes(deps.settings);
596
+ if (!key) {
597
+ throw new HTTPException(503, {
598
+ message: "Opengeni Review Bot requires configured secret encryption",
599
+ });
600
+ }
601
+ return key;
602
+ }
603
+
604
+ async function mapPrReviewUniqueConflict<T>(operation: Promise<T>, message: string): Promise<T> {
605
+ try {
606
+ return await operation;
607
+ } catch (error) {
608
+ if (nestedPostgresSqlState(error) === "23505") {
609
+ throw new HTTPException(409, { message });
610
+ }
611
+ throw error;
612
+ }
613
+ }
614
+
615
+ function positiveInteger(value: unknown): number | null {
616
+ if (typeof value === "number" && Number.isSafeInteger(value) && value > 0) return value;
617
+ if (typeof value === "string" && /^\d+$/.test(value)) {
618
+ const parsed = Number(value);
619
+ return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : null;
620
+ }
621
+ return null;
622
+ }