3 Commits
Author SHA1 Message Date
dtzp555-maxandGitHub d67ba3d675 docs(adr): Phase 7 Amendment 1 — supersede PR-B with ephemeral-home + ISOLATION contract (#66)
Co-merging ADR 0014 Amendment 1 (4-layer Solution 1) + ADR 0002 Amendment 9 (Provider ISOLATION contract).

Reviewed by 2 fresh-context opus subagents per Iron Rule 10. Second review verdict APPROVE after 6 citation-discipline fold-ins applied.

PR-B outer-bwrap archived to branch phase-7-pr-b-outer-bwrap-snapshot.
2026-05-29 10:00:38 +10:00
taodengandClaude Sonnet 4.6 d0dcd281ef 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>
2026-05-28 17:26:34 +10:00
taodengandClaude Opus 4.7 07d9c8a6ae feat(sandbox): Phase 7 PR-A — @anthropic-ai/sandbox-runtime dep + doctor + ADR 0014
Lays the foundation for multi-tenant provider spawning isolation per
ADR 0014 § Decision. NO production wiring — PR-B (anthropic.mjs spawn
wrap) lands separately and requires bubblewrap + socat + ripgrep
installed on PI231 first.

Files:
- package.json: add @anthropic-ai/sandbox-runtime ^0.0.52
- lib/sandbox/doctor.mjs (new): preflight checkSandboxAvailability +
  describeSandboxStatus; pure module, no state, no initialize() call
- server.mjs: /health response gains 'sandbox' field with availability
  + missing deps + install hint; result memoized via _sandboxStatusCache;
  __resetSandboxStatusCache() test seam exported
- docs/adr/0014-sandbox-runtime-integration.md (new): 4-PR layered
  rollout decision per Iron Rule 11; PR-B/C/D acceptance criteria
  previewed; 6 spike pitfalls recorded; 282 lines
- CHANGELOG.md: Unreleased entry under Phase 7 PR-A
- test-features.mjs Suite 42 (+8 tests, 797 → 805, all pass)

Authority:
- @anthropic-ai/sandbox-runtime v0.0.52 — anthropic-experimental org
  https://github.com/anthropic-experimental/sandbox-runtime
- 2026-05-28 PoC spike (verdict YELLOW; report at /tmp/sandbox-spike/
  on PI231): clean arm64 install, dep check fail-closed behaviour
  confirmed, three PoC scripts parked
- cc-mem incident memory § 4 (prior-art search — ecosystem hasn't
  solved multi-tenant fs/tool isolation)
- ADR 0009 Amendment 1 § Caveats #3 — sandbox is cloud prerequisite
- docs/plans/cloud-deployment-family.md § 5

Spike note (macOS): on dev Mac mini with rg via Homebrew,
SandboxManager.isSupportedPlatform()=true and checkDependencies()
returns no errors — macOS uses built-in sandbox-exec, not bwrap.
/health.sandbox.available=true on macOS dev, false on PI231 until
apt install.

Operational follow-ups (NOT this PR):
1. sudo apt-get install -y bubblewrap socat ripgrep on PI231 (5-min window)
2. PR-B: lib/providers/anthropic.mjs spawn wrap + negative test
   (in-sandbox cat of OAuth token MUST fail)
3. PR-C: lib/providers/codex.mjs wrap with enableWeakerNestedSandbox:true
4. PR-D: cloud deployment plan update + unblock

Tests: 797 → 805 (all pass, 0 fail).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 17:09:37 +10:00