docs(04-01): complete credential mount and audit redesign plan

- Add 04-01-SUMMARY.md with task details, decisions, deviations, threat flags
This commit is contained in:
Christopher Mühl 2026-04-10 09:22:02 +00:00
parent def8e67126
commit 20fbd3f7d3

View file

@ -0,0 +1,120 @@
---
phase: 04
plan: 1
subsystem: sandbox-script
tags: [credentials, auth, audit, bwrap]
dependency_graph:
requires: []
provides: [credential-mount, unified-audit]
affects: [claudebox.sh]
tech_stack:
added: []
patterns: [conditional-bwrap-args-array, unified-audit-prefixes]
key_files:
created: []
modified:
- claudebox.sh
decisions:
- "Used BWRAP_ARGS array instead of inline exec bwrap to support conditional credential mount"
- "Used [~]/[>]/[+] text prefixes (not color-only) for accessibility"
- "print_audit depends on CREDS_MOUNT set earlier in script — no API change needed"
metrics:
duration: "2m 30s"
completed: "2026-04-10"
tasks_completed: 2
tasks_total: 2
files_changed: 1
---
# Phase 4 Plan 1: Credential Mount + Audit Redesign Summary
**One-liner:** Read-write `~/.claude/.credentials.json` bind mount for OAuth passthrough plus unified `[~]/[>]/[+]` env audit with Mounts and Network sections.
## What Was Built
### Task 4.1.1 — Add credential file mount
Added conditional detection and mounting of `~/.claude/.credentials.json` into the sandbox:
- `CREDS_FILE` / `CREDS_MOUNT` variables set after `mkdir -p "$HOME/.claudebox"`
- When `CREDS_MOUNT=true`: `--bind "$CREDS_FILE" "$HOME/.claude/.credentials.json"` added to bwrap args
- Silent skip when file absent — no error or warning output
- Uses `--bind` (not `--ro-bind`) so OAuth token refresh can write back to the file
- `exec bwrap` refactored to use `BWRAP_ARGS` array to support the conditional mount cleanly
- Credential bind mirrored in `--dry-run` display block
### Task 4.1.2 — Rewrite print_audit
Rewrote `print_audit` from three separate sections to a unified list:
- Single loop ordering: sandbox keys `[~]` (green) → host allowlisted `[>]` (yellow) → extra `[+]` (cyan)
- Text prefixes readable without color (accessibility — D-07)
- PATH retains multiline indented display
- New `Mounts:` section shows CWD, `~/.claude`, and conditional credentials line
- New `Network:` section shows `full (host network)` as Phase 6 placeholder
- All print_audit output goes to stderr
- `mask_value` called for every env var value in all three loops
## Decisions Made
1. **BWRAP_ARGS array:** The `exec bwrap ... \` inline form cannot have a conditional in the middle. Refactored to build a `BWRAP_ARGS` array and `exec bwrap "${BWRAP_ARGS[@]}"`. This is cleaner and extensible for future conditional mounts (network tiers, profile mounts).
2. **Text prefixes for accessibility:** `[~]`, `[>]`, `[+]` are printed as literal text (not just color differences). Color is additive — the prefix meaning is clear in monochrome terminals and when piped.
3. **CREDS_MOUNT scoping:** `CREDS_MOUNT` is set at script top-level (before `print_audit`), so the Mounts section in `print_audit` can read it without needing to re-check the filesystem.
## Commits
| Task | Hash | Message |
|-------|---------|---------|
| 4.1.1 | 6465da8 | feat(04-01): add credential file mount for OAuth passthrough |
| 4.1.2 | def8e67 | feat(04-01): rewrite print_audit to unified env list with Mounts and Network sections |
## Verification
```
bash -n claudebox.sh # SYNTAX OK
grep 'CREDS_FILE' claudebox.sh # line 105: CREDS_FILE="$HOME/.claude/.credentials.json"
grep 'CREDS_MOUNT' claudebox.sh # detection + dry-run + bwrap + Mounts section
grep 'credentials.json' claudebox.sh # lines 105, 267, 331, 364 (dry-run + bwrap)
grep 'ro-bind.*credentials' claudebox.sh # (no output — correct, uses --bind)
grep '[~]' claudebox.sh # lines 239, 242, 248
grep '[>]' claudebox.sh # lines 239, 253
grep '[+]' claudebox.sh # lines 239, 257
grep 'Mounts:' claudebox.sh # line 263
grep 'Network:' claudebox.sh # line 273
grep 'full (host network)' claudebox.sh # line 274
```
## Deviations from Plan
### Auto-fixed Issues
**1. [Rule 1 - Refactor] Refactored exec bwrap to BWRAP_ARGS array**
- **Found during:** Task 4.1.1
- **Issue:** The `exec bwrap ... \` inline multi-line form cannot include a conditional mount (`if [[ "$CREDS_MOUNT" == true ]]; then ... fi`) in the middle of the argument list.
- **Fix:** Replaced the inline `exec bwrap` form with a `BWRAP_ARGS` array built up with conditional appends, then `exec bwrap "${BWRAP_ARGS[@]}"`. This preserves identical runtime behavior while enabling conditional mounts.
- **Files modified:** claudebox.sh
- **Commit:** 6465da8
## Known Stubs
- **Network section:** `full (host network)` in `print_audit` is an intentional Phase 4 placeholder. Network isolation tiers will replace this in Phase 6.
## Threat Flags
| Flag | File | Description |
|------|------|-------------|
| threat_flag: credential-exfil | claudebox.sh | Read-write bind of `~/.claude/.credentials.json` gives sandbox read access to OAuth tokens; sandbox has full host network, so exfiltration is possible. Accepted risk per plan threat model — Phase 6 network tiers reduce surface. |
## Self-Check: PASSED
- claudebox.sh exists and was modified: FOUND
- Commit 6465da8 exists: FOUND
- Commit def8e67 exists: FOUND
- bash -n claudebox.sh: PASSES
- credentials.json appears in both exec bwrap block and dry-run block: CONFIRMED (lines 364, 331)
- [~]/[>]/[+] prefixes present in print_audit: CONFIRMED
- Mounts: / Network: sections present: CONFIRMED
- full (host network) present: CONFIRMED