From bea433015f4af01cfcd2630e448219e893055926 Mon Sep 17 00:00:00 2001 From: didericis Date: Tue, 12 May 2026 21:19:20 -0400 Subject: [PATCH] docs(readme): add git-gate to architecture diagram Bumps the sidecar count from two to up to three; the diagram and bullet list now cover the git-gate alongside pipelock and ssh-gate, including the ~/.gitconfig pushInsteadOf wiring that fires the agent's git push through the gate. --- README.md | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 4a08dfb..56a8f13 100644 --- a/README.md +++ b/README.md @@ -56,12 +56,14 @@ pieces of v1. ## Architecture -A bottle is three containers 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) or the ssh-gate sidecar -(for SSH). Both sidecars also sit 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. +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 ssh-gate sidecar (for SSH), or the +git-gate sidecar (for `git push`). 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. ``` host ( ./cli.py ) @@ -76,11 +78,17 @@ container that enforces the manifest before it leaves the host. │ │ built locally) │ │ (TLS bump, DLP,│ │ hosts │ │ │ │ allowlist) │ │ │ │ skills, env, │ └────────────────┘ │ - │ │ ~/.ssh/config │ │ - │ │ │ ssh ┌────────────────┐ │ TCP to + │ │ ~/.ssh/config, │ │ + │ │ ~/.gitconfig │ ssh ┌────────────────┐ │ TCP to │ │ │ ───────────────► │ socat/ssh image│──┼──► bottle.ssh │ │ │ │ (alpine/socat, │ │ upstreams │ │ │ │ L4 forwarder) │ │ + │ │ │ └────────────────┘ │ + │ │ │ │ + │ │ │ git push ┌────────────────┐ │ SSH (push) + │ │ │ ───────────────► │ git-gate image │──┼──► to bottle.git + │ │ │ │ (gitleaks + │ │ upstreams + │ │ │ │ git daemon) │ │ │ └──────────────────┘ └────────────────┘ │ │ │ │ agent on internal network (no default route); │ @@ -90,7 +98,8 @@ container that enforces the manifest before it leaves the host. - **agent image** — built from the repo `Dockerfile` (`node:22-slim` base) on first run; runs `claude` with the manifest-granted skills, - env vars, and `~/.ssh/config`. + env vars, `~/.ssh/config`, and `~/.gitconfig` (the latter for the + git-gate's `pushInsteadOf` rules when `bottle.git` is set). - **pipelock image** — per-agent sidecar. Terminates the agent's outbound HTTP/HTTPS, enforces the resolved allowlist, runs DLP scanning. Design in `docs/prds/0001-per-agent-egress-proxy-via-pipelock.md` @@ -99,9 +108,17 @@ container that enforces the manifest before it leaves the host. One container, one socat listener per `bottle.ssh` entry, each forwarding TCP to the upstream `Hostname:Port`. SSH does *not* go through pipelock. Design in `docs/prds/0007-ssh-egress-gate.md`. +- **git-gate image** — per-agent sidecar built on `zricethezav/gitleaks` + (alpine + gitleaks + git-daemon + openssh-client). Runs + `git daemon --enable=receive-pack` so the agent can push to it + via `git://`; a pre-receive hook gitleaks-scans each incoming ref + and forwards clean refs to the real upstream over SSH using a + credential the agent never sees. Brought up only when `bottle.git` + has entries. Design in `docs/prds/0008-git-gate.md`. -When the agent exits, `cli.py` tears down both sidecars and the two -networks; nothing about a bottle persists between runs. +When the agent exits, `cli.py` tears down every sidecar that was +brought up and the two networks; nothing about a bottle persists +between runs. ## Quickstart