9cd583fbbb
Finishes PRD 0017. The `cred-proxy-block` MCP tool is renamed and
its remediation apply path is repointed at egress-proxy.
- `claude_bottle/supervise.py` — `TOOL_CRED_PROXY_BLOCK` →
`TOOL_EGRESS_PROXY_BLOCK`; `COMPONENT_FOR_TOOL` maps the new
tool ID to `egress-proxy` for audit-log routing.
- `claude_bottle/supervise_server.py` — tool definition renamed
+ description rewritten: "Call when egress-proxy refused your
HTTPS request ... Read the current routes.yaml from /etc/
claude-bottle/current-config/routes.yaml, compose a modified
version, pass the full new file plus a justification." The
syntactic validator dispatches on the new tool ID.
- `claude_bottle/backend/docker/egress_proxy_apply.py` — renamed
from `cred_proxy_apply.py`. Reads routes.yaml from
/etc/egress-proxy/routes.yaml via `docker exec cat`; validates
via `egress_proxy_addon_core.load_routes` (so both sides use
the same parser); writes via `docker cp`; SIGHUPs egress-proxy
with `docker kill --signal HUP`. `EgressProxyApplyError`
replaces `CredProxyApplyError`.
- `claude_bottle/cli/dashboard.py` — wires the new apply +
`discover_egress_proxy_slugs` helper; the operator-initiated
`routes edit <bottle>` verb now writes to egress-proxy with
`.yaml` suffix. Stale follow-up comment about path-aware
filtering removed — PRD 0017 settled that question.
- `tests/integration/test_supervise_sidecar.py` — restores the
approval round-trip test (chunk 2 had switched it to a reject
path because no cred-proxy existed). Approval stubs
`apply_routes_change` so the test focuses on the supervise
queue/response plumbing rather than docker-exec into a real
egress-proxy sidecar (that's covered separately).
- `tests/unit/test_egress_proxy_apply.py` — rewritten against
the new validator; covers JSON shape, missing routes key,
partial-auth-pair rejection (the addon-core parser catches
these before SIGHUP).
- PRDs 0010 + 0014 — status headers updated to
Superseded / Retargeted with a callout block pointing at PRD
0017's migration section. Historical text preserved.
384 unit + integration tests pass.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
77 lines
4.2 KiB
Markdown
77 lines
4.2 KiB
Markdown
# PRD 0014: cred-proxy block remediation
|
|
|
|
- **Status:** Retargeted by [PRD 0017](0017-egress-proxy-via-mitmproxy.md)
|
|
- **Author:** didericis
|
|
- **Created:** 2026-05-25
|
|
- **Retargeted:** 2026-05-25
|
|
- **Parent:** PRD 0012
|
|
- **Depends on:** PRD 0013
|
|
|
|
> **Retarget notice.** The remediation shape this PRD describes (MCP
|
|
> tool → operator approve → SIGHUP a sidecar) is intact, but the
|
|
> sidecar moved: cred-proxy is gone, replaced by egress-proxy under
|
|
> PRD 0017. The MCP tool is now named `egress-proxy-block`; the
|
|
> proposed file is `routes.yaml` (JSON content) in egress-proxy's
|
|
> route shape (host + path_allowlist + nested `auth` block); the
|
|
> apply path docker-cps + SIGHUPs egress-proxy. The audit-log
|
|
> component label changed from `cred-proxy` to `egress-proxy`.
|
|
> Operator-initiated `routes edit <bottle>` still exists with the
|
|
> same UX, now pointed at the egress-proxy sidecar.
|
|
|
|
## Summary
|
|
|
|
Wires the **cred-proxy block** path (PRD 0012 *Stuck categories*) end-to-end. cred-proxy gains SIGHUP-based hot reload of `routes.json`. The supervisor, on approval of a `cred-proxy-block` proposal, writes the new `routes.json` to the host and SIGHUPs cred-proxy — no restart, no dropped connections. The TUI gains a proactive `routes edit <bottle>` verb for operator-initiated edits unrelated to a tool call. The cred-proxy audit log (format defined in PRD 0013) is filled in with real entries on every edit.
|
|
|
|
## Problem
|
|
|
|
See PRD 0012. This PRD specifically addresses: with 0013 in place, the operator can approve a `cred-proxy-block` proposal but nothing happens — `routes.json` doesn't change and cred-proxy doesn't notice. This PRD closes the loop.
|
|
|
|
## Goals / Success Criteria
|
|
|
|
A real cred-proxy block recovers end-to-end: the agent's HTTP request fails with a 403, the agent calls `cred-proxy-block` with a proposed `routes.json` and a justification, the operator approves in the TUI, the supervisor writes the new file and SIGHUPs cred-proxy, the agent retries against the now-reloaded proxy and proceeds. In-flight connections to cred-proxy do not drop during the reload.
|
|
|
|
## Non-goals
|
|
|
|
- Pipelock or capability handling (covered by 0015 and 0016).
|
|
- Auto-rotation of expired tokens. The operator decides whether to issue a new token; this PRD just delivers approved config changes to cred-proxy.
|
|
|
|
## Scope
|
|
|
|
### In scope
|
|
|
|
- SIGHUP reload of `routes.json` on cred-proxy. ~30 lines added to the server.
|
|
- Supervisor write path: on operator approval of a `cred-proxy-block` proposal, write the proposed `routes.json` to the host-side path cred-proxy reads, then send SIGHUP.
|
|
- `routes edit <bottle>` TUI verb: open the bottle's `routes.json` in `$EDITOR`, write + SIGHUP on save. Not gated on a pending proposal.
|
|
- cred-proxy audit log entries: every routes edit (from a tool-call approval or from a proactive `routes edit`) appends an entry with timestamp, diff, justification (if from tool call), and operator action.
|
|
|
|
### Out of scope
|
|
|
|
- Restart-based reload as a fallback. SIGHUP only.
|
|
- Pipelock equivalents (PRD 0015).
|
|
|
|
## Proposed Design
|
|
|
|
### New services / components
|
|
|
|
- **`routes edit <bottle>` TUI verb.** Opens the bottle's current `routes.json` in `$EDITOR`. On save, the supervisor writes the new file and SIGHUPs cred-proxy. Useful when the operator wants to add a route without waiting for an agent prompt.
|
|
|
|
### Existing code touched
|
|
|
|
- **cred-proxy** (PRD 0010) — gains a SIGHUP signal handler that re-reads `routes.json` without dropping connections or breaking in-flight calls.
|
|
- **MCP sidecar** (PRD 0013) — the `cred-proxy-block` approval handler stops being a no-op; on approval, calls the supervisor's write+SIGHUP path.
|
|
- **`cli.py`** — dashboard subcommand gains the `routes edit` verb.
|
|
|
|
### Data model changes
|
|
|
|
None beyond PRD 0013. The audit log format is defined there; this PRD fills it in.
|
|
|
|
## Open questions
|
|
|
|
- **SIGHUP race window.** An agent that retries within msec of the SIGHUP may hit old routes once before the reload completes, fail, and retry against the new routes. Assumption is that normal HTTP retry semantics absorb this; worth confirming under real usage rather than designing around it preemptively.
|
|
|
|
## References
|
|
|
|
- PRD 0010 — cred-proxy.
|
|
- PRD 0012 — stuck-agent recovery flow overview.
|
|
- PRD 0013 — supervise plane foundation (prerequisite).
|