From 6b915067066dd2d518e7b97f4eceea4c2410b377 Mon Sep 17 00:00:00 2001 From: didericis Date: Sun, 24 May 2026 14:23:26 -0400 Subject: [PATCH] docs: redraw README architecture to show pipelock as HTTP/S chokepoint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous diagram showed three parallel egress lanes — agent ↔ pipelock, agent ↔ git-gate, agent ↔ cred-proxy — each going off-box independently. That was true of an earlier shape but is now wrong on two counts: 1. cred-proxy's outbound HTTPS routes through pipelock (set when the SSRF / CA-trust wiring landed). All cred-proxy upstream bytes pass pipelock's allowlist + body scanner. 2. git-gate's SSH push/fetch is direct out the egress network and has never gone through pipelock — pipelock is HTTP-only. Reflect both: the diagram now collapses to one HTTP/HTTPS chokepoint (pipelock) that the agent and cred-proxy share, plus a separate SSH lane for git-gate. Prose paragraph above the diagram updated to call out the "everything except SSH" framing explicitly. Verified against the current code: HTTPS_PROXY=pipelock set on the agent in launch.py and on cred-proxy in DockerCredProxy.start; git-gate's create-args carry no proxy env vars. --- README.md | 72 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 43bbfc3..32b2469 100644 --- a/README.md +++ b/README.md @@ -71,43 +71,53 @@ pieces of v1. A bottle is the agent container plus up to three per-protocol egress sidecars on a per-agent Docker `--internal` network. The agent has no -default route off-box; its only way out is through the pipelock -sidecar (for HTTP/HTTPS), the git-gate sidecar (for git operations -against declared upstreams), or the cred-proxy sidecar (for API -calls that need a manifest-declared token — Anthropic OAuth, GitHub -PAT, Gitea PAT, npm). Each sidecar also sits on an egress network -that does have internet access, so the agent's traffic always passes -through a container that enforces the manifest before it leaves the -host. +default route off-box. All HTTP and HTTPS egress — from the agent +*and* from cred-proxy when it dials an upstream — funnels through +pipelock, where the egress allowlist, TLS interception, and +request-body DLP scanner enforce the manifest before any byte leaves +the host. The only egress that doesn't traverse pipelock is git-gate's +SSH push/fetch to `bottle.git` upstreams — pipelock can't proxy SSH, +so git-gate is its own L4-style egress path with gitleaks doing the +pre-receive scan. ``` host ( ./cli.py ) │ starts │ stops ▼ - ┌─────────────────────────── bottle ──────────────────────────┐ - │ │ - │ ┌──────────────────┐ │ - │ │ agent image │ HTTPS_PROXY ┌────────────────┐ │ HTTPS to - │ │ (claude-code, │ ───────────────► │ pipelock image │──┼──► allowlisted - │ │ built locally) │ │ (TLS bump, DLP,│ │ hosts - │ │ │ │ allowlist) │ │ - │ │ skills, env, │ └────────────────┘ │ - │ │ ~/.gitconfig, │ │ - │ │ ~/.npmrc, tea │ git ops ┌────────────────┐ │ SSH (push/ - │ │ │ ───────────────► │ git-gate image │──┼──► fetch) to - │ │ │ │ (gitleaks + │ │ bottle.git - │ │ environ: URLs │ │ git daemon) │ │ upstreams - │ │ only, no real │ └────────────────┘ │ - │ │ tokens │ bearer-auth ┌────────────────┐ │ HTTPS to - │ │ │ ───────────────► │ cred-proxy │──┼──► bottle.tokens - │ │ │ HTTP, plain │ (strips/injects│ │ upstreams - │ │ │ │ Authorization)│ │ (with the - │ └──────────────────┘ └────────────────┘ │ real token) - │ │ - │ agent on internal network (no default route); │ - │ sidecars also attached to an egress network. │ - └─────────────────────────────────────────────────────────────┘ + ┌─────────────────────────── bottle ──────────────────────────────────┐ + │ │ + │ ┌──────────────────┐ │ + │ │ agent image │ HTTPS_PROXY │ + │ │ (claude-code, │ ────────────────────────┐ │ + │ │ built locally) │ │ │ + │ │ │ plain HTTP │ │ + │ │ skills, env, │ (token injection) ┌────▼─────────┐ │ + │ │ ~/.gitconfig, │ ──────────────────►│ cred-proxy │ │ + │ │ ~/.npmrc, tea │ │ (strips/inj │ │ + │ │ │ │ Authoriz.) │ │ + │ │ environ: URLs │ └─────┬────────┘ │ + │ │ only, no real │ HTTPS_PROXY │ │ + │ │ tokens │ ▼ │ + │ │ │ ┌────────────────┐ │ HTTPS to + │ │ │ │ pipelock image │──────────┼──► allowlisted + │ │ │ │ (TLS bump, DLP │ │ hosts (incl. + │ │ │ │ body scan, │ │ cred-proxy + │ │ │ │ allowlist) │ │ upstreams) + │ │ │ └────────────────┘ │ + │ │ │ │ + │ │ │ git:// ┌────────────────┐ │ SSH push/fetch + │ │ │ ────────────────►│ git-gate image │──────────┼──► to bottle.git + │ │ │ │ (gitleaks + │ │ upstreams + │ └──────────────────┘ │ git daemon) │ │ (direct — not + │ └────────────────┘ │ via pipelock) + │ │ + │ agent on internal network (no default route); pipelock, │ + │ cred-proxy, and git-gate straddle internal + egress networks. │ + │ pipelock is the single HTTP/HTTPS chokepoint — cred-proxy's │ + │ outbound traverses it too. git-gate's SSH egress is direct │ + │ because pipelock is HTTP-only. │ + └─────────────────────────────────────────────────────────────────────┘ ``` - **agent image** — built from the repo `Dockerfile` (`node:22-slim`