From 071ccc92accb489919c655f20b5739c8ef2097b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christopher=20M=C3=BChl?= Date: Mon, 13 Apr 2026 09:57:38 +0000 Subject: [PATCH] docs(05-01): create execution summary --- .../05-01-SUMMARY.md | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 .planning/phases/05-per-project-instance-isolation/05-01-SUMMARY.md diff --git a/.planning/phases/05-per-project-instance-isolation/05-01-SUMMARY.md b/.planning/phases/05-per-project-instance-isolation/05-01-SUMMARY.md new file mode 100644 index 0000000..27077a7 --- /dev/null +++ b/.planning/phases/05-per-project-instance-isolation/05-01-SUMMARY.md @@ -0,0 +1,118 @@ +--- +phase: 05-per-project-instance-isolation +plan: "01" +subsystem: sandbox-mount-architecture +tags: [bwrap, mounts, isolation, per-project, instance-hash, worktree] +dependency-graph: + requires: [] + provides: [per-project-instance-isolation, direct-claude-bind, instance-hash-dirs] + affects: [claudebox.sh, REQUIREMENTS.md] +tech-stack: + added: [] + patterns: + - sha256sum[:16] of canonical git root path for per-project instance identity + - git rev-parse --git-common-dir for worktree-aware canonical root resolution + - bwrap overlay mounts (last-mount-wins) on top of direct ~/.claude bind +key-files: + created: [] + modified: + - claudebox.sh + - .planning/REQUIREMENTS.md +decisions: + - D-01: Direct bind of ~/.claude (not ~/.claudebox symlink) gives plugins/skills/hooks/MCP full visibility + - D-02: Per-project projects/ overlay via SHA-256[:16] of canonical root path + - D-03: history.jsonl bind overlay from ~/.claudebox/history.jsonl + - D-06: SANDBOX.md injected as file overlay; CLAUDE.md injection removed (user's real CLAUDE.md already has @SANDBOX.md) + - D-08: compute_canonical_root uses git rev-parse --git-common-dir for worktree awareness + - D-13: INST-03 satisfied architecturally — Claude Code manages its own file concurrency; no locking needed in claudebox.sh + - /bin/sh symlink added to sandbox so hooks can exec sh (ENOENT fix) +metrics: + duration: "~45 minutes" + completed: "2026-04-13" + tasks_completed: 3 + files_modified: 2 +--- + +# Phase 05 Plan 01: Mount Architecture Rewrite and Per-Project Instance Isolation Summary + +Direct bind of `~/.claude` into sandbox with SHA-256-keyed per-project overlay mounts, replacing the old `~/.claudebox` symlink approach that hid all plugins, skills, hooks, and MCP configs from Claude Code. + +## What Was Built + +### Mount Architecture Rewrite (claudebox.sh) + +Replaced the old mount approach (`--bind ~/.claudebox ~/.claudebox` + `--symlink ~/.claudebox ~/.claude`) with a new architecture: + +- `--bind "$HOME/.claude" "$HOME/.claude"` — direct bind, makes all Claude Code config (plugins, skills, hooks, MCP, commands, settings) visible inside the sandbox (D-01) +- `--bind "$INSTANCE_DIR" "$HOME/.claude/projects"` — per-project overlay; each project gets its own isolated directory mounted over the real `~/.claude/projects/` (D-02, INST-01) +- `--bind "$HOME/.claudebox/history.jsonl" "$HOME/.claude/history.jsonl"` — history overlay; conversation history stored sandbox-side (D-03) +- `--bind "$HOME/.claudebox/SANDBOX.md" "$HOME/.claude/SANDBOX.md"` — SANDBOX.md injected as file overlay (D-06) +- `--bind "$CREDS_FILE" "$HOME/.claude/.credentials.json"` — credential mount updated to new target path + +### Per-Project Instance Isolation + +Added `compute_canonical_root()` function using `git -C "$cwd" rev-parse --git-common-dir` to resolve worktree-aware canonical repo root. Git worktrees return a path pointing to the main worktree's `.git/`, so `dirname(readlink -f(git_common))` gives the main worktree root for any worktree. + +Instance hash computed as: `INSTANCE_HASH=$(printf '%s' "$CANONICAL_ROOT" | sha256sum | cut -c1-16)` + +Each project gets `~/.claudebox/projects/$INSTANCE_HASH/` with a `project-root` file recording the canonical path. Directory created at startup with `mkdir -p`. + +### Removed + +- Old `--symlink "$HOME/.claudebox" "$HOME/.claude"` (D-01 replacement) +- Old `--bind "$HOME/.claudebox" "$HOME/.claudebox"` (D-01 replacement) +- CLAUDE.md injection block (`CLAUDEMD="$HOME/.claudebox/CLAUDE.md"`) — user's real `~/.claude/CLAUDE.md` already has `@SANDBOX.md` (D-06) + +### Preserved + +- `CLAUDE_JSON_FILE` / `CLAUDE_JSON_MOUNT` conditional bind (`--bind "$CLAUDE_JSON_FILE" "$HOME/.claude.json"`) — critical for auth token persistence + +### Updated + +- Dry-run block echoes new mount layout including instance dir and CLAUDE_JSON conditional +- `print_audit` shows projects/ mount with instance dir path and canonical root for transparency +- SANDBOX.md heredoc updated to remove `~/.claudebox` references (no longer visible in sandbox) + +### /bin/sh Symlink Fix + +Added `--symlink $(which bash) /bin/sh` to BWRAP_ARGS. Without it, git hooks and other scripts that use `/bin/sh` fail with `posix_spawn '/bin/sh': ENOENT` inside the sandbox. Not in original plan scope — auto-fixed per deviation Rule 1 (bug) and confirmed approved by user at checkpoint. + +### Requirements Registration + +Added INST-01 through INST-04 to `.planning/REQUIREMENTS.md` under new `### Instance Isolation` section, with traceability table entries mapping all four to Phase 5. + +## Verification Results + +- `bash -n claudebox.sh` passes (syntax clean) +- `compute_canonical_root` present in claudebox.sh +- `INSTANCE_HASH` computation present in claudebox.sh +- New mount lines confirmed present via search +- Old symlink/claudebox bind lines confirmed absent +- Human checkpoint approved by user + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 1 - Bug] Added /bin/sh symlink so hooks can exec sh** +- **Found during:** Task 1 (anticipated based on bwrap behavior + user confirmation at checkpoint) +- **Issue:** Sandbox has no `/bin/sh` — git hooks and POSIX scripts that call `/bin/sh` fail with `posix_spawn '/bin/sh': ENOENT` +- **Fix:** Added `--symlink $(which bash) /bin/sh` to BWRAP_ARGS +- **Files modified:** claudebox.sh +- **Commit:** 4baf576 + +## Known Stubs + +None. All mount architecture changes are fully wired. Per-project instance dirs are created and used at runtime. No placeholder data flows to any UI or output. + +## Threat Flags + +None. No new network endpoints, auth paths, or unplanned trust boundary crossings introduced. The STRIDE mitigations in the plan's threat model (T-05-01 through T-05-04) were all implemented: `readlink -f` for symlink resolution, correct overlay mount order, hex-only INSTANCE_HASH path construction, and per-project isolation of `~/.claude/projects/`. + +## Self-Check: PASSED + +- FOUND: claudebox.sh (syntax check passed, compute_canonical_root present, INSTANCE_HASH present) +- FOUND: .planning/REQUIREMENTS.md (INST-01 through INST-04 present) +- FOUND: commit c5e8cca (mount architecture rewrite) +- FOUND: commit 6eb3b46 (INST-01 through INST-04 registration) +- FOUND: commit 4baf576 (/bin/sh symlink fix)