@opengeni/api-router 3.0.1 → 3.1.2

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 (546) hide show
  1. package/dist/access-grant-rls.d.ts +8 -1
  2. package/dist/admission-trace.d.ts +8 -0
  3. package/dist/app.d.ts +50 -3
  4. package/dist/app.js +10 -1
  5. package/dist/artifact-catalog-cursor.d.ts +1 -0
  6. package/dist/attached-browser-viewer.d.ts +11 -0
  7. package/dist/auth/managed-auth-attempt-context.d.ts +2 -0
  8. package/dist/auth/managed-auth-rate-limits.d.ts +167 -0
  9. package/dist/auth/managed-auth-session-adapter.d.ts +9 -1
  10. package/dist/auth/managed-auth.d.ts +72 -5
  11. package/dist/auth/managed-sign-in-notifications.d.ts +4 -0
  12. package/dist/auth/new-signups-gate.d.ts +23 -0
  13. package/dist/auth/signup-funnel-metrics.d.ts +44 -0
  14. package/dist/azure-live.d.ts +28 -0
  15. package/dist/browser-action-fences.d.ts +13 -0
  16. package/dist/browser-controller-authority.d.ts +1 -61
  17. package/dist/browser-ephemeral.d.ts +5 -0
  18. package/dist/browser-lost-runtime-end.d.ts +24 -0
  19. package/dist/browser-state-authority.d.ts +1 -27
  20. package/dist/chunk-OGQDXVXY.js +18 -0
  21. package/dist/chunk-OGQDXVXY.js.map +1 -0
  22. package/dist/{chunk-AJ62T5QN.js → chunk-OT56OY4V.js} +80503 -39869
  23. package/dist/chunk-OT56OY4V.js.map +1 -0
  24. package/dist/claude-default-models.d.ts +19 -0
  25. package/dist/claude-subscription-core.d.ts +50 -0
  26. package/dist/claude-subscription-oauth.d.ts +36 -0
  27. package/dist/claude-subscription-profile.d.ts +9 -0
  28. package/dist/claude-subscription-usage.d.ts +6 -0
  29. package/dist/claude-workspace-connection.d.ts +15 -0
  30. package/dist/codemode.d.ts +40 -5
  31. package/dist/codex-realtime.d.ts +29 -3
  32. package/dist/codex-session-pointers.d.ts +19 -0
  33. package/dist/connection-ownership.d.ts +6 -3
  34. package/dist/controller-data-plane.d.ts +16 -0
  35. package/dist/credit-promotion-snapshot.d.ts +6 -0
  36. package/dist/editable-artifact-source-session.d.ts +3 -0
  37. package/dist/editable-artifact-websocket.d.ts +5 -3
  38. package/dist/fatal-process-boundary.d.ts +9 -1
  39. package/dist/github-access.d.ts +7 -1
  40. package/dist/github-browser-flow.d.ts +1 -1
  41. package/dist/http/acting-person.d.ts +36 -0
  42. package/dist/http/api-contract-compat.d.ts +19 -0
  43. package/dist/http/api-error.d.ts +50 -1
  44. package/dist/http/auth.d.ts +8 -1
  45. package/dist/http/cors.d.ts +12 -0
  46. package/dist/http/deprecation.d.ts +42 -0
  47. package/dist/http/keyed-admission.d.ts +12 -0
  48. package/dist/http/local-browser-boundary.d.ts +72 -0
  49. package/dist/http/metrics-listener.d.ts +22 -0
  50. package/dist/http/path-identifier.d.ts +17 -0
  51. package/dist/http/registered-route-label.d.ts +16 -0
  52. package/dist/http/rejection-telemetry.d.ts +34 -0
  53. package/dist/http/request-body.d.ts +27 -0
  54. package/dist/http/request-source.d.ts +41 -3
  55. package/dist/http/sse.d.ts +12 -1
  56. package/dist/http/unmatched-route.d.ts +18 -0
  57. package/dist/http/user-content.d.ts +36 -0
  58. package/dist/http/variable-sets-removed.d.ts +41 -0
  59. package/dist/http/websocket-upgrade-dispatch.d.ts +18 -0
  60. package/dist/index.js +1279 -108
  61. package/dist/index.js.map +1 -1
  62. package/dist/integration-connect-metrics.d.ts +35 -0
  63. package/dist/integration-endpoint-test.d.ts +20 -0
  64. package/dist/integrations/api-integrations.d.ts +2 -2
  65. package/dist/integrations/atlassian.d.ts +8 -3
  66. package/dist/integrations/fiken.d.ts +3 -1
  67. package/dist/integrations/github-lens-connect.d.ts +37 -66
  68. package/dist/integrations/google-drive.d.ts +2 -0
  69. package/dist/integrations/integration-commit-authority.d.ts +13 -0
  70. package/dist/integrations/marketplace-plugin.d.ts +43 -43
  71. package/dist/integrations/oauth-client.d.ts +171 -12
  72. package/dist/integrations/oauth-profiles.d.ts +42 -13
  73. package/dist/integrations/onepassword-vault-provider.d.ts +9 -0
  74. package/dist/integrations/slack-bot.d.ts +285 -7
  75. package/dist/integrations/slack-file-upload-flow.d.ts +62 -0
  76. package/dist/integrations/slack-interactions.d.ts +89 -10
  77. package/dist/integrations/slack-mrkdwn.d.ts +41 -0
  78. package/dist/integrations/slack-routing.d.ts +1 -1
  79. package/dist/integrations/slack-session-defaults.d.ts +58 -0
  80. package/dist/integrations/slack-task-file-upload.d.ts +36 -0
  81. package/dist/integrations/slack-tool-review.d.ts +5 -0
  82. package/dist/interaction-agent-access.d.ts +13 -8
  83. package/dist/interaction-agent-version.d.ts +21 -0
  84. package/dist/interaction-holder-heartbeat.d.ts +5 -0
  85. package/dist/interaction-metrics.d.ts +27 -2
  86. package/dist/interaction-route-stages.d.ts +25 -0
  87. package/dist/interaction-secrets-vault.d.ts +20 -0
  88. package/dist/interaction-secrets.d.ts +103 -0
  89. package/dist/mcp/action-catalog-types.d.ts +14 -0
  90. package/dist/mcp/action-catalog.gen.d.ts +2 -0
  91. package/dist/mcp/action-descriptions.d.ts +4 -0
  92. package/dist/mcp/action-schema-imports.gen.d.ts +1 -0
  93. package/dist/mcp/capability-account-readiness.d.ts +7 -0
  94. package/dist/mcp/child-read-evidence.d.ts +9 -0
  95. package/dist/mcp/company-profile-agent-admin.d.ts +12 -0
  96. package/dist/mcp/contract-input.d.ts +13 -0
  97. package/dist/mcp/documents.d.ts +2 -0
  98. package/dist/mcp/first-party-tool-permissions.d.ts +3 -606
  99. package/dist/mcp/notification-tools.d.ts +26 -0
  100. package/dist/mcp/orchestration-failure-diagnostic.d.ts +43 -0
  101. package/dist/mcp/scheduled-task-input.d.ts +1309 -0
  102. package/dist/mcp/scheduled-task-view.d.ts +217 -3
  103. package/dist/mcp/secret-tools.d.ts +14 -0
  104. package/dist/mcp/server.d.ts +108 -5
  105. package/dist/mcp/session-admin-access-tools.d.ts +33 -0
  106. package/dist/mcp/session-event-errors.d.ts +28 -0
  107. package/dist/mcp/session-event-view.d.ts +62 -0
  108. package/dist/mcp/session-view.d.ts +15 -0
  109. package/dist/mcp/session-wait.d.ts +18 -0
  110. package/dist/mcp/site-agent-clamp-tools.d.ts +38 -0
  111. package/dist/mcp/site-data-tools.d.ts +22 -0
  112. package/dist/mcp/site-publication-tools.d.ts +19 -0
  113. package/dist/mcp/site-sql-tools.d.ts +27 -0
  114. package/dist/mcp-oauth.d.ts +37 -4
  115. package/dist/model-calls/chat-completions.d.ts +87 -0
  116. package/dist/model-calls/pending-usage-settlements.d.ts +57 -0
  117. package/dist/model-calls/service.d.ts +36 -0
  118. package/dist/model-catalog.d.ts +9 -3
  119. package/dist/native-push-dispatch.d.ts +69 -0
  120. package/dist/observability.d.ts +3 -1
  121. package/dist/organization-mcp.d.ts +82 -0
  122. package/dist/prepared-mcp-actor.d.ts +77 -0
  123. package/dist/prepared-mcp-permissions.d.ts +8 -0
  124. package/dist/routes/analytics-consent.d.ts +26 -0
  125. package/dist/routes/api-integrations.d.ts +11 -0
  126. package/dist/routes/api-keys.d.ts +7 -7
  127. package/dist/routes/automations.d.ts +2 -0
  128. package/dist/routes/billing.d.ts +59 -0
  129. package/dist/routes/browser-sessions.d.ts +65 -2
  130. package/dist/routes/chat-completions.d.ts +11 -0
  131. package/dist/routes/claude-core-usage.d.ts +20 -0
  132. package/dist/routes/claude-subscription-accounts.d.ts +3 -0
  133. package/dist/routes/claude-subscription-oauth.d.ts +3 -0
  134. package/dist/routes/client-errors.d.ts +182 -0
  135. package/dist/routes/codex-core.d.ts +401 -0
  136. package/dist/routes/codex.d.ts +64 -2
  137. package/dist/routes/computer-sessions.d.ts +6 -1
  138. package/dist/routes/desktop-distribution.d.ts +32 -0
  139. package/dist/routes/github-browser-fonts.gen.d.ts +2 -0
  140. package/dist/routes/github-browser-pages.d.ts +27 -0
  141. package/dist/routes/inbox.d.ts +13 -0
  142. package/dist/routes/insights-response-cache.d.ts +10 -0
  143. package/dist/routes/insights-usage.d.ts +12 -0
  144. package/dist/routes/insights.d.ts +28 -0
  145. package/dist/routes/interaction-placement-message.d.ts +7 -0
  146. package/dist/routes/managed-sign-in-methods.d.ts +6 -0
  147. package/dist/routes/model-account-choice.d.ts +13 -0
  148. package/dist/routes/model-account-settings.d.ts +19 -0
  149. package/dist/routes/native-app-auth.d.ts +12 -0
  150. package/dist/routes/organization-integration-policy.d.ts +8 -0
  151. package/dist/routes/organization-integrations.d.ts +6 -0
  152. package/dist/routes/organization-mcp-connections.d.ts +3 -0
  153. package/dist/routes/organization-model-defaults.d.ts +9 -0
  154. package/dist/routes/organization-service-accounts.d.ts +3 -0
  155. package/dist/routes/personal-api-keys.d.ts +3 -0
  156. package/dist/routes/session-admin-access.d.ts +3 -0
  157. package/dist/routes/session-artifact-associations.d.ts +4 -0
  158. package/dist/routes/session-history-imports.d.ts +20 -0
  159. package/dist/routes/sessions.d.ts +38 -2
  160. package/dist/routes/site-data.d.ts +18 -0
  161. package/dist/routes/site-publishing.d.ts +5 -0
  162. package/dist/routes/site-runtime.d.ts +31 -0
  163. package/dist/routes/site-sql.d.ts +16 -0
  164. package/dist/routes/slack-bot-access.d.ts +3 -0
  165. package/dist/routes/subscription-account-pools.d.ts +21 -0
  166. package/dist/routes/subscription-core-http.d.ts +5 -0
  167. package/dist/routes/subscription-pool-access.d.ts +37 -0
  168. package/dist/routes/subscription-pool-core.d.ts +153 -0
  169. package/dist/routes/supergrok.d.ts +6 -6
  170. package/dist/routes/usage-allowances.d.ts +12 -0
  171. package/dist/routes/variable-sets-removed.d.ts +2 -0
  172. package/dist/routes/vault-providers.d.ts +34 -0
  173. package/dist/routes/vaults.d.ts +3 -0
  174. package/dist/routes/workspace-integrations.d.ts +35 -0
  175. package/dist/routes/workspace-model-providers.d.ts +4 -0
  176. package/dist/routes/workspaces.d.ts +11 -2
  177. package/dist/sandbox/agent-update.d.ts +64 -0
  178. package/dist/sandbox/auth-callout.d.ts +8 -0
  179. package/dist/sandbox/channel-a.d.ts +15 -1
  180. package/dist/sandbox/enrollment.d.ts +26 -4
  181. package/dist/sandbox/machine-audience.d.ts +29 -0
  182. package/dist/sandbox/machines.d.ts +15 -2
  183. package/dist/sandbox/metrics-ingestion.d.ts +6 -2
  184. package/dist/sandbox/screen-control.d.ts +85 -0
  185. package/dist/sandbox/viewer.d.ts +5 -1
  186. package/dist/sandbox-file-artifacts.d.ts +17 -1
  187. package/dist/scheduled-task-blockers.d.ts +39 -0
  188. package/dist/scheduled-task-deletion.d.ts +3 -4
  189. package/dist/scheduled-task-lifecycle.d.ts +14 -0
  190. package/dist/secret-answers.d.ts +40 -0
  191. package/dist/session-create-observability.d.ts +5 -0
  192. package/dist/session-event-view-36GO3IL7.js +528 -0
  193. package/dist/session-event-view-36GO3IL7.js.map +1 -0
  194. package/dist/signed-state-secret.d.ts +18 -0
  195. package/dist/site-agent-guard.d.ts +53 -0
  196. package/dist/site-data/operations.d.ts +103 -0
  197. package/dist/site-data/service.d.ts +203 -0
  198. package/dist/site-frame-guard.d.ts +32 -0
  199. package/dist/site-publishing/agent-data-tools.d.ts +84 -0
  200. package/dist/site-publishing/agent-model.d.ts +58 -0
  201. package/dist/site-publishing/agent-session.d.ts +16 -0
  202. package/dist/site-publishing/content-scanner.d.ts +31 -0
  203. package/dist/site-publishing/edge-sync.d.ts +48 -0
  204. package/dist/site-publishing/gateway-signature.d.ts +56 -0
  205. package/dist/site-publishing/limits.d.ts +63 -0
  206. package/dist/site-publishing/page-tool-authority.d.ts +30 -0
  207. package/dist/site-publishing/platform-usage.d.ts +113 -0
  208. package/dist/site-publishing/platform.d.ts +21 -0
  209. package/dist/site-publishing/readiness.d.ts +62 -0
  210. package/dist/site-publishing/runtime.d.ts +179 -0
  211. package/dist/site-publishing/service.d.ts +264 -0
  212. package/dist/site-publishing/session-events.d.ts +22 -0
  213. package/dist/site-publishing/session-views.d.ts +36 -0
  214. package/dist/site-publishing/viewer.d.ts +40 -0
  215. package/dist/site-session-origin.d.ts +31 -6
  216. package/dist/site-sql/format.d.ts +47 -0
  217. package/dist/site-sql/gateway.d.ts +50 -0
  218. package/dist/site-sql/service.d.ts +213 -0
  219. package/dist/temporal-schedule-sync.d.ts +26 -0
  220. package/dist/transcription/billing-refusal.d.ts +8 -0
  221. package/dist/transcription/normalize.d.ts +23 -0
  222. package/dist/transcription/providers/azure-mai.d.ts +12 -0
  223. package/dist/transcription/providers/azure-openai.d.ts +4 -0
  224. package/dist/transcription/providers/openai.d.ts +16 -0
  225. package/dist/transcription/providers/subscription-core.d.ts +39 -0
  226. package/dist/transcription/service.d.ts +10 -1
  227. package/dist/transcription/wav-duration.d.ts +8 -0
  228. package/dist/workspace-tool-gateway-attestations.d.ts +37 -0
  229. package/dist/workspace-tool-gateway-observability.d.ts +16 -0
  230. package/dist/workspace-tool-gateway-secrets.d.ts +27 -0
  231. package/dist/workspace-tool-gateway.d.ts +102 -6
  232. package/dist/workspace-tool-target-fence.d.ts +116 -0
  233. package/dist/workspace-tool-target.d.ts +225 -0
  234. package/dist/workspace-webhook-dispatch.d.ts +26 -0
  235. package/dist/xai-subscription-core.d.ts +60 -0
  236. package/package.json +25 -20
  237. package/src/access-grant-rls.ts +64 -14
  238. package/src/admission-trace.ts +14 -0
  239. package/src/app.ts +1684 -252
  240. package/src/artifact-catalog-cursor.ts +1 -0
  241. package/src/attached-browser-viewer.ts +26 -0
  242. package/src/auth/managed-auth-attempt-context.ts +9 -0
  243. package/src/auth/managed-auth-rate-limits.ts +252 -0
  244. package/src/auth/managed-auth-session-adapter.ts +64 -29
  245. package/src/auth/managed-auth.ts +303 -35
  246. package/src/auth/managed-email.ts +18 -1
  247. package/src/auth/managed-sign-in-notifications.ts +81 -0
  248. package/src/auth/new-signups-gate.ts +49 -0
  249. package/src/auth/organization-user-setup.ts +3 -3
  250. package/src/auth/signup-funnel-metrics.ts +164 -0
  251. package/src/azure-live.ts +103 -0
  252. package/src/browser-action-fences.ts +45 -0
  253. package/src/browser-controller-authority.ts +1 -186
  254. package/src/browser-ephemeral.ts +39 -0
  255. package/src/browser-lost-runtime-end.ts +71 -0
  256. package/src/browser-state-authority.ts +1 -236
  257. package/src/claude-default-models.ts +37 -0
  258. package/src/claude-subscription-core.ts +154 -0
  259. package/src/claude-subscription-oauth.ts +352 -0
  260. package/src/claude-subscription-profile.ts +73 -0
  261. package/src/claude-subscription-usage.ts +51 -0
  262. package/src/claude-workspace-connection.ts +82 -0
  263. package/src/codemode.ts +236 -39
  264. package/src/codex-realtime.ts +181 -53
  265. package/src/codex-session-pointers.ts +80 -0
  266. package/src/company-brain-okf.ts +1 -1
  267. package/src/connected-machine-computer-access.ts +2 -1
  268. package/src/connection-ownership.ts +19 -13
  269. package/src/controller-data-plane.ts +34 -0
  270. package/src/credit-promotion-snapshot.ts +36 -0
  271. package/src/editable-artifact-production.ts +10 -0
  272. package/src/editable-artifact-source-session.ts +123 -0
  273. package/src/editable-artifact-websocket.ts +16 -3
  274. package/src/fatal-process-boundary.ts +67 -3
  275. package/src/gateway-realtime.ts +12 -8
  276. package/src/github-access.ts +31 -5
  277. package/src/github-browser-flow.ts +1 -1
  278. package/src/http/acting-person.ts +105 -0
  279. package/src/http/api-contract-compat.ts +49 -0
  280. package/src/http/api-error.ts +210 -2
  281. package/src/http/auth.ts +68 -4
  282. package/src/http/cors.ts +37 -5
  283. package/src/http/deprecation.ts +118 -0
  284. package/src/http/keyed-admission.ts +29 -0
  285. package/src/http/local-browser-boundary.ts +343 -0
  286. package/src/http/metrics-listener.ts +57 -0
  287. package/src/http/path-identifier.ts +54 -0
  288. package/src/http/registered-route-label.ts +34 -0
  289. package/src/http/rejection-telemetry.ts +120 -0
  290. package/src/http/request-body.ts +127 -0
  291. package/src/http/request-source.ts +154 -13
  292. package/src/http/sse.ts +88 -28
  293. package/src/http/unmatched-route.ts +60 -0
  294. package/src/http/user-content.ts +158 -0
  295. package/src/http/variable-sets-removed.ts +122 -0
  296. package/src/http/websocket-upgrade-dispatch.ts +29 -0
  297. package/src/index.ts +107 -57
  298. package/src/integration-connect-metrics.ts +228 -0
  299. package/src/integration-endpoint-test.ts +291 -0
  300. package/src/integrations/api-integrations.ts +81 -7
  301. package/src/integrations/atlassian.ts +202 -83
  302. package/src/integrations/fiken.ts +66 -38
  303. package/src/integrations/github-app-connect.ts +64 -18
  304. package/src/integrations/github-lens-connect.ts +8 -29
  305. package/src/integrations/google-drive.ts +448 -152
  306. package/src/integrations/integration-commit-authority.ts +69 -0
  307. package/src/integrations/marketplace-plugin.ts +1 -1
  308. package/src/integrations/oauth-client.ts +733 -193
  309. package/src/integrations/oauth-profiles.ts +116 -45
  310. package/src/integrations/onepassword-vault-provider.ts +16 -0
  311. package/src/integrations/personal-github-repositories.ts +1 -1
  312. package/src/integrations/personal-github.ts +61 -35
  313. package/src/integrations/provider-oauth.ts +67 -85
  314. package/src/integrations/slack-app-home.ts +5 -5
  315. package/src/integrations/slack-bot.ts +893 -201
  316. package/src/integrations/slack-file-upload-flow.ts +147 -0
  317. package/src/integrations/slack-install.ts +7 -7
  318. package/src/integrations/slack-interactions.ts +1589 -299
  319. package/src/integrations/slack-mrkdwn.ts +193 -0
  320. package/src/integrations/slack-routing.ts +2 -2
  321. package/src/integrations/slack-session-defaults.ts +224 -0
  322. package/src/integrations/slack-task-file-upload.ts +323 -0
  323. package/src/integrations/slack-tool-review.ts +65 -0
  324. package/src/integrations/social-oauth.ts +90 -58
  325. package/src/interaction-agent-access.ts +40 -20
  326. package/src/interaction-agent-version.ts +85 -0
  327. package/src/interaction-holder-heartbeat.ts +24 -8
  328. package/src/interaction-metrics.ts +164 -2
  329. package/src/interaction-route-stages.ts +94 -0
  330. package/src/interaction-secrets-vault.ts +213 -0
  331. package/src/interaction-secrets.ts +426 -0
  332. package/src/mcp/action-catalog-types.ts +14 -0
  333. package/src/mcp/action-catalog.gen.ts +8014 -0
  334. package/src/mcp/action-descriptions.ts +299 -0
  335. package/src/mcp/action-schema-imports.gen.ts +304 -0
  336. package/src/mcp/capability-account-readiness.ts +17 -0
  337. package/src/mcp/child-read-evidence.ts +19 -0
  338. package/src/mcp/company-profile-agent-admin.ts +13 -0
  339. package/src/mcp/contract-input.ts +165 -0
  340. package/src/mcp/documents.ts +9 -2
  341. package/src/mcp/editable-artifacts.ts +29 -11
  342. package/src/mcp/files.ts +5 -1
  343. package/src/mcp/first-party-tool-permissions.ts +7 -285
  344. package/src/mcp/knowledge-entries.ts +108 -34
  345. package/src/mcp/notification-tools.ts +480 -0
  346. package/src/mcp/orchestration-failure-diagnostic.ts +43 -0
  347. package/src/mcp/scheduled-task-input.ts +89 -0
  348. package/src/mcp/scheduled-task-view.ts +63 -3
  349. package/src/mcp/secret-tools.ts +185 -0
  350. package/src/mcp/server.ts +2213 -1116
  351. package/src/mcp/session-admin-access-tools.ts +163 -0
  352. package/src/mcp/session-event-errors.ts +123 -0
  353. package/src/mcp/session-event-view.ts +395 -13
  354. package/src/mcp/session-view.ts +3 -0
  355. package/src/mcp/session-wait.ts +67 -7
  356. package/src/mcp/site-agent-clamp-tools.ts +140 -0
  357. package/src/mcp/site-data-tools.ts +339 -0
  358. package/src/mcp/site-publication-tools.ts +201 -0
  359. package/src/mcp/site-sql-tools.ts +427 -0
  360. package/src/mcp-oauth.ts +635 -45
  361. package/src/model-calls/chat-completions.ts +352 -0
  362. package/src/model-calls/pending-usage-settlements.ts +125 -0
  363. package/src/model-calls/service.ts +694 -0
  364. package/src/model-catalog.ts +68 -17
  365. package/src/native-push-dispatch.ts +457 -0
  366. package/src/observability.ts +15 -1
  367. package/src/organization-mcp.ts +485 -0
  368. package/src/prepared-mcp-actor.ts +154 -0
  369. package/src/prepared-mcp-permissions.ts +38 -0
  370. package/src/routes/analytics-consent.ts +123 -0
  371. package/src/routes/api-integrations.ts +268 -9
  372. package/src/routes/api-keys.ts +164 -25
  373. package/src/routes/artifact-catalog.ts +111 -0
  374. package/src/routes/automations.ts +163 -90
  375. package/src/routes/billing.ts +535 -59
  376. package/src/routes/browser-sessions.ts +966 -342
  377. package/src/routes/canonical-human-identities.ts +61 -0
  378. package/src/routes/capabilities.ts +112 -5
  379. package/src/routes/channels.ts +4 -3
  380. package/src/routes/chat-completions.ts +235 -0
  381. package/src/routes/claude-core-usage.ts +147 -0
  382. package/src/routes/claude-subscription-accounts.ts +233 -0
  383. package/src/routes/claude-subscription-oauth.ts +175 -0
  384. package/src/routes/client-errors.ts +394 -0
  385. package/src/routes/codex-core.ts +687 -0
  386. package/src/routes/codex.ts +1277 -1119
  387. package/src/routes/company-brain.ts +4 -0
  388. package/src/routes/computer-sessions.ts +319 -85
  389. package/src/routes/connect.ts +277 -175
  390. package/src/routes/connections.ts +690 -363
  391. package/src/routes/desktop-distribution.ts +217 -0
  392. package/src/routes/documents.ts +13 -7
  393. package/src/routes/editable-artifacts.ts +74 -4
  394. package/src/routes/enrollments.ts +110 -16
  395. package/src/routes/external-identity-links.ts +13 -12
  396. package/src/routes/files.ts +41 -16
  397. package/src/routes/github-browser-fonts.gen.ts +12 -0
  398. package/src/routes/github-browser-pages.ts +258 -0
  399. package/src/routes/github.ts +200 -75
  400. package/src/routes/inbox.ts +353 -0
  401. package/src/routes/insights-response-cache.ts +83 -0
  402. package/src/routes/insights-usage.ts +345 -0
  403. package/src/routes/insights.ts +103 -8
  404. package/src/routes/install.ts +51 -10
  405. package/src/routes/integration-facets.ts +70 -28
  406. package/src/routes/interaction-placement-message.ts +12 -0
  407. package/src/routes/knowledge.ts +136 -27
  408. package/src/routes/machines.ts +189 -135
  409. package/src/routes/managed-auth-session-sets.ts +43 -10
  410. package/src/routes/managed-onboarding.ts +39 -19
  411. package/src/routes/managed-sign-in-methods.ts +433 -0
  412. package/src/routes/memory-slack-publications.ts +3 -2
  413. package/src/routes/model-account-choice.ts +194 -0
  414. package/src/routes/model-account-settings.ts +235 -0
  415. package/src/routes/model-connection-access.ts +210 -48
  416. package/src/routes/native-app-auth.ts +296 -0
  417. package/src/routes/organization-integration-policy.ts +116 -0
  418. package/src/routes/organization-integrations.ts +326 -0
  419. package/src/routes/organization-mcp-connections.ts +183 -0
  420. package/src/routes/organization-memberships.ts +205 -19
  421. package/src/routes/organization-model-defaults.ts +110 -0
  422. package/src/routes/organization-model-providers.ts +74 -3
  423. package/src/routes/organization-service-accounts.ts +128 -0
  424. package/src/routes/organization-sessions.ts +21 -5
  425. package/src/routes/personal-api-keys.ts +184 -0
  426. package/src/routes/personal-github-git-broker.ts +2 -2
  427. package/src/routes/personal-github.ts +9 -4
  428. package/src/routes/plugins.ts +46 -7
  429. package/src/routes/pr-review-github.ts +105 -118
  430. package/src/routes/pr-review.ts +88 -82
  431. package/src/routes/preference-registry.ts +18 -0
  432. package/src/routes/rigs.ts +48 -13
  433. package/src/routes/scheduled-tasks.ts +347 -27
  434. package/src/routes/session-admin-access.ts +271 -0
  435. package/src/routes/session-artifact-associations.ts +164 -0
  436. package/src/routes/session-history-imports.ts +305 -0
  437. package/src/routes/sessions.ts +1682 -363
  438. package/src/routes/site-data.ts +340 -0
  439. package/src/routes/site-publishing.ts +584 -0
  440. package/src/routes/site-runtime.ts +1944 -0
  441. package/src/routes/site-sql.ts +263 -0
  442. package/src/routes/skill-content.ts +72 -7
  443. package/src/routes/skills.ts +5 -4
  444. package/src/routes/slack-bot-access.ts +108 -0
  445. package/src/routes/social.ts +27 -15
  446. package/src/routes/subscription-account-pools.ts +209 -0
  447. package/src/routes/subscription-core-http.ts +18 -0
  448. package/src/routes/subscription-pool-access.ts +180 -0
  449. package/src/routes/subscription-pool-core.ts +552 -0
  450. package/src/routes/supergrok.ts +174 -655
  451. package/src/routes/transcription-recordings.ts +71 -4
  452. package/src/routes/transcriptions.ts +26 -2
  453. package/src/routes/usage-allowances.ts +381 -0
  454. package/src/routes/variable-sets-removed.ts +19 -0
  455. package/src/routes/vault-providers.ts +782 -0
  456. package/src/routes/vaults.ts +421 -0
  457. package/src/routes/video-generation.ts +30 -12
  458. package/src/routes/workspace-artifacts.ts +165 -53
  459. package/src/routes/workspace-integrations.ts +576 -0
  460. package/src/routes/workspace-model-providers.ts +148 -0
  461. package/src/routes/workspace-state.ts +4 -0
  462. package/src/routes/workspaces.ts +625 -117
  463. package/src/sandbox/agent-update.ts +315 -0
  464. package/src/sandbox/auth-callout.ts +104 -21
  465. package/src/sandbox/channel-a.ts +165 -55
  466. package/src/sandbox/enrollment.ts +131 -22
  467. package/src/sandbox/machine-audience.ts +192 -0
  468. package/src/sandbox/machines.ts +75 -31
  469. package/src/sandbox/metrics-ingestion.ts +133 -2
  470. package/src/sandbox/rematerialize.ts +51 -21
  471. package/src/sandbox/screen-control.ts +289 -0
  472. package/src/sandbox/viewer.ts +33 -58
  473. package/src/sandbox-file-artifacts.ts +53 -27
  474. package/src/scheduled-task-blockers.ts +293 -0
  475. package/src/scheduled-task-deletion.ts +13 -3
  476. package/src/scheduled-task-lifecycle.ts +84 -0
  477. package/src/secret-answers.ts +119 -0
  478. package/src/session-create-observability.ts +46 -0
  479. package/src/session-realtime-context.ts +26 -4
  480. package/src/signed-state-secret.ts +58 -0
  481. package/src/site-agent-guard.ts +261 -0
  482. package/src/site-data/operations.ts +777 -0
  483. package/src/site-data/service.ts +1043 -0
  484. package/src/site-frame-guard.ts +107 -0
  485. package/src/site-publishing/agent-data-tools.ts +250 -0
  486. package/src/site-publishing/agent-model.ts +127 -0
  487. package/src/site-publishing/agent-session.ts +148 -0
  488. package/src/site-publishing/content-scanner.ts +93 -0
  489. package/src/site-publishing/edge-sync.ts +148 -0
  490. package/src/site-publishing/gateway-signature.ts +198 -0
  491. package/src/site-publishing/limits.ts +315 -0
  492. package/src/site-publishing/page-tool-authority.ts +111 -0
  493. package/src/site-publishing/platform-usage.ts +479 -0
  494. package/src/site-publishing/platform.ts +98 -0
  495. package/src/site-publishing/readiness.ts +330 -0
  496. package/src/site-publishing/runtime.ts +831 -0
  497. package/src/site-publishing/service.ts +1282 -0
  498. package/src/site-publishing/session-events.ts +262 -0
  499. package/src/site-publishing/session-views.ts +262 -0
  500. package/src/site-publishing/viewer.ts +75 -0
  501. package/src/site-session-origin.ts +91 -6
  502. package/src/site-sql/format.ts +134 -0
  503. package/src/site-sql/gateway.ts +168 -0
  504. package/src/site-sql/service.ts +1636 -0
  505. package/src/site-uploads.ts +27 -5
  506. package/src/temporal-schedule-sync.ts +74 -0
  507. package/src/transcription/billing-refusal.ts +14 -0
  508. package/src/transcription/normalize.ts +77 -0
  509. package/src/transcription/providers/azure-mai.ts +98 -0
  510. package/src/transcription/providers/azure-openai.ts +16 -7
  511. package/src/transcription/providers/codex-subscription.ts +190 -67
  512. package/src/transcription/providers/openai.ts +79 -5
  513. package/src/transcription/providers/subscription-core.ts +125 -0
  514. package/src/transcription/providers/xai-subscription.ts +81 -83
  515. package/src/transcription/segmenter.ts +7 -1
  516. package/src/transcription/service.ts +239 -10
  517. package/src/transcription/wav-duration.ts +39 -0
  518. package/src/workspace-deletion.ts +25 -1
  519. package/src/workspace-tool-gateway-attestations.ts +133 -0
  520. package/src/workspace-tool-gateway-observability.ts +64 -0
  521. package/src/workspace-tool-gateway-secrets.ts +104 -0
  522. package/src/workspace-tool-gateway.ts +921 -103
  523. package/src/workspace-tool-target-fence.ts +380 -0
  524. package/src/workspace-tool-target.ts +554 -0
  525. package/src/workspace-webhook-dispatch.ts +225 -0
  526. package/src/xai-realtime.ts +85 -81
  527. package/src/xai-subscription-core.ts +172 -0
  528. package/dist/browser-auth-broker.d.ts +0 -20
  529. package/dist/chunk-AJ62T5QN.js.map +0 -1
  530. package/dist/connection-authority-owner.d.ts +0 -59
  531. package/dist/routes/connection-authorities.d.ts +0 -3
  532. package/dist/routes/environments.d.ts +0 -5
  533. package/dist/routes/host-mcp-bindings.d.ts +0 -5
  534. package/dist/routes/host-mcp-resolvers.d.ts +0 -3
  535. package/dist/routes/packs.d.ts +0 -3
  536. package/dist/session-event-view-MU3HMNV3.js +0 -264
  537. package/dist/session-event-view-MU3HMNV3.js.map +0 -1
  538. package/dist/xai-subscription-auth.d.ts +0 -23
  539. package/src/browser-auth-broker.ts +0 -155
  540. package/src/connection-authority-owner.ts +0 -61
  541. package/src/routes/connection-authorities.ts +0 -139
  542. package/src/routes/environments.ts +0 -388
  543. package/src/routes/host-mcp-bindings.ts +0 -122
  544. package/src/routes/host-mcp-resolvers.ts +0 -41
  545. package/src/routes/packs.ts +0 -784
  546. package/src/xai-subscription-auth.ts +0 -139
@@ -38,6 +38,8 @@ import {
38
38
  clearEnrollmentWentOffline,
39
39
  disconnectAttachedBrowserDevices,
40
40
  advanceEnrollmentAgentUpdate,
41
+ enrollmentMacPermissionCapabilities,
42
+ enrollmentMacPermissions,
41
43
  getEnrollment,
42
44
  getLiveEnrollmentConnection,
43
45
  ingestMachineMetricsSample,
@@ -50,27 +52,34 @@ import {
50
52
  setEnrollmentOpStreamState,
51
53
  type AppendEventInput,
52
54
  type Database,
55
+ type EnrollmentMacPermissions,
53
56
  type MachineMetricsSample,
54
57
  } from "@opengeni/db";
55
58
  import {
59
+ AttachedBrowserConnectionEnd as AttachedBrowserConnectionEndContract,
56
60
  AttachedBrowserInventorySnapshot as AttachedBrowserInventoryContract,
57
61
  type AttachedBrowserInventorySnapshot as AttachedBrowserInventoryContractValue,
62
+ type AttachedBrowserConnectionEnd as AttachedBrowserConnectionEndValue,
58
63
  } from "@opengeni/contracts";
59
64
  import { appendAndPublishEvents, type EventBus } from "@opengeni/events";
60
65
  import type { Observability } from "@opengeni/observability";
61
66
  import { normalizeConnectedMachineWorkspaceRoot } from "@opengeni/runtime/sandbox";
67
+ import type { AutomaticAgentUpdater } from "./agent-update";
62
68
  import {
63
69
  AgentEvent,
64
70
  AgentUpdateStage,
65
71
  Arch,
72
+ AttachedBrowserConnectionEndReason as WireConnectionEndReason,
66
73
  GoingOfflineReason,
67
74
  Hello,
68
75
  Os,
69
76
  goingOfflineReasonToJSON,
77
+ type AttachedBrowserConnectionEnd as WireAttachedBrowserConnectionEnd,
70
78
  type AttachedBrowserInventorySnapshot as WireAttachedBrowserInventorySnapshot,
71
79
  type MetricsSample,
72
80
  } from "@opengeni/agent-proto";
73
81
  import { AGENT_CONNECTION_LEASE_MS } from "./connection-authority";
82
+ import { reconcileScreenControlOnHello } from "./screen-control";
74
83
 
75
84
  /** The wildcard subject the agent event plane publishes heartbeats on. */
76
85
  export const AGENT_EVENTS_SUBJECT = "agent.*.*.connection.*.events";
@@ -314,9 +323,53 @@ export function wireAttachedBrowserInventoryToContract(
314
323
  tabCount: safeWireInteger(device.tabCount, "attached browser tab count"),
315
324
  capabilities: device.capabilities,
316
325
  })),
326
+ connectionEnds: (wire.connectionEnds ?? []).flatMap(wireConnectionEndToContract),
317
327
  });
318
328
  }
319
329
 
330
+ const WIRE_CONNECTION_END_REASONS = new Map<
331
+ WireConnectionEndReason,
332
+ AttachedBrowserConnectionEndValue["reason"]
333
+ >([
334
+ [
335
+ WireConnectionEndReason.ATTACHED_BROWSER_CONNECTION_END_REASON_BROWSER_CLOSED_PORT,
336
+ "browser_closed_port",
337
+ ],
338
+ [
339
+ WireConnectionEndReason.ATTACHED_BROWSER_CONNECTION_END_REASON_BROWSER_MESSAGE_INVALID,
340
+ "browser_message_invalid",
341
+ ],
342
+ [
343
+ WireConnectionEndReason.ATTACHED_BROWSER_CONNECTION_END_REASON_BROWSER_OUTPUT_FAILED,
344
+ "browser_output_failed",
345
+ ],
346
+ [
347
+ WireConnectionEndReason.ATTACHED_BROWSER_CONNECTION_END_REASON_NATIVE_HOST_LOST,
348
+ "native_host_lost",
349
+ ],
350
+ [WireConnectionEndReason.ATTACHED_BROWSER_CONNECTION_END_REASON_AGENT_REJECTED, "agent_rejected"],
351
+ ]);
352
+
353
+ /** Connection ends are diagnostics. One the contract cannot hold (a future
354
+ * reason, or the generation of a hello the bridge rejected as malformed) is
355
+ * dropped instead of rejecting the authoritative device inventory. */
356
+ function wireConnectionEndToContract(
357
+ wire: WireAttachedBrowserConnectionEnd,
358
+ ): AttachedBrowserConnectionEndValue[] {
359
+ const reason = WIRE_CONNECTION_END_REASONS.get(wire.reason);
360
+ const endedAtMs = Number(wire.endedAtUnixMs);
361
+ if (!reason || !Number.isSafeInteger(endedAtMs) || endedAtMs <= 0) return [];
362
+ const parsed = AttachedBrowserConnectionEndContract.safeParse({
363
+ deviceId: wire.deviceId,
364
+ connectionGeneration: wire.connectionGeneration,
365
+ reason,
366
+ detail: wire.detail.slice(0, 512) || null,
367
+ endedAt: new Date(endedAtMs).toISOString(),
368
+ connectedMs: Math.min(Number(wire.connectedMs) || 0, Number.MAX_SAFE_INTEGER),
369
+ });
370
+ return parsed.success ? [parsed.data] : [];
371
+ }
372
+
320
373
  function safeWireInteger(value: string | number, label: string): number {
321
374
  let parsed: bigint;
322
375
  try {
@@ -452,6 +505,7 @@ export async function handleAgentEventPayload(
452
505
  payload: Uint8Array,
453
506
  subject: string,
454
507
  bus?: EventBus,
508
+ agentUpdates?: AutomaticAgentUpdater | null,
455
509
  ): Promise<void> {
456
510
  const ids = parseAgentEventSubject(subject);
457
511
  if (!ids) {
@@ -619,6 +673,9 @@ export async function handleAgentEventPayload(
619
673
  });
620
674
  return;
621
675
  }
676
+ // A live machine behind its promoted build is asked to update; the decision
677
+ // reads only this enrollment, and a request never blocks heartbeat ingestion.
678
+ agentUpdates?.consider(enrollment);
622
679
  if (heartbeat.attachedBrowserInventory) {
623
680
  try {
624
681
  await ingestAttachedBrowserInventory(db, {
@@ -633,6 +690,41 @@ export async function handleAgentEventPayload(
633
690
  });
634
691
  }
635
692
  }
693
+ if (heartbeat.desktopStatus) {
694
+ try {
695
+ const status = heartbeat.desktopStatus;
696
+ const available = status.available && !status.unavailableReason;
697
+ const reason = status.unavailableReason || null;
698
+ const macPermissions = status.macPermissions;
699
+ const stored = enrollmentMacPermissions(enrollment.agentCapabilities);
700
+ // The heartbeat already read the exact enrollment. Steady state adds no
701
+ // extra query; the change path re-reads and fences its eventual write.
702
+ if (
703
+ enrollment.hasDisplay !== available ||
704
+ (enrollment.desktopUnavailableReason ?? null) !== reason ||
705
+ enrollment.agentCapabilities?.desktop !== available ||
706
+ (macPermissions !== undefined &&
707
+ (stored?.screenRecording !== macPermissions.screenRecording ||
708
+ stored?.accessibility !== macPermissions.accessibility ||
709
+ stored?.inputMonitoring !== macPermissions.inputMonitoring))
710
+ ) {
711
+ await refreshEnrollmentDisplay(db, {
712
+ workspaceId: ids.workspaceId,
713
+ agentId: ids.agentId,
714
+ hasDisplay: available,
715
+ desktopUnavailableReason: reason,
716
+ runtimeDesktop: available,
717
+ ...(macPermissions ? { macPermissions } : {}),
718
+ connectionInstanceId: ids.connectionInstanceId,
719
+ });
720
+ }
721
+ } catch (error) {
722
+ observability?.warn?.("Failed to refresh a machine desktop heartbeat", {
723
+ subject,
724
+ error: error instanceof Error ? error.message : String(error),
725
+ });
726
+ }
727
+ }
636
728
  const metrics = heartbeat.metrics;
637
729
  if (!metrics) return;
638
730
  try {
@@ -659,10 +751,18 @@ export function startMetricsIngestion(deps: {
659
751
  db: Database;
660
752
  bus: EventBus;
661
753
  observability?: Observability;
754
+ agentUpdates?: AutomaticAgentUpdater | null;
662
755
  }): () => void {
663
756
  const scheduler = createAgentEventIngestionScheduler(
664
757
  (payload, subject) =>
665
- handleAgentEventPayload(deps.db, deps.observability, payload, subject, deps.bus),
758
+ handleAgentEventPayload(
759
+ deps.db,
760
+ deps.observability,
761
+ payload,
762
+ subject,
763
+ deps.bus,
764
+ deps.agentUpdates,
765
+ ),
666
766
  {
667
767
  onHeartbeatCoalesced: () =>
668
768
  deps.observability?.incrementCounter({
@@ -742,6 +842,9 @@ export function helloRuntimeCapabilities(hello: Hello): Record<string, boolean>
742
842
  operationResourcePolicy: caps.operationResourcePolicy === true,
743
843
  operationCpuQuota: caps.operationCpuQuota === true,
744
844
  transactionalFsWrite: caps.transactionalFsWrite === true,
845
+ credentialRenew: caps.credentialRenew === true,
846
+ screenControl: caps.consentedScreenControl === true,
847
+ ...(caps.macPermissions ? enrollmentMacPermissionCapabilities(caps.macPermissions) : {}),
745
848
  };
746
849
  }
747
850
 
@@ -781,6 +884,8 @@ export async function refreshEnrollmentDisplay(
781
884
  agentId: string;
782
885
  hasDisplay: boolean;
783
886
  desktopUnavailableReason?: string | null;
887
+ runtimeDesktop?: boolean;
888
+ macPermissions?: EnrollmentMacPermissions;
784
889
  connectionInstanceId?: string;
785
890
  },
786
891
  ): Promise<{ updated: boolean }> {
@@ -791,7 +896,16 @@ export async function refreshEnrollmentDisplay(
791
896
  }
792
897
  if (
793
898
  enrollment.hasDisplay === input.hasDisplay &&
794
- (enrollment.desktopUnavailableReason ?? null) === desktopUnavailableReason
899
+ (enrollment.desktopUnavailableReason ?? null) === desktopUnavailableReason &&
900
+ (input.runtimeDesktop === undefined ||
901
+ enrollment.agentCapabilities?.desktop === input.runtimeDesktop) &&
902
+ (input.macPermissions === undefined ||
903
+ JSON.stringify(enrollmentMacPermissions(enrollment.agentCapabilities)) ===
904
+ JSON.stringify({
905
+ screenRecording: input.macPermissions.screenRecording,
906
+ accessibility: input.macPermissions.accessibility,
907
+ inputMonitoring: input.macPermissions.inputMonitoring,
908
+ }))
795
909
  ) {
796
910
  // Both fields unchanged — do not even issue the UPDATE (no churn on a
797
911
  // steady-state Hello).
@@ -803,6 +917,8 @@ export async function refreshEnrollmentDisplay(
803
917
  enrollmentId: input.agentId,
804
918
  hasDisplay: input.hasDisplay,
805
919
  desktopUnavailableReason,
920
+ ...(input.runtimeDesktop !== undefined ? { runtimeDesktop: input.runtimeDesktop } : {}),
921
+ ...(input.macPermissions ? { macPermissions: input.macPermissions } : {}),
806
922
  ...(input.connectionInstanceId ? { connectionInstanceId: input.connectionInstanceId } : {}),
807
923
  });
808
924
  }
@@ -926,6 +1042,21 @@ export async function handleHelloPayload(
926
1042
  error: error instanceof Error ? error.message : String(error),
927
1043
  });
928
1044
  }
1045
+ // Screen control allowed while this machine was offline (or before its agent
1046
+ // could renew on request) applies now. Detached: it waits for the agent to
1047
+ // subscribe and must not hold up Hello ingestion.
1048
+ void reconcileScreenControlOnHello(
1049
+ { bus, observability },
1050
+ {
1051
+ authority,
1052
+ hello,
1053
+ target: {
1054
+ workspaceId: ids.workspaceId,
1055
+ enrollmentId: ids.agentId,
1056
+ connectionInstanceId: ids.connectionInstanceId,
1057
+ },
1058
+ },
1059
+ );
929
1060
  // A reconnect Hello re-announces the machine, so any pending clean going-offline
930
1061
  // marker no longer holds — clear it so the liveness derivation stops reading the
931
1062
  // machine offline. Best-effort + fail-soft, and change-guarded in the DB (a
@@ -7,6 +7,7 @@ import {
7
7
  failSandboxRematerialization,
8
8
  failWarmingToCold,
9
9
  markSandboxRestoreVerifying,
10
+ sessionHoldsFreshWorkspaceRecovery,
10
11
  recordWarmingSandboxCreated,
11
12
  SandboxLeaseRecoveryBlockedError,
12
13
  SandboxLeaseSupersededError,
@@ -29,6 +30,7 @@ import {
29
30
  verifySandboxExecReadiness,
30
31
  withoutSandboxProviderIdentity,
31
32
  WorkspaceArchiveIntegrityError,
33
+ workspaceArchiveDownloadTemporaryDirectory,
32
34
  type EstablishedSandboxSession,
33
35
  type WorkspaceArchiveDescriptor,
34
36
  } from "@opengeni/runtime/sandbox";
@@ -73,8 +75,9 @@ async function materializeArchiveObjectRef(
73
75
  }
74
76
  if (!objectStorage) {
75
77
  throw new WorkspaceArchiveIntegrityError(
76
- "archive_base64_invalid",
78
+ "archive_storage_unavailable",
77
79
  "workspace archive object storage is not configured",
80
+ { retryable: true },
78
81
  );
79
82
  }
80
83
  const descriptor = parseWorkspaceArchiveDescriptor(sessionState.workspaceArchiveMeta);
@@ -136,13 +139,29 @@ export async function establishApiSandboxSpawner(input: {
136
139
  dataPlaneUrl: string | null;
137
140
  objectStorage?: ObjectStorage | null;
138
141
  }): Promise<{ established: EstablishedSandboxSession; lease: LeaseSnapshot }> {
142
+ // An audited decision to continue a definitively lost workspace on a new
143
+ // EMPTY box: hydrate nothing, including a per-session legacy archive, and
144
+ // never resume a prior provider identity. Commit verifies the decision.
145
+ const freshWorkspaceRecoveryId = input.acquiredLease.freshWorkspaceRecoveryId ?? null;
146
+ // Backstop: a session already told its workspace is empty never gets a
147
+ // legacy per-session archive back, even if the lease marker was lost.
148
+ const legacyFallbackRefused =
149
+ !freshWorkspaceRecoveryId &&
150
+ input.acquiredLease.recovery.archive.status === "none" &&
151
+ hasWorkspaceArchive(input.fallbackEnvelope) &&
152
+ (await sessionHoldsFreshWorkspaceRecovery(input.db, input.workspaceId, input.sessionId));
139
153
  const fallbackArchiveEnvelope =
154
+ !freshWorkspaceRecoveryId &&
155
+ !legacyFallbackRefused &&
140
156
  input.acquiredLease.recovery.archive.status === "none" &&
141
157
  hasWorkspaceArchive(input.fallbackEnvelope)
142
158
  ? withoutSandboxProviderIdentity(input.fallbackEnvelope)
143
159
  : null;
144
- let spawnEnvelope =
145
- fallbackArchiveEnvelope ?? input.acquiredLease.resumeState ?? input.fallbackEnvelope;
160
+ let spawnEnvelope = freshWorkspaceRecoveryId
161
+ ? null
162
+ : legacyFallbackRefused
163
+ ? (input.acquiredLease.resumeState ?? null)
164
+ : (fallbackArchiveEnvelope ?? input.acquiredLease.resumeState ?? input.fallbackEnvelope);
146
165
  const archiveSource =
147
166
  input.acquiredLease.recovery.archive.status === "none"
148
167
  ? fallbackArchiveEnvelope
@@ -161,9 +180,12 @@ export async function establishApiSandboxSpawner(input: {
161
180
  const continuityRecovery = input.acquiredLease.recovery.continuity;
162
181
  try {
163
182
  if (
164
- (input.acquiredLease.recovery.archive.status === "available" &&
165
- input.acquiredLease.archiveComplete) ||
166
- (input.acquiredLease.recovery.archive.status === "none" && hasWorkspaceArchive(archiveSource))
183
+ !freshWorkspaceRecoveryId &&
184
+ ((input.acquiredLease.recovery.archive.status === "available" &&
185
+ (input.acquiredLease.archiveComplete ||
186
+ input.acquiredLease.historicalRecoveryAuthorized === true)) ||
187
+ (input.acquiredLease.recovery.archive.status === "none" &&
188
+ hasWorkspaceArchive(archiveSource)))
167
189
  ) {
168
190
  const id = crypto.randomUUID();
169
191
  const legacyNativeArchive = legacyNativeArchiveFromEnvelope(archiveSource);
@@ -206,7 +228,11 @@ export async function establishApiSandboxSpawner(input: {
206
228
  legacyCheckpoint: begun.checkpointArtifact === null ? legacyNativeArchive : null,
207
229
  legacyProviderBinding: null,
208
230
  };
209
- } else if (input.acquiredLease.recovery.archive.status !== "none" && !continuityRecovery) {
231
+ } else if (
232
+ !freshWorkspaceRecoveryId &&
233
+ input.acquiredLease.recovery.archive.status !== "none" &&
234
+ !continuityRecovery
235
+ ) {
210
236
  throw new SandboxLeaseRecoveryBlockedError(
211
237
  input.sandboxGroupId,
212
238
  input.expectedEpoch,
@@ -225,10 +251,12 @@ export async function establishApiSandboxSpawner(input: {
225
251
  ? {
226
252
  loadHostWorkspaceArchive: async (ref) => {
227
253
  try {
228
- return await downloadWorkspaceArchiveSpool(input.objectStorage!, ref.key, {
229
- bytes: ref.bytes,
230
- sha256: ref.sha256,
231
- });
254
+ return await downloadWorkspaceArchiveSpool(
255
+ input.objectStorage!,
256
+ ref.key,
257
+ { bytes: ref.bytes, sha256: ref.sha256 },
258
+ { temporaryDirectory: workspaceArchiveDownloadTemporaryDirectory },
259
+ );
232
260
  } catch (error) {
233
261
  if (error instanceof WorkspaceArchiveStorageError) {
234
262
  throw new WorkspaceArchiveIntegrityError(error.code, error.message, {
@@ -383,16 +411,18 @@ export async function establishApiSandboxSpawner(input: {
383
411
  dataPlaneUrl: input.dataPlaneUrl,
384
412
  resumeBackendId: established.backendId,
385
413
  resumeState,
386
- ...(established.providerContinuity
387
- ? { continuityRecovery: established.providerContinuity }
388
- : rematerialization
389
- ? {
390
- rematerialization: {
391
- id: rematerialization.id,
392
- verifiedRevision: rematerialization.selectedRevision,
393
- },
394
- }
395
- : {}),
414
+ ...(freshWorkspaceRecoveryId
415
+ ? { freshWorkspace: { operationId: freshWorkspaceRecoveryId } }
416
+ : established.providerContinuity
417
+ ? { continuityRecovery: established.providerContinuity }
418
+ : rematerialization
419
+ ? {
420
+ rematerialization: {
421
+ id: rematerialization.id,
422
+ verifiedRevision: rematerialization.selectedRevision,
423
+ },
424
+ }
425
+ : {}),
396
426
  leaseTtlMs: input.settings.sandboxLeaseTtlMs,
397
427
  });
398
428
  if (!committed.committed || !committed.lease) {
@@ -0,0 +1,289 @@
1
+ // Screen control and macOS permission setup for an already-connected machine.
2
+ //
3
+ // Screen-control consent lives on the enrollment row and in the credentials the
4
+ // machine holds (the agent's own dispatch gate checks them). Turning it on
5
+ // records the consent on the row, in place (same id, scope, owner and
6
+ // credential generation), then asks the live agent to renew its credentials
7
+ // now. That renewal is the same install-key-signed exchange the agent runs on
8
+ // its own schedule, and it re-reads consent from the row, so nothing new is
9
+ // trusted: no token, no installer, no restart, no second connection file. A
10
+ // machine that is offline, or whose agent predates credential_renew, picks the
11
+ // consent up when it next says Hello (reconcileScreenControlOnHello).
12
+
13
+ import { ControlRequest, ErrorCode, type Hello } from "@opengeni/agent-proto";
14
+ import {
15
+ EnableMachineScreenControlResponse,
16
+ OpenMachinePrivacySettingsResponse,
17
+ type MachinePrivacySettingsPane,
18
+ } from "@opengeni/contracts";
19
+ import { runOnEnrollmentDirect, type FleetServices } from "@opengeni/core";
20
+ import {
21
+ allowEnrollmentScreenControl,
22
+ getLiveEnrollmentConnection,
23
+ type EnrollmentRecord,
24
+ } from "@opengeni/db";
25
+ import type { EventBus } from "@opengeni/events";
26
+ import type { Observability } from "@opengeni/observability";
27
+ import { NatsControlRpc, subjectFor } from "@opengeni/runtime/sandbox";
28
+
29
+ type Services = Pick<FleetServices, "db" | "settings" | "bus"> & {
30
+ observability?: Observability | undefined;
31
+ };
32
+ type EnrollmentAccess = string | { accountId: string; workspaceId: string; subjectId: string };
33
+
34
+ /** The agent's renewal HTTP call is bounded at 20s; leave room for the reply. */
35
+ const CREDENTIAL_RENEW_TIMEOUT_MS = 30_000;
36
+ /** Opening a System Settings pane is instant; never hold a request open longer. */
37
+ const PRIVACY_PANE_TIMEOUT_MS = 15_000;
38
+
39
+ /** macOS System Settings deep links for the three desktop permissions. */
40
+ export const MAC_PRIVACY_PANE_URLS: Record<MachinePrivacySettingsPane, string> = {
41
+ screen_recording: "x-apple.systempreferences:com.apple.preference.security?Privacy_ScreenCapture",
42
+ accessibility: "x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility",
43
+ input_monitoring: "x-apple.systempreferences:com.apple.preference.security?Privacy_ListenEvent",
44
+ };
45
+
46
+ /** Read access for live-connection lookups, matching the machine's scope. */
47
+ export function enrollmentAccess(
48
+ enrollment: Pick<EnrollmentRecord, "scope" | "workspaceId">,
49
+ personal: { accountId: string; workspaceId: string; subjectId: string },
50
+ ): EnrollmentAccess {
51
+ return enrollment.scope === "user" ? personal : enrollment.workspaceId;
52
+ }
53
+
54
+ export type CredentialRenewOutcome =
55
+ | { kind: "renewed"; consentedScreenControl: boolean }
56
+ | { kind: "offline" }
57
+ | { kind: "failed"; failureCode: string };
58
+
59
+ /** Ask one exact live runner process to renew its credentials now. */
60
+ export async function requestCredentialRenew(
61
+ bus: EventBus | undefined,
62
+ target: { workspaceId: string; enrollmentId: string; connectionInstanceId: string },
63
+ ): Promise<CredentialRenewOutcome> {
64
+ if (!bus) return { kind: "offline" };
65
+ const rpc = new NatsControlRpc(async () => bus.getRequestConnection() ?? null);
66
+ const request: ControlRequest = {
67
+ requestId: crypto.randomUUID(),
68
+ // Process-scoped, like agentUpdateApply: the subject names the instance.
69
+ epoch: 0,
70
+ resourcePolicy: undefined,
71
+ op: { $case: "credentialRenew", credentialRenew: {} },
72
+ };
73
+ const response = await rpc.request(
74
+ subjectFor(target.workspaceId, target.enrollmentId, target.connectionInstanceId),
75
+ request,
76
+ { timeoutMs: CREDENTIAL_RENEW_TIMEOUT_MS },
77
+ );
78
+ if (response.error) {
79
+ if (response.error.code === ErrorCode.ERROR_CODE_AGENT_OFFLINE) return { kind: "offline" };
80
+ return {
81
+ kind: "failed",
82
+ failureCode:
83
+ response.error.detail.failure_code ??
84
+ (response.error.code === ErrorCode.ERROR_CODE_TIMEOUT ? "timeout" : "agent_error"),
85
+ };
86
+ }
87
+ if (response.result?.$case !== "credentialRenew") {
88
+ return { kind: "failed", failureCode: "invalid_agent_response" };
89
+ }
90
+ return {
91
+ kind: "renewed",
92
+ consentedScreenControl: response.result.credentialRenew.consentedScreenControl,
93
+ };
94
+ }
95
+
96
+ const pending = (
97
+ reason: "offline" | "agent_update_required" | "renewal_failed" | "reconnect_required",
98
+ message: string,
99
+ ): EnableMachineScreenControlResponse =>
100
+ EnableMachineScreenControlResponse.parse({ status: "pending", reason, message });
101
+
102
+ const ACTIVE = { status: "active", reason: null, message: null } as const;
103
+
104
+ /** Agent failure codes that no retry fixes: the connection must be redone. */
105
+ const PERMANENT_RENEW_FAILURES = new Set([
106
+ "connection_missing",
107
+ "legacy_origin",
108
+ "local_state_unavailable",
109
+ ]);
110
+
111
+ /** The enrollment was revoked or removed between lookup and update. */
112
+ export class MachineNotActiveError extends Error {
113
+ constructor() {
114
+ super("machine is no longer connected to this workspace");
115
+ this.name = "MachineNotActiveError";
116
+ }
117
+ }
118
+
119
+ /** Who turned screen control on, for the audit trail. */
120
+ export type ScreenControlActor = {
121
+ subjectId: string | null;
122
+ sessionId?: string | null;
123
+ attemptId?: string | null;
124
+ };
125
+
126
+ /**
127
+ * Turn screen control on for one enrolled machine, in place. The caller has
128
+ * already authorized the actor for this enrollment (enrollments:manage, plus
129
+ * account:admin for an organization machine, plus personal-machine admission
130
+ * for an agent attempt). Safe to repeat: a retry re-requests the renewal.
131
+ */
132
+ export async function enableMachineScreenControl(
133
+ services: Services,
134
+ input: { enrollment: EnrollmentRecord; access: EnrollmentAccess; actor: ScreenControlActor },
135
+ ): Promise<EnableMachineScreenControlResponse> {
136
+ const { enrollment } = input;
137
+ if (!enrollment.allowScreenControl) {
138
+ const allowed = await allowEnrollmentScreenControl(services.db, {
139
+ accountId: enrollment.accountId,
140
+ workspaceId: enrollment.workspaceId,
141
+ enrollmentId: enrollment.id,
142
+ ...input.actor,
143
+ });
144
+ if (!allowed.active) throw new MachineNotActiveError();
145
+ }
146
+ const live = await getLiveEnrollmentConnection(services.db, input.access, enrollment.id);
147
+ if (!live?.connectionInstanceId) {
148
+ return pending(
149
+ "offline",
150
+ "Screen control is allowed. The machine is offline, so it turns on when the machine reconnects.",
151
+ );
152
+ }
153
+ // The live agent's Hello already carries the consent: nothing to renew, so
154
+ // repeated calls never churn the connection.
155
+ if (live.allowScreenControl && live.agentCapabilities.screenControl === true) {
156
+ return EnableMachineScreenControlResponse.parse(ACTIVE);
157
+ }
158
+ if (live.agentCapabilities.credentialRenew !== true) {
159
+ return pending(
160
+ "agent_update_required",
161
+ "Screen control is allowed. This machine's agent is too old to switch it on while connected: update the agent and it turns on after the update.",
162
+ );
163
+ }
164
+ const outcome = await requestCredentialRenew(services.bus, {
165
+ workspaceId: live.workspaceId,
166
+ enrollmentId: enrollment.id,
167
+ connectionInstanceId: live.connectionInstanceId,
168
+ });
169
+ if (outcome.kind === "renewed" && outcome.consentedScreenControl) {
170
+ return EnableMachineScreenControlResponse.parse(ACTIVE);
171
+ }
172
+ services.observability?.warn?.("Screen control renewal did not complete", {
173
+ workspaceId: live.workspaceId,
174
+ enrollmentId: enrollment.id,
175
+ outcome: outcome.kind,
176
+ failureCode: outcome.kind === "failed" ? outcome.failureCode : null,
177
+ });
178
+ if (outcome.kind === "offline") {
179
+ return pending(
180
+ "offline",
181
+ "Screen control is allowed. The machine went offline, so it turns on when the machine reconnects.",
182
+ );
183
+ }
184
+ if (outcome.kind === "failed" && PERMANENT_RENEW_FAILURES.has(outcome.failureCode)) {
185
+ return pending(
186
+ "reconnect_required",
187
+ "Screen control is allowed, but this machine's connection can't take it in place. Run the connect command on the machine again with screen control on.",
188
+ );
189
+ }
190
+ return pending(
191
+ "renewal_failed",
192
+ "The machine couldn't refresh its credentials. Try again in a moment.",
193
+ );
194
+ }
195
+
196
+ const HELLO_RENEW_DELAYS_MS = [2_000, 5_000] as const;
197
+
198
+ /**
199
+ * A machine whose enrollment allows screen control but whose credentials do
200
+ * not (it was offline, or updated from an agent without credential_renew)
201
+ * renews them as soon as it says Hello. The agent subscribes to requests just
202
+ * after its Hello, so wait briefly and retry once. Never throws.
203
+ */
204
+ export async function reconcileScreenControlOnHello(
205
+ deps: {
206
+ bus: EventBus | undefined;
207
+ observability?: Observability | undefined;
208
+ sleep?: (ms: number) => Promise<void>;
209
+ },
210
+ input: {
211
+ authority: Pick<EnrollmentRecord, "allowScreenControl">;
212
+ hello: Hello;
213
+ target: {
214
+ workspaceId: string;
215
+ enrollmentId: string;
216
+ connectionInstanceId: string;
217
+ };
218
+ },
219
+ ): Promise<CredentialRenewOutcome | null> {
220
+ const capabilities = input.hello.capabilities;
221
+ if (
222
+ !input.authority.allowScreenControl ||
223
+ !capabilities?.credentialRenew ||
224
+ capabilities.consentedScreenControl
225
+ ) {
226
+ return null;
227
+ }
228
+ const sleep = deps.sleep ?? ((ms: number) => new Promise((resolve) => setTimeout(resolve, ms)));
229
+ let outcome: CredentialRenewOutcome = { kind: "offline" };
230
+ try {
231
+ for (const delay of HELLO_RENEW_DELAYS_MS) {
232
+ await sleep(delay);
233
+ outcome = await requestCredentialRenew(deps.bus, input.target);
234
+ if (outcome.kind !== "offline") break;
235
+ }
236
+ } catch (error) {
237
+ outcome = {
238
+ kind: "failed",
239
+ failureCode: error instanceof Error ? error.message : "request_failed",
240
+ };
241
+ }
242
+ if (outcome.kind !== "renewed") {
243
+ deps.observability?.warn?.("Could not apply allowed screen control after a Hello", {
244
+ workspaceId: input.target.workspaceId,
245
+ enrollmentId: input.target.enrollmentId,
246
+ outcome: outcome.kind,
247
+ failureCode: outcome.kind === "failed" ? outcome.failureCode : null,
248
+ });
249
+ }
250
+ return outcome;
251
+ }
252
+
253
+ /** Open one macOS Privacy & Security pane on a connected Mac. Opening a pane
254
+ * grants nothing; the person flips the switch for Opengeni. */
255
+ export async function openMachinePrivacySettings(
256
+ services: Services,
257
+ input: {
258
+ enrollment: EnrollmentRecord;
259
+ access: EnrollmentAccess;
260
+ pane: MachinePrivacySettingsPane;
261
+ },
262
+ ): Promise<OpenMachinePrivacySettingsResponse> {
263
+ if (input.enrollment.os !== "macos") {
264
+ return OpenMachinePrivacySettingsResponse.parse({
265
+ opened: false,
266
+ message: "Privacy & Security panes exist only on macOS.",
267
+ });
268
+ }
269
+ const result = await runOnEnrollmentDirect(services, {
270
+ access: input.access,
271
+ enrollmentId: input.enrollment.id,
272
+ target: input.enrollment.id,
273
+ cmd: `open '${MAC_PRIVACY_PANE_URLS[input.pane]}'`,
274
+ execTimeoutMs: PRIVACY_PANE_TIMEOUT_MS,
275
+ });
276
+ const opened = result.ok && result.exitCode === 0;
277
+ if (!opened) {
278
+ services.observability?.warn?.("Could not open a macOS privacy pane", {
279
+ enrollmentId: input.enrollment.id,
280
+ pane: input.pane,
281
+ exitCode: result.ok ? (result.exitCode ?? null) : null,
282
+ timedOut: result.timedOut === true,
283
+ });
284
+ }
285
+ return OpenMachinePrivacySettingsResponse.parse({
286
+ opened,
287
+ message: opened ? null : "The Mac isn't reachable right now.",
288
+ });
289
+ }