@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,537 @@
1
+ import {
2
+ normalizeSlackScopes,
3
+ OPENGENI_SLACK_REST_USER_SCOPES,
4
+ slackRestMcpToolsForScopes,
5
+ } from "@opengeni/contracts/slack-rest-mcp";
6
+ import { OPENGENI_PERSONAL_SLACK_MCP_URL, type ConnectionOwnership } from "@opengeni/contracts";
7
+ import type { Settings } from "@opengeni/config";
8
+ import { HTTPException } from "hono/http-exception";
9
+ import { z } from "zod";
10
+ import { GMAIL_REST_MCP_TOOLS, gmailToolSupportsScopes } from "@opengeni/runtime/gmail-rest-mcp";
11
+ import { canonicalProviderDomain } from "./provider-domain";
12
+
13
+ /**
14
+ * Provider OAuth quirks as data.
15
+ *
16
+ * Some providers do not support DCR or CIMD and need a pre-registered client
17
+ * with pinned metadata; some issue personal tokens only; some reject RFC 8707's
18
+ * `resource` parameter. Each used to be a hand-written branch set inside
19
+ * `oauth-client.ts`; every quirk is now a field on an `OAuthProviderProfile`.
20
+ * The flow reads exactly one resolved profile and contains no provider-name
21
+ * conditional.
22
+ *
23
+ * Profiles come from two layers:
24
+ *
25
+ * 1. Built-in profiles pin known authorization servers and protocol quirks.
26
+ * Ownership defaults guide setup; users may choose personal or workspace.
27
+ * Authorization-server pins never depend on catalog import state.
28
+ * 2. A validated `oauthProfile` object on a global catalog row (curated
29
+ * overlay -> importer -> `capability_catalog_items.metadata`). A catalog
30
+ * profile applies only when no built-in matches, and it can only narrow the
31
+ * default behavior, never loosen a built-in fence.
32
+ */
33
+
34
+ export const OFFICIAL_SLACK_MCP_URL = OPENGENI_PERSONAL_SLACK_MCP_URL;
35
+ export const OFFICIAL_GMAIL_MCP_URL = "https://gmailmcp.googleapis.com/mcp/v1";
36
+ export const OFFICIAL_GMAIL_MCP_SCOPES = [
37
+ "https://www.googleapis.com/auth/gmail.readonly",
38
+ "https://www.googleapis.com/auth/gmail.compose",
39
+ "https://www.googleapis.com/auth/gmail.modify",
40
+ ] as const;
41
+
42
+ const SLACK_OAUTH_ORIGIN = "https://slack.com";
43
+ const SLACK_MCP_ORIGIN = "https://mcp.slack.com";
44
+ const GOOGLE_OAUTH_ISSUER_ORIGIN = "https://accounts.google.com";
45
+ const GOOGLE_TOKEN_ORIGIN = "https://oauth2.googleapis.com";
46
+
47
+ /** The slice of discovered authorization-server metadata the pins constrain. */
48
+ export type PinnableAuthorizationServer = {
49
+ issuer: string;
50
+ authorizationServer: string;
51
+ authorizationEndpoint: string;
52
+ tokenEndpoint: string;
53
+ };
54
+
55
+ export type AuthorizationServerPins = {
56
+ /** Origins `issuer` and `authorizationServer` must both belong to. */
57
+ issuerOrigins: readonly string[];
58
+ /** Origins the authorization endpoint must belong to. */
59
+ authorizationEndpointOrigins: readonly string[];
60
+ /** Origins the token endpoint must belong to. */
61
+ tokenEndpointOrigins: readonly string[];
62
+ /** Exact 422 message when a pin fails. */
63
+ message: string;
64
+ /** Skip enforcement in a local test environment (loopback fixtures). */
65
+ skipInLocalTest: boolean;
66
+ };
67
+
68
+ export type OAuthProviderProfile = {
69
+ /** Stable identity for guards, logs, and tests. */
70
+ key: string;
71
+ /** Built-in matching; catalog profiles match their own row's exact mcpUrl. */
72
+ match: {
73
+ mcpUrls?: readonly string[];
74
+ providerDomains?: readonly string[];
75
+ };
76
+ /**
77
+ * Canonical provider identity forced when the profile matches by URL, so a
78
+ * caller cannot relabel a pinned resource under another domain.
79
+ */
80
+ canonicalProviderDomain?: string;
81
+ /** Reject a caller-supplied manual OAuth client (deployment-managed only). */
82
+ rejectCallerOAuthClient?: { message: string };
83
+ /** The payload's explicit providerDomain must canonicalize to this domain. */
84
+ requireProviderDomain?: { domain: string; message: string };
85
+ /** Outside a local test environment, the start URL must be exactly this. */
86
+ requireExactMcpUrl?: { url: string; message: string };
87
+ /** Deployment-managed client credentials must be configured (503 otherwise). */
88
+ requireDeploymentClient?: { key: DeploymentManagedClientKey; message: string };
89
+ /** Suggested ownership; explicit choices remain subject to requiredOwnership. */
90
+ defaultOwnership?: ConnectionOwnership;
91
+ /** Built-in-only ownership restriction, including old reconnect/callback state. */
92
+ requiredOwnership?: { ownership: ConnectionOwnership; message: string };
93
+ /** Bind reconnect/dedupe to the exact mcpUrl, not just the provider domain. */
94
+ exactMcpBinding: boolean;
95
+ /** How an existing connection is chosen for reconnect coalescing. */
96
+ connectionSelection: "canonical_personal" | "first_active";
97
+ /** Post-discovery authorization-server origin pins. */
98
+ authorizationServer?: AuthorizationServerPins;
99
+ /**
100
+ * Post-discovery identity check: the resolved providerDomain must equal this
101
+ * domain (the reserved-authorization-server guard shares its message).
102
+ */
103
+ postDiscoveryProviderDomain?: { domain: string; message: string };
104
+ /**
105
+ * Client registration preference. `dcr` or `cimd` forces that advertised
106
+ * self-registration mechanism after operator/deployment clients. Without an
107
+ * explicit preference, DCR wins when both mechanisms are advertised.
108
+ */
109
+ clientSource?: "deployment_managed" | "cimd" | "dcr";
110
+ /** Send RFC 8707 `resource` on authorize and token requests. */
111
+ sendResourceParameter: boolean;
112
+ /** Extra authorize-URL query parameters (e.g. offline-consent opts). */
113
+ extraAuthorizeParams?: Readonly<Record<string, string>>;
114
+ /** Exact scope override; the caller can never widen past it. */
115
+ requestedScopes?: readonly string[];
116
+ /** Reviewed local bridge grant normalization and token verification. Catalog profiles cannot supply code. */
117
+ normalizeGrantedScopes?: (scopes: readonly string[] | string) => string[];
118
+ reportedScopesRequired?: boolean;
119
+ /** Built-in durable API bridges may refuse a new grant without offline access. */
120
+ freshRefreshTokenRequired?: boolean;
121
+ /** The reviewed bridge exposes one tool contract, not a partial-scope variant. */
122
+ fullRequestedScopesRequired?: boolean;
123
+ /** Built-in web OAuth clients must use a configured secret and provider-supported authentication. */
124
+ confidentialClientRequired?: boolean;
125
+ /** Built-in API bridge discovery; catalog metadata cannot redirect this seam. */
126
+ providerOAuthDiscovery?: { issuer: string; metadataUrl: string };
127
+ localToolVerification?: {
128
+ url: string;
129
+ method?: "GET" | "POST";
130
+ /** An API bridge may require a verified account before accepting a grant. */
131
+ required?: boolean;
132
+ /** Distinguish a rejected OAuth grant from a temporary verification failure. */
133
+ isRejectedGrant?: (payload: Record<string, unknown>) => boolean;
134
+ validateIdentity: (payload: Record<string, unknown>) => Record<string, string>;
135
+ toolsForScopes: (scopes: readonly string[]) => Array<{ name: string; description?: string }>;
136
+ };
137
+ };
138
+
139
+ export const DEFAULT_OAUTH_PROFILE: OAuthProviderProfile = {
140
+ key: "default",
141
+ match: {},
142
+ exactMcpBinding: false,
143
+ connectionSelection: "first_active",
144
+ sendResourceParameter: true,
145
+ };
146
+
147
+ const HOSTED_SLACK_PROFILE: OAuthProviderProfile = {
148
+ key: "hosted-slack-mcp",
149
+ match: { mcpUrls: [OFFICIAL_SLACK_MCP_URL], providerDomains: ["slack.com"] },
150
+ canonicalProviderDomain: "slack.com",
151
+ rejectCallerOAuthClient: {
152
+ message: "Slack OAuth client credentials are deployment-managed",
153
+ },
154
+ requireProviderDomain: {
155
+ domain: "slack.com",
156
+ message: "Slack provider identity does not match slack.com",
157
+ },
158
+ requireExactMcpUrl: {
159
+ url: OFFICIAL_SLACK_MCP_URL,
160
+ message: `Slack MCP OAuth must use ${OFFICIAL_SLACK_MCP_URL}`,
161
+ },
162
+ requireDeploymentClient: {
163
+ key: "slack",
164
+ message: "Slack MCP OAuth requires OPENGENI_SLACK_CLIENT_ID and OPENGENI_SLACK_CLIENT_SECRET",
165
+ },
166
+ exactMcpBinding: true,
167
+ connectionSelection: "canonical_personal",
168
+ authorizationServer: {
169
+ issuerOrigins: [SLACK_OAUTH_ORIGIN, SLACK_MCP_ORIGIN],
170
+ authorizationEndpointOrigins: [SLACK_OAUTH_ORIGIN],
171
+ tokenEndpointOrigins: [SLACK_OAUTH_ORIGIN],
172
+ message: "Slack MCP authorization metadata did not remain bound to slack.com",
173
+ skipInLocalTest: true,
174
+ },
175
+ sendResourceParameter: true,
176
+ requestedScopes: OPENGENI_SLACK_REST_USER_SCOPES,
177
+ normalizeGrantedScopes: normalizeSlackScopes,
178
+ reportedScopesRequired: true,
179
+ localToolVerification: {
180
+ url: "https://slack.com/api/auth.test",
181
+ isRejectedGrant: (payload) =>
182
+ payload.ok === false &&
183
+ ["invalid_auth", "not_authed", "token_revoked", "account_inactive", "token_expired"].includes(
184
+ typeof payload.error === "string" ? payload.error : "",
185
+ ),
186
+ validateIdentity: (payload) => {
187
+ if (
188
+ payload.ok !== true ||
189
+ typeof payload.team_id !== "string" ||
190
+ !payload.team_id ||
191
+ typeof payload.user_id !== "string" ||
192
+ !payload.user_id ||
193
+ payload.bot_id
194
+ ) {
195
+ throw new Error("Slack account verification failed");
196
+ }
197
+ return {
198
+ slackTeamId: payload.team_id,
199
+ slackUserId: payload.user_id,
200
+ ...(typeof payload.team === "string" && payload.team.trim()
201
+ ? { slackTeamName: payload.team }
202
+ : {}),
203
+ ...(typeof payload.user === "string" && payload.user.trim()
204
+ ? { slackUserName: payload.user }
205
+ : {}),
206
+ };
207
+ },
208
+ toolsForScopes: slackRestMcpToolsForScopes,
209
+ },
210
+ };
211
+
212
+ const OFFICIAL_GMAIL_PROFILE: OAuthProviderProfile = {
213
+ key: "official-gmail",
214
+ match: { mcpUrls: [OFFICIAL_GMAIL_MCP_URL] },
215
+ requireExactMcpUrl: {
216
+ url: OFFICIAL_GMAIL_MCP_URL,
217
+ message: `Gmail OAuth must use ${OFFICIAL_GMAIL_MCP_URL}`,
218
+ },
219
+ defaultOwnership: "personal",
220
+ requiredOwnership: { ownership: "personal", message: "Gmail connections must be personal-owned" },
221
+ exactMcpBinding: true,
222
+ connectionSelection: "first_active",
223
+ authorizationServer: {
224
+ issuerOrigins: [GOOGLE_OAUTH_ISSUER_ORIGIN],
225
+ authorizationEndpointOrigins: [GOOGLE_OAUTH_ISSUER_ORIGIN],
226
+ tokenEndpointOrigins: [GOOGLE_TOKEN_ORIGIN],
227
+ message: "Gmail MCP authorization metadata did not remain bound to Google",
228
+ skipInLocalTest: false,
229
+ },
230
+ postDiscoveryProviderDomain: {
231
+ domain: "gmailmcp.googleapis.com",
232
+ message: `Google OAuth is allowed only for ${OFFICIAL_GMAIL_MCP_URL}`,
233
+ },
234
+ // Google's OAuth endpoints do not implement RFC 8707's `resource` parameter.
235
+ sendResourceParameter: false,
236
+ // Explicit offline consent is required to obtain the refresh token used by
237
+ // the durable connection broker. These are Gmail profile data, not behavior
238
+ // implied by suppressing the resource parameter.
239
+ extraAuthorizeParams: {
240
+ access_type: "offline",
241
+ include_granted_scopes: "true",
242
+ prompt: "consent",
243
+ },
244
+ // The Gmail PRM advertises broader grants, including full-mail access. The
245
+ // reviewed connector never lets a caller widen the capability contract.
246
+ requestedScopes: OFFICIAL_GMAIL_MCP_SCOPES,
247
+ reportedScopesRequired: true,
248
+ freshRefreshTokenRequired: true,
249
+ fullRequestedScopesRequired: true,
250
+ confidentialClientRequired: true,
251
+ providerOAuthDiscovery: {
252
+ issuer: GOOGLE_OAUTH_ISSUER_ORIGIN,
253
+ metadataUrl: `${GOOGLE_OAUTH_ISSUER_ORIGIN}/.well-known/openid-configuration`,
254
+ },
255
+ localToolVerification: {
256
+ url: "https://gmail.googleapis.com/gmail/v1/users/me/profile",
257
+ method: "GET",
258
+ required: true,
259
+ validateIdentity: (payload) => {
260
+ if (
261
+ typeof payload.emailAddress !== "string" ||
262
+ !/^[^\s@]+@[^\s@]+$/u.test(payload.emailAddress)
263
+ ) {
264
+ throw new Error("Gmail account verification failed");
265
+ }
266
+ return { gmailEmail: payload.emailAddress };
267
+ },
268
+ toolsForScopes: (scopes) => {
269
+ return GMAIL_REST_MCP_TOOLS.filter((tool) => gmailToolSupportsScopes(tool.name, scopes)).map(
270
+ ({ name, description }) => ({ name, ...(description ? { description } : {}) }),
271
+ );
272
+ },
273
+ },
274
+ };
275
+
276
+ const BUILT_IN_OAUTH_PROFILES: readonly OAuthProviderProfile[] = [
277
+ HOSTED_SLACK_PROFILE,
278
+ OFFICIAL_GMAIL_PROFILE,
279
+ ];
280
+
281
+ /** Exact built-in profile by its stable key; throws on an unknown key. */
282
+ export function builtInOAuthProfileByKey(key: string): OAuthProviderProfile {
283
+ const profile = BUILT_IN_OAUTH_PROFILES.find((candidate) => candidate.key === key);
284
+ if (!profile) {
285
+ throw new Error(`missing built-in OAuth profile: ${key}`);
286
+ }
287
+ return profile;
288
+ }
289
+
290
+ /**
291
+ * Authorization servers reserved for exactly one profile: discovering one of
292
+ * these identities on any other flow is rejected before registration.
293
+ */
294
+ const RESERVED_AUTHORIZATION_SERVERS: readonly {
295
+ issuerOrigins: readonly string[];
296
+ allowedProfileKey: string;
297
+ message: string;
298
+ }[] = [
299
+ {
300
+ issuerOrigins: [GOOGLE_OAUTH_ISSUER_ORIGIN],
301
+ allowedProfileKey: OFFICIAL_GMAIL_PROFILE.key,
302
+ message: `Google OAuth is allowed only for ${OFFICIAL_GMAIL_MCP_URL}`,
303
+ },
304
+ {
305
+ // A URL variant that dodges the hosted-Slack profile match (for example a
306
+ // trailing slash yielding providerDomain mcp.slack.com) must not reach
307
+ // Slack's authorization server as a default-profile flow: that would mint
308
+ // a workspace-ownable Slack identity with the deployment client.
309
+ issuerOrigins: [SLACK_OAUTH_ORIGIN, SLACK_MCP_ORIGIN],
310
+ allowedProfileKey: HOSTED_SLACK_PROFILE.key,
311
+ message: `Slack OAuth is allowed only for ${OFFICIAL_SLACK_MCP_URL}`,
312
+ },
313
+ ];
314
+
315
+ export type DeploymentManagedClientKey = "slack";
316
+
317
+ /**
318
+ * Pre-registered deployment clients resolved from dedicated settings, keyed by
319
+ * the authorization-server origins they serve. Consulted before the operator
320
+ * clients JSON so a deployment-managed provider can never be shadowed.
321
+ */
322
+ export const DEPLOYMENT_MANAGED_CLIENTS: readonly {
323
+ key: DeploymentManagedClientKey;
324
+ issuerOrigins: readonly string[];
325
+ resolve: (settings: Settings) => {
326
+ clientId: string;
327
+ clientSecret: string;
328
+ tokenEndpointAuthMethod: "client_secret_post";
329
+ } | null;
330
+ }[] = [
331
+ {
332
+ key: "slack",
333
+ issuerOrigins: [SLACK_OAUTH_ORIGIN, SLACK_MCP_ORIGIN],
334
+ resolve: (settings) =>
335
+ settings.slackClientId?.trim() && settings.slackClientSecret?.trim()
336
+ ? {
337
+ clientId: settings.slackClientId.trim(),
338
+ clientSecret: settings.slackClientSecret.trim(),
339
+ tokenEndpointAuthMethod: "client_secret_post",
340
+ }
341
+ : null,
342
+ },
343
+ ];
344
+
345
+ export function deploymentManagedClientFor(
346
+ settings: Settings,
347
+ key: DeploymentManagedClientKey,
348
+ ): ReturnType<(typeof DEPLOYMENT_MANAGED_CLIENTS)[number]["resolve"]> {
349
+ const entry = DEPLOYMENT_MANAGED_CLIENTS.find((candidate) => candidate.key === key);
350
+ return entry ? entry.resolve(settings) : null;
351
+ }
352
+
353
+ /** Built-in profile for a start target, or null when only the default applies. */
354
+ export function builtInOAuthProfileFor(input: {
355
+ mcpUrl: string;
356
+ providerDomain?: string | undefined;
357
+ }): OAuthProviderProfile | null {
358
+ for (const profile of BUILT_IN_OAUTH_PROFILES) {
359
+ if (profile.match.mcpUrls?.includes(input.mcpUrl)) {
360
+ return profile;
361
+ }
362
+ if (
363
+ input.providerDomain !== undefined &&
364
+ profile.match.providerDomains?.includes(canonicalProviderDomain(input.providerDomain))
365
+ ) {
366
+ return profile;
367
+ }
368
+ }
369
+ return null;
370
+ }
371
+
372
+ /** Ownership an omitted request defaults to under a profile. */
373
+ export function defaultOwnershipFor(profile: OAuthProviderProfile): ConnectionOwnership {
374
+ return profile.defaultOwnership ?? "workspace";
375
+ }
376
+
377
+ /** Enforces a profile's authorization-server origin pins with its exact message. */
378
+ export function assertAuthorizationServerPins(
379
+ as: PinnableAuthorizationServer,
380
+ pins: Pick<
381
+ AuthorizationServerPins,
382
+ "issuerOrigins" | "authorizationEndpointOrigins" | "tokenEndpointOrigins" | "message"
383
+ >,
384
+ ): void {
385
+ const issuerOrigins = [as.issuer, as.authorizationServer].map((value) => new URL(value).origin);
386
+ const authorizationOrigin = new URL(as.authorizationEndpoint).origin;
387
+ const tokenOrigin = new URL(as.tokenEndpoint).origin;
388
+ if (
389
+ issuerOrigins.some((origin) => !pins.issuerOrigins.includes(origin)) ||
390
+ !pins.authorizationEndpointOrigins.includes(authorizationOrigin) ||
391
+ !pins.tokenEndpointOrigins.includes(tokenOrigin)
392
+ ) {
393
+ throw new HTTPException(422, { message: pins.message });
394
+ }
395
+ }
396
+
397
+ /**
398
+ * Reserved-authorization-server guard: a discovered identity claimed by one
399
+ * profile is rejected on every other flow with that guard's exact message.
400
+ */
401
+ export function assertAuthorizationServerNotReserved(
402
+ as: PinnableAuthorizationServer,
403
+ profile: OAuthProviderProfile,
404
+ ): void {
405
+ const identities = [as.issuer, as.authorizationServer].map((value) => new URL(value).origin);
406
+ for (const guard of RESERVED_AUTHORIZATION_SERVERS) {
407
+ if (profile.key === guard.allowedProfileKey) {
408
+ continue;
409
+ }
410
+ if (identities.some((origin) => guard.issuerOrigins.includes(origin))) {
411
+ throw new HTTPException(422, { message: guard.message });
412
+ }
413
+ }
414
+ }
415
+
416
+ /**
417
+ * Catalog-row profile: the declarative subset a curated row may carry. It can
418
+ * only narrow the default flow; the fields that grant authority (deployment
419
+ * client settings, reserved-server membership) are built-in-only by
420
+ * construction because the schema cannot express them.
421
+ */
422
+ /**
423
+ * Authorize-URL parameters owned by the OAuth client itself. A profile's
424
+ * `extraAuthorizeParams` may never name one: overriding `scope` or `resource`
425
+ * would widen the grant past the recorded contract, and the rest carry the
426
+ * PKCE/state security machinery. Enforced in this schema, in the curation
427
+ * parser, and defensively again in `buildAuthorizationUrl`.
428
+ */
429
+ export const RESERVED_AUTHORIZE_PARAMS: ReadonlySet<string> = new Set([
430
+ "client_id",
431
+ "code_challenge",
432
+ "code_challenge_method",
433
+ "redirect_uri",
434
+ "resource",
435
+ "response_type",
436
+ "scope",
437
+ "state",
438
+ ]);
439
+
440
+ export const catalogOAuthProfileSchema = z
441
+ .object({
442
+ clientSource: z.enum(["deployment_managed", "cimd", "dcr"]).optional(),
443
+ exactMcpUrl: z.string().url().optional(),
444
+ pinnedIssuerOrigins: z.array(z.string().url()).min(1).optional(),
445
+ pinnedEndpointOrigins: z.array(z.string().url()).min(1).optional(),
446
+ sendResourceParameter: z.boolean().optional(),
447
+ defaultOwnership: z.enum(["personal", "workspace"]).optional(),
448
+ requestedScopes: z.array(z.string().min(1)).min(1).optional(),
449
+ extraAuthorizeParams: z
450
+ .record(z.string(), z.string())
451
+ .optional()
452
+ .refine(
453
+ (value) => !value || Object.keys(value).every((key) => !RESERVED_AUTHORIZE_PARAMS.has(key)),
454
+ { message: "extraAuthorizeParams may not name a reserved OAuth parameter" },
455
+ ),
456
+ })
457
+ .strict();
458
+
459
+ export type CatalogOAuthProfile = z.infer<typeof catalogOAuthProfileSchema>;
460
+
461
+ function originOf(value: string): string {
462
+ return new URL(value).origin;
463
+ }
464
+
465
+ /**
466
+ * Canonical catalog lookup key for an MCP URL, mirroring the importer's
467
+ * `canonicalMcpUrl` (`scripts/catalog-curation.ts`): no fragment, lowercase
468
+ * host, default ports stripped, trailing slashes collapsed. Without this, a
469
+ * trailing-slash or uppercase-host variant of a profiled URL would miss the
470
+ * row and silently fall back to the default profile.
471
+ */
472
+ export function catalogMcpUrlKey(value: string): string {
473
+ const url = new URL(value);
474
+ url.hash = "";
475
+ url.hostname = url.hostname.toLowerCase();
476
+ if (
477
+ (url.protocol === "https:" && url.port === "443") ||
478
+ (url.protocol === "http:" && url.port === "80")
479
+ ) {
480
+ url.port = "";
481
+ }
482
+ url.pathname = url.pathname.replace(/\/+$/, "") || "/";
483
+ return url.toString();
484
+ }
485
+
486
+ /**
487
+ * Applies a validated catalog profile over the default profile for a row with
488
+ * no built-in. `deployment_managed` from catalog data resolves through the
489
+ * operator clients JSON (issuer-keyed) only; named settings-backed clients
490
+ * remain built-in-only.
491
+ *
492
+ * A present-but-invalid profile fails closed with a 422: the row's operator
493
+ * declared constraints, and silently degrading to the default profile would
494
+ * drop an origin pin on a JSON typo.
495
+ */
496
+ export function oauthProfileFromCatalog(mcpUrl: string, raw: unknown): OAuthProviderProfile {
497
+ const parsed = catalogOAuthProfileSchema.safeParse(raw);
498
+ if (!parsed.success) {
499
+ throw new HTTPException(422, {
500
+ message:
501
+ "this integration's catalog OAuth profile is invalid; re-run the catalog import or fix the curated overlay",
502
+ });
503
+ }
504
+ const data = parsed.data;
505
+ const issuerOrigins = data.pinnedIssuerOrigins?.map(originOf);
506
+ const endpointOrigins = data.pinnedEndpointOrigins?.map(originOf);
507
+ const pins =
508
+ issuerOrigins || endpointOrigins
509
+ ? {
510
+ issuerOrigins: issuerOrigins ?? endpointOrigins ?? [],
511
+ authorizationEndpointOrigins: endpointOrigins ?? issuerOrigins ?? [],
512
+ tokenEndpointOrigins: endpointOrigins ?? issuerOrigins ?? [],
513
+ message: "authorization metadata did not remain bound to the reviewed provider origins",
514
+ skipInLocalTest: false,
515
+ }
516
+ : undefined;
517
+ return {
518
+ key: `catalog:${mcpUrl}`,
519
+ match: { mcpUrls: [mcpUrl] },
520
+ ...(data.defaultOwnership ? { defaultOwnership: data.defaultOwnership } : {}),
521
+ exactMcpBinding: Boolean(data.exactMcpUrl),
522
+ ...(data.exactMcpUrl
523
+ ? {
524
+ requireExactMcpUrl: {
525
+ url: data.exactMcpUrl,
526
+ message: `OAuth for this integration must use ${data.exactMcpUrl}`,
527
+ },
528
+ }
529
+ : {}),
530
+ connectionSelection: "first_active",
531
+ ...(pins ? { authorizationServer: pins } : {}),
532
+ ...(data.clientSource ? { clientSource: data.clientSource } : {}),
533
+ sendResourceParameter: data.sendResourceParameter ?? true,
534
+ ...(data.requestedScopes ? { requestedScopes: data.requestedScopes } : {}),
535
+ ...(data.extraAuthorizeParams ? { extraAuthorizeParams: data.extraAuthorizeParams } : {}),
536
+ };
537
+ }
@@ -0,0 +1,18 @@
1
+ import { HTTPException } from "hono/http-exception";
2
+
3
+ export function safeReturnPath(value: string): string {
4
+ if (!value.startsWith("/") || value.startsWith("//")) {
5
+ throw new HTTPException(400, {
6
+ message: "OAuth returnPath must be a relative path",
7
+ });
8
+ }
9
+ const parsed = new URL(value, "https://opengeni.local");
10
+ // `..` segments can normalize back into a `//host` prefix, which browsers
11
+ // resolve as a protocol-relative absolute URL. Reject the NORMALIZED path.
12
+ if (parsed.origin !== "https://opengeni.local" || parsed.pathname.startsWith("//")) {
13
+ throw new HTTPException(400, {
14
+ message: "OAuth returnPath must be a relative path",
15
+ });
16
+ }
17
+ return `${parsed.pathname}${parsed.search}${parsed.hash}`;
18
+ }