Skip to content

doors: a containment row for the one way out, a refusal ledger, a timeout knob, and the write node's own follow-up switch - #12

Merged
itswl merged 1 commit into
mainfrom
doors-ledger-and-containment-row
Oct 19, 2026
Merged

itswl merged 1 commit into
mainfrom
doors-ledger-and-containment-row

Conversation

@itswl

@itswl itswl commented Oct 19, 2026

Copy link
Copy Markdown
Owner

Four small things left over from this week's reading, none of which changes what a round reports.

  • docs/containment.md gains the row it was missing. The composes and proxy.py both say "see docs/containment.md" for the egress boundary, and the page had no row for it among its fifteen. It now has one — what the allowlist, the shapes, the address vetting and the port list stop, what they do not, and where each lives — and sits in the "holds against a hostile model" list with its residual named: it bounds WHERE, not what.
  • The proxy's refusals go to a ledger. They were one WARNING line in the doors container's log, which a recreate throws away, while the gate beside them writes calls.jsonl on the volume. With EGRESS_LEDGER set (the work compose points it at /data/egress.jsonl, the same volume) every refusal is one JSON line: target, code, reason. Best-effort like the gate's ledger. Test: a refused CONNECT lands as a row.
  • MCPGATE_UPSTREAM_TIMEOUT. The gate's idle timeout for a silent upstream was a constant; it is a knob now, default the same 60 s. A second deployment running a copy of gate.py carried exactly this as its only local change; with it here the two files are the same file again.
  • The write node's follow-ups have their own switch. probe-work read HOOKPROBE_FOLLOW_UP_SENDERS like the planner and the watcher, so the .env value that lets a person continue a plan from a chat thread also applied to the one node that holds a write credential. It now reads WORK_FOLLOW_UP_SENDERS, empty by default: the pipe already keeps a reply under a plan card off the write node by routing (by_work=False); this is the second lock. Nobody loses anything today — the stack is stopped — and an operator who wants it back names the senders in .env.

Also in docs/deployments.md: the pipe's ledger is a WAL database on a bind mount and only the container opens it; read it stopped and immutably. The integrity check taken on 2026-10-19 was clean.

Gate: STACK GATE GREEN locally; CI read back below before merging.

… and a timeout knob; the write node's follow-ups get their own switch

docs/containment.md had no row for the egress proxy although the composes and proxy.py both point at it; it has one now, sorted into the holds-against-a-hostile-model list with its residual named (it bounds WHERE, not what). The proxy's refusals go to EGRESS_LEDGER as JSON lines beside the gate's calls.jsonl — a container's log leaves with the container, and the refusal log is the product. MCPGATE_UPSTREAM_TIMEOUT makes the gate's idle timeout a knob, default the same 60 s; a second deployment running a copy of gate.py carried exactly this as its only local change. probe-work reads WORK_FOLLOW_UP_SENDERS, empty by default, instead of the value the planner and the watcher share: the pipe already keeps a reply under a plan card off the write node by routing, and this is the second lock on the one node with a write credential.

docs/deployments.md: the pipe's ledger is a WAL database on a bind mount and only the container opens it; read it stopped and immutably. The integrity check of 2026-10-19 was clean at 446 events.
@itswl
itswl merged commit ceaf565 into main Oct 19, 2026
6 checks passed
@itswl
itswl deleted the doors-ledger-and-containment-row branch October 19, 2026 03:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant