refactor(cleanup): compose-ls driven + drop pipelock CIDR allowlist #36
Reference in New Issue
Block a user
Delete Branch "chunk-4-cleanup-cli"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
PRD 0018 chunk 4. Two commits:
Commit 1 — spike result: networks become compose-managed. I empirically verified that pipelock's SSRF guard checks the destination of proxied requests (e.g.
api.anthropic.com→ public IP) and not the source IP of incoming connections. The bottle's own internal CIDR was being added tossrf.ip_allowlistdefensively, but probing pipelock directly (curl --proxy http://pipelock https://api.anthropic.com/) returns 404 from upstream rather than blocking — the allowlist isn't load-bearing. So networks become compose-managed (internal: trueon the internal network); chunk 3's pre-create + CIDR introspection + pipelock yaml re-render dance all come out.Commit 2 — cleanup CLI on
docker compose ls. Backend'sprepare_cleanupderives its work fromdocker compose ls --all --format jsonfiltered toclaude-bottle-projects. Per project: onecompose down --volumesremoves the containers + compose-managed networks atomically. Three fallback buckets handle anything outside that — stray containers without compose labels (pre-compose orphans), stray networks (same), and orphan state dirs (no live project + no.preservemarker).The CLI collapses to one y/N — backend handles state-dir reaping inside the same plan instead of via a separate prompt.
.preserve(capability-block or crash auto-preserve) explicitly opts out of reaping; manualrm -rfremains the only path for preserved state.Stacking note
This branch is based on PR #35 (chunk 3), not main. Merge order: #35 first, then this.
Status
./cli.py start implementerend-to-end works with compose-managed networks (no SSRF blocks)./cli.py cleanupcorrectly enumerates + reaps projects, strays, and orphan state dirsPRD 0018 chunk 4. `claude-bottle cleanup` now derives its work from `docker compose ls --all --format json`, filtered to projects whose name starts with `claude-bottle-`. Per project: one `compose down --volumes` removes the containers + the compose-managed networks atomically. The plan also enumerates three fallback buckets: - Stray containers — `claude-bottle-*` containers with no `com.docker.compose.project` label (left over from pre-compose code paths). Cleared via `docker rm -f`. - Stray networks — `claude-bottle-*` networks with no compose project label. Cleared via `docker network rm`. - Orphan state dirs — per-bottle `~/.claude-bottle/state/<id>/` dirs with no live project AND no `.preserve` marker. The `.preserve` marker (capability-block or auto-preserve-on-crash) explicitly opts-out of reaping; manual `rm -rf` is the only path for preserved state. cli/cleanup.py collapses to a single y/N prompt — backend.prepare_cleanup returns everything in one plan, backend.cleanup processes everything, no more double-prompt for state. The CLI-side state-dir enumeration + `_state_summary` flags from PR #25 are gone; the backend's orphan-detection rules subsume them.9f2498397ftoaee249f119