feat(example): sandbox-acp-agent — the live composition; RFCs to implemented
The three-entry cordis.yml (dsh-sandbox-local + dsh-bash-sandbox at a read-only default + dsh-approval) served over ACP: the first live approval composition. Recorded snapshot scenarios pin the wire end to end — config-options advertisement, the mode-switching arc as the suite pinned header (both switches, the prompt-section delta, one changed-by-the-user notice per knob, a confined write landing under the switched mode), and both escalation branches over scripted permissionAnswers (a grant runs confined under workspace-write; a rejection executes nothing and pins the fail-closed text). The with-key escalation e2e drives a real model + real runner + the real bridge answerer, world-verified; ci.yml snapshot lane and e2e.yml install bubblewrap so the confined replays actually execute. Both RFCs move to implemented/ (Decision/Consequences form, deferred phases tracked in their own sections), with every cross-reference flipped.
This commit is contained in:
@@ -7,6 +7,6 @@ The confinement half of the [capability-seam split](../../docs/rfc/implemented/a
|
||||
| `sandbox/` | Abstract process-sandbox seam (the `SandboxProvider` contract + the mode/enforcement/policy vocabulary) | `ctx.sandbox` |
|
||||
| `sandbox-local/` | Local backends by platform chain: Linux `bwrap` else the `landlock-run` launcher (the npm-distributed [`node-addon-landlock-run`](https://www.npmjs.com/package/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`) |
|
||||
|
||||
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 RFC](../../docs/rfc/proposed/feature/2026-07-06-sandbox.md).
|
||||
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 RFC](../../docs/rfc/implemented/feature/2026-07-06-sandbox.md).
|
||||
|
||||
The staged first consumer is the sandboxed bash executor (it hands over the exact `['bash', '-c', command]` argv it is about to spawn). In-process tools (fs/web) cannot be confined by an OS wrapper — their sandbox semantics are policy at their own seams (the sandbox RFC's cross-family phase).
|
||||
Consumers today: [`bash/bash-sandbox`](../bash/bash-sandbox/) (wraps `['bash', '-c', command]`; see [examples/sandbox-acp-agent](../../examples/sandbox-acp-agent/) for the composed leaf). In-process tools (fs/web) cannot be confined by an OS wrapper — their sandbox semantics are policy at their own seams (the sandbox RFC's cross-family phase).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# @deepseek-ai/dsh-sandbox-local
|
||||
|
||||
Local implementation of the [`@deepseek-ai/dsh-sandbox`](../sandbox/) seam: wraps a caller's argv in a platform confinement runner. Selection is BY PLATFORM, resolved once and cached: each platform names its runner chain, a chain of one is selected directly (probing arbitrates between candidates — a sole candidate leaves nothing to arbitrate), and a chain of several is probed functionally in preference order. Linux: [`bwrap`](https://github.com/containers/bubblewrap) when its probe passes, else the [`landlock-run`](https://www.npmjs.com/package/node-addon-landlock-run) Landlock launcher (kernel confinement that needs no userns/mount privileges — see the [sandbox RFC](../../../docs/rfc/proposed/feature/2026-07-06-sandbox.md) for the prebuilt-binary decision and profile-parity notes); darwin: `sandbox-exec` speaking a Seatbelt (SBPL) profile, unprobed. A platform with no chain means `confine()` FAILS CLOSED with the seam's structured `SANDBOX_UNAVAILABLE` error (win32 today: a reserved, deliberately empty chain awaiting an AppContainer-family runner); an unprobed runner that turns out unusable fails closed at EXECUTION instead — it refuses to run the command, and every wrap's `runnerFailureSignatures` let the consumer classify that as a sandbox failure rather than a task failure. Never a silent unconfined passthrough on any path.
|
||||
Local implementation of the [`@deepseek-ai/dsh-sandbox`](../sandbox/) seam: wraps a caller's argv in a platform confinement runner. Selection is BY PLATFORM, resolved once and cached: each platform names its runner chain, a chain of one is selected directly (probing arbitrates between candidates — a sole candidate leaves nothing to arbitrate), and a chain of several is probed functionally in preference order. Linux: [`bwrap`](https://github.com/containers/bubblewrap) when its probe passes, else the [`landlock-run`](https://www.npmjs.com/package/node-addon-landlock-run) Landlock launcher (kernel confinement that needs no userns/mount privileges — see the [sandbox RFC](../../../docs/rfc/implemented/feature/2026-07-06-sandbox.md) for the prebuilt-binary decision and profile-parity notes); darwin: `sandbox-exec` speaking a Seatbelt (SBPL) profile, unprobed. A platform with no chain means `confine()` FAILS CLOSED with the seam's structured `SANDBOX_UNAVAILABLE` error (win32 today: a reserved, deliberately empty chain awaiting an AppContainer-family runner); an unprobed runner that turns out unusable fails closed at EXECUTION instead — it refuses to run the command, and every wrap's `runnerFailureSignatures` let the consumer classify that as a sandbox failure rather than a task failure. Never a silent unconfined passthrough on any path.
|
||||
|
||||
Policy is per call (`SandboxPolicy`: mode + workspace root); the provider holds only the mechanism and the cached ladder verdict. Every wrap reports the selected runner's `enforcement` (`full`, or `partial` on an older Landlock ABI that governs only a subset of accesses — read from the launcher's `--probe` report line) and its `denialSignatures` — the stderr dialect that rung's kernel speaks on a denied file effect (EROFS text under bwrap, EACCES under Landlock, EPERM under Seatbelt), which stderr-inferring consumers match instead of a cross-runner union. A non-empty `runnerCommand` config is the operator's assertion of a runner that fully enforces the bwrap-shaped profile: the ladder and probes are skipped (the wrap carries both Linux denial dialects, the mechanism being unknown) — also the deterministic fake-runner seam for keyless test tiers. Its runner-failure dialect is the OUTER shell's argv0-scoped failure shapes (`exec: <argv0>: not found`, `<argv0>: No such file or directory`, `<argv0>: Permission denied`) — the consumer re-joins the wrap through `bash -c 'exec …'`, so a missing or unexecutable configured runner classifies as a sandbox failure (fail closed at execution), never as a failing command or a denial. `probeTimeoutMs` (default 5000) bounds each functional probe, the escape hatch for hosts slow enough that a timed-out probe would otherwise misread as `SANDBOX_UNAVAILABLE`.
|
||||
|
||||
@@ -15,4 +15,4 @@ Every rung has its keyless world-proof (`tests/bwrap.e2e.ts`, `tests/landlock.e2
|
||||
name: '@deepseek-ai/dsh-sandbox-local'
|
||||
```
|
||||
|
||||
The staged first consumer is the sandboxed bash executor.
|
||||
Consumers: [`@deepseek-ai/dsh-bash-sandbox`](../../bash/bash-sandbox/); see [`examples/sandbox-acp-agent`](../../../examples/sandbox-acp-agent/) for the runnable composition.
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* `bwrap`, else the `landlock-run` Landlock launcher (kernel confinement
|
||||
* that needs no userns/mount privileges; distributed as the npm package
|
||||
* family `node-addon-landlock-run` — the decision recorded in
|
||||
* docs/rfc/proposed/feature/2026-07-06-sandbox.md); darwin: macOS
|
||||
* docs/rfc/implemented/feature/2026-07-06-sandbox.md); darwin: macOS
|
||||
* `sandbox-exec` speaking a Seatbelt (SBPL) profile, unprobed.
|
||||
* When the platform has no chain or no candidate passes,
|
||||
* {@link LocalSandboxProvider.confine} FAILS CLOSED with the seam's
|
||||
|
||||
@@ -6,6 +6,6 @@ The contract in one line: `ctx.sandbox.confine(argv, policy)` returns the argv t
|
||||
|
||||
Policy rides the call, not the provider: two consumers may confine under different policies at the same instant (bash under `read-only` while a confined child agent keeps its state directory writable), and an approved escalated retry is just a new call with a wider policy.
|
||||
|
||||
**Same-world confinement only.** A backend shares the host's filesystem and kernel (`bwrap`, Landlock, Seatbelt); `workspaceRoot` names a real host path. Containers, microVMs, and remote executors are NOT backends of this seam — they replace whole capability implementations (`ctx.bash`, `ctx.fs`) as environment-coherent groups. The boundary and its rationale: [the sandbox RFC](../../../docs/rfc/proposed/feature/2026-07-06-sandbox.md).
|
||||
**Same-world confinement only.** A backend shares the host's filesystem and kernel (`bwrap`, Landlock, Seatbelt); `workspaceRoot` names a real host path. Containers, microVMs, and remote executors are NOT backends of this seam — they replace whole capability implementations (`ctx.bash`, `ctx.fs`) as environment-coherent groups. The boundary and its rationale: [the sandbox RFC](../../../docs/rfc/implemented/feature/2026-07-06-sandbox.md).
|
||||
|
||||
Implementations: [`@deepseek-ai/dsh-sandbox-local`](../sandbox-local/) (Linux: `bwrap`, else the per-platform Landlock launcher; macOS: `sandbox-exec`/Seatbelt). The staged first consumer is the sandboxed bash executor (wrapping `['bash', '-c', command]`).
|
||||
Implementations: [`@deepseek-ai/dsh-sandbox-local`](../sandbox-local/) (Linux: `bwrap`, else the per-platform Landlock launcher; macOS: `sandbox-exec`/Seatbelt). Consumers: [`@deepseek-ai/dsh-bash-sandbox`](../../bash/bash-sandbox/) (wraps `['bash', '-c', command]`).
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* npm-distributed `landlock-run` launcher, macOS `sandbox-exec`/Seatbelt) is
|
||||
* the first.
|
||||
* Consumers hand over the exact argv they are about to spawn
|
||||
* (the staged bash executor wraps `['bash', '-c', command]`; a
|
||||
* (`@deepseek-ai/dsh-bash-sandbox` wraps `['bash', '-c', command]`; a
|
||||
* subagent backend wraps its child-agent argv) and spawn the returned argv
|
||||
* instead.
|
||||
*
|
||||
@@ -17,7 +17,7 @@
|
||||
* backends of this seam — they are sibling implementations of whole
|
||||
* capability seams (`ctx.bash`, `ctx.fs`), deployed as environment-coherent
|
||||
* groups; the boundary is recorded in
|
||||
* docs/rfc/proposed/feature/2026-07-06-sandbox.md.
|
||||
* docs/rfc/implemented/feature/2026-07-06-sandbox.md.
|
||||
*
|
||||
* @module @deepseek-ai/dsh-sandbox
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user