From 655683c9e0ef71dba71b592d4e4d80d55b53a65f Mon Sep 17 00:00:00 2001 From: "K. Isom" Date: Tue, 22 Sep 2026 22:30:04 -0700 Subject: [PATCH] Apply P13: tool containers run from one Nix-built image named by digest Co-Authored-By: Claude Opus 5.5 (1M context) --- docs/decisions.md | 5 ++--- docs/design.md | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/decisions.md b/docs/decisions.md index f8cdd77..da112e8 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -82,9 +82,8 @@ Later changes to the brief: |---|---|---| | 2026-09-17 | The roles table gained a one-sentence Purpose column, and the crates that are not roles got a purpose table under Code constraints. No behaviour changed. | Owner's request: a reader, human or agent, should learn what each piece is for before what it holds. | | 2026-09-18 | P14, State: the list gained `broker/sessions/.json`, each session's taint and untrusted flag, written only by `brokerd`. | The M3a spec keeps this state in files the list did not name. It can be rebuilt from the audit log's `result` records, so the audit log stays the record of truth. Owner: a plain file also makes debugging easier. | +| 2026-09-22 | P13, Authority contract 4: tool containers run from one image built from source by Nix and named by digest; nothing is pulled at call time. | Approved with the M3 design (2026-09-18); applied when the M3b spec came to rely on it. A pull at call time would be unlisted egress. | ## Proposed changes to the design brief -| # | Change | Reason | -|---|---|---| -| P13 | Authority contract 4: add "Tool containers run from one image built from source by Nix and named by digest; nothing is pulled at call time." | The brief does not say where tool images come from; a pull at call time would be unlisted egress. Decided 2026-09-18 above. | +None pending. diff --git a/docs/design.md b/docs/design.md index e83a7a4..4ef487e 100644 --- a/docs/design.md +++ b/docs/design.md @@ -145,7 +145,8 @@ a multi-turn tool conversation and tool parsing had no failures in 20 trials. 3. No matching grant means deny. `ask` routes an approval request to the owner through `gatewayd` and the turn suspends until answered or expired. 4. Each approved call runs in a fresh rootless container: no network unless granted, only granted - paths mounted, only the granted secret injected. + paths mounted, only the granted secret injected. Tool containers run from one image built from + source by Nix and named by digest; nothing is pulled at call time. 5. **Audit log**: append-only JSONL, hash-chained, one record per decision including denials. 6. **Data classes**: every tool result is labelled `public`, `private`, or `secret`. A session's taint is the union of labels it has seen. The cloud-consult tool is refused for tainted sessions