@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,674 @@
1
+ import {
2
+ PERSONAL_GITHUB_API_ORIGIN,
3
+ PERSONAL_GITHUB_PROVIDER_DOMAIN,
4
+ PERSONAL_GITHUB_REPOSITORY_CATALOG_MAX,
5
+ PersonalGitHubRepository,
6
+ canonicalPersonalGitHubRepositoryUrl,
7
+ isPersonalGitHubConnection,
8
+ type PersonalGitHubRepository as PersonalGitHubRepositoryContract,
9
+ type PersonalGitHubRepositorySelectionInput,
10
+ } from "@opengeni/contracts/personal-github";
11
+ import {
12
+ GitHubRepositoryBranchesResponse,
13
+ type GitHubRepositoryBranchesResponse as GitHubRepositoryBranchesResponseContract,
14
+ type ListGitHubRepositoryBranchesQuery,
15
+ } from "@opengeni/contracts/github-repository-contracts";
16
+ import type { ApiRouteDeps } from "@opengeni/core";
17
+ import {
18
+ buildConnectionTokenResolver,
19
+ getConnectionMetadata,
20
+ getPersonalGitHubRepositorySelectionState,
21
+ type PersonalGitHubRepositorySelectionState as DbPersonalGitHubRepositorySelectionState,
22
+ } from "@opengeni/db";
23
+ import { readResponseTextBounded } from "@opengeni/network";
24
+ import { HTTPException } from "hono/http-exception";
25
+ import JSONBig from "json-bigint";
26
+
27
+ const GITHUB_API_VERSION = "2022-11-28";
28
+ const GITHUB_REQUEST_TIMEOUT_MS = 10_000;
29
+ const GITHUB_REPOSITORIES_RESPONSE_MAX_BYTES = 1024 * 1024;
30
+ const GITHUB_BRANCHES_RESPONSE_MAX_BYTES = 256 * 1024;
31
+ const personalGitHubProviderJsonParser = JSONBig({
32
+ storeAsString: true,
33
+ protoAction: "error",
34
+ constructorAction: "error",
35
+ });
36
+
37
+ export type PersonalGitHubRepositoryConnection = NonNullable<
38
+ Awaited<ReturnType<typeof getConnectionMetadata>>
39
+ >;
40
+
41
+ type PersonalGitHubRepositoryProviderOperation =
42
+ | "repositories_list"
43
+ | "repository_branches_list"
44
+ | "repository_verify";
45
+
46
+ type ExpectedPersonalGitHubRepositoryAuthority = {
47
+ selectionGeneration: number;
48
+ repositoryId: string;
49
+ fullName: string;
50
+ };
51
+
52
+ type PersonalGitHubProviderJsonOptions = {
53
+ operation: PersonalGitHubRepositoryProviderOperation;
54
+ expectedRepositoryAuthority?: ExpectedPersonalGitHubRepositoryAuthority;
55
+ responseLabel?: string;
56
+ responseMaxBytes?: number;
57
+ };
58
+
59
+ export type PersonalGitHubRepositoryBranchServices = {
60
+ requireConnection: typeof requirePersonalGitHubRepositoryConnection;
61
+ getSelectionState: (
62
+ deps: ApiRouteDeps,
63
+ input: {
64
+ accountId: string;
65
+ originWorkspaceId: string;
66
+ subjectId: string;
67
+ connectionId: string;
68
+ },
69
+ ) => Promise<DbPersonalGitHubRepositorySelectionState | null>;
70
+ providerJson: (input: {
71
+ deps: ApiRouteDeps;
72
+ connection: PersonalGitHubRepositoryConnection;
73
+ subjectId: string;
74
+ url: URL;
75
+ expectedConnectionAuthorityGeneration: number;
76
+ options: PersonalGitHubProviderJsonOptions;
77
+ }) => Promise<unknown>;
78
+ };
79
+
80
+ const personalGitHubRepositoryBranchServices: PersonalGitHubRepositoryBranchServices = {
81
+ requireConnection: requirePersonalGitHubRepositoryConnection,
82
+ getSelectionState: async (deps, input) =>
83
+ await getPersonalGitHubRepositorySelectionState(deps.db, input),
84
+ providerJson: async (input) =>
85
+ await personalGitHubProviderJson(
86
+ input.deps,
87
+ input.connection,
88
+ input.subjectId,
89
+ input.url,
90
+ input.expectedConnectionAuthorityGeneration,
91
+ input.options,
92
+ ),
93
+ };
94
+
95
+ export type PersonalGitHubRepositoryProviderErrorCode =
96
+ | "connection_changed"
97
+ | "connection_inactive"
98
+ | "invalid_provider_response"
99
+ | "provider_denied"
100
+ | "provider_rate_limited"
101
+ | "provider_unavailable"
102
+ | "repository_archived"
103
+ | "repository_not_found"
104
+ | "repository_not_selected"
105
+ | "repository_read_denied"
106
+ | "repository_selection_changed"
107
+ | "repository_write_denied";
108
+
109
+ export class PersonalGitHubRepositoryProviderError extends Error {
110
+ constructor(readonly code: PersonalGitHubRepositoryProviderErrorCode) {
111
+ super(code);
112
+ this.name = "PersonalGitHubRepositoryProviderError";
113
+ }
114
+ }
115
+
116
+ export async function requirePersonalGitHubRepositoryConnection(
117
+ deps: ApiRouteDeps,
118
+ input: { accountId: string; workspaceId: string; subjectId: string; connectionId: string },
119
+ ): Promise<PersonalGitHubRepositoryConnection> {
120
+ if (!deps.settings.githubPersonalOauthEnabled) {
121
+ throw new HTTPException(404, {
122
+ message: "personal GitHub repository discovery is not enabled",
123
+ });
124
+ }
125
+ const connection = await getConnectionMetadata(
126
+ deps.db,
127
+ input.workspaceId,
128
+ input.connectionId,
129
+ input.subjectId,
130
+ );
131
+ if (
132
+ !connection ||
133
+ connection.accountId !== input.accountId ||
134
+ connection.subjectId !== input.subjectId ||
135
+ !isPersonalGitHubConnection(connection)
136
+ ) {
137
+ throw new HTTPException(404, { message: "personal GitHub connection not found" });
138
+ }
139
+ if (connection.status !== "active") {
140
+ throw new HTTPException(409, { message: "personal GitHub connection must be reconnected" });
141
+ }
142
+ return connection;
143
+ }
144
+
145
+ export async function listLivePersonalGitHubRepositories(
146
+ deps: ApiRouteDeps,
147
+ input: {
148
+ workspaceId: string;
149
+ accountId: string;
150
+ subjectId: string;
151
+ connectionId: string;
152
+ expectedConnectionAuthorityGeneration: number;
153
+ page: number;
154
+ limit: number;
155
+ },
156
+ ): Promise<{ repositories: PersonalGitHubRepositoryContract[]; nextPage: number | null }> {
157
+ const connection = await requirePersonalGitHubRepositoryConnection(deps, input);
158
+ const url = new URL("/user/repos", PERSONAL_GITHUB_API_ORIGIN);
159
+ url.searchParams.set("affiliation", "owner,collaborator,organization_member");
160
+ url.searchParams.set("direction", "asc");
161
+ url.searchParams.set("page", String(input.page));
162
+ url.searchParams.set("per_page", String(input.limit));
163
+ url.searchParams.set("sort", "full_name");
164
+ const payload = await personalGitHubProviderJson(
165
+ deps,
166
+ connection,
167
+ input.subjectId,
168
+ url,
169
+ input.expectedConnectionAuthorityGeneration,
170
+ { operation: "repositories_list" },
171
+ );
172
+ if (!Array.isArray(payload) || payload.length > PERSONAL_GITHUB_REPOSITORY_CATALOG_MAX) {
173
+ throw new PersonalGitHubRepositoryProviderError("invalid_provider_response");
174
+ }
175
+ const repositories: PersonalGitHubRepositoryContract[] = [];
176
+ const seen = new Set<string>();
177
+ for (const value of payload) {
178
+ const repository = parsePersonalGitHubRepository(value);
179
+ if (seen.has(repository.repositoryId)) {
180
+ throw new PersonalGitHubRepositoryProviderError("invalid_provider_response");
181
+ }
182
+ seen.add(repository.repositoryId);
183
+ if (personalGitHubRepositoryCanRead(repository.permissions)) repositories.push(repository);
184
+ }
185
+ return {
186
+ repositories,
187
+ nextPage: payload.length === input.limit && input.page < 10_000 ? input.page + 1 : null,
188
+ };
189
+ }
190
+
191
+ export async function listLivePersonalGitHubRepositoryBranches(
192
+ deps: ApiRouteDeps,
193
+ input: {
194
+ workspaceId: string;
195
+ accountId: string;
196
+ subjectId: string;
197
+ connectionId: string;
198
+ repositoryId: string;
199
+ query: ListGitHubRepositoryBranchesQuery;
200
+ },
201
+ services: PersonalGitHubRepositoryBranchServices = personalGitHubRepositoryBranchServices,
202
+ ): Promise<GitHubRepositoryBranchesResponseContract> {
203
+ const connection = await services.requireConnection(deps, input);
204
+ const current = await requireSelectedPersonalGitHubRepository(
205
+ deps,
206
+ connection,
207
+ input,
208
+ null,
209
+ services.getSelectionState,
210
+ );
211
+ const [owner, repositoryName] = current.repository.fullName.split("/");
212
+ if (!owner || !repositoryName) {
213
+ throw new PersonalGitHubRepositoryProviderError("invalid_provider_response");
214
+ }
215
+ const url = new URL(
216
+ `/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repositoryName)}/branches`,
217
+ PERSONAL_GITHUB_API_ORIGIN,
218
+ );
219
+ url.searchParams.set("page", String(input.query.cursor));
220
+ url.searchParams.set("per_page", String(input.query.limit));
221
+ const expectedRepositoryAuthority = {
222
+ selectionGeneration: current.selectionGeneration,
223
+ repositoryId: current.repository.repositoryId,
224
+ fullName: current.repository.fullName,
225
+ };
226
+ const payload = await services.providerJson({
227
+ deps,
228
+ connection,
229
+ subjectId: input.subjectId,
230
+ url,
231
+ expectedConnectionAuthorityGeneration: current.connectionAuthorityGeneration,
232
+ options: {
233
+ operation: "repository_branches_list",
234
+ expectedRepositoryAuthority,
235
+ responseLabel: "GitHub repository branches response",
236
+ responseMaxBytes: GITHUB_BRANCHES_RESPONSE_MAX_BYTES,
237
+ },
238
+ });
239
+ if (!Array.isArray(payload) || payload.length > input.query.limit) {
240
+ throw new PersonalGitHubRepositoryProviderError("invalid_provider_response");
241
+ }
242
+ const branches: string[] = [];
243
+ const seen = new Set<string>();
244
+ for (const value of payload) {
245
+ const name =
246
+ value && typeof value === "object" && !Array.isArray(value)
247
+ ? (value as Record<string, unknown>).name
248
+ : null;
249
+ if (typeof name !== "string" || name.length === 0 || name.length > 1024 || seen.has(name)) {
250
+ throw new PersonalGitHubRepositoryProviderError("invalid_provider_response");
251
+ }
252
+ seen.add(name);
253
+ branches.push(name);
254
+ }
255
+ await requireSelectedPersonalGitHubRepository(
256
+ deps,
257
+ connection,
258
+ input,
259
+ expectedRepositoryAuthority,
260
+ services.getSelectionState,
261
+ );
262
+ const response = GitHubRepositoryBranchesResponse.safeParse({
263
+ branches: branches.map((name) => ({
264
+ name,
265
+ isDefault: name === current.repository.defaultBranch,
266
+ })),
267
+ nextCursor:
268
+ branches.length === input.query.limit && input.query.cursor < 10_000
269
+ ? input.query.cursor + 1
270
+ : null,
271
+ });
272
+ if (!response.success) {
273
+ throw new PersonalGitHubRepositoryProviderError("invalid_provider_response");
274
+ }
275
+ return response.data;
276
+ }
277
+
278
+ /** Serial by design: one bounded provider request and one authority check at a time. */
279
+ export async function verifyLivePersonalGitHubRepositories(
280
+ deps: ApiRouteDeps,
281
+ input: {
282
+ workspaceId: string;
283
+ accountId: string;
284
+ subjectId: string;
285
+ connectionId: string;
286
+ expectedConnectionAuthorityGeneration: number;
287
+ repositories: PersonalGitHubRepositorySelectionInput[];
288
+ },
289
+ ): Promise<Array<PersonalGitHubRepositoryContract & { selectedAccess: "read" | "write" }>> {
290
+ const connection = await requirePersonalGitHubRepositoryConnection(deps, input);
291
+ const verified: Array<PersonalGitHubRepositoryContract & { selectedAccess: "read" | "write" }> =
292
+ [];
293
+ for (const selection of input.repositories) {
294
+ const [owner, repositoryName] = selection.fullName.split("/");
295
+ if (!owner || !repositoryName) {
296
+ throw new PersonalGitHubRepositoryProviderError("invalid_provider_response");
297
+ }
298
+ const url = new URL(
299
+ `/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repositoryName)}`,
300
+ PERSONAL_GITHUB_API_ORIGIN,
301
+ );
302
+ const payload = await personalGitHubProviderJson(
303
+ deps,
304
+ connection,
305
+ input.subjectId,
306
+ url,
307
+ input.expectedConnectionAuthorityGeneration,
308
+ { operation: "repository_verify" },
309
+ );
310
+ const repository = parsePersonalGitHubRepository(payload);
311
+ if (
312
+ repository.repositoryId !== selection.repositoryId ||
313
+ repository.fullName.toLowerCase() !== selection.fullName.toLowerCase()
314
+ ) {
315
+ throw new PersonalGitHubRepositoryProviderError("repository_not_found");
316
+ }
317
+ if (!personalGitHubRepositoryCanRead(repository.permissions)) {
318
+ throw new PersonalGitHubRepositoryProviderError("repository_read_denied");
319
+ }
320
+ if (selection.access === "write") {
321
+ if (repository.archived || repository.disabled) {
322
+ throw new PersonalGitHubRepositoryProviderError("repository_archived");
323
+ }
324
+ if (!personalGitHubRepositoryCanWrite(repository.permissions)) {
325
+ throw new PersonalGitHubRepositoryProviderError("repository_write_denied");
326
+ }
327
+ }
328
+ verified.push({ ...repository, selectedAccess: selection.access });
329
+ }
330
+ return verified;
331
+ }
332
+
333
+ async function requireSelectedPersonalGitHubRepository(
334
+ deps: ApiRouteDeps,
335
+ connection: PersonalGitHubRepositoryConnection,
336
+ input: {
337
+ accountId: string;
338
+ subjectId: string;
339
+ connectionId: string;
340
+ repositoryId: string;
341
+ },
342
+ expected: ExpectedPersonalGitHubRepositoryAuthority | null,
343
+ getSelectionState: PersonalGitHubRepositoryBranchServices["getSelectionState"],
344
+ ): Promise<{
345
+ connectionAuthorityGeneration: number;
346
+ selectionGeneration: number;
347
+ repository: NonNullable<
348
+ Awaited<ReturnType<typeof getPersonalGitHubRepositorySelectionState>>
349
+ >["repositories"][number];
350
+ }> {
351
+ const selection = await getSelectionState(deps, {
352
+ accountId: input.accountId,
353
+ originWorkspaceId: connection.workspaceId,
354
+ subjectId: input.subjectId,
355
+ connectionId: input.connectionId,
356
+ });
357
+ if (!selection) {
358
+ throw new PersonalGitHubRepositoryProviderError(
359
+ expected ? "repository_selection_changed" : "repository_not_selected",
360
+ );
361
+ }
362
+ const repository = selection.repositories.find(
363
+ (candidate) => candidate.repositoryId === input.repositoryId,
364
+ );
365
+ if (!repository) {
366
+ throw new PersonalGitHubRepositoryProviderError(
367
+ expected ? "repository_selection_changed" : "repository_not_selected",
368
+ );
369
+ }
370
+ if (
371
+ expected &&
372
+ (selection.selectionGeneration !== expected.selectionGeneration ||
373
+ repository.repositoryId !== expected.repositoryId ||
374
+ repository.fullName !== expected.fullName)
375
+ ) {
376
+ throw new PersonalGitHubRepositoryProviderError("repository_selection_changed");
377
+ }
378
+ return {
379
+ connectionAuthorityGeneration: selection.connectionAuthorityGeneration,
380
+ selectionGeneration: selection.selectionGeneration,
381
+ repository,
382
+ };
383
+ }
384
+
385
+ export function personalGitHubRepositoryProviderHttpError(
386
+ error: PersonalGitHubRepositoryProviderError,
387
+ ): HTTPException {
388
+ switch (error.code) {
389
+ case "connection_changed":
390
+ return new HTTPException(409, {
391
+ message: "personal GitHub connection changed; refresh and try again",
392
+ });
393
+ case "connection_inactive":
394
+ case "provider_denied":
395
+ return new HTTPException(401, { message: "personal GitHub must be reconnected" });
396
+ case "provider_rate_limited":
397
+ return new HTTPException(503, { message: "GitHub is temporarily rate limited" });
398
+ case "repository_not_found":
399
+ return new HTTPException(422, { message: "a selected GitHub repository is unavailable" });
400
+ case "repository_not_selected":
401
+ return new HTTPException(404, {
402
+ message: "personal GitHub repository is not selected for this connection",
403
+ });
404
+ case "repository_selection_changed":
405
+ return new HTTPException(409, {
406
+ message: "personal GitHub repository selection changed; refresh and try again",
407
+ });
408
+ case "repository_archived":
409
+ return new HTTPException(422, {
410
+ message: "an archived or disabled GitHub repository cannot be selected for write access",
411
+ });
412
+ case "repository_read_denied":
413
+ return new HTTPException(422, {
414
+ message: "a selected GitHub repository is not readable",
415
+ });
416
+ case "repository_write_denied":
417
+ return new HTTPException(422, {
418
+ message: "a selected GitHub repository does not allow writes",
419
+ });
420
+ case "invalid_provider_response":
421
+ case "provider_unavailable":
422
+ return new HTTPException(502, { message: "GitHub repository discovery is unavailable" });
423
+ }
424
+ }
425
+
426
+ async function personalGitHubProviderJson(
427
+ deps: ApiRouteDeps,
428
+ connection: PersonalGitHubRepositoryConnection,
429
+ subjectId: string,
430
+ url: URL,
431
+ expectedConnectionAuthorityGeneration: number,
432
+ options: PersonalGitHubProviderJsonOptions,
433
+ ): Promise<unknown> {
434
+ if (url.origin !== PERSONAL_GITHUB_API_ORIGIN) {
435
+ throw new PersonalGitHubRepositoryProviderError("invalid_provider_response");
436
+ }
437
+ let response = await personalGitHubProviderFetch(
438
+ deps,
439
+ connection,
440
+ subjectId,
441
+ url,
442
+ expectedConnectionAuthorityGeneration,
443
+ options.operation,
444
+ options.expectedRepositoryAuthority,
445
+ false,
446
+ );
447
+ if (response.status === 401) {
448
+ await cancelResponse(response);
449
+ response = await personalGitHubProviderFetch(
450
+ deps,
451
+ connection,
452
+ subjectId,
453
+ url,
454
+ expectedConnectionAuthorityGeneration,
455
+ options.operation,
456
+ options.expectedRepositoryAuthority,
457
+ true,
458
+ );
459
+ }
460
+ if (response.status >= 300 && response.status < 400) {
461
+ await cancelResponse(response);
462
+ throw new PersonalGitHubRepositoryProviderError("provider_unavailable");
463
+ }
464
+ if (!response.ok) {
465
+ const status = response.status;
466
+ const rateLimited =
467
+ status === 429 ||
468
+ (status === 403 &&
469
+ (response.headers.get("x-ratelimit-remaining") === "0" ||
470
+ response.headers.has("retry-after")));
471
+ await cancelResponse(response);
472
+ if (status === 401 || status === 403) {
473
+ throw new PersonalGitHubRepositoryProviderError(
474
+ rateLimited ? "provider_rate_limited" : "provider_denied",
475
+ );
476
+ }
477
+ if (status === 429) {
478
+ throw new PersonalGitHubRepositoryProviderError("provider_rate_limited");
479
+ }
480
+ if (status === 404 && options.operation !== "repositories_list") {
481
+ throw new PersonalGitHubRepositoryProviderError("repository_not_found");
482
+ }
483
+ throw new PersonalGitHubRepositoryProviderError("provider_unavailable");
484
+ }
485
+ try {
486
+ return parsePersonalGitHubProviderJson(
487
+ await readResponseTextBounded(
488
+ response,
489
+ options.responseMaxBytes ?? GITHUB_REPOSITORIES_RESPONSE_MAX_BYTES,
490
+ options.responseLabel ??
491
+ (options.operation === "repositories_list"
492
+ ? "GitHub repositories response"
493
+ : "GitHub repository response"),
494
+ ),
495
+ );
496
+ } catch {
497
+ throw new PersonalGitHubRepositoryProviderError("invalid_provider_response");
498
+ }
499
+ }
500
+
501
+ /** Keep provider integer lexemes exact before repository IDs become bigint-backed strings. */
502
+ export function parsePersonalGitHubProviderJson(value: string): unknown {
503
+ return personalGitHubProviderJsonParser.parse(value) as unknown;
504
+ }
505
+
506
+ async function personalGitHubProviderFetch(
507
+ deps: ApiRouteDeps,
508
+ connection: PersonalGitHubRepositoryConnection,
509
+ subjectId: string,
510
+ url: URL,
511
+ expectedConnectionAuthorityGeneration: number,
512
+ operation: PersonalGitHubRepositoryProviderOperation,
513
+ expectedRepositoryAuthority: ExpectedPersonalGitHubRepositoryAuthority | undefined,
514
+ forceRefresh: boolean,
515
+ ): Promise<Response> {
516
+ const resolver = buildConnectionTokenResolver(deps.db, deps.settings, undefined, {
517
+ ...(deps.githubPersonalFetch
518
+ ? { refreshTransport: { fetchImpl: deps.githubPersonalFetch } }
519
+ : {}),
520
+ });
521
+ const credential = await resolver({
522
+ workspaceId: connection.workspaceId,
523
+ subjectId,
524
+ serverId: "github-personal-repository-picker",
525
+ toolName: operation,
526
+ connectionRef: {
527
+ connectionId: connection.id,
528
+ providerDomain: PERSONAL_GITHUB_PROVIDER_DOMAIN,
529
+ kind: "oauth2",
530
+ subjectScope: "subject",
531
+ scopes: ["repo"],
532
+ },
533
+ destinationUrl: url.toString(),
534
+ credentialTarget: "http_api",
535
+ forceRefresh,
536
+ });
537
+ if (credential.status !== "ok") {
538
+ throw new PersonalGitHubRepositoryProviderError("connection_inactive");
539
+ }
540
+ if (credential.connectionId !== connection.id || credential.connectionVersion === undefined) {
541
+ throw new PersonalGitHubRepositoryProviderError("connection_changed");
542
+ }
543
+ const current = await getConnectionMetadata(
544
+ deps.db,
545
+ connection.workspaceId,
546
+ connection.id,
547
+ subjectId,
548
+ );
549
+ if (
550
+ !current ||
551
+ current.version !== credential.connectionVersion ||
552
+ current.subjectId !== subjectId ||
553
+ current.status !== "active" ||
554
+ !isPersonalGitHubConnection(current)
555
+ ) {
556
+ throw new PersonalGitHubRepositoryProviderError("connection_changed");
557
+ }
558
+ const authority = await getPersonalGitHubRepositorySelectionState(deps.db, {
559
+ accountId: connection.accountId,
560
+ originWorkspaceId: connection.workspaceId,
561
+ subjectId,
562
+ connectionId: connection.id,
563
+ });
564
+ if (
565
+ !authority ||
566
+ authority.connectionAuthorityGeneration !== expectedConnectionAuthorityGeneration
567
+ ) {
568
+ throw new PersonalGitHubRepositoryProviderError("connection_changed");
569
+ }
570
+ if (expectedRepositoryAuthority) {
571
+ const repository = authority.repositories.find(
572
+ (candidate) => candidate.repositoryId === expectedRepositoryAuthority.repositoryId,
573
+ );
574
+ if (
575
+ authority.selectionGeneration !== expectedRepositoryAuthority.selectionGeneration ||
576
+ !repository ||
577
+ repository.fullName !== expectedRepositoryAuthority.fullName
578
+ ) {
579
+ throw new PersonalGitHubRepositoryProviderError("repository_selection_changed");
580
+ }
581
+ }
582
+ const authorization = Object.entries(credential.headers).find(
583
+ ([name]) => name.toLowerCase() === "authorization",
584
+ )?.[1];
585
+ if (!authorization) {
586
+ throw new PersonalGitHubRepositoryProviderError("connection_inactive");
587
+ }
588
+ try {
589
+ return await (deps.githubPersonalFetch ?? fetch)(url, {
590
+ method: "GET",
591
+ redirect: "manual",
592
+ headers: {
593
+ accept: "application/vnd.github+json",
594
+ authorization,
595
+ "user-agent": "OpenGeni",
596
+ "x-github-api-version": GITHUB_API_VERSION,
597
+ },
598
+ signal: AbortSignal.timeout(GITHUB_REQUEST_TIMEOUT_MS),
599
+ });
600
+ } catch {
601
+ throw new PersonalGitHubRepositoryProviderError("provider_unavailable");
602
+ }
603
+ }
604
+
605
+ export function personalGitHubRepositoryCanRead(
606
+ permissions: PersonalGitHubRepositoryContract["permissions"],
607
+ ): boolean {
608
+ return (
609
+ permissions.pull ||
610
+ permissions.triage ||
611
+ permissions.push ||
612
+ permissions.maintain ||
613
+ permissions.admin
614
+ );
615
+ }
616
+
617
+ export function personalGitHubRepositoryCanWrite(
618
+ permissions: PersonalGitHubRepositoryContract["permissions"],
619
+ ): boolean {
620
+ return permissions.push || permissions.maintain || permissions.admin;
621
+ }
622
+
623
+ export function parsePersonalGitHubRepository(value: unknown): PersonalGitHubRepositoryContract {
624
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
625
+ throw new PersonalGitHubRepositoryProviderError("invalid_provider_response");
626
+ }
627
+ const payload = value as Record<string, unknown>;
628
+ const repositoryId = providerRepositoryId(payload.id);
629
+ const fullName = requiredProviderString(payload.full_name, 255);
630
+ const defaultBranch = requiredProviderString(payload.default_branch, 255);
631
+ const permissions = payload.permissions;
632
+ if (!permissions || typeof permissions !== "object" || Array.isArray(permissions)) {
633
+ throw new PersonalGitHubRepositoryProviderError("invalid_provider_response");
634
+ }
635
+ const permissionRecord = permissions as Record<string, unknown>;
636
+ const parsed = PersonalGitHubRepository.safeParse({
637
+ repositoryId,
638
+ fullName,
639
+ canonicalUrl: canonicalPersonalGitHubRepositoryUrl(fullName),
640
+ defaultBranch,
641
+ visibility: payload.visibility,
642
+ private: payload.private,
643
+ archived: payload.archived,
644
+ disabled: payload.disabled,
645
+ permissions: {
646
+ pull: permissionRecord.pull,
647
+ push: permissionRecord.push,
648
+ admin: permissionRecord.admin,
649
+ maintain: permissionRecord.maintain,
650
+ triage: permissionRecord.triage,
651
+ },
652
+ });
653
+ if (!parsed.success) {
654
+ throw new PersonalGitHubRepositoryProviderError("invalid_provider_response");
655
+ }
656
+ return parsed.data;
657
+ }
658
+
659
+ function providerRepositoryId(value: unknown): string {
660
+ if (typeof value === "number" && Number.isSafeInteger(value) && value > 0) return String(value);
661
+ if (typeof value === "string" && /^[1-9]\d*$/u.test(value)) return value;
662
+ throw new PersonalGitHubRepositoryProviderError("invalid_provider_response");
663
+ }
664
+
665
+ function requiredProviderString(value: unknown, maxLength: number): string {
666
+ if (typeof value !== "string" || value.length === 0 || value.length > maxLength) {
667
+ throw new PersonalGitHubRepositoryProviderError("invalid_provider_response");
668
+ }
669
+ return value;
670
+ }
671
+
672
+ async function cancelResponse(response: Response): Promise<void> {
673
+ await response.body?.cancel().catch(() => undefined);
674
+ }