@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
@@ -1,10 +1,17 @@
1
+ import { withOrganizationIntegrationAcquisition } from "@opengeni/db/organization-integration-policy";
2
+ import { claimOAuthAcquisition, finishOAuthAcquisition } from "./oauth-client";
3
+ import { safeReturnPath } from "./oauth-return-path";
1
4
  import type { ApiRouteDeps } from "@opengeni/core";
2
5
  import type { Settings } from "@opengeni/config";
6
+ import { createHash } from "node:crypto";
7
+ import { ExternalActorContinuation } from "@opengeni/contracts/external-identities";
8
+ import { requireConnectOwnerAuthority } from "@opengeni/core";
3
9
  import {
4
10
  FIKEN_CREDENTIAL_LABEL,
5
11
  FIKEN_CREDENTIAL_ROLE,
6
12
  FIKEN_PROVIDER_DOMAIN,
7
13
  FikenOAuthStartResponse,
14
+ FikenInstallRequest,
8
15
  type AccessGrant,
9
16
  type ConnectionMetadata,
10
17
  type FikenCompanySummary,
@@ -13,7 +20,6 @@ import {
13
20
  } from "@opengeni/contracts";
14
21
  import {
15
22
  fikenConnectionMetadata,
16
- hasPermission,
17
23
  isFikenConnection,
18
24
  preferredFikenConnection,
19
25
  requireEnvironmentEncryption,
@@ -24,9 +30,12 @@ import {
24
30
  consumeIntegrationOAuthStateNonce,
25
31
  createConnection,
26
32
  encryptEnvironmentValue,
33
+ decryptEnvironmentValue,
34
+ getConnectAttempt,
35
+ finishConnectOperation,
27
36
  getConnectionMetadata,
28
- getWorkspaceGrant,
29
37
  listConnectionsMetadata,
38
+ loadConnectionCredentialForBroker,
30
39
  recordAuditEvent,
31
40
  setConnectionStatus,
32
41
  updateConnection,
@@ -37,8 +46,10 @@ import { readResponseJsonBounded, type FetchLike } from "@opengeni/network";
37
46
  import { HTTPException } from "hono/http-exception";
38
47
  import {
39
48
  integrationBaseUrl,
49
+ oauthStateFailureReturn,
40
50
  oauthStateTtlMs,
41
51
  requireIntegrationsStateSecret,
52
+ workspaceIntegrationsPath,
42
53
  } from "./oauth-client";
43
54
 
44
55
  const FIKEN_API_BASE = "https://api.fiken.no/api/v2";
@@ -54,6 +65,87 @@ const MAX_DRAFT_LINES = 100;
54
65
  // Fiken company slugs as issued by Fiken: lowercase alphanumerics and dashes.
55
66
  const COMPANY_SLUG_PATTERN = /^[a-z0-9][a-z0-9-]{0,127}$/;
56
67
 
68
+ /** Shared native/embedded token adapter. Provider verification happens before
69
+ * persistence; the caller reauthorizes inside its durable commit transaction.
70
+ * That caller must acquire the organization policy fence for `fiken` BEFORE
71
+ * owner/tenancy locks and invoke the returned writer with that exact tx. */
72
+ export async function prepareFikenTokenInstall(
73
+ deps: ApiRouteDeps,
74
+ grant: Pick<AccessGrant, "accountId" | "workspaceId" | "subjectId">,
75
+ raw: unknown,
76
+ expectedVersion?: number,
77
+ ): Promise<(tx: Database) => Promise<ConnectionMetadata>> {
78
+ const payload = FikenInstallRequest.parse(raw);
79
+ await withOrganizationIntegrationAcquisition(deps.db, grant, ["fiken"], async () => {});
80
+ const key = requireEnvironmentEncryption(deps.settings);
81
+ const existing = payload.connectionId
82
+ ? await getConnectionMetadata(deps.db, grant.workspaceId, payload.connectionId, null)
83
+ : null;
84
+ if (payload.connectionId && !existing)
85
+ throw new HTTPException(404, { message: "connection not found" });
86
+ if (existing && !isFikenConnection(existing))
87
+ throw new HTTPException(422, { message: "connectionId is not a Fiken connection" });
88
+ if (expectedVersion !== undefined && existing?.version !== expectedVersion)
89
+ throw new HTTPException(409, { message: "The selected Fiken account changed" });
90
+ const verified = await verifyFikenApiToken(payload.apiToken, deps.fikenFetch ?? fetch);
91
+ const defaultCompanySlug = resolveFikenDefaultCompanySlug({
92
+ requested: payload.defaultCompanySlug ?? null,
93
+ previous: existing
94
+ ? (fikenConnectionMetadata(existing.metadata)?.defaultCompanySlug ?? null)
95
+ : null,
96
+ companies: verified.companies,
97
+ });
98
+ if (payload.defaultCompanySlug && defaultCompanySlug !== payload.defaultCompanySlug)
99
+ throw new HTTPException(422, {
100
+ message: "The selected company is not accessible with this token",
101
+ });
102
+ const metadata = {
103
+ credentialRole: FIKEN_CREDENTIAL_ROLE,
104
+ credentialLabel: FIKEN_CREDENTIAL_LABEL,
105
+ companies: verified.companies,
106
+ defaultCompanySlug,
107
+ verifiedAt: new Date().toISOString(),
108
+ };
109
+ const credentialEncrypted = encryptEnvironmentValue(
110
+ key,
111
+ JSON.stringify(fikenCredentialBundle(payload.apiToken)),
112
+ );
113
+ return async (tx) => {
114
+ if (existing) {
115
+ const updated = await updateConnection(tx, {
116
+ workspaceId: grant.workspaceId,
117
+ connectionId: existing.id,
118
+ visibleToSubjectId: null,
119
+ expectedVersion: existing.version,
120
+ kind: "api_key",
121
+ status: "active",
122
+ credentialEncrypted,
123
+ grantedScopes: [],
124
+ expiresAt: null,
125
+ metadata,
126
+ updatedBySubjectId: grant.subjectId,
127
+ });
128
+ if (!updated)
129
+ throw new HTTPException(409, {
130
+ message: "The Fiken connection changed; reload before retrying",
131
+ });
132
+ return updated;
133
+ }
134
+ return createConnection(tx, {
135
+ accountId: grant.accountId,
136
+ workspaceId: grant.workspaceId,
137
+ subjectId: null,
138
+ providerDomain: FIKEN_PROVIDER_DOMAIN,
139
+ kind: "api_key",
140
+ credentialEncrypted,
141
+ grantedScopes: [],
142
+ expiresAt: null,
143
+ metadata,
144
+ createdBySubjectId: grant.subjectId,
145
+ });
146
+ };
147
+ }
148
+
57
149
  export type FikenOperation =
58
150
  | "companies.list"
59
151
  | "contacts.list"
@@ -102,6 +194,8 @@ type FikenContext = {
102
194
  sessionId: string | null;
103
195
  };
104
196
 
197
+ type FikenProviderAuthorization = () => Promise<boolean | void>;
198
+
105
199
  /**
106
200
  * Fiken allows only a single concurrent API request per credential; concurrent
107
201
  * requests can 429 and repeated violations can get the token banned. Serialize
@@ -281,6 +375,7 @@ export type FikenListInput = {
281
375
 
282
376
  export class FikenClient {
283
377
  private readonly resolveCredential: ReturnType<typeof buildConnectionTokenResolver>;
378
+ private expectedConnectionVersion: number;
284
379
 
285
380
  constructor(
286
381
  private readonly db: Database,
@@ -289,11 +384,22 @@ export class FikenClient {
289
384
  private readonly metadata: FikenConnectionMetadata,
290
385
  private readonly context: FikenContext,
291
386
  private readonly fetchImpl: FetchLike = fetch,
387
+ private readonly authorizeProviderRequest?: FikenProviderAuthorization,
292
388
  ) {
389
+ this.expectedConnectionVersion = connection.version;
293
390
  // OAuth-kind connections refresh through the generic broker; route that
294
- // token-endpoint transport through the same injectable Fiken fetch.
391
+ // token-endpoint transport through the same injectable Fiken fetch. Keep
392
+ // the optional authorization immediately before actual refresh I/O.
393
+ const refreshFetch: FetchLike = this.authorizeProviderRequest
394
+ ? async (input, init) => {
395
+ if ((await this.authorizeProviderRequest?.()) === false) {
396
+ throw new Error("the Fiken credential refresh is no longer authorized");
397
+ }
398
+ return await this.fetchImpl(input, init);
399
+ }
400
+ : fetchImpl;
295
401
  this.resolveCredential = buildConnectionTokenResolver(db, settings, undefined, {
296
- refreshTransport: { fetchImpl },
402
+ refreshTransport: { fetchImpl: refreshFetch },
297
403
  });
298
404
  }
299
405
 
@@ -619,17 +725,27 @@ export class FikenClient {
619
725
  for (const [key, value] of Object.entries(input.query ?? {})) {
620
726
  url.searchParams.set(key, value);
621
727
  }
622
- // Credential resolution (DB read + possible broker refresh) happens
623
- // outside the serialization chain: only the provider HTTP call itself
624
- // must obey Fiken's single-concurrent-request rule.
625
- const headers = await this.headersFor(operation, url.toString());
626
728
  const result = await serializedPerConnection(this.connection.id, async () => {
729
+ const authority = await this.currentAuthority(this.expectedConnectionVersion);
730
+ const credential = await this.credentialFor(operation, url.toString());
731
+ await this.currentAuthority(credential.connectionVersion, authority.authorityGeneration);
732
+ // The adapter callback is a fallible preflight. The canonical
733
+ // credential callback below records the physical-use fact, so it must
734
+ // be the final await before the target fetch.
735
+ if (this.authorizeProviderRequest && (await this.authorizeProviderRequest()) === false) {
736
+ throw new Error("the Fiken provider request is no longer authorized");
737
+ }
738
+ await this.currentAuthority(credential.connectionVersion, authority.authorityGeneration);
739
+ if (credential.authorizeProviderRequest && !(await credential.authorizeProviderRequest())) {
740
+ throw new Error("the Fiken provider request is no longer authorized");
741
+ }
742
+ this.expectedConnectionVersion = credential.connectionVersion;
627
743
  let response: Response;
628
744
  try {
629
745
  response = await this.fetchImpl(url, {
630
746
  method,
631
747
  headers: {
632
- ...headers,
748
+ ...credential.headers,
633
749
  accept: "application/json",
634
750
  ...(input.body !== undefined ? { "content-type": "application/json" } : {}),
635
751
  },
@@ -642,7 +758,7 @@ export class FikenClient {
642
758
  } catch {
643
759
  throw new FikenProviderError("transport_error");
644
760
  }
645
- return await this.readResponse(operation, response);
761
+ return await this.readResponse(operation, response, credential.connectionVersion);
646
762
  });
647
763
  await this.recordAudit(operation, "succeeded");
648
764
  return result;
@@ -655,15 +771,14 @@ export class FikenClient {
655
771
  private async readResponse(
656
772
  operation: FikenOperation,
657
773
  response: Response,
774
+ credentialVersion: number,
658
775
  ): Promise<{ payload: unknown; page: FikenPage | null; locationId: number | null }> {
659
776
  if (response.status === 401) {
660
777
  await response.body?.cancel().catch(() => undefined);
661
- // A 401 after resolution means the credential is genuinely rejected
662
- // (revoked token or revoked OAuth grant). setConnectionStatus is a
663
- // strict version CAS and a broker refresh may have bumped the version
664
- // since this client resolved the row, so re-read the current version
665
- // instead of using the resolution-time snapshot.
666
- await this.markNeedsReauth().catch(() => undefined);
778
+ // Only the exact active credential generation sent on this request may
779
+ // transition. A late 401 must not poison a reconnect or revocation that
780
+ // became current while the provider response was in flight.
781
+ await this.markNeedsReauth(credentialVersion).catch(() => undefined);
667
782
  throw new FikenProviderError("credential_rejected", 401);
668
783
  }
669
784
  if (response.status === 429) {
@@ -699,27 +814,67 @@ export class FikenClient {
699
814
  return { payload, page: pageFromHeaders(response.headers), locationId };
700
815
  }
701
816
 
702
- private async markNeedsReauth(): Promise<void> {
817
+ private async markNeedsReauth(credentialVersion: number): Promise<void> {
703
818
  const current = await getConnectionMetadata(
704
819
  this.db,
705
820
  this.context.workspaceId,
706
821
  this.connection.id,
707
822
  null,
708
823
  );
709
- if (!current || current.status === "needs_reauth") return;
824
+ if (
825
+ !current ||
826
+ current.status !== "active" ||
827
+ current.version !== credentialVersion ||
828
+ !isFikenConnection(current)
829
+ ) {
830
+ return;
831
+ }
710
832
  await setConnectionStatus(
711
833
  this.db,
712
834
  this.context.workspaceId,
713
835
  "needs_reauth",
714
836
  "Fiken rejected the credential",
715
- { id: current.id, version: current.version, subjectId: null },
837
+ { id: current.id, version: credentialVersion, subjectId: null },
716
838
  );
717
839
  }
718
840
 
719
- private async headersFor(
841
+ private async currentAuthority(
842
+ expectedVersion: number,
843
+ expectedAuthorityGeneration?: number,
844
+ ): Promise<{ version: number; authorityGeneration: number }> {
845
+ const current = await loadConnectionCredentialForBroker(this.db, this.settings, {
846
+ workspaceId: this.context.workspaceId,
847
+ connectionId: this.connection.id,
848
+ providerDomain: FIKEN_PROVIDER_DOMAIN,
849
+ kind: this.connection.kind === "oauth2" ? "oauth2" : "api_key",
850
+ subjectId: null,
851
+ ...(expectedAuthorityGeneration !== undefined ? { expectedAuthorityGeneration } : {}),
852
+ });
853
+ if (
854
+ !current ||
855
+ current.accountId !== this.context.accountId ||
856
+ current.workspaceId !== this.context.workspaceId ||
857
+ current.subjectId !== null ||
858
+ current.providerDomain !== FIKEN_PROVIDER_DOMAIN ||
859
+ current.kind !== this.connection.kind ||
860
+ current.status !== "active" ||
861
+ current.version !== expectedVersion ||
862
+ current.authorityGeneration === undefined ||
863
+ !fikenConnectionMetadata(current.metadata)
864
+ ) {
865
+ throw new Error("the Fiken connection authority changed");
866
+ }
867
+ return { version: current.version, authorityGeneration: current.authorityGeneration };
868
+ }
869
+
870
+ private async credentialFor(
720
871
  operation: FikenOperation,
721
872
  destinationUrl: string,
722
- ): Promise<Record<string, string>> {
873
+ ): Promise<{
874
+ headers: Record<string, string>;
875
+ connectionVersion: number;
876
+ authorizeProviderRequest?: () => Promise<boolean>;
877
+ }> {
723
878
  const result = await this.resolveCredential({
724
879
  workspaceId: this.context.workspaceId,
725
880
  serverId: "opengeni-fiken",
@@ -732,10 +887,20 @@ export class FikenClient {
732
887
  },
733
888
  destinationUrl,
734
889
  });
735
- if (result.status !== "ok" || result.connectionId !== this.connection.id) {
890
+ if (
891
+ result.status !== "ok" ||
892
+ result.connectionId !== this.connection.id ||
893
+ result.connectionVersion === undefined
894
+ ) {
736
895
  throw new Error("the Fiken connection needs to be reconnected");
737
896
  }
738
- return result.headers;
897
+ return {
898
+ headers: result.headers,
899
+ connectionVersion: result.connectionVersion,
900
+ ...(result.authorizeProviderRequest
901
+ ? { authorizeProviderRequest: result.authorizeProviderRequest }
902
+ : {}),
903
+ };
739
904
  }
740
905
 
741
906
  private receipt(operation: FikenOperation, operationId?: string) {
@@ -771,7 +936,12 @@ export class FikenClient {
771
936
  }
772
937
 
773
938
  export function createFikenClient(
774
- deps: { db: Database; settings: Settings; fikenFetch?: typeof fetch },
939
+ deps: {
940
+ db: Database;
941
+ settings: Settings;
942
+ fikenFetch?: typeof fetch;
943
+ authorizeProviderRequest?: FikenProviderAuthorization;
944
+ },
775
945
  resolved: Awaited<ReturnType<typeof resolveFikenConnectionForTool>>,
776
946
  ): FikenClient {
777
947
  return new FikenClient(
@@ -781,6 +951,7 @@ export function createFikenClient(
781
951
  resolved.metadata,
782
952
  resolved.context,
783
953
  deps.fikenFetch,
954
+ deps.authorizeProviderRequest,
784
955
  );
785
956
  }
786
957
 
@@ -898,6 +1069,8 @@ export class FikenOAuthCallbackError extends Error {
898
1069
  }
899
1070
 
900
1071
  type FikenOAuthState = {
1072
+ externalContinuation?: ExternalActorContinuation;
1073
+ connectAttemptId?: string;
901
1074
  accountId: string;
902
1075
  workspaceId: string;
903
1076
  subjectId: string;
@@ -931,8 +1104,11 @@ export async function startFikenOAuth(
931
1104
  subjectId: string;
932
1105
  requestUrl: string;
933
1106
  payload: FikenOAuthStartRequest;
1107
+ externalContinuation?: ExternalActorContinuation;
1108
+ connectAttemptId?: string;
934
1109
  },
935
1110
  ): Promise<FikenOAuthStartResponse> {
1111
+ await withOrganizationIntegrationAcquisition(deps.db, input, ["fiken"], async () => {});
936
1112
  const fiken = requireFikenOAuthSettings(deps.settings);
937
1113
  const existing = input.payload.connectionId
938
1114
  ? await getConnectionMetadata(deps.db, input.workspaceId, input.payload.connectionId, null)
@@ -948,7 +1124,18 @@ export async function startFikenOAuth(
948
1124
  accountId: input.accountId,
949
1125
  workspaceId: input.workspaceId,
950
1126
  subjectId: input.subjectId,
951
- returnPath: `/workspaces/${input.workspaceId}/capabilities`,
1127
+ returnPath: safeReturnPath(
1128
+ input.payload.returnPath ?? workspaceIntegrationsPath(input.workspaceId),
1129
+ ),
1130
+ ...(input.connectAttemptId ? { connectAttemptId: input.connectAttemptId } : {}),
1131
+ ...(input.externalContinuation
1132
+ ? {
1133
+ encryptedExternalContinuation: encryptEnvironmentValue(
1134
+ requireEnvironmentEncryption(deps.settings),
1135
+ JSON.stringify(ExternalActorContinuation.parse(input.externalContinuation)),
1136
+ ),
1137
+ }
1138
+ : {}),
952
1139
  ...(existing ? { connectionId: existing.id, connectionVersion: existing.version } : {}),
953
1140
  });
954
1141
  const authorizationUrl = new URL(FIKEN_AUTHORIZE_URL);
@@ -970,12 +1157,38 @@ export async function completeFikenOAuthCallback(
970
1157
  error?: string | undefined;
971
1158
  requestUrl: string;
972
1159
  },
973
- ): Promise<{ redirectTo: string }> {
1160
+ ): Promise<{ redirectTo: string; exactReturn?: boolean }> {
974
1161
  const baseUrl = integrationBaseUrl(deps.settings.publicBaseUrl, input.requestUrl);
975
1162
  const returnBaseUrl = deps.settings.webBaseUrl?.replace(/\/+$/, "") ?? baseUrl;
976
1163
  let state: FikenOAuthState | null = null;
1164
+ let exactReturnUrl: string | undefined;
1165
+ let operation: { attemptId: string; operationId: string; inputDigest: string } | undefined;
977
1166
  try {
978
1167
  state = readFikenOAuthState(input.state, deps.settings);
1168
+ if (state.connectAttemptId) {
1169
+ const stored = await getConnectAttempt(deps.db, state, state.connectAttemptId);
1170
+ if (stored.attempt.providerId !== "fiken-oauth" || stored.attempt.ownership !== "workspace")
1171
+ throw new FikenOAuthCallbackError("invalid_state");
1172
+ exactReturnUrl = stored.returnUrl;
1173
+ operation = {
1174
+ attemptId: state.connectAttemptId,
1175
+ operationId: `oauth:${state.nonce}`,
1176
+ inputDigest: createHash("sha256").update(input.state!).digest("hex"),
1177
+ };
1178
+ const claim = await claimOAuthAcquisition(
1179
+ deps.db,
1180
+ state,
1181
+ {
1182
+ ...operation,
1183
+ expectedRevision: stored.attempt.revision,
1184
+ authorize: (tx, _attempt, origin) =>
1185
+ requireConnectOwnerAuthority(tx, state!, "connections:write", origin),
1186
+ },
1187
+ "fiken",
1188
+ Boolean(input.code && !input.error),
1189
+ );
1190
+ if (claim.status === "replayed") return { redirectTo: exactReturnUrl, exactReturn: true };
1191
+ }
979
1192
  await requireFikenCallbackGrant(deps.db, state);
980
1193
  const consumed = await consumeIntegrationOAuthStateNonce(deps.db, {
981
1194
  accountId: state.accountId,
@@ -988,6 +1201,27 @@ export async function completeFikenOAuthCallback(
988
1201
  if (!consumed) {
989
1202
  throw new FikenOAuthCallbackError("state_replayed");
990
1203
  }
1204
+ // A proven pre-exchange rejection is terminal, not an uncertain provider
1205
+ // effect. Persist its receipt so repeated browser callbacks cannot retry it.
1206
+ if (operation && (input.error || !input.code)) {
1207
+ await finishConnectOperation(deps.db, state, {
1208
+ ...operation,
1209
+ authorize: (tx, _attempt, origin) =>
1210
+ requireConnectOwnerAuthority(tx, state!, "connections:write", origin),
1211
+ commit: async (_tx, current) => ({
1212
+ ...current,
1213
+ revision: current.revision + 1,
1214
+ state: input.error === "access_denied" ? "cancelled" : "failed",
1215
+ nextAction: { type: "none" },
1216
+ error: {
1217
+ code: input.error ? "provider_denied" : "missing_code",
1218
+ message: "Authorization was not completed. Start a new connection attempt.",
1219
+ retryable: false,
1220
+ },
1221
+ }),
1222
+ });
1223
+ return { redirectTo: exactReturnUrl!, exactReturn: true };
1224
+ }
991
1225
  if (input.error) {
992
1226
  throw new FikenOAuthCallbackError(
993
1227
  input.error === "access_denied" ? "provider_denied" : "provider_error",
@@ -996,6 +1230,7 @@ export async function completeFikenOAuthCallback(
996
1230
  if (!input.code) {
997
1231
  throw new FikenOAuthCallbackError("missing_code");
998
1232
  }
1233
+ await withOrganizationIntegrationAcquisition(deps.db, state, ["fiken"], async () => {});
999
1234
  const fiken = requireFikenOAuthSettings(deps.settings);
1000
1235
  const key = requireEnvironmentEncryption(deps.settings);
1001
1236
  const fetchImpl = deps.fikenFetch ?? fetch;
@@ -1052,34 +1287,76 @@ export async function completeFikenOAuthCallback(
1052
1287
  defaultCompanySlug,
1053
1288
  verifiedAt: new Date().toISOString(),
1054
1289
  };
1055
- const connection = existing
1056
- ? await updateConnection(deps.db, {
1057
- workspaceId: state.workspaceId,
1058
- connectionId: existing.id,
1059
- visibleToSubjectId: null,
1060
- expectedVersion: existing.version,
1061
- kind: "oauth2",
1062
- status: "active",
1063
- credentialEncrypted,
1064
- expiresAt: token.expiresAt,
1065
- metadata,
1066
- updatedBySubjectId: state.subjectId,
1067
- })
1068
- : await createConnection(deps.db, {
1069
- accountId: state.accountId,
1070
- workspaceId: state.workspaceId,
1071
- // Workspace-owned by design, like the pasted-token install: the
1072
- // first-party fiken tools resolve only workspace connections until
1073
- // the delegation-snapshot lane exists for personal ownership.
1074
- subjectId: null,
1075
- providerDomain: FIKEN_PROVIDER_DOMAIN,
1076
- kind: "oauth2",
1077
- credentialEncrypted,
1078
- grantedScopes: [],
1079
- expiresAt: token.expiresAt,
1080
- metadata,
1081
- createdBySubjectId: state.subjectId,
1082
- });
1290
+ const persist = (tx: Database) =>
1291
+ existing
1292
+ ? updateConnection(tx, {
1293
+ workspaceId: state!.workspaceId,
1294
+ connectionId: existing.id,
1295
+ visibleToSubjectId: null,
1296
+ expectedVersion: existing.version,
1297
+ kind: "oauth2",
1298
+ status: "active",
1299
+ credentialEncrypted,
1300
+ expiresAt: token.expiresAt,
1301
+ metadata,
1302
+ updatedBySubjectId: state!.subjectId,
1303
+ })
1304
+ : createConnection(tx, {
1305
+ accountId: state!.accountId,
1306
+ workspaceId: state!.workspaceId,
1307
+ // Workspace-owned by design, like the pasted-token install: the
1308
+ // first-party fiken tools resolve only workspace connections until
1309
+ // the delegation-snapshot lane exists for personal ownership.
1310
+ subjectId: null,
1311
+ providerDomain: FIKEN_PROVIDER_DOMAIN,
1312
+ kind: "oauth2",
1313
+ credentialEncrypted,
1314
+ grantedScopes: [],
1315
+ expiresAt: token.expiresAt,
1316
+ metadata,
1317
+ createdBySubjectId: state!.subjectId,
1318
+ });
1319
+ if (operation) {
1320
+ await finishOAuthAcquisition(
1321
+ deps.db,
1322
+ state,
1323
+ {
1324
+ ...operation,
1325
+ authorize: (tx, _attempt, origin) =>
1326
+ requireConnectOwnerAuthority(tx, state!, "connections:write", origin),
1327
+ commit: async (tx, current) => {
1328
+ const connection = await persist(tx);
1329
+ if (!connection) throw new FikenOAuthCallbackError("connection_conflict");
1330
+ return {
1331
+ ...current,
1332
+ revision: current.revision + 1,
1333
+ state: "complete",
1334
+ credentialsCommitted: true,
1335
+ nextAction: { type: "none" },
1336
+ account: {
1337
+ id: connection.id,
1338
+ version: connection.version,
1339
+ providerId: "fiken-oauth",
1340
+ label: "Fiken",
1341
+ ownership: "workspace",
1342
+ status: "connected",
1343
+ },
1344
+ };
1345
+ },
1346
+ },
1347
+ "fiken",
1348
+ );
1349
+ return { redirectTo: exactReturnUrl!, exactReturn: true };
1350
+ }
1351
+ const connection = await withOrganizationIntegrationAcquisition(
1352
+ deps.db,
1353
+ state,
1354
+ ["fiken"],
1355
+ async (tx) => {
1356
+ await requireFikenCallbackGrant(tx, state!);
1357
+ return persist(tx);
1358
+ },
1359
+ );
1083
1360
  if (!connection) {
1084
1361
  throw new FikenOAuthCallbackError("connection_conflict");
1085
1362
  }
@@ -1087,12 +1364,17 @@ export async function completeFikenOAuthCallback(
1087
1364
  redirectTo: fikenReturnUrl(returnBaseUrl, state.returnPath, "connected", connection.id),
1088
1365
  };
1089
1366
  } catch (error) {
1367
+ if (exactReturnUrl) return { redirectTo: exactReturnUrl, exactReturn: true };
1368
+ // Reading the state is the first step, so no state means the link itself
1369
+ // was unusable: say whether it expired instead of suggesting a token.
1370
+ const failure = state ? null : oauthStateFailureReturn(deps.settings, input.state);
1090
1371
  return {
1091
1372
  redirectTo: fikenReturnUrl(
1092
1373
  returnBaseUrl,
1093
- state?.returnPath ?? "/integrations",
1374
+ state?.returnPath ?? failure!.returnPath,
1094
1375
  "error",
1095
- error instanceof FikenOAuthCallbackError ? error.reason : "callback_failed",
1376
+ failure?.reason ??
1377
+ (error instanceof FikenOAuthCallbackError ? error.reason : "callback_failed"),
1096
1378
  ),
1097
1379
  };
1098
1380
  }
@@ -1190,6 +1472,21 @@ function readFikenOAuthState(raw: string | undefined, settings: Settings): Fiken
1190
1472
  workspaceId: required(payload.workspaceId),
1191
1473
  subjectId: required(payload.subjectId),
1192
1474
  returnPath: required(payload.returnPath),
1475
+ ...(typeof payload.connectAttemptId === "string"
1476
+ ? { connectAttemptId: required(payload.connectAttemptId) }
1477
+ : {}),
1478
+ ...(typeof payload.encryptedExternalContinuation === "string"
1479
+ ? {
1480
+ externalContinuation: ExternalActorContinuation.parse(
1481
+ JSON.parse(
1482
+ decryptEnvironmentValue(
1483
+ requireEnvironmentEncryption(settings),
1484
+ payload.encryptedExternalContinuation,
1485
+ ),
1486
+ ),
1487
+ ),
1488
+ }
1489
+ : {}),
1193
1490
  ...(typeof payload.connectionId === "string" ? { connectionId: payload.connectionId } : {}),
1194
1491
  ...(typeof payload.connectionVersion === "number"
1195
1492
  ? { connectionVersion: payload.connectionVersion }
@@ -1200,14 +1497,7 @@ function readFikenOAuthState(raw: string | undefined, settings: Settings): Fiken
1200
1497
  }
1201
1498
 
1202
1499
  async function requireFikenCallbackGrant(db: Database, state: FikenOAuthState): Promise<void> {
1203
- const grant = await getWorkspaceGrant(db, state.subjectId, state.workspaceId);
1204
- if (
1205
- !grant ||
1206
- grant.accountId !== state.accountId ||
1207
- !hasPermission(grant.permissions, "connections:write")
1208
- ) {
1209
- throw new FikenOAuthCallbackError("permission_lost");
1210
- }
1500
+ await requireConnectOwnerAuthority(db, state);
1211
1501
  }
1212
1502
 
1213
1503
  function fikenReturnUrl(