mirror of
https://github.com/dtzp555-max/olp.git
synced 2026-07-19 09:45:07 +00:00
feat(sandbox): Phase 7 PR-B — anthropic.mjs spawn wrapped in sandbox-runtime
Wraps the claude CLI spawn in @anthropic-ai/sandbox-runtime per ADR 0014 § PR-B. Achieves multi-tenant filesystem + network isolation: the spawned claude subprocess can no longer read ~/.olp/keys.json, ~/.claude/.credentials.json, ~/.ssh/, or any other per-client OAuth material. Only api.anthropic.com and statsig.anthropic.com are reachable; only /tmp/olp-spawn/<uuid>/ is writable per spawn (ephemeral, UUID-scoped to prevent cross-request contamination). ## Authority citations - @anthropic-ai/sandbox-runtime v0.0.52 https://github.com/anthropic-experimental/sandbox-runtime dist/sandbox/sandbox-manager.js — SandboxManager.initialize(), wrapWithSandbox() dist/sandbox/sandbox-utils.js — getDefaultWritePaths() - 2026-05-28 spike report at /tmp/sandbox-spike/report.md on PI231: spike-anthropic.mjs (wrapWithSandbox call signature + NDJSON proof), spike-deny.mjs (cat ~/.olp/keys.json MUST fail) - OLP ADR 0014 § 2.1 PR-B, § 4.1 PR-B acceptance criteria - OLP ADR 0009 Amendment 1 § Caveats #3 (sandbox is cloud prerequisite) - OLP ALIGNMENT.md Rule 1 — provider plugin authority citation - cc-mem incident 2026-05-27 § 3 (multi-tenant OAuth token exposure via prompt injection) ## Files changed - lib/sandbox/manager.mjs (new): bootstrap + spawn-wrap layer. Exports: bootstrapSandbox(), isSandboxActive(), wrapSpawn(), __resetSandboxManagerForTests(). Config-at-boot model (one SandboxManager.initialize() at server start; per-request wrapWithSandbox() reads from already-initialized state). Transparent pass-through when inactive. - lib/providers/anthropic.mjs: spawn site wrapped via wrapSpawn({ bin, args, env, allowedDomains: ['api.anthropic.com','statsig.anthropic.com'] }). ADR 0009 Amendment 1 spawn args unchanged — only execution is wrapped. - server.mjs: bootstrapSandbox() called before server.listen(); startup banner logs sandbox.active state. /health.sandbox now includes active:boolean field (distinguishes "deps present" from "SandboxManager initialized and wrapping"). - test-features.mjs: Suite 43 (8 tests — manager unit: bootstrap state, idempotency, isSandboxActive, wrapSpawn passthrough, /health.active field) + Suite 44 (2 PI231-gated tests: 44a security negative test + 44b positive echo test, skipped by default, run with OLP_E2E_SANDBOX=1 npm test). - CHANGELOG.md, docs/adr/0014-sandbox-runtime-integration.md: PR-B status updated; ADR table + /health JSON example updated with active field. ## Test count 805 (pre-PR-B) → 813 (+8 Suite 43; Suite 44 skipped on macOS, runs on PI231) All 813 pass on macOS dev machine. 0 regressions. ## PI231 validation (required before merge — Suite 44) After apt-get install bubblewrap socat (ripgrep already present) + server restart: 1. curl /health → confirm sandbox.available=true AND sandbox.active=true 2. Real anthropic request → confirm stream-json still works end-to-end 3. OLP_E2E_SANDBOX=1 npm test → confirm Suite 44a (cat ~/.olp/keys.json MUST fail) and Suite 44b (echo SANDBOX_PROOF succeeds) Reviewer: must SSH PI231, run Suite 44, and confirm the ADR 0014 § 4.1 criteria. This commit is ready to push; do NOT push before Suite 44 transcript is captured. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -65,7 +65,7 @@ The sandbox integration is split into four discrete PRs, each independently revi
|
||||
| PR | Scope | Blocking condition | Status |
|
||||
|---|---|---|---|
|
||||
| **PR-A** (this PR) | npm dep `@anthropic-ai/sandbox-runtime ^0.0.52` + `lib/sandbox/doctor.mjs` (preflight module) + `/health` `sandbox` field + ADR 0014 | None — no runtime initialization | ✅ Accepted |
|
||||
| **PR-B** | `lib/providers/anthropic.mjs` spawn wrapped in `SandboxManager.wrapWithSandbox` | `bubblewrap` + `socat` + `rg` installed on PI231 (`sudo apt-get install -y bubblewrap socat ripgrep`) | 🔲 Blocked on apt install |
|
||||
| **PR-B** | `lib/sandbox/manager.mjs` (bootstrap + spawn-wrap) + `lib/providers/anthropic.mjs` spawn wrapped + server startup wiring + `/health.sandbox.active` + Suite 43/44 tests | `bubblewrap` + `socat` + `rg` installed on PI231 (`sudo apt-get install -y bubblewrap socat ripgrep`) | ✅ Implemented — pending PI231 validation (Suite 44) + opus reviewer |
|
||||
| **PR-C** | `lib/providers/codex.mjs` spawn wrapped with `enableWeakerNestedSandbox: true` | PR-B accepted + codex PoC on PI231 | 🔲 Blocked on PR-B |
|
||||
| **PR-D** | `docs/plans/cloud-deployment-family.md` § "Phase 7 prerequisite met" update; cloud rollout unblocked | PR-B + PR-C accepted | 🔲 Blocked on PR-C |
|
||||
|
||||
@@ -142,25 +142,34 @@ The result is memoized process-wide via `_sandboxStatusCache` in `server.mjs`. T
|
||||
}
|
||||
```
|
||||
|
||||
When available (after apt install + process restart):
|
||||
When available (after apt install + process restart) and PR-B bootstrapped:
|
||||
|
||||
```json
|
||||
{
|
||||
"sandbox": {
|
||||
"available": true,
|
||||
"active": true,
|
||||
"missing": [],
|
||||
"platform": "linux"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
(PR-A shape did not include `active`. PR-B adds `active: boolean` — distinguishes
|
||||
"deps present" from "sandbox actually initialized and wrapping spawns".)
|
||||
|
||||
---
|
||||
|
||||
## 4. PR-B/C/D acceptance criteria (preview — locked in later PRs)
|
||||
## 4. PR-B/C/D acceptance criteria
|
||||
|
||||
These criteria are recorded here to prevent scope creep in the later PRs. Criteria may be refined by subsequent ADR amendments.
|
||||
### 4.1 PR-B (anthropic.mjs spawn wrap) — ✅ Implementation shipped, PI231 validation pending
|
||||
|
||||
### 4.1 PR-B (anthropic.mjs spawn wrap)
|
||||
**PR-B implementation (commit pending reviewer):**
|
||||
- `lib/sandbox/manager.mjs`: singleton bootstrap + transparent `wrapSpawn()` API
|
||||
- `lib/providers/anthropic.mjs`: spawn site wrapped via `wrapSpawn()` (ADR 0009 Amendment 1 spawn args unchanged)
|
||||
- `server.mjs`: `bootstrapSandbox()` called before `server.listen()`, `/health.sandbox.active` field added
|
||||
- `test-features.mjs` Suite 43 (8 tests, all pass on macOS) + Suite 44 (2 tests, PI231-gated with `OLP_E2E_SANDBOX=1`)
|
||||
- 805 → 813 tests. Suite 44 skipped by default; runs on PI231 after apt install.
|
||||
|
||||
**Load-bearing negative test (required for PR-B to merge):**
|
||||
|
||||
|
||||
Reference in New Issue
Block a user