The parent implementation introduced sandboxMode and approvalPolicy as generic SessionHeader fields, then propagated those fields through both persistence backends, session-query indexes, collision checks, policy-specific seed-boundary folds, catalogs, and a broad test matrix. That storage plane is unnecessary: Session already accepts a validated constructor seed, and persistence captures that seed when the session is announced before committing its first batch. Capture each parent override synchronously at delegation, append source-tagged sandbox/mode and approval/policy records after the optional fork prefix, and create the child with that combined seed. Keeping header.seedLength at the original fork-prefix length preserves lineage while ordinary last-event-wins folds make the inherited records outrank stale parent history and remain subordinate to later child switches. Unswitched parents still stamp nothing, so children continue to follow deployment defaults. Remove the generic header fields and every persistence/query/schema branch built around them. Collapse the inheritance suite from ten leaking scenarios to four owned-context cases covering real filesystem confinement, stale fork precedence, delegation-time capture, and the no-override path. The assembled headless snapshot now asserts the persisted inheritance event directly. This keeps the security behavior while restoring policy ownership to the existing event log and deleting the speculative durability machinery that the original tests did not exercise.
sandbox/ — process-sandbox capability family
English | 中文
The confinement half of the capability-seam split: an abstract provider interface, platform backends, and the shared policy home. Consumers hand ctx.sandbox the exact argv they are about to spawn and spawn the returned (wrapped) argv instead; a complete SandboxExecutionPolicy (mode + workspace root) rides each capability call, and its confined subset becomes the provider's SandboxPolicy. Different sessions and consumers can therefore confine under different policies at the same instant. All product packages.
| Package | Role | ctx key |
|---|---|---|
sandbox/ |
Abstract process-sandbox seam (the SandboxProvider contract + the mode/enforcement/policy vocabulary) plus the shared ESCALATION kit (approveEscalation, the strictly-wider ladder, the denial/hint markers) and the writableRoots derivation every enforcement dialect shares |
ctx.sandbox |
sandbox-local/ |
Local backends by platform chain: Linux bwrap else the landlock-run launcher (the npm-distributed node-addon-landlock-run family, built and released from its own repository), darwin sandbox-exec/Seatbelt — multi-candidate chains functionally probed, sole candidates selected directly, verdict cached, fail-closed |
(registers ctx.sandbox) |
sandbox-policy/ |
The policy resolver: deployment fallbacks plus each session's durable mode and immutable cwd root. Both enforcing families consume its complete per-call result, so bash and fs cannot confine to different roots | ctx.sandboxPolicy |
The seam confines SAME-WORLD subprocesses only (shared filesystem and kernel). Containers, microVMs, and remote executors are NOT backends here — they replace whole capability implementations (ctx.bash, ctx.fs) as environment-coherent groups; the boundary is recorded in the sandbox Agent Note.
Consumers today: bash/bash-sandbox (wraps ['bash', '-c', command] through ctx.sandbox) and fs/fs-sandbox (an in-process path fence, not an argv wrapper — reads ctx.sandboxPolicy and enforces the shared mode on write/edit). The cross-family boundary is the sandbox Agent Note's cross-family fs sandbox phase; the shared vocabulary lets both families teach the model one denial marker and one escalation flow.