@namzu/sandbox 13.0.0 → 14.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 (67) hide show
  1. package/CHANGELOG.md +309 -0
  2. package/README.md +151 -0
  3. package/dist/backends/firecracker/protocol.d.ts +22 -0
  4. package/dist/backends/firecracker/protocol.d.ts.map +1 -1
  5. package/dist/backends/firecracker/protocol.js.map +1 -1
  6. package/dist/backends/firecracker/transport.d.ts +104 -9
  7. package/dist/backends/firecracker/transport.d.ts.map +1 -1
  8. package/dist/backends/firecracker/transport.js +139 -13
  9. package/dist/backends/firecracker/transport.js.map +1 -1
  10. package/dist/backends/kubernetes/egress-policy.d.ts +219 -0
  11. package/dist/backends/kubernetes/egress-policy.d.ts.map +1 -0
  12. package/dist/backends/kubernetes/egress-policy.js +314 -0
  13. package/dist/backends/kubernetes/egress-policy.js.map +1 -0
  14. package/dist/backends/kubernetes/index.d.ts +374 -0
  15. package/dist/backends/kubernetes/index.d.ts.map +1 -0
  16. package/dist/backends/kubernetes/index.js +671 -0
  17. package/dist/backends/kubernetes/index.js.map +1 -0
  18. package/dist/backends/kubernetes/k8s-client.d.ts +125 -0
  19. package/dist/backends/kubernetes/k8s-client.d.ts.map +1 -0
  20. package/dist/backends/kubernetes/k8s-client.js +246 -0
  21. package/dist/backends/kubernetes/k8s-client.js.map +1 -0
  22. package/dist/backends/kubernetes/lease.d.ts +119 -0
  23. package/dist/backends/kubernetes/lease.d.ts.map +1 -0
  24. package/dist/backends/kubernetes/lease.js +151 -0
  25. package/dist/backends/kubernetes/lease.js.map +1 -0
  26. package/dist/backends/kubernetes/objects.d.ts +282 -0
  27. package/dist/backends/kubernetes/objects.d.ts.map +1 -0
  28. package/dist/backends/kubernetes/objects.js +156 -0
  29. package/dist/backends/kubernetes/objects.js.map +1 -0
  30. package/dist/backends/kubernetes/privilege-probe.d.ts +136 -0
  31. package/dist/backends/kubernetes/privilege-probe.d.ts.map +1 -0
  32. package/dist/backends/kubernetes/privilege-probe.js +185 -0
  33. package/dist/backends/kubernetes/privilege-probe.js.map +1 -0
  34. package/dist/backends/kubernetes/sandbox.d.ts +123 -0
  35. package/dist/backends/kubernetes/sandbox.d.ts.map +1 -0
  36. package/dist/backends/kubernetes/sandbox.js +299 -0
  37. package/dist/backends/kubernetes/sandbox.js.map +1 -0
  38. package/dist/backends/kubernetes/transport.d.ts +122 -0
  39. package/dist/backends/kubernetes/transport.d.ts.map +1 -0
  40. package/dist/backends/kubernetes/transport.js +197 -0
  41. package/dist/backends/kubernetes/transport.js.map +1 -0
  42. package/dist/backends/kubernetes/workspace.d.ts +381 -0
  43. package/dist/backends/kubernetes/workspace.d.ts.map +1 -0
  44. package/dist/backends/kubernetes/workspace.js +1064 -0
  45. package/dist/backends/kubernetes/workspace.js.map +1 -0
  46. package/dist/index.d.ts +132 -2
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +102 -34
  49. package/dist/index.js.map +1 -1
  50. package/dist/testing/sandbox-conformance.d.ts +193 -0
  51. package/dist/testing/sandbox-conformance.d.ts.map +1 -0
  52. package/dist/testing/sandbox-conformance.js +465 -0
  53. package/dist/testing/sandbox-conformance.js.map +1 -0
  54. package/package.json +5 -4
  55. package/src/backends/firecracker/protocol.ts +27 -0
  56. package/src/backends/firecracker/transport.ts +199 -28
  57. package/src/backends/kubernetes/egress-policy.ts +437 -0
  58. package/src/backends/kubernetes/index.ts +1012 -0
  59. package/src/backends/kubernetes/k8s-client.ts +352 -0
  60. package/src/backends/kubernetes/lease.ts +198 -0
  61. package/src/backends/kubernetes/objects.ts +363 -0
  62. package/src/backends/kubernetes/privilege-probe.ts +261 -0
  63. package/src/backends/kubernetes/sandbox.ts +395 -0
  64. package/src/backends/kubernetes/transport.ts +286 -0
  65. package/src/backends/kubernetes/workspace.ts +1386 -0
  66. package/src/index.ts +257 -35
  67. package/src/testing/sandbox-conformance.ts +667 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox-conformance.js","sourceRoot":"","sources":["../../src/testing/sandbox-conformance.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@namzu/sandbox",
3
- "version": "13.0.0",
3
+ "version": "14.0.0",
4
4
  "description": "Pluggable sandbox provider for @namzu/sdk. Process-level isolation (bubblewrap on Linux, Seatbelt on macOS, via @anthropic-ai/sandbox-runtime) for developer dev loops; container-level isolation (HTTP worker + a loopback-bound egress proxy that allows by resolved address and brokers outbound credentials so they never enter the sandbox) for multi-tenant production. Backend selected at construction time; the SDK consumes both through the same SandboxProvider interface.",
5
5
  "license": "FSL-1.1-MIT",
6
6
  "engines": {
@@ -46,19 +46,20 @@
46
46
  "provenance": true
47
47
  },
48
48
  "peerDependencies": {
49
- "@namzu/sdk": "^39.0.0"
49
+ "@namzu/sdk": "^40.0.0"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@biomejs/biome": "^1.9.4",
53
53
  "@types/node": "^22.19.17",
54
54
  "typescript": "^5.5.0",
55
55
  "vitest": "^3.2.6",
56
- "@namzu/sdk": "^39.0.0"
56
+ "yaml": "^2.9.0",
57
+ "@namzu/sdk": "^40.0.0"
57
58
  },
58
59
  "scripts": {
59
60
  "build": "tsc --build",
60
61
  "dev": "tsc --build --watch",
61
- "lint": "biome check src/ worker/ agent/",
62
+ "lint": "biome check src/ worker/ agent/ k8s/",
62
63
  "lint:fix": "biome check --write src/",
63
64
  "format": "biome format --write src/",
64
65
  "test": "vitest run --passWithNoTests",
@@ -19,6 +19,33 @@ import type { SandboxExecOptions, SandboxExecResult } from '@namzu/sdk'
19
19
 
20
20
  import { RemoteCommandError, RemoteProtocolError } from '../remote-execution-controller.js'
21
21
 
22
+ // ---------------------------------------------------------------------------
23
+ // Credential — the one optional field every request envelope may carry
24
+ // ---------------------------------------------------------------------------
25
+
26
+ /**
27
+ * The per-instance credential a framed request may present, mixed into
28
+ * the request envelope alongside its `op`.
29
+ *
30
+ * Absent on the vsock and unix transports: that control channel is
31
+ * host↔guest only and never traverses guest egress, so the guest agent
32
+ * authenticates nothing there and this field is simply never written.
33
+ * A guest reached over a ROUTED network has no such boundary, so it is
34
+ * started with a per-instance token (`NAMZU_AGENT_BIND_TOKEN`, fed the
35
+ * pod's own identity by its orchestrator) and refuses every op but
36
+ * `healthz` that does not present exactly that value — from the first
37
+ * frame, since the agent dispatches a connection on its first frame and
38
+ * there is no handshake to defer the check to.
39
+ *
40
+ * The field is OPTIONAL and additive, so a host that never sets it
41
+ * speaks the same wire it always did and
42
+ * `FIRECRACKER_AGENT_PROTOCOL_VERSION` is deliberately unchanged: this
43
+ * needs no coupled golden-image and host rollout.
44
+ */
45
+ export interface AgentRequestCredential {
46
+ readonly token?: string
47
+ }
48
+
22
49
  // ---------------------------------------------------------------------------
23
50
  // Exec — request + the NDJSON event shapes (verbatim from worker/server.js)
24
51
  // ---------------------------------------------------------------------------
@@ -73,6 +73,7 @@ import {
73
73
  RemoteProtocolError,
74
74
  } from '../remote-execution-controller.js'
75
75
  import {
76
+ type AgentRequestCredential,
76
77
  type ExecRequest,
77
78
  ExecResultAccumulator,
78
79
  type ReadFileRequest,
@@ -117,6 +118,18 @@ import {
117
118
  * (`tls.TLSSocket` is a `net.Socket`). The container-app NEVER sees
118
119
  * a host-local `udsPath`; the cert material is injected by the
119
120
  * Vandal host layer, never returned by the orchestrator.
121
+ * - `tcp` — the guest agent listening directly on a routed pod
122
+ * network (the kubernetes backend). The dialer does a plain
123
+ * `net.connect({ host, port })` — no relay, no routing preamble, no
124
+ * ack: there is nothing between the host and the guest's own listen
125
+ * socket to route through, so the framing loop starts on the very
126
+ * first byte, exactly as the `unix` arm's does. `host` may be a
127
+ * Service FQDN rather than a literal IP; every call dials fresh (see
128
+ * `dial()` below), so DNS is re-resolved on every request and a
129
+ * resumed pod's new address is picked up for free. `token` rides in
130
+ * each request envelope (see `AgentRequestCredential` in
131
+ * `protocol.ts`) because a routed listener authenticates what the
132
+ * vsock/unix control channel never had to.
120
133
  */
121
134
  export type SandboxAgentHandle =
122
135
  | { readonly kind: 'unix'; readonly path: string }
@@ -133,6 +146,7 @@ export type SandboxAgentHandle =
133
146
  readonly servername?: string
134
147
  }
135
148
  }
149
+ | { readonly kind: 'tcp'; readonly host: string; readonly port: number; readonly token?: string }
136
150
 
137
151
  /**
138
152
  * The mTLS cert material the consumer injects onto a wire `mtls` handle (the
@@ -148,12 +162,17 @@ export interface MtlsClientMaterial {
148
162
  }
149
163
 
150
164
  /**
151
- * The WIRE shape of an agent handle as the orchestrator returns it. Identical
152
- * to {@link SandboxAgentHandle} EXCEPT the `mtls` arm omits the `tls` cert
153
- * block: the orchestrator returns only host/port/sandboxId, and the consumer
154
- * (Vandal host layer) merges the cert material in (see `normalizeHandle`)
155
- * before constructing the transport. The `unix`/`vsock` arms are unchanged
156
- * (they carry no cert material).
165
+ * The WIRE shape of an agent handle as the FIRECRACKER orchestrator
166
+ * returns it. Identical to {@link SandboxAgentHandle} EXCEPT the `mtls`
167
+ * arm omits the `tls` cert block: the orchestrator returns only
168
+ * host/port/sandboxId, and the consumer (Vandal host layer) merges the
169
+ * cert material in (see `normalizeHandle`) before constructing the
170
+ * transport. The `unix`/`vsock` arms are unchanged (they carry no cert
171
+ * material). There is deliberately no `tcp` arm here: that kind belongs
172
+ * to the kubernetes backend, which builds its {@link SandboxAgentHandle}
173
+ * directly (host/port from the claimed Sandbox's status, token from the
174
+ * pod's own identity) and never goes through this orchestrator wire
175
+ * shape or `normalizeHandle`.
157
176
  */
158
177
  export type WireSandboxAgentHandle =
159
178
  | { readonly kind: 'unix'; readonly path: string }
@@ -174,7 +193,7 @@ export type WireSandboxAgentHandle =
174
193
  * used the URL path (`/execute`, `/read-file`, `/write-file`,
175
194
  * `/healthz`) — over vsock the same selector rides in the framed JSON.
176
195
  */
177
- export type AgentRequest =
196
+ export type AgentRequest = (
178
197
  | { readonly op: 'execute'; readonly body: ExecRequest }
179
198
  | { readonly op: 'reserve-execution' }
180
199
  | {
@@ -186,6 +205,12 @@ export type AgentRequest =
186
205
  | { readonly op: 'terminal'; readonly body: TerminalOpenRequest }
187
206
  | { readonly op: 'tcp-connect'; readonly body: TcpConnectRequest }
188
207
  | { readonly op: 'healthz' }
208
+ ) &
209
+ // Intersected, not repeated per arm: the credential is orthogonal to
210
+ // the op, and every arm may carry it. Optional and additive, so a host
211
+ // that writes no token speaks the wire it always did — see
212
+ // {@link AgentRequestCredential}.
213
+ AgentRequestCredential
189
214
 
190
215
  export interface VsockTransportOptions {
191
216
  /** Per-attempt connect + handshake timeout. Default 5000ms. */
@@ -202,6 +227,15 @@ export interface VsockTransportOptions {
202
227
  * against the agent's fresh listen socket. Default 60000ms.
203
228
  */
204
229
  readonly readIdleTimeoutMs?: number
230
+ /**
231
+ * Fires once per successful dial with how long the connect took, in
232
+ * milliseconds. Never fires with the handle's `token` or any request
233
+ * content — a bare number. Used by callers that build their own
234
+ * `RemoteExecutionAdapter` on top of this transport (the kubernetes
235
+ * backend's `KubernetesAgentTransport`) to attribute wall time; the
236
+ * vsock/mtls/unix arms are free to ignore it.
237
+ */
238
+ readonly onDial?: (durationMs: number) => void
205
239
  }
206
240
 
207
241
  const DEFAULT_CONNECT_TIMEOUT_MS = 5_000
@@ -217,6 +251,39 @@ const EXECUTION_TRANSPORT_GRACE_MS = 10_000
217
251
  const POST_RESPONSE_CLOSE_TIMEOUT_MS = 1_000
218
252
  const MAX_TIMER_DELAY_MS = 2_147_483_647
219
253
 
254
+ /**
255
+ * The guest agent's default pre-auth frame ceiling for a routed (`tcp`)
256
+ * connection — mirrors `agent.cjs`'s `MAX_PREAUTH_FRAME_BYTES`
257
+ * (`NAMZU_AGENT_MAX_PREAUTH_FRAME_BYTES`, default 8 MiB). The gate on
258
+ * that side cannot run until a whole frame is parsed (the credential
259
+ * rides inside the envelope), so it bounds what an UNAUTHENTICATED
260
+ * connection's first frame may announce. This transport dials fresh per
261
+ * call — there is no persistent, already-authenticated connection to
262
+ * reuse — so EVERY `tcp` request is that connection's first frame, and
263
+ * this ceiling is therefore the effective per-request budget, not just
264
+ * a one-time cost paid on first use.
265
+ *
266
+ * Checked here, client-side, BEFORE dialing: an oversized request fails
267
+ * fast with a clear error instead of opening a connection the guest is
268
+ * going to refuse anyway. Chunking a `write-file` body across multiple
269
+ * frames would lift this ceiling; it is a documented follow-up, not
270
+ * implemented by this transport.
271
+ */
272
+ export const TCP_PREAUTH_FRAME_LIMIT_BYTES = 8 * 1024 * 1024
273
+
274
+ /**
275
+ * Thrown when a `tcp`-handle request's framed envelope (op + body +
276
+ * token) would exceed {@link TCP_PREAUTH_FRAME_LIMIT_BYTES}. Named so a
277
+ * caller can distinguish "this body needs chunking" from every other
278
+ * transport failure.
279
+ */
280
+ export class AgentPreauthFrameTooLargeError extends Error {
281
+ constructor(message: string) {
282
+ super(message)
283
+ this.name = 'AgentPreauthFrameTooLargeError'
284
+ }
285
+ }
286
+
220
287
  /** Exact guest wire version accepted by this Firecracker transport. */
221
288
  export const FIRECRACKER_AGENT_PROTOCOL_VERSION = REMOTE_EXECUTION_PROTOCOL_VERSION
222
289
 
@@ -286,6 +353,7 @@ export class VsockAgentTransport {
286
353
  private readonly connectRetryBudgetMs: number
287
354
  private readonly connectRetryIntervalMs: number
288
355
  private readonly readIdleTimeoutMs: number
356
+ private readonly onDial?: (durationMs: number) => void
289
357
  private readonly executionController: RemoteExecutionController<
290
358
  Pick<ExecRequest, 'stdin' | 'maxOutputBytes'>
291
359
  >
@@ -297,6 +365,7 @@ export class VsockAgentTransport {
297
365
  this.connectRetryIntervalMs =
298
366
  options.connectRetryIntervalMs ?? DEFAULT_CONNECT_RETRY_INTERVAL_MS
299
367
  this.readIdleTimeoutMs = options.readIdleTimeoutMs ?? DEFAULT_READ_IDLE_TIMEOUT_MS
368
+ this.onDial = options.onDial
300
369
  const adapter: RemoteExecutionAdapter<Pick<ExecRequest, 'stdin' | 'maxOutputBytes'>> = {
301
370
  label: 'framed microVM agent',
302
371
  reserve: async (signal) => await this.reserveExecution(signal),
@@ -330,11 +399,14 @@ export class VsockAgentTransport {
330
399
  */
331
400
  private async dial(signal?: AbortSignal): Promise<net.Socket> {
332
401
  const deadline = Date.now() + this.connectRetryBudgetMs
402
+ const dialStartedAt = Date.now()
333
403
  let lastErr: unknown
334
404
  for (;;) {
335
405
  signal?.throwIfAborted()
336
406
  try {
337
- return await this.connectOnce(signal)
407
+ const socket = await this.connectOnce(signal)
408
+ this.onDial?.(Date.now() - dialStartedAt)
409
+ return socket
338
410
  } catch (err) {
339
411
  if (signal?.aborted) throw signal.reason
340
412
  lastErr = err
@@ -353,6 +425,7 @@ export class VsockAgentTransport {
353
425
  private connectOnce(signal?: AbortSignal): Promise<net.Socket> {
354
426
  const handle = this.handle
355
427
  if (handle.kind === 'mtls') return this.connectOnceMtls(handle, signal)
428
+ if (handle.kind === 'tcp') return this.connectOnceTcp(handle, signal)
356
429
  return new Promise<net.Socket>((resolve, reject) => {
357
430
  const path = handle.kind === 'unix' ? handle.path : handle.udsPath
358
431
  const socket = net.connect({ path })
@@ -508,12 +581,89 @@ export class VsockAgentTransport {
508
581
  })
509
582
  }
510
583
 
584
+ /**
585
+ * Dial a `tcp` handle: a plain `net.connect({ host, port })`. NO
586
+ * routing preamble and NO ack — there is no relay to route through
587
+ * and no handshake line the guest expects, so the socket is handed
588
+ * to the framing loop the instant it connects, exactly like the
589
+ * `unix` arm above (whose body this deliberately does not touch).
590
+ */
591
+ private connectOnceTcp(
592
+ handle: Extract<SandboxAgentHandle, { kind: 'tcp' }>,
593
+ signal?: AbortSignal,
594
+ ): Promise<net.Socket> {
595
+ return new Promise<net.Socket>((resolve, reject) => {
596
+ const socket = net.connect({ host: handle.host, port: handle.port })
597
+ let settled = false
598
+ const fail = (err: Error) => {
599
+ if (settled) return
600
+ settled = true
601
+ clearTimeout(timer)
602
+ signal?.removeEventListener('abort', abort)
603
+ socket.destroy()
604
+ reject(err)
605
+ }
606
+ const abort = () => fail(signalError(signal))
607
+ const timer = setTimeout(
608
+ () => fail(new Error(`connect/handshake timed out after ${this.connectTimeoutMs}ms`)),
609
+ this.connectTimeoutMs,
610
+ )
611
+ timer.unref()
612
+
613
+ socket.once('error', fail)
614
+ if (signal?.aborted) {
615
+ abort()
616
+ return
617
+ }
618
+ signal?.addEventListener('abort', abort, { once: true })
619
+
620
+ socket.once('connect', () => {
621
+ if (settled) return
622
+ settled = true
623
+ clearTimeout(timer)
624
+ signal?.removeEventListener('abort', abort)
625
+ socket.removeListener('error', fail)
626
+ resolve(socket)
627
+ })
628
+ })
629
+ }
630
+
631
+ /**
632
+ * Fold the handle's credential into a request envelope. Only the
633
+ * `tcp` arm carries a token — the vsock/unix/mtls control channels
634
+ * are host↔guest only and the agent authenticates nothing there, so
635
+ * a request built for those arms passes through unchanged.
636
+ */
637
+ private withCredential(req: AgentRequest): AgentRequest {
638
+ if (this.handle.kind === 'tcp' && this.handle.token !== undefined) {
639
+ return { ...req, token: this.handle.token }
640
+ }
641
+ return req
642
+ }
643
+
644
+ /**
645
+ * Refuse an oversized `tcp` envelope BEFORE dialing. See
646
+ * {@link TCP_PREAUTH_FRAME_LIMIT_BYTES}. A no-op for every other
647
+ * handle kind, which the guest never gates on frame size pre-auth.
648
+ */
649
+ private assertPreauthBudget(payload: string): void {
650
+ if (this.handle.kind !== 'tcp') return
651
+ const size = Buffer.byteLength(payload, 'utf8')
652
+ if (size <= TCP_PREAUTH_FRAME_LIMIT_BYTES) return
653
+ throw new AgentPreauthFrameTooLargeError(
654
+ `kubernetes tcp transport: request envelope is ${size} bytes, which exceeds the ${TCP_PREAUTH_FRAME_LIMIT_BYTES}-byte limit the guest agent enforces on an unauthenticated connection's first frame (NAMZU_AGENT_MAX_PREAUTH_FRAME_BYTES, default 8 MiB). Every tcp request dials a fresh connection, so this request WOULD be that connection's first frame. Chunking a large body across multiple frames is not implemented; reduce the payload or raise the deployment's NAMZU_AGENT_MAX_PREAUTH_FRAME_BYTES.`,
655
+ )
656
+ }
657
+
511
658
  /**
512
659
  * Send one framed request and read one framed JSON reply (file-IO +
513
660
  * healthz). Applies the read-idle timeout so a post-resume hung read
514
661
  * is torn down rather than wedging the caller.
515
662
  */
516
663
  async request<T>(req: AgentRequest, signal?: AbortSignal): Promise<T> {
664
+ const envelope = this.withCredential(req)
665
+ const payload = JSON.stringify(envelope)
666
+ this.assertPreauthBudget(payload)
517
667
  const socket = await this.dial(signal)
518
668
  return await new Promise<T>((resolve, reject) => {
519
669
  const reader = new FrameReader()
@@ -581,7 +731,7 @@ export class VsockAgentTransport {
581
731
  }
582
732
  signal?.addEventListener('abort', abort, { once: true })
583
733
  idle.bump()
584
- socket.write(frame(JSON.stringify(req)))
734
+ socket.write(frame(payload))
585
735
  })
586
736
  }
587
737
 
@@ -595,6 +745,9 @@ export class VsockAgentTransport {
595
745
  opts?: SandboxExecOptions,
596
746
  signal?: AbortSignal,
597
747
  ): Promise<SandboxExecResult> {
748
+ const envelope = this.withCredential({ op: 'execute', body } satisfies AgentRequest)
749
+ const payload = JSON.stringify(envelope)
750
+ this.assertPreauthBudget(payload)
598
751
  const socket = await this.dial(signal)
599
752
  const start = Date.now()
600
753
  return await new Promise<SandboxExecResult>((resolve, reject) => {
@@ -687,7 +840,7 @@ export class VsockAgentTransport {
687
840
  return
688
841
  }
689
842
  signal?.addEventListener('abort', abort, { once: true })
690
- socket.write(frame(JSON.stringify({ op: 'execute', body } satisfies AgentRequest)))
843
+ socket.write(frame(payload))
691
844
  })
692
845
  }
693
846
 
@@ -732,6 +885,27 @@ export class VsockAgentTransport {
732
885
  return await this.executionController.exec(command, argv, opts)
733
886
  }
734
887
 
888
+ /**
889
+ * The raw `/execute` primitive with NO admission/reservation
890
+ * semantics: dial, send one framed request, accumulate the streamed
891
+ * NDJSON reply. Public (unlike the identical-in-spirit
892
+ * {@link reserveExecution}/{@link cancelExecution}, reached through
893
+ * the already-public {@link request}) so a caller running its OWN
894
+ * {@link RemoteExecutionController} — the kubernetes backend's
895
+ * adapter — can reuse this exact dial + framing rather than
896
+ * reimplementing it, while still supplying that controller its own
897
+ * `reserve`/`cancel`/`execute` triple as {@link RemoteExecutionAdapter}
898
+ * requires. Callers that just want a reserve-before-admission `exec`
899
+ * should use {@link execute} or {@link exec} instead.
900
+ */
901
+ async executeStreamed(
902
+ body: ExecRequest,
903
+ opts?: SandboxExecOptions,
904
+ signal?: AbortSignal,
905
+ ): Promise<SandboxExecResult> {
906
+ return await this.executeRaw(body, opts, signal)
907
+ }
908
+
735
909
  private async reserveExecution(signal: AbortSignal): Promise<unknown> {
736
910
  const response = await this.request<Record<string, unknown>>(
737
911
  { op: 'reserve-execution' },
@@ -848,7 +1022,6 @@ export class VsockAgentTransport {
848
1022
  * the session and its authenticated WebSocket attachment.
849
1023
  */
850
1024
  async openTerminal(options: OpenTerminalOptions): Promise<TerminalSession> {
851
- const socket = await this.dial()
852
1025
  const request: TerminalOpenRequest = {
853
1026
  ...(options.command !== undefined ? { command: options.command } : {}),
854
1027
  ...(options.args !== undefined ? { args: options.args } : {}),
@@ -857,6 +1030,11 @@ export class VsockAgentTransport {
857
1030
  cols: options.size.cols,
858
1031
  rows: options.size.rows,
859
1032
  }
1033
+ const openPayload = JSON.stringify(
1034
+ this.withCredential({ op: 'terminal', body: request } satisfies AgentRequest),
1035
+ )
1036
+ this.assertPreauthBudget(openPayload)
1037
+ const socket = await this.dial()
860
1038
 
861
1039
  return await new Promise<TerminalSession>((resolve, reject) => {
862
1040
  const KILL_GRACE_MS = 5_000
@@ -986,14 +1164,7 @@ export class VsockAgentTransport {
986
1164
  finish(new Error('vsock transport: terminal socket closed before exit')),
987
1165
  )
988
1166
  idle.bump()
989
- socket.write(
990
- frame(
991
- JSON.stringify({
992
- op: 'terminal',
993
- body: request,
994
- } satisfies AgentRequest),
995
- ),
996
- )
1167
+ socket.write(frame(openPayload))
997
1168
  })
998
1169
  }
999
1170
 
@@ -1006,8 +1177,12 @@ export class VsockAgentTransport {
1006
1177
  if (host !== '127.0.0.1' && host !== '::1') {
1007
1178
  throw new Error('firecracker TCP connections are restricted to guest loopback')
1008
1179
  }
1009
- const socket = await this.dial()
1010
1180
  const request: TcpConnectRequest = { host, port: options.port }
1181
+ const openPayload = JSON.stringify(
1182
+ this.withCredential({ op: 'tcp-connect', body: request } satisfies AgentRequest),
1183
+ )
1184
+ this.assertPreauthBudget(openPayload)
1185
+ const socket = await this.dial()
1011
1186
 
1012
1187
  return await new Promise<SandboxTcpConnection>((resolve, reject) => {
1013
1188
  const reader = new FrameReader()
@@ -1127,14 +1302,7 @@ export class VsockAgentTransport {
1127
1302
  finish(ready ? null : new Error('vsock TCP socket closed before readiness')),
1128
1303
  )
1129
1304
  idle.bump()
1130
- socket.write(
1131
- frame(
1132
- JSON.stringify({
1133
- op: 'tcp-connect',
1134
- body: request,
1135
- } satisfies AgentRequest),
1136
- ),
1137
- )
1305
+ socket.write(frame(openPayload))
1138
1306
  })
1139
1307
  }
1140
1308
  }
@@ -1214,6 +1382,9 @@ function describeHandle(handle: SandboxAgentHandle): string {
1214
1382
  return `vsock:${handle.udsPath}#${handle.port}`
1215
1383
  case 'mtls':
1216
1384
  return `mtls:${handle.host}:${handle.port}/${handle.sandboxId}`
1385
+ case 'tcp':
1386
+ // Never the token: this string lands in thrown error messages.
1387
+ return `tcp:${handle.host}:${handle.port}`
1217
1388
  }
1218
1389
  }
1219
1390