@opengeni/api-router 0.30.3 → 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 (434) 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-source-session.d.ts +3 -0
  35. package/dist/editable-artifact-websocket.d.ts +10 -18
  36. package/dist/editable-artifact-workspace-files.d.ts +1 -1
  37. package/dist/fatal-process-boundary.d.ts +25 -0
  38. package/dist/github-access.d.ts +31 -2
  39. package/dist/http/acting-person.d.ts +24 -0
  40. package/dist/http/api-contract-compat.d.ts +19 -0
  41. package/dist/http/api-error.d.ts +27 -1
  42. package/dist/http/cors.d.ts +17 -0
  43. package/dist/http/deprecation.d.ts +42 -0
  44. package/dist/http/interaction-control-error.d.ts +13 -0
  45. package/dist/http/keyed-admission.d.ts +12 -0
  46. package/dist/http/local-browser-boundary.d.ts +72 -0
  47. package/dist/http/metrics-listener.d.ts +22 -0
  48. package/dist/http/path-identifier.d.ts +17 -0
  49. package/dist/http/registered-route-label.d.ts +16 -0
  50. package/dist/http/request-body.d.ts +27 -0
  51. package/dist/http/request-source.d.ts +52 -0
  52. package/dist/http/sse.d.ts +17 -6
  53. package/dist/http/unmatched-route.d.ts +18 -0
  54. package/dist/http/user-content.d.ts +36 -0
  55. package/dist/http/websocket-upgrade-dispatch.d.ts +18 -0
  56. package/dist/index.d.ts +10 -3
  57. package/dist/index.js +1091 -162
  58. package/dist/index.js.map +1 -1
  59. package/dist/integration-endpoint-test.d.ts +20 -0
  60. package/dist/integrations/api-integrations.d.ts +2 -2
  61. package/dist/integrations/atlassian.d.ts +29 -3
  62. package/dist/integrations/connect-authority.d.ts +1 -0
  63. package/dist/integrations/connect-callback-return.d.ts +6 -0
  64. package/dist/integrations/fiken.d.ts +16 -2
  65. package/dist/integrations/github-app-connect.d.ts +47 -0
  66. package/dist/integrations/github-installation-proof.d.ts +3 -0
  67. package/dist/integrations/github-lens-connect.d.ts +116 -0
  68. package/dist/integrations/github-skill-source.d.ts +1 -5
  69. package/dist/integrations/google-drive.d.ts +24 -0
  70. package/dist/integrations/integration-commit-authority.d.ts +13 -0
  71. package/dist/integrations/marketplace-plugin.d.ts +2691 -0
  72. package/dist/integrations/oauth-client.d.ts +178 -18
  73. package/dist/integrations/oauth-profiles.d.ts +222 -0
  74. package/dist/integrations/oauth-return-path.d.ts +1 -0
  75. package/dist/integrations/personal-github-repositories.d.ts +84 -0
  76. package/dist/integrations/personal-github.d.ts +42 -0
  77. package/dist/integrations/pr-review-provider.d.ts +22 -0
  78. package/dist/integrations/provider-oauth.d.ts +19 -1
  79. package/dist/integrations/slack-app-home.d.ts +24 -0
  80. package/dist/integrations/slack-bot.d.ts +367 -12
  81. package/dist/integrations/slack-file-upload-flow.d.ts +62 -0
  82. package/dist/integrations/slack-install.d.ts +20 -0
  83. package/dist/integrations/slack-interactions.d.ts +107 -9
  84. package/dist/integrations/slack-mrkdwn.d.ts +41 -0
  85. package/dist/integrations/slack-routing.d.ts +120 -0
  86. package/dist/integrations/slack-session-defaults.d.ts +58 -0
  87. package/dist/integrations/slack-task-file-upload.d.ts +36 -0
  88. package/dist/integrations/social-oauth.d.ts +7 -0
  89. package/dist/interaction-agent-access.d.ts +15 -0
  90. package/dist/interaction-frame-proxy.d.ts +68 -0
  91. package/dist/interaction-metrics.d.ts +2 -0
  92. package/dist/mcp/action-catalog-types.d.ts +9 -0
  93. package/dist/mcp/action-catalog.gen.d.ts +2 -0
  94. package/dist/mcp/capability-account-readiness.d.ts +7 -0
  95. package/dist/mcp/child-read-evidence.d.ts +9 -0
  96. package/dist/mcp/command-read.d.ts +24 -0
  97. package/dist/mcp/company-profile-agent-admin.d.ts +44 -0
  98. package/dist/mcp/contract-input.d.ts +11 -0
  99. package/dist/mcp/documents.d.ts +7 -5
  100. package/dist/mcp/files.d.ts +2 -2
  101. package/dist/mcp/first-party-tool-permissions.d.ts +650 -0
  102. package/dist/mcp/knowledge-entries.d.ts +5 -0
  103. package/dist/mcp/orchestration-failure-diagnostic.d.ts +43 -0
  104. package/dist/mcp/receipts.d.ts +9 -0
  105. package/dist/mcp/request-abort.d.ts +19 -0
  106. package/dist/mcp/scheduled-task-input.d.ts +1189 -0
  107. package/dist/mcp/scheduled-task-view.d.ts +22 -4
  108. package/dist/mcp/server.d.ts +255 -3
  109. package/dist/mcp/session-event-view.d.ts +94 -0
  110. package/dist/mcp/session-view.d.ts +66 -2
  111. package/dist/mcp/session-wait.d.ts +174 -0
  112. package/dist/mcp-oauth.d.ts +52 -0
  113. package/dist/model-catalog.d.ts +11 -31
  114. package/dist/observability.d.ts +3 -1
  115. package/dist/organization-mcp.d.ts +52 -0
  116. package/dist/organization-recovery-notifications.d.ts +41 -0
  117. package/dist/routes/analytics-consent.d.ts +26 -0
  118. package/dist/routes/api-integrations.d.ts +25 -0
  119. package/dist/routes/api-keys.d.ts +17 -0
  120. package/dist/routes/artifact-catalog.d.ts +6 -0
  121. package/dist/routes/automations.d.ts +19 -0
  122. package/dist/routes/billing.d.ts +49 -0
  123. package/dist/routes/browser-sessions.d.ts +59 -2
  124. package/dist/routes/claude-subscription-accounts.d.ts +3 -0
  125. package/dist/routes/claude-subscription-oauth.d.ts +3 -0
  126. package/dist/routes/client-errors.d.ts +146 -0
  127. package/dist/routes/codex.d.ts +76 -2
  128. package/dist/routes/company-brain.d.ts +3 -0
  129. package/dist/routes/company-profile.d.ts +2 -1
  130. package/dist/routes/computer-sessions.d.ts +14 -0
  131. package/dist/routes/connect.d.ts +5 -0
  132. package/dist/routes/editable-artifacts.d.ts +2 -0
  133. package/dist/routes/external-identity-links.d.ts +6 -0
  134. package/dist/routes/feedback.d.ts +3 -0
  135. package/dist/routes/github-browser-pages.d.ts +12 -0
  136. package/dist/routes/github.d.ts +2 -0
  137. package/dist/routes/insights-response-cache.d.ts +10 -0
  138. package/dist/routes/insights-usage.d.ts +12 -0
  139. package/dist/routes/insights.d.ts +30 -1
  140. package/dist/routes/knowledge.d.ts +3 -0
  141. package/dist/routes/managed-auth-session-sets.d.ts +26 -0
  142. package/dist/routes/managed-onboarding.d.ts +29 -0
  143. package/dist/routes/managed-sign-in-methods.d.ts +6 -0
  144. package/dist/routes/model-connection-access.d.ts +3 -0
  145. package/dist/routes/organization-integration-policy.d.ts +3 -0
  146. package/dist/routes/organization-integrations.d.ts +6 -0
  147. package/dist/routes/organization-mcp-connections.d.ts +3 -0
  148. package/dist/routes/organization-model-providers.d.ts +3 -0
  149. package/dist/routes/organization-recovery.d.ts +19 -0
  150. package/dist/routes/organization-service-accounts.d.ts +3 -0
  151. package/dist/routes/organization-sessions.d.ts +26 -0
  152. package/dist/routes/personal-github-git-broker.d.ts +29 -0
  153. package/dist/routes/personal-github.d.ts +3 -0
  154. package/dist/routes/pr-review-github.d.ts +3 -0
  155. package/dist/routes/pr-review.d.ts +3 -0
  156. package/dist/routes/session-artifact-associations.d.ts +4 -0
  157. package/dist/routes/session-history-imports.d.ts +9 -0
  158. package/dist/routes/sessions.d.ts +44 -6
  159. package/dist/routes/skill-content.d.ts +4 -0
  160. package/dist/routes/skill-install-authority.d.ts +6 -0
  161. package/dist/routes/subscription-account-pools.d.ts +34 -0
  162. package/dist/routes/subscription-pool-access.d.ts +16 -0
  163. package/dist/routes/supergrok.d.ts +6 -1
  164. package/dist/routes/usage-allowances.d.ts +12 -0
  165. package/dist/routes/user-resource-authorities.d.ts +3 -0
  166. package/dist/routes/workspace-artifacts.d.ts +2 -1
  167. package/dist/routes/workspace-capture.d.ts +10 -2
  168. package/dist/routes/workspace-integrations.d.ts +35 -0
  169. package/dist/routes/workspace-learning.d.ts +3 -0
  170. package/dist/routes/workspace-model-providers.d.ts +4 -0
  171. package/dist/routes/workspaces.d.ts +29 -0
  172. package/dist/sandbox/auth-callout.d.ts +8 -0
  173. package/dist/sandbox/channel-a.d.ts +19 -1
  174. package/dist/sandbox/connection-authority.d.ts +3 -0
  175. package/dist/sandbox/enrollment.d.ts +9 -1
  176. package/dist/sandbox/machines.d.ts +5 -2
  177. package/dist/sandbox/metrics-ingestion.d.ts +28 -20
  178. package/dist/sandbox/rematerialize.d.ts +2 -0
  179. package/dist/sandbox/session-attach-variable-sets.d.ts +30 -0
  180. package/dist/sandbox/viewer.d.ts +26 -1
  181. package/dist/sandbox-file-artifacts.d.ts +50 -0
  182. package/dist/scheduled-task-deletion.d.ts +13 -0
  183. package/dist/session-create-observability.d.ts +5 -0
  184. package/dist/session-event-view-MPS2OZD3.js +292 -0
  185. package/dist/session-event-view-MPS2OZD3.js.map +1 -0
  186. package/dist/site-session-origin.d.ts +13 -0
  187. package/dist/site-uploads.d.ts +41 -0
  188. package/dist/slack-reaction-files.d.ts +1 -1
  189. package/dist/temporal-schedule-cleanup.d.ts +1 -0
  190. package/dist/temporal-schedule-sync.d.ts +26 -0
  191. package/dist/transcription/providers/xai-subscription.d.ts +1 -0
  192. package/dist/transcription/service.d.ts +2 -1
  193. package/dist/work-discovery-observability.d.ts +33 -0
  194. package/dist/workspace-artifact-content.d.ts +28 -0
  195. package/dist/workspace-artifact-provenance.d.ts +7 -0
  196. package/dist/workspace-delete-observability.d.ts +10 -0
  197. package/dist/workspace-deletion.d.ts +6 -0
  198. package/dist/workspace-state-projection.d.ts +3 -5
  199. package/dist/workspace-tool-gateway-observability.d.ts +17 -0
  200. package/dist/workspace-tool-gateway.d.ts +123 -0
  201. package/dist/workspace-webhook-dispatch.d.ts +26 -0
  202. package/package.json +23 -19
  203. package/src/access-grant-rls.ts +75 -0
  204. package/src/admission-trace.ts +14 -0
  205. package/src/api-websocket.ts +23 -0
  206. package/src/app.ts +1967 -252
  207. package/src/artifact-catalog-cursor.ts +60 -0
  208. package/src/auth/managed-auth-attempt-context.ts +70 -0
  209. package/src/auth/managed-auth-rate-limits.ts +252 -0
  210. package/src/auth/managed-auth-session-adapter.ts +222 -0
  211. package/src/auth/managed-auth.ts +536 -60
  212. package/src/auth/managed-email.ts +174 -0
  213. package/src/auth/managed-sign-in-notifications.ts +81 -0
  214. package/src/auth/new-signups-gate.ts +49 -0
  215. package/src/auth/organization-user-setup.ts +307 -0
  216. package/src/auth/signup-funnel-metrics.ts +164 -0
  217. package/src/browser-controller-authority.ts +1 -186
  218. package/src/browser-ephemeral.ts +39 -0
  219. package/src/browser-state-authority.ts +1 -236
  220. package/src/claude-subscription-account-conflicts.ts +12 -0
  221. package/src/claude-subscription-account-usage.ts +48 -0
  222. package/src/claude-subscription-oauth.ts +362 -0
  223. package/src/claude-subscription-profile.ts +73 -0
  224. package/src/claude-subscription-usage.ts +97 -0
  225. package/src/claude-workspace-connection.ts +82 -0
  226. package/src/codemode.ts +194 -30
  227. package/src/codex-realtime.ts +8 -2
  228. package/src/company-brain-okf.ts +340 -0
  229. package/src/connected-machine-computer-access.ts +33 -0
  230. package/src/connection-ownership.ts +199 -0
  231. package/src/controller-data-plane.ts +81 -0
  232. package/src/editable-artifact-native-kernel.ts +26 -15
  233. package/src/editable-artifact-office-import.ts +28 -3
  234. package/src/editable-artifact-production.ts +23 -7
  235. package/src/editable-artifact-source-session.ts +123 -0
  236. package/src/editable-artifact-websocket.ts +27 -21
  237. package/src/editable-artifact-workspace-files.ts +31 -6
  238. package/src/fatal-process-boundary.ts +246 -0
  239. package/src/gateway-realtime.ts +1 -1
  240. package/src/github-access.ts +147 -5
  241. package/src/http/acting-person.ts +71 -0
  242. package/src/http/api-contract-compat.ts +49 -0
  243. package/src/http/api-error.ts +115 -1
  244. package/src/http/auth.ts +48 -0
  245. package/src/http/cors.ts +67 -0
  246. package/src/http/deprecation.ts +118 -0
  247. package/src/http/interaction-control-error.ts +164 -0
  248. package/src/http/keyed-admission.ts +29 -0
  249. package/src/http/local-browser-boundary.ts +343 -0
  250. package/src/http/metrics-listener.ts +57 -0
  251. package/src/http/path-identifier.ts +54 -0
  252. package/src/http/registered-route-label.ts +34 -0
  253. package/src/http/request-body.ts +127 -0
  254. package/src/http/request-source.ts +178 -0
  255. package/src/http/sse.ts +486 -132
  256. package/src/http/unmatched-route.ts +60 -0
  257. package/src/http/user-content.ts +158 -0
  258. package/src/http/websocket-upgrade-dispatch.ts +29 -0
  259. package/src/index.ts +157 -52
  260. package/src/integration-endpoint-test.ts +291 -0
  261. package/src/integrations/api-integrations.ts +98 -11
  262. package/src/integrations/atlassian.ts +474 -136
  263. package/src/integrations/connect-authority.ts +2 -0
  264. package/src/integrations/connect-callback-return.ts +86 -0
  265. package/src/integrations/fiken.ts +354 -64
  266. package/src/integrations/github-app-connect.ts +435 -0
  267. package/src/integrations/github-installation-proof.ts +60 -0
  268. package/src/integrations/github-lens-connect.ts +76 -0
  269. package/src/integrations/github-skill-source.ts +2 -142
  270. package/src/integrations/google-drive.ts +717 -225
  271. package/src/integrations/integration-commit-authority.ts +69 -0
  272. package/src/integrations/marketplace-plugin.ts +48 -0
  273. package/src/integrations/oauth-client.ts +1356 -459
  274. package/src/integrations/oauth-profiles.ts +537 -0
  275. package/src/integrations/oauth-return-path.ts +18 -0
  276. package/src/integrations/personal-github-repositories.ts +674 -0
  277. package/src/integrations/personal-github.ts +825 -0
  278. package/src/integrations/pr-review-provider.ts +246 -0
  279. package/src/integrations/provider-oauth.ts +250 -22
  280. package/src/integrations/slack-app-home.ts +300 -0
  281. package/src/integrations/slack-bot.ts +963 -239
  282. package/src/integrations/slack-file-upload-flow.ts +147 -0
  283. package/src/integrations/slack-install.ts +83 -0
  284. package/src/integrations/slack-interactions.ts +3167 -474
  285. package/src/integrations/slack-mrkdwn.ts +193 -0
  286. package/src/integrations/slack-routing.ts +337 -0
  287. package/src/integrations/slack-session-defaults.ts +224 -0
  288. package/src/integrations/slack-task-file-upload.ts +323 -0
  289. package/src/integrations/social-oauth.ts +213 -15
  290. package/src/interaction-agent-access.ts +48 -0
  291. package/src/interaction-frame-proxy.ts +409 -0
  292. package/src/interaction-metrics.ts +30 -0
  293. package/src/mcp/action-catalog-types.ts +9 -0
  294. package/src/mcp/action-catalog.gen.ts +6696 -0
  295. package/src/mcp/capability-account-readiness.ts +17 -0
  296. package/src/mcp/child-read-evidence.ts +19 -0
  297. package/src/mcp/command-read.ts +109 -0
  298. package/src/mcp/company-profile-agent-admin.ts +198 -0
  299. package/src/mcp/contract-input.ts +141 -0
  300. package/src/mcp/documents.ts +65 -377
  301. package/src/mcp/editable-artifacts.ts +12 -6
  302. package/src/mcp/files.ts +80 -43
  303. package/src/mcp/first-party-tool-permissions.ts +305 -0
  304. package/src/mcp/knowledge-entries.ts +322 -0
  305. package/src/mcp/orchestration-failure-diagnostic.ts +43 -0
  306. package/src/mcp/receipts.ts +34 -0
  307. package/src/mcp/request-abort.ts +44 -0
  308. package/src/mcp/scheduled-task-input.ts +76 -0
  309. package/src/mcp/scheduled-task-view.ts +44 -3
  310. package/src/mcp/server.ts +3030 -1267
  311. package/src/mcp/session-event-view.ts +383 -0
  312. package/src/mcp/session-view.ts +84 -3
  313. package/src/mcp/session-wait.ts +665 -0
  314. package/src/mcp-oauth.ts +1123 -0
  315. package/src/model-catalog.ts +91 -333
  316. package/src/observability.ts +15 -1
  317. package/src/organization-mcp.ts +397 -0
  318. package/src/organization-recovery-notifications.ts +103 -0
  319. package/src/routes/analytics-consent.ts +123 -0
  320. package/src/routes/api-integrations.ts +364 -74
  321. package/src/routes/api-keys.ts +336 -10
  322. package/src/routes/artifact-catalog.ts +279 -0
  323. package/src/routes/automations.ts +768 -0
  324. package/src/routes/billing.ts +461 -46
  325. package/src/routes/browser-sessions.ts +780 -112
  326. package/src/routes/canonical-human-identities.ts +90 -14
  327. package/src/routes/capabilities.ts +107 -6
  328. package/src/routes/channels.ts +20 -3
  329. package/src/routes/claude-subscription-accounts.ts +334 -0
  330. package/src/routes/claude-subscription-oauth.ts +142 -0
  331. package/src/routes/client-errors.ts +362 -0
  332. package/src/routes/codex.ts +833 -116
  333. package/src/routes/company-brain.ts +322 -0
  334. package/src/routes/company-profile.ts +65 -1
  335. package/src/routes/computer-sessions.ts +557 -106
  336. package/src/routes/connect.ts +1938 -0
  337. package/src/routes/connections.ts +1039 -349
  338. package/src/routes/documents.ts +488 -287
  339. package/src/routes/editable-artifacts.ts +79 -9
  340. package/src/routes/enrollments.ts +135 -39
  341. package/src/routes/environments.ts +154 -58
  342. package/src/routes/external-identity-links.ts +201 -0
  343. package/src/routes/feedback.ts +113 -0
  344. package/src/routes/files.ts +267 -33
  345. package/src/routes/github-browser-pages.ts +162 -0
  346. package/src/routes/github.ts +446 -144
  347. package/src/routes/insights-response-cache.ts +83 -0
  348. package/src/routes/insights-usage.ts +345 -0
  349. package/src/routes/insights.ts +153 -19
  350. package/src/routes/install.ts +133 -38
  351. package/src/routes/integration-facets.ts +107 -33
  352. package/src/routes/interaction-resources.ts +30 -3
  353. package/src/routes/knowledge.ts +488 -0
  354. package/src/routes/machines.ts +313 -15
  355. package/src/routes/managed-auth-session-sets.ts +1218 -0
  356. package/src/routes/managed-onboarding.ts +337 -0
  357. package/src/routes/managed-sign-in-methods.ts +433 -0
  358. package/src/routes/memory-slack-publications.ts +3 -2
  359. package/src/routes/model-connection-access.ts +208 -0
  360. package/src/routes/organization-integration-policy.ts +116 -0
  361. package/src/routes/organization-integrations.ts +326 -0
  362. package/src/routes/organization-mcp-connections.ts +178 -0
  363. package/src/routes/organization-memberships.ts +1019 -27
  364. package/src/routes/organization-model-providers.ts +293 -0
  365. package/src/routes/organization-recovery.ts +325 -0
  366. package/src/routes/organization-service-accounts.ts +128 -0
  367. package/src/routes/organization-sessions.ts +350 -0
  368. package/src/routes/personal-github-git-broker.ts +785 -0
  369. package/src/routes/personal-github.ts +370 -0
  370. package/src/routes/plugins.ts +251 -22
  371. package/src/routes/pr-review-github.ts +881 -0
  372. package/src/routes/pr-review.ts +622 -0
  373. package/src/routes/preference-registry.ts +12 -93
  374. package/src/routes/rigs.ts +167 -50
  375. package/src/routes/scheduled-tasks.ts +346 -41
  376. package/src/routes/session-artifact-associations.ts +87 -0
  377. package/src/routes/session-history-imports.ts +280 -0
  378. package/src/routes/sessions.ts +2306 -264
  379. package/src/routes/skill-content.ts +297 -0
  380. package/src/routes/skill-install-authority.ts +64 -0
  381. package/src/routes/skills.ts +62 -9
  382. package/src/routes/social.ts +46 -18
  383. package/src/routes/subscription-account-pools.ts +436 -0
  384. package/src/routes/subscription-pool-access.ts +126 -0
  385. package/src/routes/supergrok.ts +219 -303
  386. package/src/routes/transcription-recordings.ts +38 -3
  387. package/src/routes/transcriptions.ts +4 -0
  388. package/src/routes/usage-allowances.ts +378 -0
  389. package/src/routes/user-resource-authorities.ts +138 -0
  390. package/src/routes/video-generation.ts +14 -10
  391. package/src/routes/workspace-artifacts.ts +275 -69
  392. package/src/routes/workspace-capture.ts +21 -0
  393. package/src/routes/workspace-integrations.ts +576 -0
  394. package/src/routes/workspace-learning.ts +159 -0
  395. package/src/routes/workspace-model-providers.ts +148 -0
  396. package/src/routes/workspace-state.ts +38 -25
  397. package/src/routes/workspaces.ts +1004 -127
  398. package/src/sandbox/auth-callout.ts +96 -19
  399. package/src/sandbox/channel-a.ts +323 -24
  400. package/src/sandbox/connection-authority.ts +3 -0
  401. package/src/sandbox/enrollment.ts +81 -6
  402. package/src/sandbox/machines.ts +218 -76
  403. package/src/sandbox/metrics-ingestion.ts +411 -62
  404. package/src/sandbox/rematerialize.ts +121 -19
  405. package/src/sandbox/session-attach-variable-sets.ts +131 -0
  406. package/src/sandbox/viewer.ts +280 -25
  407. package/src/sandbox-file-artifacts.ts +413 -0
  408. package/src/scheduled-task-deletion.ts +138 -0
  409. package/src/session-create-observability.ts +46 -0
  410. package/src/session-realtime-context.ts +6 -3
  411. package/src/site-session-origin.ts +48 -0
  412. package/src/site-uploads.ts +224 -0
  413. package/src/slack-reaction-files.ts +16 -5
  414. package/src/temporal-schedule-cleanup.ts +13 -0
  415. package/src/temporal-schedule-sync.ts +74 -0
  416. package/src/transcription/providers/codex-subscription.ts +2 -0
  417. package/src/transcription/providers/openai.ts +1 -0
  418. package/src/transcription/providers/xai-subscription.ts +49 -3
  419. package/src/transcription/segmenter.ts +8 -2
  420. package/src/transcription/service.ts +43 -6
  421. package/src/work-discovery-observability.ts +121 -0
  422. package/src/workspace-artifact-content.ts +144 -0
  423. package/src/workspace-artifact-provenance.ts +104 -0
  424. package/src/workspace-delete-observability.ts +75 -0
  425. package/src/workspace-deletion.ts +73 -0
  426. package/src/workspace-state-projection.ts +18 -148
  427. package/src/workspace-tool-gateway-observability.ts +100 -0
  428. package/src/workspace-tool-gateway.ts +870 -0
  429. package/src/workspace-webhook-dispatch.ts +190 -0
  430. package/src/xai-subscription-auth.ts +9 -2
  431. package/dist/chunk-WCXHI3FF.js +0 -49920
  432. package/dist/chunk-WCXHI3FF.js.map +0 -1
  433. package/dist/routes/packs.d.ts +0 -3
  434. package/src/routes/packs.ts +0 -729
@@ -1,15 +1,63 @@
1
- import type {
2
- GitHubBindingStatus,
3
- GitHubInstallationBinding,
4
- GitHubRepository,
1
+ import {
2
+ defaultRepositoryMountPath,
3
+ type GitHubAppRepositoryBranchPage,
4
+ type GitHubBindingStatus,
5
+ type GitHubInstallationBinding,
6
+ type GitHubRepository,
7
+ type RepositoryResourceRef,
5
8
  } from "@opengeni/contracts";
6
9
  import {
10
+ GitHubRepositoryBranchesResponse as GitHubRepositoryBranchesResponseSchema,
11
+ type GitHubRepositoryBranchesResponse,
12
+ type ListGitHubRepositoryBranchesQuery,
13
+ } from "@opengeni/contracts/github-repository-contracts";
14
+ import {
15
+ areGitHubRepositoriesAllowedForWorkspace,
7
16
  hasAuditableGitHubInstallationAuthority,
8
17
  listGitHubInstallationAccessForWorkspace,
9
18
  } from "@opengeni/db";
10
- import { listGitHubAppInstallationSummaries, listGitHubAppRepositories } from "@opengeni/github";
19
+ import {
20
+ GitHubAppApiError,
21
+ listGitHubAppInstallationSummaries,
22
+ listGitHubAppRepositories,
23
+ listGitHubAppRepositoryBranches,
24
+ } from "@opengeni/github";
11
25
  import type { ApiRouteDeps } from "@opengeni/core";
12
26
 
27
+ export type GitHubRepositoryBranchAuthorityErrorCode = "changed" | "not_authorized";
28
+
29
+ export class GitHubRepositoryBranchAuthorityError extends Error {
30
+ constructor(readonly code: GitHubRepositoryBranchAuthorityErrorCode) {
31
+ super(code);
32
+ this.name = "GitHubRepositoryBranchAuthorityError";
33
+ }
34
+ }
35
+
36
+ export type WorkspaceGitHubRepositoryBranchServices = {
37
+ listInstallationAccess: typeof listGitHubInstallationAccessForWorkspace;
38
+ areRepositoriesAllowed: typeof areGitHubRepositoriesAllowedForWorkspace;
39
+ listProviderBranches: (
40
+ deps: ApiRouteDeps,
41
+ input: {
42
+ installationId: number;
43
+ repositoryId: number;
44
+ page: number;
45
+ limit: number;
46
+ },
47
+ ) => Promise<GitHubAppRepositoryBranchPage | null>;
48
+ };
49
+
50
+ const workspaceGitHubRepositoryBranchServices: WorkspaceGitHubRepositoryBranchServices = {
51
+ listInstallationAccess: listGitHubInstallationAccessForWorkspace,
52
+ areRepositoriesAllowed: areGitHubRepositoriesAllowedForWorkspace,
53
+ listProviderBranches: async (deps, input) =>
54
+ deps.githubAppApi?.listRepositoryBranches
55
+ ? await deps.githubAppApi.listRepositoryBranches(input)
56
+ : deps.githubAppApi
57
+ ? null
58
+ : await listGitHubAppRepositoryBranches(deps.settings, input),
59
+ };
60
+
13
61
  export async function listWorkspaceGitHubInstallationBindings(
14
62
  deps: ApiRouteDeps,
15
63
  workspaceId: string,
@@ -153,3 +201,97 @@ export async function listWorkspaceGitHubRepositories(
153
201
  return installation.repositoryIds.includes(repository.id);
154
202
  });
155
203
  }
204
+
205
+ /**
206
+ * The exact session repository resource for one workspace GitHub App
207
+ * repository: its default branch, a canonical clone URI, and the installation
208
+ * identity that platform-brokered Git auth and create-time validation check.
209
+ */
210
+ export function githubRepositoryResourceRef(repository: GitHubRepository): RepositoryResourceRef {
211
+ const uri = normalizedRepositoryUri(repository.cloneUrl);
212
+ return {
213
+ kind: "repository",
214
+ uri,
215
+ ref: repository.defaultBranch,
216
+ provider: "github",
217
+ mountPath: defaultRepositoryMountPath(uri, "github"),
218
+ githubInstallationId: repository.installationId,
219
+ githubRepositoryId: repository.id,
220
+ };
221
+ }
222
+
223
+ function normalizedRepositoryUri(value: string): string {
224
+ const url = new URL(value);
225
+ const path = url.pathname.replace(/^\/+|\/+$/g, "").replace(/\.git$/, "");
226
+ return `https://${url.host.toLowerCase()}/${path}.git`;
227
+ }
228
+
229
+ export async function listWorkspaceGitHubRepositoryBranches(
230
+ deps: ApiRouteDeps,
231
+ input: {
232
+ accountId: string;
233
+ workspaceId: string;
234
+ installationId: number;
235
+ repositoryId: number;
236
+ query: ListGitHubRepositoryBranchesQuery;
237
+ },
238
+ services: WorkspaceGitHubRepositoryBranchServices = workspaceGitHubRepositoryBranchServices,
239
+ ): Promise<GitHubRepositoryBranchesResponse> {
240
+ const installations = await services.listInstallationAccess(deps.db, input.workspaceId);
241
+ const installation = installations.find(
242
+ (candidate) => candidate.installationId === input.installationId,
243
+ );
244
+ if (
245
+ !installation ||
246
+ installation.accountId !== input.accountId ||
247
+ !hasAuditableGitHubInstallationAuthority(installation) ||
248
+ !installation.repositoryIds.includes(input.repositoryId)
249
+ ) {
250
+ throw new GitHubRepositoryBranchAuthorityError("not_authorized");
251
+ }
252
+ if (
253
+ !(await services.areRepositoriesAllowed(deps.db, input.workspaceId, input.installationId, [
254
+ input.repositoryId,
255
+ ]))
256
+ ) {
257
+ throw new GitHubRepositoryBranchAuthorityError("changed");
258
+ }
259
+ const page = await services.listProviderBranches(deps, {
260
+ installationId: input.installationId,
261
+ repositoryId: input.repositoryId,
262
+ page: input.query.cursor,
263
+ limit: input.query.limit,
264
+ });
265
+ if (!page) {
266
+ throw new GitHubAppApiError(
267
+ "The configured GitHub provider cannot list exact repository branches",
268
+ );
269
+ }
270
+ if (
271
+ page.installationId !== input.installationId ||
272
+ page.repositoryId !== input.repositoryId ||
273
+ page.branches.length > input.query.limit ||
274
+ (page.nextPage !== null && page.nextPage !== input.query.cursor + 1) ||
275
+ (page.branches.length < input.query.limit && page.nextPage !== null)
276
+ ) {
277
+ throw new GitHubAppApiError("GitHub returned an invalid repository branches page");
278
+ }
279
+ const response = GitHubRepositoryBranchesResponseSchema.safeParse({
280
+ branches: page.branches.map((name) => ({
281
+ name,
282
+ isDefault: name === page.defaultBranch,
283
+ })),
284
+ nextCursor: page.nextPage,
285
+ });
286
+ if (!response.success) {
287
+ throw new GitHubAppApiError("GitHub returned an invalid repository branches page");
288
+ }
289
+ if (
290
+ !(await services.areRepositoriesAllowed(deps.db, input.workspaceId, input.installationId, [
291
+ input.repositoryId,
292
+ ]))
293
+ ) {
294
+ throw new GitHubRepositoryBranchAuthorityError("changed");
295
+ }
296
+ return response.data;
297
+ }
@@ -0,0 +1,71 @@
1
+ import type { Permission } from "@opengeni/contracts";
2
+ import { verifiedDelegatedHumanAuthorizationForRequest } from "@opengeni/core";
3
+ import type { Context } from "hono";
4
+ import { HTTPException } from "hono/http-exception";
5
+
6
+ /* ----------------------------------------------------------------------------
7
+ An agent acting as a person: an organization MCP action this server
8
+ dispatched in process for someone who signed the agent in (see
9
+ organization-mcp.ts). Routes that otherwise need the person's browser
10
+ cookie accept it, within the connection's organization and access setting.
11
+ The person's live role is still checked by the route, exactly as for the
12
+ browser.
13
+
14
+ Only Opengeni sign-in, approving a connection, third-party provider consent
15
+ and account recovery stay in the browser; those routes don't call this.
16
+ -------------------------------------------------------------------------- */
17
+
18
+ export type ActingPerson = { subjectId: string };
19
+
20
+ /** True when this request is an agent acting as a person. */
21
+ export function isAgentActingAsPerson(c: Context): boolean {
22
+ return verifiedDelegatedHumanAuthorizationForRequest(c.req.raw) !== null;
23
+ }
24
+
25
+ /**
26
+ * The person this agent acts as, for an action in `organizationId` that needs
27
+ * `permission`; null when the request is not an agent acting as a person.
28
+ * Another organization reads as not found; a permission the connection's
29
+ * access setting leaves out is refused.
30
+ */
31
+ export function agentActingAsPerson(
32
+ c: Context,
33
+ organizationId: string,
34
+ permission: Permission,
35
+ ): ActingPerson | null {
36
+ const proof = verifiedDelegatedHumanAuthorizationForRequest(c.req.raw);
37
+ if (!proof) return null;
38
+ if (proof.organizationId.toLowerCase() !== organizationId.toLowerCase()) {
39
+ throw new HTTPException(404, { message: "organization not found" });
40
+ }
41
+ if (!proof.permissions.includes(permission)) {
42
+ throw new HTTPException(403, {
43
+ message: `This connection's access doesn't include ${permission}.`,
44
+ });
45
+ }
46
+ return { subjectId: proof.subjectId };
47
+ }
48
+
49
+ /**
50
+ * The person an agent acts as, with no organization or permission check here:
51
+ * only for a route that next requires this same person's workspace grant,
52
+ * which carries the connection's organization, workspaces and access.
53
+ */
54
+ export function agentActingAsPersonBeforeGrantCheck(c: Context): ActingPerson | null {
55
+ const proof = verifiedDelegatedHumanAuthorizationForRequest(c.req.raw);
56
+ return proof ? { subjectId: proof.subjectId } : null;
57
+ }
58
+
59
+ /** Organization settings: reading needs account:read, changing needs account:admin. */
60
+ export function organizationSettingsPermission(c: Context): Permission {
61
+ return c.req.method === "GET" || c.req.method === "HEAD" ? "account:read" : "account:admin";
62
+ }
63
+
64
+ /** Refuse an agent on a browser-only step (provider consent, cross-organization actions). */
65
+ export function requireNotAgent(c: Context, what: string): void {
66
+ if (isAgentActingAsPerson(c)) {
67
+ throw new HTTPException(403, {
68
+ message: `${what} has to be done by the person in the Opengeni app in a browser.`,
69
+ });
70
+ }
71
+ }
@@ -0,0 +1,49 @@
1
+ import type { MiddlewareHandler } from "hono";
2
+ import { OPENGENI_API_CONTRACT_HEADER, OPENGENI_API_CONTRACT_REVISION } from "@opengeni/contracts";
3
+
4
+ const BEARER_AUTHORIZATION = /^bearer\s+\S/i;
5
+
6
+ /**
7
+ * Keep published SDKs working across additive contract-revision bumps.
8
+ *
9
+ * Every `@opengeni/sdk` release up to 7.x throws `OpenGeniApiContractMismatchError`
10
+ * on ANY response whose `x-opengeni-api-contract` header differs from the
11
+ * revision it was built with, reads included. The header exists to make a
12
+ * stale first-party browser tab reload (docs/design/api-compatibility-policy.md
13
+ * (e)); a backend integration pinned to an SDK version cannot reload, so the
14
+ * next additive revision bump would break every call it makes.
15
+ *
16
+ * For a bearer-authenticated caller (API key, delegated token) that announced a
17
+ * different revision, the response therefore omits the header instead of
18
+ * advertising one the caller is known to reject. Cookie/unauthenticated
19
+ * callers (the stock web app) keep it, and so does an explicit
20
+ * `API_CONTRACT_CHANGED` refusal, so a refused client can still explain the
21
+ * mismatch. This is not an authorization boundary: routes authorize as usual.
22
+ */
23
+ export function bearerApiContractHeaderCompatibility(): MiddlewareHandler {
24
+ return async (context, next) => {
25
+ await next();
26
+ const claimed = context.req.header(OPENGENI_API_CONTRACT_HEADER);
27
+ if (claimed === undefined || claimed === OPENGENI_API_CONTRACT_REVISION) return;
28
+ if (!BEARER_AUTHORIZATION.test(context.req.header("authorization") ?? "")) return;
29
+ if (!context.res.headers.has(OPENGENI_API_CONTRACT_HEADER)) return;
30
+ if (context.res.status === 409 && (await isContractRefusal(context.res))) return;
31
+ try {
32
+ context.res.headers.delete(OPENGENI_API_CONTRACT_HEADER);
33
+ } catch {
34
+ // Immutable headers (a proxied or redirect response): copy once.
35
+ context.res = new Response(context.res.body, context.res);
36
+ context.res.headers.delete(OPENGENI_API_CONTRACT_HEADER);
37
+ }
38
+ };
39
+ }
40
+
41
+ async function isContractRefusal(response: Response): Promise<boolean> {
42
+ if (!/^application\/json/i.test(response.headers.get("content-type") ?? "")) return false;
43
+ try {
44
+ const body = (await response.clone().json()) as { code?: unknown };
45
+ return body?.code === "API_CONTRACT_CHANGED";
46
+ } catch {
47
+ return false;
48
+ }
49
+ }
@@ -1,4 +1,11 @@
1
- import type { ErrorCode } from "@opengeni/contracts";
1
+ import {
2
+ AgentConfigError,
3
+ AllowanceExhaustedRefusal,
4
+ ModelUnavailableError,
5
+ ScheduledTaskTargetAccessChange,
6
+ type ErrorCode,
7
+ } from "@opengeni/contracts";
8
+ import { WorkspaceControlBusyError } from "@opengeni/db";
2
9
  import type { ContentfulStatusCode } from "hono/utils/http-status";
3
10
  import { HTTPException } from "hono/http-exception";
4
11
 
@@ -6,6 +13,7 @@ type ApiHttpErrorOptions = {
6
13
  code: ErrorCode;
7
14
  message: string;
8
15
  retryable?: boolean;
16
+ outcomeUnknown?: boolean;
9
17
  details?: Record<string, unknown>;
10
18
  };
11
19
 
@@ -13,6 +21,7 @@ type ApiHttpErrorOptions = {
13
21
  export class ApiHttpError extends HTTPException {
14
22
  readonly code: ErrorCode;
15
23
  readonly retryable: boolean | undefined;
24
+ readonly outcomeUnknown: boolean | undefined;
16
25
  readonly details: Record<string, unknown> | undefined;
17
26
 
18
27
  constructor(status: number, options: ApiHttpErrorOptions) {
@@ -20,6 +29,111 @@ export class ApiHttpError extends HTTPException {
20
29
  this.name = "ApiHttpError";
21
30
  this.code = options.code;
22
31
  this.retryable = options.retryable;
32
+ this.outcomeUnknown = options.outcomeUnknown;
23
33
  this.details = options.details;
24
34
  }
25
35
  }
36
+
37
+ export function scheduledTaskTargetAccessHttpError(error: unknown): ApiHttpError | null {
38
+ if (!(error instanceof HTTPException) || error.status !== 409) return null;
39
+ const result = ScheduledTaskTargetAccessChange.safeParse(error.cause);
40
+ return result.success
41
+ ? new ApiHttpError(409, {
42
+ code: "conflict",
43
+ message: error.message,
44
+ retryable: false,
45
+ outcomeUnknown: false,
46
+ details: result.data,
47
+ })
48
+ : null;
49
+ }
50
+
51
+ /** Preserve typed admission details through the common public error envelope. */
52
+ export function allowanceExhaustedHttpError(error: unknown): ApiHttpError | null {
53
+ if (!(error instanceof HTTPException) || error.status !== 402) return null;
54
+ const parsed = AllowanceExhaustedRefusal.safeParse(
55
+ error.cause && typeof error.cause === "object"
56
+ ? Object.fromEntries(Object.entries(error.cause).filter(([key]) => key !== "allowed"))
57
+ : error.cause,
58
+ );
59
+ if (!parsed.success) return null;
60
+ const { code, message, ...details } = parsed.data;
61
+ return new ApiHttpError(402, {
62
+ code,
63
+ message,
64
+ retryable: false,
65
+ outcomeUnknown: false,
66
+ details,
67
+ });
68
+ }
69
+
70
+ /**
71
+ * A request-scoped session/workspace mutation could not enter the workspace
72
+ * control prefix within its bounded wait. The transaction rolled back before
73
+ * any write, so the outcome is known and the client may retry. `app.onError`
74
+ * applies this once for every route; Slack interactions keep the raw typed
75
+ * error so their retry classifier treats it as transient.
76
+ */
77
+ export function workspaceControlBusyHttpError(error: unknown): ApiHttpError | null {
78
+ const busy =
79
+ error instanceof WorkspaceControlBusyError
80
+ ? error
81
+ : error instanceof HTTPException && error.cause instanceof WorkspaceControlBusyError
82
+ ? error.cause
83
+ : null;
84
+ if (!busy) return null;
85
+ return new ApiHttpError(503, {
86
+ code: "upstream_unavailable",
87
+ message: "The workspace is busy applying other session commands; retry shortly.",
88
+ retryable: true,
89
+ outcomeUnknown: false,
90
+ details: { code: busy.code, lockTimeoutMs: busy.lockTimeoutMs },
91
+ });
92
+ }
93
+
94
+ /**
95
+ * A typed agent-configuration failure (capability unavailable, conflict,
96
+ * widening, not enabled). Rendered as 422 validation_failed with the specific
97
+ * code in `details.code` so clients can branch without parsing messages.
98
+ */
99
+ export function agentConfigHttpError(error: unknown): ApiHttpError | null {
100
+ const cause =
101
+ error instanceof AgentConfigError
102
+ ? error
103
+ : error instanceof HTTPException && error.cause instanceof AgentConfigError
104
+ ? error.cause
105
+ : null;
106
+ if (!cause) return null;
107
+ return new ApiHttpError(422, {
108
+ code: "validation_failed",
109
+ message: cause.message,
110
+ retryable: false,
111
+ details: {
112
+ code: cause.code,
113
+ ...(cause.capability ? { capability: cause.capability } : {}),
114
+ },
115
+ });
116
+ }
117
+
118
+ /**
119
+ * The requested or stored model is not in the live catalog. Rendered as the
120
+ * same 422 `validation_failed` with its historical message, plus
121
+ * `details.code: "model_unavailable"` and the model id so clients can ask for
122
+ * another model rather than offer a retry that cannot succeed.
123
+ */
124
+ export function modelUnavailableHttpError(error: unknown): ApiHttpError | null {
125
+ const cause =
126
+ error instanceof ModelUnavailableError
127
+ ? error
128
+ : error instanceof HTTPException && error.cause instanceof ModelUnavailableError
129
+ ? error.cause
130
+ : null;
131
+ if (!cause) return null;
132
+ return new ApiHttpError(422, {
133
+ code: "validation_failed",
134
+ message: cause.message,
135
+ retryable: false,
136
+ outcomeUnknown: false,
137
+ details: { code: cause.code, modelId: cause.modelId },
138
+ });
139
+ }
package/src/http/auth.ts CHANGED
@@ -1,10 +1,20 @@
1
1
  import { resolveFirstPartyDelegationSecret, type Settings } from "@opengeni/config";
2
2
  import { verifyDelegatedAccessToken } from "@opengeni/contracts";
3
+ import { verifiedDelegatedHumanAuthorizationForRequest } from "@opengeni/core";
3
4
  import type { Context, MiddlewareHandler } from "hono";
5
+ import { ANALYTICS_CONSENT_PATH } from "../routes/analytics-consent";
6
+ import { CLIENT_ERRORS_PATH } from "../routes/client-errors";
4
7
  import { installExactPaths, isInstallRedirectPath } from "../routes/install";
8
+ import {
9
+ isMcpOAuthPublicProtocolPath,
10
+ isMcpOAuthResourcePath,
11
+ mcpOAuthBearerToken,
12
+ } from "../mcp-oauth";
5
13
 
6
14
  const githubConnectPathPattern = /^\/v1\/workspaces\/[^/]+\/github\/connect$/;
7
15
  const githubInstallationLinkPathPattern = /^\/v1\/workspaces\/[^/]+\/github\/installations$/;
16
+ const prReviewGithubBrowserPathPattern =
17
+ /^\/v1\/workspaces\/[^/]+\/pr-review\/github\/(?:connect|installations\/select|installations\/[^/]+\/configure)$/;
8
18
 
9
19
  export function requireAccessKey(settings: Settings): MiddlewareHandler {
10
20
  return async (c, next) => {
@@ -30,16 +40,43 @@ function isAuthExempt(c: Context, settings: Settings): boolean {
30
40
  if (c.req.method === "OPTIONS") {
31
41
  return true;
32
42
  }
43
+ // An organization MCP action dispatched in this process for a verified
44
+ // person. Only server code can stamp the exact Request object.
45
+ if (verifiedDelegatedHumanAuthorizationForRequest(c.req.raw)) {
46
+ return true;
47
+ }
33
48
  const path = new URL(c.req.url).pathname;
49
+ if (settings.mcpOauthEnabled && isMcpOAuthPublicProtocolPath(path)) {
50
+ return true;
51
+ }
52
+ if (settings.mcpOauthEnabled && isMcpOAuthResourcePath(path) && mcpOAuthBearerToken(c.req.raw)) {
53
+ return true;
54
+ }
34
55
  if (path === "/v1/config/client") {
35
56
  return true;
36
57
  }
58
+ // The web error beacon must count failures before sign-in. Its payload is a
59
+ // closed, content-free report and the route bounds its own admission.
60
+ if (c.req.method === "POST" && path === CLIENT_ERRORS_PATH) {
61
+ return true;
62
+ }
63
+ // The analytics banner is answered before sign-in too. The report is one
64
+ // closed decision and the route bounds its own admission.
65
+ if (c.req.method === "POST" && path === ANALYTICS_CONSENT_PATH) {
66
+ return true;
67
+ }
37
68
  if (path === "/v1/auth" || path.startsWith("/v1/auth/")) {
38
69
  return true;
39
70
  }
40
71
  if (path === "/v1/webhooks/stripe") {
41
72
  return true;
42
73
  }
74
+ if (c.req.method === "POST" && path.startsWith("/v1/webhooks/automations/")) {
75
+ return true;
76
+ }
77
+ if (c.req.method === "POST" && path === "/v1/webhooks/pr-review/github") {
78
+ return true;
79
+ }
43
80
  if (
44
81
  path === "/v1/github/setup" ||
45
82
  path === "/v1/github/install/callback" ||
@@ -48,9 +85,17 @@ function isAuthExempt(c: Context, settings: Settings): boolean {
48
85
  ) {
49
86
  return true;
50
87
  }
88
+ if (
89
+ path === "/v1/pr-review/github/setup" ||
90
+ path === "/v1/pr-review/github/install/callback" ||
91
+ path === "/v1/pr-review/github/oauth/callback"
92
+ ) {
93
+ return true;
94
+ }
51
95
  if (
52
96
  path === "/v1/integrations/oauth/callback" ||
53
97
  path === "/v1/integrations/provider-oauth/callback" ||
98
+ path === "/v1/integrations/github-personal/oauth/callback" ||
54
99
  path === "/v1/integrations/google-drive/callback" ||
55
100
  path === "/v1/integrations/oauth/client-metadata.json" ||
56
101
  path === "/v1/integrations/slack/callback" ||
@@ -79,6 +124,9 @@ function isAuthExempt(c: Context, settings: Settings): boolean {
79
124
  if (githubConnectPathPattern.test(path)) {
80
125
  return true;
81
126
  }
127
+ if (prReviewGithubBrowserPathPattern.test(path)) {
128
+ return true;
129
+ }
82
130
  // Compatibility endpoint for stale chooser submissions. It remains public
83
131
  // only so already-rendered forms can authenticate their signed account and
84
132
  // workspace state locally before terminating with 410; it does not parse a
package/src/http/cors.ts CHANGED
@@ -1,3 +1,70 @@
1
+ import { HTTPException } from "hono/http-exception";
2
+
1
3
  export function allowedCorsOrigin(pattern: string, origin: string): boolean {
2
4
  return new RegExp(`^(?:${pattern})$`).test(origin);
3
5
  }
6
+
7
+ export function validateInteractionRequestOrigin(
8
+ value: string | undefined,
9
+ input: {
10
+ corsAllowOriginRegex: string;
11
+ publicBaseUrl?: string | undefined;
12
+ webBaseUrl?: string | undefined;
13
+ },
14
+ ): string | null {
15
+ if (!value) return null;
16
+ let url: URL;
17
+ try {
18
+ url = new URL(value);
19
+ } catch {
20
+ throw new HTTPException(400, { message: "invalid request origin" });
21
+ }
22
+ if (
23
+ url.origin === "null" ||
24
+ (url.protocol !== "http:" && url.protocol !== "https:") ||
25
+ url.origin !== value
26
+ ) {
27
+ throw new HTTPException(400, { message: "invalid request origin" });
28
+ }
29
+ if (isConfiguredBrowserOrigin(url.origin, input)) {
30
+ return url.origin;
31
+ }
32
+ throw new HTTPException(403, { message: "request origin is not allowed" });
33
+ }
34
+
35
+ type BrowserOriginSettings = {
36
+ corsAllowOriginRegex: string;
37
+ publicBaseUrl?: string | undefined;
38
+ webBaseUrl?: string | undefined;
39
+ };
40
+
41
+ function isConfiguredBrowserOrigin(origin: string, input: BrowserOriginSettings): boolean {
42
+ return (
43
+ allowedCorsOrigin(input.corsAllowOriginRegex, origin) ||
44
+ [input.publicBaseUrl, input.webBaseUrl].some((baseUrl) =>
45
+ baseUrl ? new URL(baseUrl).origin === origin : false,
46
+ )
47
+ );
48
+ }
49
+
50
+ /**
51
+ * Whether a present `Origin` header names a browser origin this deployment
52
+ * serves its web app from: the CORS allowlist, the public base URL, or the
53
+ * separate web base URL. `null` and malformed values are never allowed.
54
+ */
55
+ export function isAllowedBrowserOrigin(value: string, input: BrowserOriginSettings): boolean {
56
+ let url: URL;
57
+ try {
58
+ url = new URL(value);
59
+ } catch {
60
+ return false;
61
+ }
62
+ if (
63
+ url.origin === "null" ||
64
+ (url.protocol !== "http:" && url.protocol !== "https:") ||
65
+ url.origin !== value
66
+ ) {
67
+ return false;
68
+ }
69
+ return isConfiguredBrowserOrigin(url.origin, input);
70
+ }