diff --git a/docs/decisions.md b/docs/decisions.md index dd5acc5..eb11ef9 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -72,10 +72,10 @@ Later changes to the brief: | Date | Change | Reason | |---|---|---| | 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. | ## 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. | -| P14 | State: add "`broker/sessions/.json` — each session's taint and untrusted flag, written only by `brokerd`". | The M3a spec keeps this state in files the brief's list does not name. It can be rebuilt from the audit log's `result` records, so the audit log stays the record of truth. | diff --git a/docs/design.md b/docs/design.md index bbdd0a5..e83a7a4 100644 --- a/docs/design.md +++ b/docs/design.md @@ -206,6 +206,8 @@ Files are the source of truth. SQLite is allowed only for rebuildable indexes an - `index/` — FTS5 and, later, vectors; disposable and rebuildable from `memory/` - `grants/*.toml` — owner-written - `audit/*.jsonl` — hash-chained +- `broker/sessions/.json` — each session's taint and untrusted flag, written only by + `brokerd`; it can be rebuilt from the audit log's `result` records - Secrets: behind a `SecretStore` trait. v0 backend is an encrypted file whose key is not stored beside it. No plaintext secrets on disk, none in config, none in the repo. diff --git a/docs/specs/2026-09-18-m3a-decision-path.md b/docs/specs/2026-09-18-m3a-decision-path.md index 94f64ee..5c8c85a 100644 --- a/docs/specs/2026-09-18-m3a-decision-path.md +++ b/docs/specs/2026-09-18-m3a-decision-path.md @@ -296,7 +296,7 @@ pub fn redecide(ask: Ask, grants: &GrantSet, state: SessionState, now: Timestamp - Writes are atomic: write `.json.tmp`, `fsync`, rename over `.json`, `fsync` the directory. - A file that exists but cannot be read or parsed is an error: every call for that session is denied with `state_unreadable` and `brokerd` prints `see docs/runbook.md#broker-state-damaged`. -- The brief's State list does not name this directory yet; P14 in `docs/decisions.md` proposes it. +- The brief's State list names this file (P14, applied 2026-09-18). - `loopd` has no access to `/broker/`. The `class` and `untrusted` values it logs are a copy for its own use and never an input to policy.