@namzu/sandbox 1.1.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 (69) hide show
  1. package/CHANGELOG.md +474 -0
  2. package/LICENSE.md +110 -0
  3. package/README.md +148 -0
  4. package/dist/backends/aci-standby-pool/index.d.ts +104 -0
  5. package/dist/backends/aci-standby-pool/index.d.ts.map +1 -0
  6. package/dist/backends/aci-standby-pool/index.js +425 -0
  7. package/dist/backends/aci-standby-pool/index.js.map +1 -0
  8. package/dist/backends/docker/__tests__/leaf-permissions.smoke.test.d.ts +40 -0
  9. package/dist/backends/docker/__tests__/leaf-permissions.smoke.test.d.ts.map +1 -0
  10. package/dist/backends/docker/__tests__/leaf-permissions.smoke.test.js +157 -0
  11. package/dist/backends/docker/__tests__/leaf-permissions.smoke.test.js.map +1 -0
  12. package/dist/backends/docker/index.d.ts +118 -0
  13. package/dist/backends/docker/index.d.ts.map +1 -0
  14. package/dist/backends/docker/index.js +645 -0
  15. package/dist/backends/docker/index.js.map +1 -0
  16. package/dist/backends/firecracker/__tests__/backend.test.d.ts +13 -0
  17. package/dist/backends/firecracker/__tests__/backend.test.d.ts.map +1 -0
  18. package/dist/backends/firecracker/__tests__/backend.test.js +353 -0
  19. package/dist/backends/firecracker/__tests__/backend.test.js.map +1 -0
  20. package/dist/backends/firecracker/__tests__/control-plane-mtls.test.d.ts +19 -0
  21. package/dist/backends/firecracker/__tests__/control-plane-mtls.test.d.ts.map +1 -0
  22. package/dist/backends/firecracker/__tests__/control-plane-mtls.test.js +201 -0
  23. package/dist/backends/firecracker/__tests__/control-plane-mtls.test.js.map +1 -0
  24. package/dist/backends/firecracker/__tests__/fixtures/mtls-pki.d.ts +39 -0
  25. package/dist/backends/firecracker/__tests__/fixtures/mtls-pki.d.ts.map +1 -0
  26. package/dist/backends/firecracker/__tests__/fixtures/mtls-pki.js +149 -0
  27. package/dist/backends/firecracker/__tests__/fixtures/mtls-pki.js.map +1 -0
  28. package/dist/backends/firecracker/__tests__/protocol.test.d.ts +6 -0
  29. package/dist/backends/firecracker/__tests__/protocol.test.d.ts.map +1 -0
  30. package/dist/backends/firecracker/__tests__/protocol.test.js +77 -0
  31. package/dist/backends/firecracker/__tests__/protocol.test.js.map +1 -0
  32. package/dist/backends/firecracker/__tests__/transport.test.d.ts +20 -0
  33. package/dist/backends/firecracker/__tests__/transport.test.d.ts.map +1 -0
  34. package/dist/backends/firecracker/__tests__/transport.test.js +449 -0
  35. package/dist/backends/firecracker/__tests__/transport.test.js.map +1 -0
  36. package/dist/backends/firecracker/index.d.ts +124 -0
  37. package/dist/backends/firecracker/index.d.ts.map +1 -0
  38. package/dist/backends/firecracker/index.js +334 -0
  39. package/dist/backends/firecracker/index.js.map +1 -0
  40. package/dist/backends/firecracker/protocol.d.ts +132 -0
  41. package/dist/backends/firecracker/protocol.d.ts.map +1 -0
  42. package/dist/backends/firecracker/protocol.js +112 -0
  43. package/dist/backends/firecracker/protocol.js.map +1 -0
  44. package/dist/backends/firecracker/transport.d.ts +251 -0
  45. package/dist/backends/firecracker/transport.d.ts.map +1 -0
  46. package/dist/backends/firecracker/transport.js +524 -0
  47. package/dist/backends/firecracker/transport.js.map +1 -0
  48. package/dist/index.d.ts +611 -0
  49. package/dist/index.d.ts.map +1 -0
  50. package/dist/index.js +376 -0
  51. package/dist/index.js.map +1 -0
  52. package/dist/index.test.d.ts +28 -0
  53. package/dist/index.test.d.ts.map +1 -0
  54. package/dist/index.test.js +670 -0
  55. package/dist/index.test.js.map +1 -0
  56. package/package.json +54 -0
  57. package/src/backends/aci-standby-pool/index.ts +602 -0
  58. package/src/backends/docker/__tests__/leaf-permissions.smoke.test.ts +169 -0
  59. package/src/backends/docker/index.ts +826 -0
  60. package/src/backends/firecracker/__tests__/backend.test.ts +418 -0
  61. package/src/backends/firecracker/__tests__/control-plane-mtls.test.ts +253 -0
  62. package/src/backends/firecracker/__tests__/fixtures/mtls-pki.ts +166 -0
  63. package/src/backends/firecracker/__tests__/protocol.test.ts +90 -0
  64. package/src/backends/firecracker/__tests__/transport.test.ts +526 -0
  65. package/src/backends/firecracker/index.ts +528 -0
  66. package/src/backends/firecracker/protocol.ts +191 -0
  67. package/src/backends/firecracker/transport.ts +667 -0
  68. package/src/index.test.ts +731 -0
  69. package/src/index.ts +930 -0
@@ -0,0 +1,611 @@
1
+ /**
2
+ * @namzu/sandbox — pluggable sandbox provider for @namzu/sdk.
3
+ *
4
+ * The SDK already declares a `SandboxProvider` shape in
5
+ * `@namzu/sdk` (`packages/sdk/src/types/sandbox/index.ts`). This
6
+ * package implements that shape with concrete BACKENDS picked at
7
+ * construction time. The set is aligned with the 2026 industrial
8
+ * standard for AI-agent code-execution sandboxes:
9
+ *
10
+ * • `docker` — plain OCI container per task, seccomp default
11
+ * profile, tmpfs workdir, no-network-by-default. The universal
12
+ * fallback every namzu host gets locally with `docker compose`
13
+ * and on every Linux replica in any cloud. What Northflank /
14
+ * Railway / Render / Compass-platform / GitHub Actions runners
15
+ * actually ship for code execution. Trust boundary: namespaces.
16
+ *
17
+ * • `e2b` — adapter for E2B's managed Firecracker microVM service
18
+ * (`e2b.dev`). Sub-second cold-start via snapshot/restore, full
19
+ * kernel-level trust boundary. The SaaS-friendly path to real
20
+ * Firecracker isolation without running our own scheduler.
21
+ *
22
+ * • `fly-machines` — adapter for Fly Machines (`fly.io/docs/machines`).
23
+ * Also Firecracker microVMs; closer to bare-metal control than
24
+ * E2B, useful when the workload is more "arbitrary tool calls"
25
+ * than "Python REPL".
26
+ *
27
+ * • `firecracker` — self-hosted `firecracker-containerd` on bare
28
+ * metal (or KVM-enabled cloud instance). For hosts that need
29
+ * Firecracker isolation AND insist on running the scheduler
30
+ * themselves. Tier 3 isolation, highest operational cost.
31
+ *
32
+ * • `gvisor` — adapter for `runsc` runtime (Google's userspace
33
+ * kernel). What OpenAI Code Interpreter and Modal Labs ship.
34
+ * Trusted-tenant tier with near-zero cold-start; runs on
35
+ * commodity Linux without nested virt. Locally via Linux Docker
36
+ * runtime; not available on macOS Docker Desktop.
37
+ *
38
+ * • `passthrough` — no isolation, runs commands directly. For
39
+ * tests and trusted environments only. Off by default; opt-in.
40
+ *
41
+ * **What we deliberately do NOT build** is yet-another Firecracker
42
+ * scheduler — that is E2B's and Fly's entire product, and writing
43
+ * our own is a years-long detour. We adapt to theirs.
44
+ *
45
+ * **Cloud portability:** the backend interface is cloud-agnostic.
46
+ * `docker` works on every cloud; `e2b` and `fly-machines` are
47
+ * managed services not tied to any cloud; `firecracker` and
48
+ * `gvisor` need infrastructure the host chooses (GKE Sandbox, AWS
49
+ * Fargate, self-hosted KVM, etc.). Picking a stronger backend may
50
+ * imply moving cloud — that's the host's call, not the SDK's.
51
+ *
52
+ * **Local dev story:** Phase 1 (`docker`) runs everywhere. Phase 2
53
+ * (`e2b` / `fly-machines`) hits the managed service from a dev
54
+ * laptop with no infra setup. Phase 3 (`firecracker` / `gvisor`)
55
+ * needs Lima/Colima on macOS or native KVM on Linux — only the
56
+ * adversarial-multi-tenant prod path needs that and it's clearly
57
+ * documented as such.
58
+ *
59
+ * This file is the public surface. Concrete backend implementations
60
+ * land under `./backends/<kind>/` in subsequent commits — the
61
+ * `SandboxBackend` interface here is the contract they implement.
62
+ *
63
+ * Refs: `e2b.dev/docs/sandbox`, `fly.io/docs/machines`,
64
+ * `firecracker-microvm.github.io`, `gvisor.dev/docs`,
65
+ * `cloud.google.com/kubernetes-engine/docs/concepts/sandbox-pods`,
66
+ * `aws.amazon.com/blogs/aws/firecracker-lightweight-virtualization-for-serverless-computing`.
67
+ */
68
+ import type { ContainerSandboxLayout, Sandbox, SandboxProvider } from '@namzu/sdk';
69
+ export type { ContainerSandboxLayout, ContainerSandboxLayoutMount, ContainerSandboxMountSource, ContainerSandboxSkillMount, ResolvedContainerSandboxLayout, } from '@namzu/sdk';
70
+ export { SANDBOX_DEFAULT_OUTPUTS_PATH, SANDBOX_DEFAULT_SKILLS_PARENT, SANDBOX_DEFAULT_TOOL_RESULTS_PATH, SANDBOX_DEFAULT_TRANSCRIPTS_PATH, SANDBOX_DEFAULT_UPLOADS_PATH, } from '@namzu/sdk';
71
+ export type { FirecrackerBackendInternalConfig, OrchestratorTokenProvider, } from './backends/firecracker/index.js';
72
+ export { type SandboxAgentHandle, type VsockTransportOptions, VsockAgentTransport, } from './backends/firecracker/transport.js';
73
+ /**
74
+ * Top-level sandbox tier. Each tier is a use-case bucket:
75
+ *
76
+ * - `process` — the agent runs on the developer's own host;
77
+ * the sandbox keeps it from reading `~/.ssh` or running
78
+ * `rm -rf ~`. Single-user; no multi-tenancy. What Anthropic
79
+ * ships with Claude Code via `@anthropic-ai/sandbox-runtime`.
80
+ *
81
+ * - `container` — the agent runs inside an OCI container per
82
+ * task. Same code path locally (`docker compose`) and on
83
+ * Linux replicas in any cloud. The default for "trusted
84
+ * prompts, contained workloads" — Northflank, Railway,
85
+ * Render, Compass-platform, GitHub Actions runners all
86
+ * ship this tier.
87
+ *
88
+ * - `microvm` — the agent runs inside a Firecracker microVM
89
+ * per task. Hardware-virtualization trust boundary; the
90
+ * industry standard for adversarial multi-tenancy
91
+ * (AWS Lambda/Fargate, Fly Machines, Replit, E2B, Daytona
92
+ * all converged here). Sub-second cold-start via
93
+ * snapshot/restore.
94
+ *
95
+ * - `passthrough` — no isolation; for tests and explicitly
96
+ * trusted environments.
97
+ *
98
+ * The concrete implementation inside a tier is picked via the
99
+ * tier-specific config (see {@link ProcessBackendConfig},
100
+ * {@link ContainerBackendConfig}, {@link MicroVMBackendConfig}).
101
+ */
102
+ export type SandboxTier = 'process' | 'container' | 'microvm' | 'passthrough';
103
+ /**
104
+ * Discriminated union of sandbox backend configurations. Each
105
+ * tier has its own configuration shape — picking a tier picks the
106
+ * shape automatically via TS narrowing.
107
+ */
108
+ export type SandboxBackendConfig = ProcessBackendConfig | ContainerBackendConfig | ACIStandbyPoolBackendConfig | MicroVMBackendConfig | PassthroughBackendConfig;
109
+ /**
110
+ * Azure Container Instances Standby Pool backend. Container tier,
111
+ * managed-microvm-ish: every claim is a fresh ACI container group
112
+ * pre-warmed in an Azure-managed standby pool (`Microsoft.StandbyPool`).
113
+ * ~1.5 s claim latency vs ~10-30 s for cold ACI spawn. Trust boundary
114
+ * = Microsoft's ACI isolation host (gVisor-equivalent depending on
115
+ * SKU; AMD SEV-SNP TEE when the pool is created with sku=Confidential).
116
+ *
117
+ * No host filesystem — workspace mounts ride `azureFileShare` sources
118
+ * (the host provisions a per-task Azure Files share upstream and
119
+ * threads it into the layout). Auth via a caller-supplied
120
+ * `getArmToken()` callback so the sandbox package stays free of
121
+ * Azure SDK dependencies; the host runtime owns Managed Identity /
122
+ * AzureCLI / federated credential picking.
123
+ *
124
+ * Use this when (a) running on Azure Container Apps and you cannot
125
+ * mount the docker socket, (b) you want per-task container
126
+ * isolation without operating a Firecracker host yourself, and
127
+ * (c) sub-2-second claim latency is acceptable.
128
+ */
129
+ export interface ACIStandbyPoolBackendConfig {
130
+ readonly tier: 'container';
131
+ readonly runtime: 'aci-standby-pool';
132
+ readonly subscriptionId: string;
133
+ readonly resourceGroup: string;
134
+ readonly location: string;
135
+ readonly standbyPoolResourceId: string;
136
+ readonly containerGroupProfileResourceId: string;
137
+ readonly containerGroupProfileRevision?: number;
138
+ /**
139
+ * Async callback returning a fresh ARM bearer token (audience
140
+ * `https://management.azure.com/`). Invoked on every ARM call.
141
+ */
142
+ readonly getArmToken: () => Promise<string>;
143
+ readonly subnetId?: string;
144
+ readonly readyPollIntervalMs?: number;
145
+ readonly readyTimeoutMs?: number;
146
+ readonly workerPort?: number;
147
+ readonly armApiVersion?: string;
148
+ /**
149
+ * Prefix for the ACI container group name and the inner worker
150
+ * container. Combined with a generated sandbox id and
151
+ * sanitised to ARM's allowed character set. Default
152
+ * `namzu-task`; consumers (e.g. Vandal) override to brand
153
+ * their own deployments.
154
+ */
155
+ readonly containerNamePrefix?: string;
156
+ }
157
+ /**
158
+ * `process` tier. Auto-detects the platform's native primitive
159
+ * unless overridden:
160
+ *
161
+ * - `bubblewrap` on Linux / WSL2 (`bwrap`)
162
+ * - `seatbelt` on macOS (`sandbox-exec`)
163
+ *
164
+ * Both are what `@anthropic-ai/sandbox-runtime` ships. Cold-start
165
+ * is process spawn (~ms). Use this when the agent runs on the
166
+ * end-user's developer machine — Claude Code's deployment model.
167
+ */
168
+ export interface ProcessBackendConfig {
169
+ readonly tier: 'process';
170
+ readonly engine?: 'auto' | 'bubblewrap' | 'seatbelt';
171
+ }
172
+ /**
173
+ * `container` tier. Two runtime options:
174
+ *
175
+ * - `docker` (default) — plain OCI container on the host's
176
+ * Docker daemon. No special runtime required.
177
+ * - `runsc` — Google's gVisor userspace-kernel runtime. Stronger
178
+ * isolation (syscall-table separation), runs on commodity
179
+ * Linux without nested virt. Trusted-tenant tier; what OpenAI
180
+ * Code Interpreter and Modal Labs ship. Requires the
181
+ * `runsc` runtime installed on the Docker daemon (Linux only;
182
+ * Docker Desktop on macOS does not support it). See
183
+ * `gvisor.dev/docs/user_guide/quick_start/docker`.
184
+ *
185
+ * `image` is the container image to spawn per task. The package
186
+ * ships a reference Dockerfile (compass-platform pattern) with
187
+ * Python doc-gen libraries, LibreOffice, pandoc, Chromium, and
188
+ * `tesseract` pre-installed; hosts that want a leaner image
189
+ * supply their own.
190
+ */
191
+ export interface ContainerBackendConfig {
192
+ readonly tier: 'container';
193
+ readonly runtime?: 'docker' | 'runsc';
194
+ readonly image: string;
195
+ /**
196
+ * How the SDK consumer reaches the in-container worker. Default
197
+ * `'host-port'` — the original loopback host-port flow, works
198
+ * when the consumer runs ON the docker host. Set
199
+ * `'container-network'` when the consumer is itself a container
200
+ * spawning siblings via the host's Docker daemon: the worker is
201
+ * reachable at `http://<containerName>:2024` over the docker
202
+ * bridge named in `network`.
203
+ */
204
+ readonly hostReachability?: 'host-port' | 'container-network';
205
+ /**
206
+ * Docker network the spawned container attaches to. Default
207
+ * `'none'` (no inbound or outbound network). Set to a docker
208
+ * bridge name when `hostReachability='container-network'` so the
209
+ * SDK consumer (also on that bridge) can reach the worker by
210
+ * container DNS name. Egress from the sandbox is governed
211
+ * separately by `EgressPolicy`.
212
+ */
213
+ readonly network?: 'none' | 'bridge' | string;
214
+ /**
215
+ * Optional `--label key=value` pairs applied to the spawned
216
+ * container. Hosts use this to make the container findable from
217
+ * out-of-band cleanup paths (reaper jobs, monitoring filters)
218
+ * via `docker ps --filter label=...`. Keys with `=` or empty
219
+ * names are rejected at construction; values are passed verbatim
220
+ * to the docker CLI argv (no shell interpolation — `spawn` argv
221
+ * not a shell pipeline). Default unset (no extra labels).
222
+ *
223
+ * Convention for namzu hosts: namespace your keys
224
+ * (`vandal.sandbox=true`, `vandal.task-id=<id>`, …) to avoid
225
+ * collisions with Docker / orchestrator labels.
226
+ */
227
+ readonly labels?: Readonly<Record<string, string>>;
228
+ }
229
+ /**
230
+ * `microvm` tier. Three concrete services, all Firecracker under
231
+ * the hood:
232
+ *
233
+ * - `e2b` — adapter for E2B's managed sandbox service
234
+ * (`e2b.dev`). TS SDK does the scheduler work; namzu wraps it.
235
+ * ~150ms cold-start (snapshot/restore). Apache-2.0 server side,
236
+ * so the same code path can run against self-hosted E2B if
237
+ * the host eventually wants to leave the managed service.
238
+ * - `fly-machines` — adapter for Fly Machines
239
+ * (`fly.io/docs/machines`). Closer to bare-metal control than
240
+ * E2B; the right tier when the workload is "arbitrary tool
241
+ * calls" rather than "Python REPL".
242
+ * - `self-hosted` — direct `firecracker-containerd` against a
243
+ * KVM-enabled host. For deployments where E2B and Fly are
244
+ * both off the table for policy reasons. Operationally the
245
+ * heaviest path; everything below ships first.
246
+ *
247
+ * Local dev: `e2b` and `fly-machines` work from any laptop with
248
+ * an API key (no infra setup). `self-hosted` requires Linux + KVM
249
+ * (Lima/Colima on macOS).
250
+ */
251
+ export type MicroVMBackendConfig = {
252
+ readonly tier: 'microvm';
253
+ readonly service: 'e2b';
254
+ readonly apiKey: string;
255
+ readonly template?: string;
256
+ } | {
257
+ readonly tier: 'microvm';
258
+ readonly service: 'fly-machines';
259
+ readonly apiToken: string;
260
+ readonly app: string;
261
+ readonly image: string;
262
+ readonly region?: string;
263
+ } | {
264
+ readonly tier: 'microvm';
265
+ readonly service: 'self-hosted';
266
+ readonly firecrackerBinary: string;
267
+ readonly kernelImage: string;
268
+ readonly rootfsImage: string;
269
+ /**
270
+ * The owned-platform seam (ses_051). When these are present the
271
+ * `self-hosted` arm targets the OWNED Azure Firecracker
272
+ * orchestrator (`backends/firecracker/`), not a local
273
+ * `firecracker-containerd`: `orchestratorEndpoint` is the
274
+ * control-plane base URL, `getToken` mints a bearer for it
275
+ * (the ACI `getArmToken` closure pattern, so this package keeps
276
+ * zero Azure-SDK deps), and `template` selects the golden
277
+ * snapshot revision to CoW-resume.
278
+ *
279
+ * The legacy local-`firecracker-containerd` shape
280
+ * (`firecrackerBinary`/`kernelImage`/`rootfsImage` only) is
281
+ * still NOT implemented and throws
282
+ * {@link SandboxBackendNotImplementedError}; supplying
283
+ * `orchestratorEndpoint` is what routes to the owned backend.
284
+ */
285
+ readonly orchestratorEndpoint?: string;
286
+ readonly getToken?: () => Promise<string>;
287
+ readonly template?: string;
288
+ /**
289
+ * Resume this per-agent captured snapshot (layered on its base
290
+ * golden) INSTEAD of a fresh golden boot. Tier-agnostic, additive,
291
+ * optional: the backend that supports it (the owned firecracker
292
+ * backend) honors it; others ignore it. Absent ⇒ the create body is
293
+ * byte-identical and the generic golden-resume hot path is unchanged
294
+ * (the field is only ever set by the host's per-agent trigger path).
295
+ * Sibling to `template` (base-golden selector) — see
296
+ * {@link AgentSnapshotRef}.
297
+ */
298
+ readonly agentSnapshot?: AgentSnapshotRef;
299
+ /** Fixed guest AF_VSOCK port the in-VM agent listens on. */
300
+ readonly agentVsockPort?: number;
301
+ readonly readyTimeoutMs?: number;
302
+ readonly readyPollIntervalMs?: number;
303
+ /**
304
+ * NETWORK-mode mTLS client material (ses_051 P4 client-proxy
305
+ * bridge). When present, the orchestrator returns an `mtls` agent
306
+ * handle (host/port/sandboxId, NO cert material) and this CA/cert/key
307
+ * is MERGED onto that handle before the transport dials the per-host
308
+ * relay over mTLS. Injected by the consumer's runtime (the Vandal
309
+ * host layer reads it from `VANDAL_SANDBOX_FC_TLS_*`), NEVER fetched
310
+ * inside this package — same dependency boundary as `getToken`, so
311
+ * `@namzu/sandbox` stays Azure-SDK-free. Absent for the single-host
312
+ * VSOCK default (the live proofs).
313
+ */
314
+ readonly mtls?: {
315
+ readonly ca: string | Buffer;
316
+ readonly cert: string | Buffer;
317
+ readonly key: string | Buffer;
318
+ readonly servername?: string;
319
+ };
320
+ /**
321
+ * CONTROL-plane mTLS client material. When present, the orchestrator
322
+ * control-plane calls (create/destroy POSTs to `orchestratorEndpoint`)
323
+ * dial over mTLS — presenting this client cert and pinning this CA —
324
+ * instead of plain `fetch`. Secures the control plane when
325
+ * `orchestratorEndpoint` is an `https://` URL reached over the PUBLIC
326
+ * internet (the non-VNet-integrated caller→FC-host hop), where the
327
+ * shared-secret bearer alone would be exposed. The bearer is STILL sent
328
+ * (defense in depth). Same `{ca,cert,key,servername}` shape + the same
329
+ * consumer-injected dependency boundary as `mtls` (the one fleet CA
330
+ * secures both planes). Absent → plain `fetch` control plane (the
331
+ * single-host VSOCK default, unchanged).
332
+ */
333
+ readonly controlPlaneMtls?: {
334
+ readonly ca: string | Buffer;
335
+ readonly cert: string | Buffer;
336
+ readonly key: string | Buffer;
337
+ readonly servername?: string;
338
+ };
339
+ };
340
+ /**
341
+ * A reference to a per-agent captured snapshot, layered on top of a base
342
+ * golden revision. Provider-AGNOSTIC: this is a sandbox-spec concept, a
343
+ * sibling to {@link MicroVMBackendConfig}'s `template` (which selects a
344
+ * base golden), not a provider-specific shape — hence no provider prefix
345
+ * in the name. A microVM backend that supports per-agent resume (the owned
346
+ * Firecracker backend) honors it by resuming this agent's captured diff
347
+ * INSTEAD of a fresh golden boot; backends that do not support it ignore it.
348
+ *
349
+ * The triple identifies exactly one captured snapshot: the owning tenant
350
+ * (`orgId`), the agent registry row (`agentId`), and the registry version
351
+ * (`version`, a decimal string so the whole triple is a set of path
352
+ * segments). The host constructs this server-side from its own registry;
353
+ * `@namzu/sandbox` only forwards it.
354
+ */
355
+ export interface AgentSnapshotRef {
356
+ readonly orgId: string;
357
+ readonly agentId: string;
358
+ readonly version: string;
359
+ }
360
+ /**
361
+ * `passthrough` tier. No isolation — runs commands directly in
362
+ * the host process. Tests and trusted environments only.
363
+ */
364
+ export interface PassthroughBackendConfig {
365
+ readonly tier: 'passthrough';
366
+ }
367
+ /**
368
+ * Egress allowlist resolution. Host-supplied policy decides whether
369
+ * an outbound request is allowed before the proxy opens a socket.
370
+ *
371
+ * Four shapes:
372
+ *
373
+ * - `deny-all` — default. Reject every outbound request.
374
+ * - `allow-all` — accept every outbound request. Tests only.
375
+ * - `static` — fixed allowlist of hostnames at construction.
376
+ * - `resolver` — async closure returning the allowlist.
377
+ * Parameterless **on purpose**: the resolver is a closure that
378
+ * captures whatever context the host has (tenantId, runId,
379
+ * auth token, etc.) at provider-construction time. Compass-
380
+ * platform's JWT-minting flow already works this way: the
381
+ * server knows the tenant when it issues the JWT, and the
382
+ * allowlist claim is baked in there. This avoids the
383
+ * "where does the resolver get its context from" plumbing
384
+ * problem — the host owns the closure, the SDK runtime
385
+ * doesn't have to forward identity through `provider.create`.
386
+ */
387
+ export type EgressPolicy = {
388
+ readonly kind: 'deny-all';
389
+ } | {
390
+ readonly kind: 'allow-all';
391
+ } | {
392
+ readonly kind: 'static';
393
+ readonly allowedHosts: readonly string[];
394
+ } | {
395
+ readonly kind: 'resolver';
396
+ readonly resolve: () => Promise<readonly string[]>;
397
+ };
398
+ /**
399
+ * Backend strategy. Each tier × concrete-service combination ships
400
+ * an implementation of this interface in its own subfolder under
401
+ * `src/backends/`.
402
+ *
403
+ * Backends are responsible for:
404
+ * - turning {@link SandboxBackendOptions} into a concrete
405
+ * {@link Sandbox} instance the SDK can use,
406
+ * - wiring {@link EgressPolicy} into whatever proxy / network
407
+ * primitive the backend has,
408
+ * - cleaning up host resources on `destroy()` (process-level
409
+ * cleanup, container teardown, microVM stop+delete, etc.).
410
+ *
411
+ * Tier-specific concepts (bind-mount layout for container, microVM
412
+ * volume id, process-tier seccomp profile) are NOT carried on
413
+ * `SandboxBackendOptions`. They are baked into the backend at
414
+ * construction time via the tier-specific config (see
415
+ * {@link SandboxProviderConfig.layout} for the container tier). This
416
+ * keeps `provider.create()` symmetric across tiers and prevents the
417
+ * SDK runtime from accidentally calling a container backend without
418
+ * a layout — the binding is at construction, not per-call.
419
+ *
420
+ * The backend does NOT see the agent or its tools — the SDK
421
+ * composes them at the runtime layer. Backends are pure isolation
422
+ * primitives.
423
+ */
424
+ export interface SandboxBackend {
425
+ readonly tier: SandboxTier;
426
+ readonly name: string;
427
+ create(options: SandboxBackendOptions): Promise<Sandbox>;
428
+ }
429
+ /**
430
+ * Per-call options handed to a backend's `create()`. Tier-agnostic
431
+ * host knobs only:
432
+ *
433
+ * - `workingDirectory` — the per-task root where the sandbox is
434
+ * rooted (e.g. `/tmp/<tenant>/<run>/`). Backends bind-mount or
435
+ * chroot this depending on platform.
436
+ * - `egress` — the allowlist policy applied to outbound network
437
+ * inside the sandbox. Backends translate this into proxy /
438
+ * iptables / domain-allowlist plumbing.
439
+ * - `timeoutMs`, `memoryLimitMb`, `maxProcesses` — resource caps
440
+ * applied per spawned process inside the sandbox.
441
+ * - `env` — environment variables added to the inside of the
442
+ * sandbox (NOT host process env). Used to forward
443
+ * `HTTP_PROXY` / `HTTPS_PROXY` to the egress proxy when one
444
+ * is in play.
445
+ *
446
+ * `layout` is **not** here — see the type-level note on
447
+ * {@link SandboxBackend}. Identity-aware fields (tenantId / runId /
448
+ * agentId) are deliberately NOT in this shape either; hosts that
449
+ * need per-tenant sandbox config bake the tenant into the closure
450
+ * that constructs the provider — see the `EgressPolicy` resolver
451
+ * shape.
452
+ */
453
+ export interface SandboxBackendOptions {
454
+ readonly workingDirectory: string;
455
+ readonly egress?: EgressPolicy;
456
+ readonly timeoutMs?: number;
457
+ readonly memoryLimitMb?: number;
458
+ readonly maxProcesses?: number;
459
+ readonly env?: Record<string, string>;
460
+ }
461
+ /**
462
+ * Configuration for {@link createSandboxProvider}. The host picks
463
+ * a tier-specific backend config (process / container / microvm /
464
+ * passthrough) and supplies cross-tier defaults that
465
+ * `provider.create()` calls can override.
466
+ *
467
+ * Container-tier backends require a per-task
468
+ * {@link ContainerSandboxLayout} captured at construction time (see
469
+ * the discriminated union). The layout is per-task — different
470
+ * `hostPath`s for different runs — so hosts call
471
+ * `createSandboxProvider` once per task with the task-specific
472
+ * layout baked in. The `Sandbox` instance returned by
473
+ * `provider.create()` then inherits that layout. This is the only
474
+ * path: there is no per-call layout argument that could be silently
475
+ * omitted by the SDK runtime.
476
+ */
477
+ export type SandboxProviderConfig = (SandboxProviderConfigBase & {
478
+ readonly backend: ContainerBackendConfig;
479
+ readonly layout: ContainerSandboxLayout;
480
+ }) | (SandboxProviderConfigBase & {
481
+ readonly backend: ProcessBackendConfig | MicroVMBackendConfig | PassthroughBackendConfig;
482
+ });
483
+ interface SandboxProviderConfigBase {
484
+ readonly defaultEgress?: EgressPolicy;
485
+ readonly defaultTimeoutMs?: number;
486
+ readonly defaultMemoryLimitMb?: number;
487
+ readonly defaultMaxProcesses?: number;
488
+ }
489
+ /**
490
+ * Build a {@link SandboxProvider} the SDK can wire into
491
+ * `drainQuery`'s `sandboxProvider` field. Selects the backend at
492
+ * construction time; subsequent `provider.create()` calls all use
493
+ * the chosen backend.
494
+ *
495
+ * Backends are loaded lazily — the package only imports the
496
+ * platform-specific modules (Anthropic's sandbox-runtime, the
497
+ * Docker SDK, the E2B SDK, …) when the corresponding backend is
498
+ * requested. That keeps `@namzu/sandbox` reasonable to install in
499
+ * environments where one backend is genuinely impossible.
500
+ *
501
+ * **Not implemented in this commit** — this file declares the
502
+ * surface; backends arrive in subsequent commits per the ses_004
503
+ * phase plan:
504
+ *
505
+ * - **P3.1** — `container` (docker runtime). Phase 1: ship now.
506
+ * - **P3.2** — `EgressPolicy` plumbing + reference egress proxy.
507
+ * - **P3.3** — `microvm` (E2B + Fly Machines adapters). Phase 2.
508
+ * - **P3.4** — `process` (Anthropic sandbox-runtime adapter).
509
+ * - **P3.5** — `microvm` (self-hosted firecracker-containerd) +
510
+ * `container` (gVisor runtime). Phase 3 adversarial-multi-tenant.
511
+ *
512
+ * Calling this function now throws
513
+ * {@link SandboxBackendNotImplementedError} so consumers get a
514
+ * clear signal during the staged rollout.
515
+ */
516
+ export declare function createSandboxProvider(config: SandboxProviderConfig): SandboxProvider;
517
+ /**
518
+ * Thrown by the factory when a backend is requested before its
519
+ * implementation has landed. Makes the staged rollout legible —
520
+ * consumers see exactly which backend is missing rather than a
521
+ * generic `TypeError: foo is not a function`.
522
+ *
523
+ * Subclasses Error so existing host error handling (instanceof
524
+ * checks, JSON.stringify, etc.) keeps working.
525
+ */
526
+ export declare class SandboxBackendNotImplementedError extends Error {
527
+ readonly backend: string;
528
+ readonly name = "SandboxBackendNotImplementedError";
529
+ constructor(backend: string);
530
+ }
531
+ /**
532
+ * Thrown when a {@link ContainerSandboxLayout} fails validation:
533
+ * missing required `outputs` mount, malformed skill id, duplicate
534
+ * skill id, duplicate `containerPath` across mounts. The `reasons`
535
+ * array carries one entry per violation so consumers can surface
536
+ * every problem in one round-trip rather than fix-then-rerun.
537
+ *
538
+ * **Transport caveat.** `JSON.stringify(err)` works because
539
+ * `toJSON()` returns a plain object with `reasons` preserved. But
540
+ * `structuredClone(err)` on the Error object itself drops the
541
+ * subclass name and any non-enumerable fields. For transport
542
+ * boundaries (postMessage, worker IPC, log shippers) call
543
+ * {@link serializeSandboxError} which returns a plain object that
544
+ * is `structuredClone`-safe and `JSON.stringify`-safe in one shape.
545
+ */
546
+ export declare class ContainerSandboxLayoutValidationError extends Error {
547
+ readonly reasons: readonly string[];
548
+ readonly name = "ContainerSandboxLayoutValidationError";
549
+ constructor(reasons: readonly string[], options?: {
550
+ cause?: unknown;
551
+ });
552
+ toJSON(): {
553
+ name: string;
554
+ message: string;
555
+ reasons: readonly string[];
556
+ cause?: unknown;
557
+ };
558
+ }
559
+ /**
560
+ * Transport-safe serialisation for any error this package raises
561
+ * (and any nested `cause` chain). Returns a plain object with
562
+ * `name`, `message`, optional `stack`, optional `cause`
563
+ * (recursively serialised into the same envelope shape), and — for
564
+ * {@link ContainerSandboxLayoutValidationError} — the `reasons`
565
+ * array. The result is **uniformly safe** through
566
+ * `structuredClone`, `postMessage`, and `JSON.stringify`:
567
+ *
568
+ * - No function / Symbol / BigInt / non-finite-number values
569
+ * leak into the envelope; non-Error causes (and non-Error
570
+ * inputs) are converted to a typed envelope by
571
+ * {@link serializeNonErrorCause}.
572
+ * - Cycles (`a.cause = a`, `a.cause = b; b.cause = a`) are
573
+ * detected via a `WeakSet` and replaced with a
574
+ * `{ name: 'CircularReference', message: '[circular]' }`
575
+ * sentinel — no stack overflow, no `JSON.stringify` throw.
576
+ * - Deep chains are walked in full (no arbitrary depth cap); the
577
+ * cycle guard, not depth, is what bounds the recursion.
578
+ *
579
+ * Why this helper exists: `Error` subclasses don't survive any
580
+ * structured-clone-like channel — `structuredClone(err)` drops the
581
+ * subclass name and non-enumerable fields, `postMessage` follows
582
+ * the same rules, and most log shippers serialise via JSON which
583
+ * calls the unhelpful default `toJSON`. Vandal's supervisor
584
+ * architecture crosses every one of those boundaries; explicit
585
+ * serialisation keeps the `reasons[]` discoverable downstream.
586
+ *
587
+ * Use:
588
+ * ```ts
589
+ * try { ... }
590
+ * catch (err) {
591
+ * logger.error(serializeSandboxError(err))
592
+ * parent.postMessage(serializeSandboxError(err))
593
+ * }
594
+ * ```
595
+ */
596
+ export interface SerializedSandboxError {
597
+ readonly name: string;
598
+ readonly message: string;
599
+ readonly stack?: string;
600
+ readonly reasons?: readonly string[];
601
+ /**
602
+ * Recursively serialised cause envelope. Always the same shape;
603
+ * non-Error causes go through {@link serializeNonErrorCause}
604
+ * before they reach this slot, so values that `JSON.stringify`
605
+ * or `structuredClone` would choke on (Function, Symbol,
606
+ * BigInt, NaN, ±Infinity, undefined) never appear here.
607
+ */
608
+ readonly cause?: SerializedSandboxError;
609
+ }
610
+ export declare function serializeSandboxError(err: unknown): SerializedSandboxError;
611
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}