From 6be00559277c0205c095adf3403cd76979305705 Mon Sep 17 00:00:00 2001 From: Stephen Waits Date: Tue, 27 Oct 2026 09:37:46 -0600 Subject: [PATCH] docs: P9a landed; the tunnel door is loopback-only and its live checks remain owner's --- plan/STATUS.md | 21 +++++++++++++++++++++ plan/served.md | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/plan/STATUS.md b/plan/STATUS.md index 62d690c..233674c 100644 --- a/plan/STATUS.md +++ b/plan/STATUS.md @@ -177,6 +177,27 @@ is where one would go. `Attention` also carries the prompt (the viewer's, so there is one copy) beyond the plan's sketch, and `PackageBooks` gained four read methods rather than a new trait. `just check` green. +**2026-10-27: P9a landed (`c8541ea9`).** The self-host recipe is in +`deploy/` (a system unit as the `wanderbooks` account, `ProtectSystem`, +`NoNewPrivileges`, loopback-only network, no seccomp/Landlock per D-32), +`books adopt` moves a book with its head check, `wanderbooks serve +--isolation enforced` makes `books.start` say `service_user (enforced)`, +and `--http` serves the same MCP door on loopback behind Caddy or a +tunnel, with the bearer still guarding every call. The door is +**loopback only**: a review found the first version bound any address, +which would have exposed a plaintext static-bearer door; it now refuses +anything but 127.0.0.0/8 or `::1` before a socket or a host exists, and +`the_tunnel_door_binds_loopback_only` proves it. `two_user.rs` has the +two-account tests; `agent_uid_cannot_read_tenant` skips unless +`WB_TWO_USER=1` and the CI job sets it. **Done-when (1) the CI job and +(2) the clean-VM walkthrough by a non-author are owner/EM to verify** — +they were not run here, and the As-built says so. `IPAddressDeny=any` +also blocks the server's own push to a remote backup repository; the +README documents the `IPAddressAllow` drop-in. One pre-existing race was +seen under load, not ours: `ledger-gui/tests/newer_journal.rs::a_live_viewer_says_update_when_the_books_move_ahead_of_it` +can read between the test's two appends; it passed alone and in the +final run, and belongs with the other load-sensitive test noted above. + The 2026-10-16 audit of the first company's books (62 verified findings, 20 engine defects) and the design discussion that followed produced diff --git a/plan/served.md b/plan/served.md index e48af04..0f6d24c 100644 --- a/plan/served.md +++ b/plan/served.md @@ -824,7 +824,7 @@ One row per unit of work. A unit is what one engineer takes into one git worktre | P6 | Evidence pipeline: extraction, dedup, annotations, company record categories | not started | U0a, U0b | S4-S7, P4, P5 (not its envelope step), P9a, P11a, P13 | `attachment_text` | 8-10 | | P7 | The TIN scanner's separators; vault v2 closed (D-48) | landed 2026-10-26 (`3e65c83f`) | none | everything | none | 1 | | P8 | Audit and attestations | not started | P6 (extraction), P4 (drafts), U0b | P9a, P11a, P13 | `audits` | 10-12 | -| P9a | Self-host recipe, `books adopt` move with the head check, static bearer over a tunnel, the two-user CI job | not started | none (code); a second machine to try it on | everything | none | 3-4 | +| P9a | Self-host recipe, `books adopt` move with the head check, static bearer over a tunnel, the two-user CI job | landed 2026-10-27 (`c8541ea9`); Done-when 1-2 are owner/EM to verify | none (code); a second machine to try it on | everything | none | 3-4 | | P9b | claude.ai through an external identity provider (D-7 b, Q-6) | not planned until Q-6 is answered | P9a | | | | | P9c | Remote viewer replica, invitations | not planned (D-51) | | | | | | P10 | The re-audit runbook and its CI mirror; the owner runs the re-audit | not started | P5, P6, P8 | P11a, P13 | none | 1 (+ owner days) |