@opengeni/core 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 (257) hide show
  1. package/README.md +4 -4
  2. package/dist/access/index.d.ts +131 -7
  3. package/dist/access/service-initiator.d.ts +3 -0
  4. package/dist/application/archived-session-imports.d.ts +6 -0
  5. package/dist/application/composer-submit.d.ts +1 -1
  6. package/dist/application/connect-operation.d.ts +6 -0
  7. package/dist/application/external-workspace-members.d.ts +13 -1
  8. package/dist/application/modal-native-live-declaration-join.d.ts +37 -0
  9. package/dist/application/modal-native-original-configuration.d.ts +79 -0
  10. package/dist/application/modal-native-worker-host-transport.d.ts +297 -0
  11. package/dist/application/new-session-drafts.d.ts +29 -2
  12. package/dist/application/organization-privacy.d.ts +57 -0
  13. package/dist/application/prepared-mcp-connection.d.ts +31 -0
  14. package/dist/application/sandbox-recovery.d.ts +58 -0
  15. package/dist/application/session-commands.d.ts +3 -0
  16. package/dist/application/session-tenancy.d.ts +13 -4
  17. package/dist/billing/agent-run-admission.d.ts +21 -0
  18. package/dist/billing/limits.d.ts +27 -1
  19. package/dist/billing/model-call-admission.d.ts +34 -0
  20. package/dist/billing/model-usage-settlement.d.ts +112 -0
  21. package/dist/canonical-human-identities.js +1 -1
  22. package/dist/{chunk-VCZFFEPB.js → chunk-7T2SZ7BI.js} +16 -2
  23. package/dist/chunk-7T2SZ7BI.js.map +1 -0
  24. package/dist/{chunk-ZYCNLYGH.js → chunk-OMJFIIWK.js} +178 -12
  25. package/dist/chunk-OMJFIIWK.js.map +1 -0
  26. package/dist/{chunk-H7X52RI2.js → chunk-QI2M2B2K.js} +83 -8
  27. package/dist/chunk-QI2M2B2K.js.map +1 -0
  28. package/dist/{chunk-OF65T3PM.js → chunk-TTWTXQB2.js} +94 -6
  29. package/dist/chunk-TTWTXQB2.js.map +1 -0
  30. package/dist/codex-model-availability.d.ts +55 -0
  31. package/dist/default-session-model.d.ts +192 -0
  32. package/dist/dependencies.d.ts +41 -7
  33. package/dist/developer-setup-credential-ceiling.d.ts +10 -0
  34. package/dist/domain/agent-config-resolution.d.ts +49 -0
  35. package/dist/domain/automations.d.ts +8 -1
  36. package/dist/domain/capabilities.d.ts +112 -8
  37. package/dist/domain/connection-account-selection-error.d.ts +8 -0
  38. package/dist/domain/connector-tool-permissions.d.ts +62 -0
  39. package/dist/domain/direct-model-provider.d.ts +3 -0
  40. package/dist/domain/editable-artifacts/agent-application.d.ts +10 -1
  41. package/dist/domain/editable-artifacts/durable-export.d.ts +22 -1
  42. package/dist/domain/editable-artifacts/ports.d.ts +10 -0
  43. package/dist/domain/editable-artifacts/service.d.ts +3 -1
  44. package/dist/domain/editable-artifacts/types.d.ts +1 -1
  45. package/dist/domain/encryption-key.d.ts +12 -0
  46. package/dist/domain/insights-timing.d.ts +16 -0
  47. package/dist/domain/insights-usage.d.ts +27 -0
  48. package/dist/domain/insights.d.ts +21 -3
  49. package/dist/domain/knowledge-files.d.ts +1 -1
  50. package/dist/domain/knowledge-preparation.d.ts +10 -0
  51. package/dist/domain/knowledge-preparation.test.d.ts +1 -0
  52. package/dist/domain/knowledge-search.d.ts +15 -76
  53. package/dist/domain/mcp-account-bindings.d.ts +17 -0
  54. package/dist/domain/mcp-account-routes.d.ts +21 -0
  55. package/dist/domain/native-mcp-connection-admission.d.ts +3 -0
  56. package/dist/domain/organization-integration-catalog.d.ts +15 -0
  57. package/dist/domain/personal-connection-delegations.d.ts +73 -12
  58. package/dist/domain/pr-review.d.ts +121 -6
  59. package/dist/domain/realtime-voice-billing.d.ts +103 -0
  60. package/dist/domain/resources.d.ts +17 -1
  61. package/dist/domain/scheduled-task-access.d.ts +265 -0
  62. package/dist/domain/scheduled-task-account-audit.d.ts +27 -0
  63. package/dist/domain/scheduled-task-audience.d.ts +70 -0
  64. package/dist/domain/scheduled-tasks.d.ts +61 -18
  65. package/dist/domain/session-connection-accounts.d.ts +53 -0
  66. package/dist/domain/session-file-access.d.ts +4 -0
  67. package/dist/domain/session-native-connection-replacement.d.ts +14 -0
  68. package/dist/domain/session-start-timing.d.ts +7 -0
  69. package/dist/domain/session-tool-policy.d.ts +102 -4
  70. package/dist/domain/sessions.d.ts +179 -15
  71. package/dist/domain/site-audience.d.ts +52 -0
  72. package/dist/domain/skills.d.ts +29 -1
  73. package/dist/domain/slack-bot.d.ts +46 -1
  74. package/dist/domain/slack-publication-secret-safety.d.ts +1 -1
  75. package/dist/domain/vaults/index.d.ts +7 -0
  76. package/dist/domain/vaults/mapping.d.ts +25 -0
  77. package/dist/domain/vaults/provider-registry.d.ts +72 -0
  78. package/dist/domain/vaults/provider-sync.d.ts +176 -0
  79. package/dist/domain/vaults/provider-writes.d.ts +57 -0
  80. package/dist/domain/vaults/secret-resolver.d.ts +34 -0
  81. package/dist/domain/vaults/types.d.ts +24 -0
  82. package/dist/domain/vaults/vault-service.d.ts +35 -0
  83. package/dist/domain/voice-input-billing.d.ts +77 -0
  84. package/dist/domain/web-search-billing.d.ts +51 -0
  85. package/dist/domain/workspace-credits.d.ts +7 -0
  86. package/dist/editable-artifact-live/application.d.ts +2 -1
  87. package/dist/editable-artifact-live/server.d.ts +5 -1
  88. package/dist/editable-artifact-live/ticket.d.ts +2 -1
  89. package/dist/editable-artifact-live/types.d.ts +9 -0
  90. package/dist/editable-artifact-live.js +2 -2
  91. package/dist/editable-artifacts.js +10 -2
  92. package/dist/goal-admission.d.ts +627 -0
  93. package/dist/host-session-usage-limit.d.ts +15 -0
  94. package/dist/index.d.ts +43 -8
  95. package/dist/index.js +22682 -11743
  96. package/dist/index.js.map +1 -1
  97. package/dist/managed-session.d.ts +110 -7
  98. package/dist/model-call.d.ts +58 -0
  99. package/dist/model-catalog.d.ts +29 -3
  100. package/dist/model-provider-credentials.d.ts +43 -0
  101. package/dist/product-usage-metrics.d.ts +30 -0
  102. package/dist/rigs/index.d.ts +1 -13
  103. package/dist/sandbox/fleet.d.ts +58 -4
  104. package/dist/sandbox/routing.d.ts +42 -2
  105. package/dist/sandbox/runtime-settings.d.ts +27 -17
  106. package/dist/session-authorization.d.ts +10 -0
  107. package/dist/session-usage-limit-metrics.d.ts +60 -0
  108. package/dist/session-usage-limits.d.ts +89 -0
  109. package/dist/site-agent-clamp.d.ts +71 -0
  110. package/dist/site-session-origin.d.ts +39 -2
  111. package/dist/transcription.d.ts +120 -3
  112. package/dist/turn-surface.d.ts +20 -0
  113. package/dist/user-presence.d.ts +32 -0
  114. package/dist/workflow-wake-contract.d.ts +13 -1
  115. package/package.json +15 -22
  116. package/src/access/index.ts +961 -38
  117. package/src/access/service-initiator.ts +50 -0
  118. package/src/application/api-integration-servers.ts +9 -0
  119. package/src/application/archived-session-imports.ts +161 -0
  120. package/src/application/composer-submit.ts +3 -2
  121. package/src/application/connect-authority.ts +3 -3
  122. package/src/application/connect-operation.ts +37 -3
  123. package/src/application/external-continuation.ts +20 -3
  124. package/src/application/external-link-work-admission.ts +3 -0
  125. package/src/application/external-workspace-members.ts +51 -3
  126. package/src/application/modal-native-live-declaration-join.ts +196 -0
  127. package/src/application/modal-native-original-configuration.ts +261 -0
  128. package/src/application/modal-native-worker-host-transport.ts +263 -0
  129. package/src/application/new-session-drafts.ts +172 -55
  130. package/src/application/organization-privacy.ts +161 -0
  131. package/src/application/prepared-mcp-connection.ts +133 -0
  132. package/src/application/sandbox-recovery.ts +78 -0
  133. package/src/application/session-commands.ts +73 -1
  134. package/src/application/session-mcp-credential-rotation.ts +61 -18
  135. package/src/application/session-tenancy.ts +262 -44
  136. package/src/application/user-resource-grants.ts +1 -29
  137. package/src/billing/agent-run-admission.ts +117 -0
  138. package/src/billing/limits.ts +138 -14
  139. package/src/billing/model-call-admission.ts +118 -0
  140. package/src/billing/model-usage-settlement.ts +472 -0
  141. package/src/codex-model-availability.ts +264 -0
  142. package/src/default-session-model.ts +692 -0
  143. package/src/dependencies.ts +48 -6
  144. package/src/developer-setup-credential-ceiling.ts +60 -0
  145. package/src/domain/agent-config-resolution.ts +148 -0
  146. package/src/domain/automations.ts +76 -2
  147. package/src/domain/capabilities.ts +830 -181
  148. package/src/domain/connection-account-selection-error.ts +19 -0
  149. package/src/domain/connector-tool-permissions.ts +572 -0
  150. package/src/domain/direct-model-provider.ts +62 -0
  151. package/src/domain/editable-artifacts/agent-application.ts +44 -6
  152. package/src/domain/editable-artifacts/durable-export.ts +100 -5
  153. package/src/domain/editable-artifacts/in-memory.ts +6 -0
  154. package/src/domain/editable-artifacts/ports.ts +11 -0
  155. package/src/domain/editable-artifacts/service.ts +20 -0
  156. package/src/domain/editable-artifacts/types.ts +1 -1
  157. package/src/domain/encryption-key.ts +26 -0
  158. package/src/domain/file-owner.ts +16 -1
  159. package/src/domain/github-action-policies.ts +1 -1
  160. package/src/domain/github-skill-source.ts +3 -1
  161. package/src/domain/insights-timing.ts +95 -0
  162. package/src/domain/insights-usage.ts +67 -0
  163. package/src/domain/insights.ts +167 -43
  164. package/src/domain/knowledge-files.ts +10 -3
  165. package/src/domain/knowledge-messages.ts +1 -0
  166. package/src/domain/knowledge-preparation.test.ts +276 -0
  167. package/src/domain/knowledge-preparation.ts +147 -0
  168. package/src/domain/knowledge-search.test.ts +617 -5
  169. package/src/domain/knowledge-search.ts +240 -23
  170. package/src/domain/mcp-account-bindings.ts +169 -0
  171. package/src/domain/mcp-account-routes.ts +152 -0
  172. package/src/domain/native-mcp-connection-admission.ts +14 -0
  173. package/src/domain/organization-integration-catalog.ts +88 -0
  174. package/src/domain/personal-connection-delegations.ts +399 -257
  175. package/src/domain/pr-review.ts +24 -8
  176. package/src/domain/realtime-voice-billing.ts +425 -0
  177. package/src/domain/resources.ts +50 -4
  178. package/src/domain/scheduled-task-access.ts +1089 -0
  179. package/src/domain/scheduled-task-account-audit.ts +90 -0
  180. package/src/domain/scheduled-task-audience.ts +249 -0
  181. package/src/domain/scheduled-tasks.ts +1313 -374
  182. package/src/domain/session-connection-accounts.ts +239 -0
  183. package/src/domain/session-file-access.ts +47 -0
  184. package/src/domain/session-native-connection-replacement.ts +64 -0
  185. package/src/domain/session-start-timing.ts +60 -0
  186. package/src/domain/session-tool-policy.ts +489 -14
  187. package/src/domain/sessions.ts +2254 -717
  188. package/src/domain/site-audience.ts +130 -0
  189. package/src/domain/skills.ts +9 -0
  190. package/src/domain/slack-bot.ts +141 -4
  191. package/src/domain/slack-publication-secret-safety.ts +1 -1
  192. package/src/domain/vaults/index.ts +19 -0
  193. package/src/domain/vaults/mapping.ts +190 -0
  194. package/src/domain/vaults/provider-registry.ts +201 -0
  195. package/src/domain/vaults/provider-sync.ts +531 -0
  196. package/src/domain/vaults/provider-writes.ts +288 -0
  197. package/src/domain/vaults/secret-resolver.ts +464 -0
  198. package/src/domain/vaults/types.ts +26 -0
  199. package/src/domain/vaults/vault-service.ts +1316 -0
  200. package/src/domain/voice-input-billing.ts +330 -0
  201. package/src/domain/web-search-billing.ts +169 -0
  202. package/src/domain/workspace-credits.ts +13 -0
  203. package/src/editable-artifact-live/application.ts +8 -1
  204. package/src/editable-artifact-live/server.ts +154 -6
  205. package/src/editable-artifact-live/ticket.ts +86 -1
  206. package/src/editable-artifact-live/types.ts +10 -0
  207. package/src/goal-admission.ts +220 -0
  208. package/src/host-session-usage-limit.ts +25 -0
  209. package/src/index.ts +75 -11
  210. package/src/managed-session.ts +137 -6
  211. package/src/model-call.ts +79 -0
  212. package/src/model-catalog.ts +345 -91
  213. package/src/model-provider-credentials.ts +394 -0
  214. package/src/product-usage-metrics.ts +101 -0
  215. package/src/rigs/index.ts +23 -111
  216. package/src/sandbox/fleet.ts +253 -28
  217. package/src/sandbox/routing.ts +204 -43
  218. package/src/sandbox/runtime-settings.ts +159 -85
  219. package/src/session-authorization.ts +172 -23
  220. package/src/session-usage-limit-metrics.ts +95 -0
  221. package/src/session-usage-limits.ts +415 -0
  222. package/src/site-agent-clamp.ts +226 -0
  223. package/src/site-session-origin.ts +84 -5
  224. package/src/transcription.ts +123 -4
  225. package/src/turn-surface.ts +47 -0
  226. package/src/user-presence.ts +134 -0
  227. package/src/workflow-wake-contract.ts +14 -1
  228. package/dist/application/host-mcp-owner.d.ts +0 -6
  229. package/dist/application/host-mcp-resolvers.d.ts +0 -13
  230. package/dist/chunk-5WZYFL45.js +0 -266
  231. package/dist/chunk-5WZYFL45.js.map +0 -1
  232. package/dist/chunk-H7X52RI2.js.map +0 -1
  233. package/dist/chunk-OF65T3PM.js.map +0 -1
  234. package/dist/chunk-VCZFFEPB.js.map +0 -1
  235. package/dist/chunk-ZYCNLYGH.js.map +0 -1
  236. package/dist/domain/connection-authority.d.ts +0 -97
  237. package/dist/domain/connection-authority.js +0 -169
  238. package/dist/domain/connection-authority.js.map +0 -1
  239. package/dist/domain/environments.d.ts +0 -33
  240. package/dist/domain/host-mcp-authority-source-admission.d.ts +0 -10
  241. package/dist/domain/host-mcp-task-admission.d.ts +0 -18
  242. package/dist/domain/packs.d.ts +0 -59
  243. package/dist/domain/product-integration-pack.d.ts +0 -44
  244. package/dist/domain/product-integration-skill.gen.d.ts +0 -5
  245. package/dist/remote-mcp-credentials.d.ts +0 -23
  246. package/dist/remote-mcp-credentials.js +0 -11
  247. package/dist/remote-mcp-credentials.js.map +0 -1
  248. package/src/application/host-mcp-owner.ts +0 -41
  249. package/src/application/host-mcp-resolvers.ts +0 -84
  250. package/src/domain/connection-authority.ts +0 -329
  251. package/src/domain/environments.ts +0 -120
  252. package/src/domain/host-mcp-authority-source-admission.ts +0 -25
  253. package/src/domain/host-mcp-task-admission.ts +0 -121
  254. package/src/domain/packs.ts +0 -699
  255. package/src/domain/product-integration-pack.ts +0 -42
  256. package/src/domain/product-integration-skill.gen.ts +0 -52
  257. package/src/remote-mcp-credentials.ts +0 -361
@@ -15,23 +15,27 @@ import { sandboxLifecycleTransitionWaitMs, type Settings } from "@opengeni/confi
15
15
  import { appendSessionCommandOutput } from "@opengeni/db/session-command-output";
16
16
  import {
17
17
  createProviderCommandRetainer,
18
- retainedProviderCommandPersistence,
18
+ supervisedCommandProtocolReady,
19
19
  } from "@opengeni/db/retained-provider-commands";
20
20
  import {
21
21
  advanceWorkspaceGenerationForDirectRequest,
22
+ retainedProviderCommandPersistence,
22
23
  advanceWorkspaceGenerationForRetainedProcess,
23
24
  getLiveEnrollmentConnection,
24
25
  getRetainedProcess,
25
26
  getSandbox,
26
27
  markWarmLeaseInstanceLost,
27
28
  readActiveSandbox,
29
+ resolvePersonalMachineConnectionForAttempt,
28
30
  retainWorkspaceMutationProcess,
29
31
  SandboxRetainedProcessPromotionFencedError,
32
+ SandboxWorkspaceMutationOutputRejectedError,
30
33
  retainedProcessSettlementIdentity,
31
34
  settleRetainedProcess,
32
35
  verifyDirectWorkspaceMutationSettlement,
33
36
  verifyRetainedProcessMutationSettlement,
34
37
  type Database,
38
+ type EnrollmentRecord,
35
39
  type SandboxRetainedProcess,
36
40
  type SandboxWorkspaceMutationAdmission,
37
41
  } from "@opengeni/db";
@@ -42,6 +46,7 @@ import {
42
46
  NatsControlRpc,
43
47
  NatsOpStreamTransport,
44
48
  RoutingSandboxSession,
49
+ RoutingMutationOutputRejectedError,
45
50
  resolveModalCheckpointProviderBindingForSession,
46
51
  type ControlRpc,
47
52
  type EstablishedSandboxSession,
@@ -52,6 +57,7 @@ import {
52
57
  type RoutingRetainedProcess,
53
58
  type RoutingRetainedProcessTerminalProof,
54
59
  type RoutingSandboxOperationObserver,
60
+ type RoutingSandboxCaptureWaitObserver,
55
61
  type SelfhostedRelayConfig,
56
62
  type SelfhostedConnectionBinding,
57
63
  type SelfhostedOpStreamDeps,
@@ -79,6 +85,18 @@ type DirectRetainedProcessRoute = {
79
85
  routeEpoch: number;
80
86
  };
81
87
 
88
+ /** Inline filesystem subprocesses stay durably retained for cancellation and
89
+ * recovery, but are not model-visible session background commands. */
90
+ export function directRetainedProcessBackgroundCommand(
91
+ process: Pick<RoutingRetainedProcess, "id">,
92
+ operation: string,
93
+ purpose?: "synchronous_filesystem",
94
+ ): { commandId: string; command: string } | undefined {
95
+ return purpose === "synchronous_filesystem"
96
+ ? undefined
97
+ : { commandId: process.id, command: operation };
98
+ }
99
+
82
100
  /** API-direct requests always use active-route authority. The default active
83
101
  * pointer is represented by a null target id; it is not a home-route write. */
84
102
  export function directRetainedProcessMatchesBackend(
@@ -116,9 +134,77 @@ export type ChannelARoutingServices = {
116
134
  settings: Settings;
117
135
  bus?: EventBus;
118
136
  onSandboxOperation?: RoutingSandboxOperationObserver;
137
+ onSandboxCaptureWait?: RoutingSandboxCaptureWaitObserver;
119
138
  waitSignal?: AbortSignal;
120
139
  };
121
140
 
141
+ /**
142
+ * Whose access a Channel-A request uses to reach a Connected Machine. A person
143
+ * uses their own. An agent acts for the person who started its turn, never as
144
+ * itself, so it reaches the same machines that person can; a personal (Only me)
145
+ * machine additionally needs that exact running attempt's per-chat permission,
146
+ * rechecked before every routed operation like the worker's turn path.
147
+ */
148
+ export type ChannelAMachineAuthority = {
149
+ subjectId: string;
150
+ personalMachineAttempt: {
151
+ turnId: string;
152
+ attemptId: string;
153
+ executionGeneration: number;
154
+ } | null;
155
+ };
156
+
157
+ /**
158
+ * Resolve a Connected Machine's live runner for one Channel-A request. The
159
+ * machine's audience can change in place, so its current scope is read from the
160
+ * enrollment itself. An agent attempt reaches a personal machine only through
161
+ * the same attempt admission as swap and run_on; everything else keeps the
162
+ * caller-scoped lookup.
163
+ */
164
+ export async function resolveChannelAMachineConnection(
165
+ db: Database,
166
+ input: {
167
+ accountId: string;
168
+ workspaceId: string;
169
+ sessionId: string;
170
+ machineWorkspaceId: string;
171
+ enrollmentId: string;
172
+ },
173
+ authority: ChannelAMachineAuthority,
174
+ ): Promise<EnrollmentRecord | null> {
175
+ const attempt = authority.personalMachineAttempt;
176
+ if (attempt) {
177
+ const current = await getLiveEnrollmentConnection(
178
+ db,
179
+ input.machineWorkspaceId,
180
+ input.enrollmentId,
181
+ );
182
+ if (!current) return null;
183
+ if (current.scope === "user") {
184
+ return await resolvePersonalMachineConnectionForAttempt(db, {
185
+ accountId: input.accountId,
186
+ workspaceId: input.workspaceId,
187
+ subjectId: authority.subjectId,
188
+ sessionId: input.sessionId,
189
+ turnId: attempt.turnId,
190
+ attemptId: attempt.attemptId,
191
+ executionGeneration: attempt.executionGeneration,
192
+ enrollmentId: input.enrollmentId,
193
+ requireActiveSandbox: true,
194
+ });
195
+ }
196
+ }
197
+ return await getLiveEnrollmentConnection(
198
+ db,
199
+ {
200
+ accountId: input.accountId,
201
+ workspaceId: input.workspaceId,
202
+ subjectId: authority.subjectId,
203
+ },
204
+ input.enrollmentId,
205
+ );
206
+ }
207
+
122
208
  /** Map the deployment relay URL to the leaf's `SelfhostedRelayConfig` shape. The
123
209
  * relay URL (`OPENGENI_SELFHOSTED_RELAY_URL`) may carry a path (the relay's wss
124
210
  * route); a path-less URL defaults to the relay's `/stream` route (M8b). */
@@ -175,11 +261,22 @@ function controlRpcFactory(bus: EventBus | undefined): () => ControlRpc {
175
261
 
176
262
  async function resolveSelfhostedConnection(
177
263
  services: ChannelARoutingServices,
178
- access: string | { accountId: string; workspaceId: string; subjectId: string },
264
+ ids: { accountId: string; workspaceId: string; sessionId: string },
265
+ authority: ChannelAMachineAuthority,
179
266
  sandbox: RoutableSandbox,
180
267
  ): Promise<SelfhostedConnectionBinding | null> {
181
268
  if (!sandbox.enrollmentId) return null;
182
- const enrollment = await getLiveEnrollmentConnection(services.db, access, sandbox.enrollmentId);
269
+ const enrollment = await resolveChannelAMachineConnection(
270
+ services.db,
271
+ {
272
+ accountId: ids.accountId,
273
+ workspaceId: ids.workspaceId,
274
+ sessionId: ids.sessionId,
275
+ machineWorkspaceId: sandbox.workspaceId,
276
+ enrollmentId: sandbox.enrollmentId,
277
+ },
278
+ authority,
279
+ );
183
280
  if (!enrollment?.connectionInstanceId) return null;
184
281
  const opStream: SelfhostedOpStreamDeps | undefined =
185
282
  services.settings.agentOpStreamEnabled === true &&
@@ -220,6 +317,10 @@ export function wrapChannelABoxWithRouting(
220
317
  workspaceId: string;
221
318
  sessionId: string;
222
319
  resourceSubjectId: string;
320
+ /** Whose access reaches Connected Machines (see ChannelAMachineAuthority).
321
+ * Resolved lazily, once, only when a request routes to a machine. Omitted,
322
+ * the request uses `resourceSubjectId`'s own access. */
323
+ machineAuthority?: () => Promise<ChannelAMachineAuthority>;
223
324
  homeLease?: {
224
325
  sandboxGroupId: string;
225
326
  leaseEpoch: number;
@@ -242,6 +343,16 @@ export function wrapChannelABoxWithRouting(
242
343
  ): EstablishedSandboxSession {
243
344
  const { db, settings, bus } = services;
244
345
  const homeLease = ids.homeLease;
346
+ let machineAuthority: Promise<ChannelAMachineAuthority> | undefined;
347
+ const resolveMachineAuthority = (): Promise<ChannelAMachineAuthority> => {
348
+ machineAuthority ??= ids.machineAuthority
349
+ ? ids.machineAuthority()
350
+ : Promise.resolve({
351
+ subjectId: ids.resourceSubjectId,
352
+ personalMachineAttempt: null,
353
+ });
354
+ return machineAuthority;
355
+ };
245
356
  const beforeMutation = homeLease
246
357
  ? async ({
247
358
  op,
@@ -292,13 +403,15 @@ export function wrapChannelABoxWithRouting(
292
403
  admission,
293
404
  outcome,
294
405
  retainedProcess,
406
+ retainedProcessPurpose,
295
407
  }: {
296
408
  op: string;
297
409
  backend: ResolvedActiveBackend;
298
410
  admission: unknown;
299
- outcome: "resolved" | "rejected";
411
+ outcome: "resolved" | "rejected" | "outcome_unknown";
300
412
  result?: unknown;
301
413
  retainedProcess?: RoutingRetainedProcess;
414
+ retainedProcessPurpose?: "synchronous_filesystem";
302
415
  }): Promise<void> => {
303
416
  if (admission === null) return;
304
417
  if (
@@ -320,7 +433,12 @@ export function wrapChannelABoxWithRouting(
320
433
  ) {
321
434
  throw new Error("API-direct workspace mutation settlement lacked its bound admission");
322
435
  }
323
- if (outcome === "resolved" && retainedProcess) {
436
+ if ((outcome === "resolved" || outcome === "outcome_unknown") && retainedProcess) {
437
+ const backgroundCommand = directRetainedProcessBackgroundCommand(
438
+ retainedProcess,
439
+ op,
440
+ retainedProcessPurpose,
441
+ );
324
442
  await retainWorkspaceProviderCommand(db, {
325
443
  accountId: ids.accountId,
326
444
  workspaceId: ids.workspaceId,
@@ -334,10 +452,7 @@ export function wrapChannelABoxWithRouting(
334
452
  admittedWorkspaceGeneration: exactAdmission.workspaceGeneration,
335
453
  operation: op,
336
454
  providerBinding: boundAdmission.providerBinding ?? null,
337
- backgroundCommand: {
338
- commandId: retainedProcess.id,
339
- command: op,
340
- },
455
+ ...(backgroundCommand ? { backgroundCommand } : {}),
341
456
  owner: {
342
457
  kind: "direct",
343
458
  requestId: ids.directRequest.requestId,
@@ -352,22 +467,42 @@ export function wrapChannelABoxWithRouting(
352
467
  });
353
468
  return;
354
469
  }
355
- await verifyDirectWorkspaceMutationSettlement(db, {
356
- accountId: ids.accountId,
357
- workspaceId: ids.workspaceId,
358
- sessionId: ids.sessionId,
359
- requestId: ids.directRequest.requestId,
360
- holderId: ids.directRequest.holderId,
361
- initiatorSubjectId: ids.resourceSubjectId,
362
- sandboxGroupId: homeLease.sandboxGroupId,
363
- expectedEpoch: backend.leaseEpoch,
364
- expectedInstanceId: backend.providerInstanceId,
365
- routeTargetId: exactAdmission.routeTargetId,
366
- routeEpoch: exactAdmission.routeEpoch,
367
- admission: exactAdmission,
368
- operation: op,
369
- outcome,
370
- });
470
+ if (outcome === "outcome_unknown")
471
+ throw new Error(
472
+ "Outcome-unknown command settlement requires its exact retained invocation",
473
+ );
474
+ try {
475
+ await verifyDirectWorkspaceMutationSettlement(db, {
476
+ accountId: ids.accountId,
477
+ workspaceId: ids.workspaceId,
478
+ sessionId: ids.sessionId,
479
+ requestId: ids.directRequest.requestId,
480
+ holderId: ids.directRequest.holderId,
481
+ initiatorSubjectId: ids.resourceSubjectId,
482
+ sandboxGroupId: homeLease.sandboxGroupId,
483
+ expectedEpoch: backend.leaseEpoch,
484
+ expectedInstanceId: backend.providerInstanceId,
485
+ routeTargetId: exactAdmission.routeTargetId,
486
+ routeEpoch: exactAdmission.routeEpoch,
487
+ admission: exactAdmission,
488
+ operation: op,
489
+ outcome,
490
+ });
491
+ } catch (error) {
492
+ if (
493
+ error instanceof SandboxWorkspaceMutationOutputRejectedError &&
494
+ error.matchesPhysicalSettlement({
495
+ accountId: ids.accountId,
496
+ workspaceId: ids.workspaceId,
497
+ admission: exactAdmission,
498
+ operation: op,
499
+ outcome,
500
+ })
501
+ ) {
502
+ throw new RoutingMutationOutputRejectedError(op, error.code, { cause: error });
503
+ }
504
+ throw error;
505
+ }
371
506
  }
372
507
  : undefined;
373
508
  const beforeProcessMutation = homeLease
@@ -412,15 +547,31 @@ export function wrapChannelABoxWithRouting(
412
547
  ) {
413
548
  throw new Error("API retained-process mutation settlement lacked its exact admission");
414
549
  }
415
- await verifyRetainedProcessMutationSettlement(db, {
416
- accountId: ids.accountId,
417
- workspaceId: ids.workspaceId,
418
- sessionId: ids.sessionId,
419
- processId: process.id,
420
- admission: admission as SandboxWorkspaceMutationAdmission,
421
- operation: op,
422
- outcome,
423
- });
550
+ try {
551
+ await verifyRetainedProcessMutationSettlement(db, {
552
+ accountId: ids.accountId,
553
+ workspaceId: ids.workspaceId,
554
+ sessionId: ids.sessionId,
555
+ processId: process.id,
556
+ admission: admission as SandboxWorkspaceMutationAdmission,
557
+ operation: op,
558
+ outcome,
559
+ });
560
+ } catch (error) {
561
+ if (
562
+ error instanceof SandboxWorkspaceMutationOutputRejectedError &&
563
+ error.matchesPhysicalSettlement({
564
+ accountId: ids.accountId,
565
+ workspaceId: ids.workspaceId,
566
+ admission: admission as SandboxWorkspaceMutationAdmission,
567
+ operation: op,
568
+ outcome,
569
+ })
570
+ ) {
571
+ throw new RoutingMutationOutputRejectedError(op, error.code, { cause: error });
572
+ }
573
+ throw error;
574
+ }
424
575
  }
425
576
  : undefined;
426
577
  const settleProcess = homeLease
@@ -474,12 +625,13 @@ export function wrapChannelABoxWithRouting(
474
625
  defaultBackend: established.session as RoutableBackendSession,
475
626
  defaultKind: established.backendId,
476
627
  getSandbox: async (sandboxId): Promise<RoutableSandbox | null> => {
628
+ const authority = await resolveMachineAuthority();
477
629
  const sandbox = await getSandbox(
478
630
  db,
479
631
  {
480
632
  accountId: ids.accountId,
481
633
  workspaceId: ids.workspaceId,
482
- subjectId: ids.resourceSubjectId,
634
+ subjectId: authority.subjectId,
483
635
  },
484
636
  sandboxId,
485
637
  );
@@ -494,14 +646,15 @@ export function wrapChannelABoxWithRouting(
494
646
  : null;
495
647
  },
496
648
  controlRpcFactory: controlRpcFactory(bus),
497
- resolveSelfhostedConnection: (sandbox) =>
649
+ resolveSelfhostedConnection: async (sandbox) =>
498
650
  resolveSelfhostedConnection(
499
651
  services,
500
652
  {
501
653
  accountId: ids.accountId,
502
654
  workspaceId: ids.workspaceId,
503
- subjectId: ids.resourceSubjectId,
655
+ sessionId: ids.sessionId,
504
656
  },
657
+ await resolveMachineAuthority(),
505
658
  sandbox,
506
659
  ),
507
660
  relay: relayConfigFromSettings(settings),
@@ -530,17 +683,23 @@ export function wrapChannelABoxWithRouting(
530
683
  });
531
684
 
532
685
  const proxy = new RoutingSandboxSession({
686
+ providerSupervisionReady: async () =>
687
+ settings.modalCommandSupervisionEnabled && (await supervisedCommandProtocolReady(db)),
533
688
  providerCommandHandle: (value) =>
534
689
  value && typeof value === "object"
535
690
  ? (value as PersistableMutationAdmission).admission?.workspaceGeneration
536
691
  : undefined,
537
692
  providerCommandPersistence: (process) =>
538
- retainedProviderCommandPersistence(db, {
539
- accountId: ids.accountId,
540
- workspaceId: ids.workspaceId,
541
- sessionId: ids.sessionId,
542
- processId: process.id,
543
- }),
693
+ retainedProviderCommandPersistence(
694
+ db,
695
+ {
696
+ accountId: ids.accountId,
697
+ workspaceId: ids.workspaceId,
698
+ sessionId: ids.sessionId,
699
+ processId: process.id,
700
+ },
701
+ bus ? (events) => bus.publish(ids.workspaceId, ids.sessionId, events) : undefined,
702
+ ),
544
703
  captureProcessOutput: async ({ process, chunkId, chunk, stream, streamFidelity }) => {
545
704
  const events = await appendSessionCommandOutput(db, {
546
705
  accountId: ids.accountId,
@@ -576,6 +735,7 @@ export function wrapChannelABoxWithRouting(
576
735
  },
577
736
  resolveActiveBackend: resolver,
578
737
  ...(services.onSandboxOperation ? { onOperation: services.onSandboxOperation } : {}),
738
+ ...(services.onSandboxCaptureWait ? { onCaptureWait: services.onSandboxCaptureWait } : {}),
579
739
  ...(beforeMutation ? { beforeMutation } : {}),
580
740
  ...(afterMutation ? { afterMutation } : {}),
581
741
  ...(beforeProcessMutation ? { beforeProcessMutation } : {}),
@@ -591,6 +751,7 @@ export function wrapChannelABoxWithRouting(
591
751
  sandboxGroupId: homeLease.sandboxGroupId,
592
752
  expectedEpoch: homeLease.leaseEpoch,
593
753
  expectedInstanceId: homeLease.instanceId,
754
+ expectedBackend: homeLease.backend,
594
755
  diagnostic: "provider_not_found_during_routed_operation",
595
756
  });
596
757
  if (marked.status === "marked" && bus) {