From 9a816643965829c0ebbf73370b6f75a9660dc208 Mon Sep 17 00:00:00 2001 From: Jason Woltje Date: Mon, 12 Oct 2026 08:18:52 -0500 Subject: [PATCH] sessions, sage: I1 survey review, cutover ready sent Co-Authored-By: Claude Opus 5.5 --- agents/sage/work/next-target/I1-review.md | 36 +++++++++++++++++++++++ docs/SESSIONS.md | 1 + 2 files changed, 37 insertions(+) create mode 100644 agents/sage/work/next-target/I1-review.md diff --git a/agents/sage/work/next-target/I1-review.md b/agents/sage/work/next-target/I1-review.md new file mode 100644 index 000000000..132860750 --- /dev/null +++ b/agents/sage/work/next-target/I1-review.md @@ -0,0 +1,36 @@ +# I1 review: Researcher's container survey + +Sage, 2026-10-12. Reviews `agents/researcher/work/i1-container-survey/REPORT.md` (25417 bytes, written 2026-10-11T22:39Z) for Q97. + +## Verdict + +Accepted as the basis for the I1 brief, with one correction. The recommendation is right: containerize by role and make reachability carry the human proof instead of `/proc` ancestry. The broker gets two sockets, and the human one is mounted only into the Console. Agents get no route to the Console and no engine socket. The report says plainly what this does not close, a host-side agent under Jason's uid, which is decision 95's accepted limit. + +## Citations checked + +These match the tree at 36e34e5b: `runtime.mjs:61-69` (`authenticateHuman`, the swap point), `human.mjs:50` (the "not peer credentials or a hostile-process wall" comment), `server.mjs:43-56` (one socket takes both `cap` and `human` envelopes), `compose.yaml:7` (`1000:1000`), `compose.yaml:36-37` (keys as env), `compose.yaml:40` (whole dataRoot read-write), `session.mjs` `ENV_ALLOW`, and `mosaic-config.mjs:32` (docker-only backend). + +## Correction + +Finding 1 is stale. The forward-auth check shipped: `previewOptions` in `packages/webui/src/serve.mjs:121-141`, rows 74 and 76, and `--send` in the unit script, row 83 (1a8ba587). Its substance stands. The header names the user and proves nothing to a caller that can reach the port, and a host agent can reach 127.0.0.1:7332 today. + +## What I decide (brief work, no Jason input) + +- Two broker listeners in containerized mode, with the agent listener refusing `human` envelopes. A new `via` value in place of `verifyHuman`. The ancestry mode stays for the local install. +- Per-run narrow mounts (run dir, instance workspace, contracts read-only). No `bus/`, `bus-host/` or `runs/` in any agent container. +- `cap_drop: [ALL]`, `no-new-privileges`, `read_only` with tmpfs, pids, memory and CPU limits, default seccomp. +- Agent containers on an `internal: true` network with one egress proxy for provider hosts. Broker and notifier on a separate network. +- The brief carries the report's unverified list as spikes, each with a test, before any design depends on it. + +## Follow-ups (rows to open 2026-10-13) + +- `compose.yaml:40` mounts the whole dataRoot into the pi worker, including `bus/broker.sock`, as the same uid. Narrow it to the worker's own paths. This exposure exists today and doesn't depend on I1. +- Stale docs: `LAYERS.md` L4 and `docs/plans/CONDUCTOR.md:17,40` describe managed sessions as containerized. They run on the host. +- The board's `/api/reply` pastes into tmux, which doesn't cross containers. It needs another delivery path before the board containerizes. + +## Jason's part (sent to Mos as checklist lines) + +1. Direction. Approve containerize-by-role with per-role sockets as the human proof (Researcher's D with A). Default from 2026-10-14: today's isolation stays (PID namespace only, same uid), and no managed Mos runs on it outside the trial. +2. Rootless Docker. The daemon here is rootful, and jwoltje is in the `docker` group, which is root-equivalent. The subuid and subgid ranges are already in place. This is a host change only Jason can make. Default from 2026-10-14: the daemon stays rootful, and no container launcher gets built until it switches. +3. WebAuthn for decisions and role changes, as a second step. It needs a pinned new dependency and a hardware key touch per action. Default from 2026-10-14: deferred, and not in the first brief. +4. Subscription path. A key-holding gateway can't cover `CLAUDE_CODE_OAUTH_TOKEN`. Choose whether managed sessions in containers use an API key behind the gateway or the subscription token as a read-only file secret. Default from 2026-10-14: the file secret, the same token the sessions use now. diff --git a/docs/SESSIONS.md b/docs/SESSIONS.md index 10991b9be..723fd09b0 100644 --- a/docs/SESSIONS.md +++ b/docs/SESSIONS.md @@ -745,3 +745,4 @@ are never rewritten or removed; corrections are new entries. 2026-10-12T04:12:27Z | sage | row 83 (#1576) gate and landing | gate green 04:07:30Z-04:10:47Z on 23d38413+patch; landed 1a8ba587, verify-commit 4 paths, done rev 635 (7a4ca67b, swept only rev 635), #1576 closed 27728; four follow-ups listed for after the cutover 2026-10-12T04:14:04Z | sage | decision 103, cutover reinstall | Mos runs the mosaic.woltje.com install at the go after ops-01's path patch, then restarts under decision 102; preview host mosaic-preview.woltje.com confirmed by Mos sage-0070 from the route proposal (0d67e926) 2026-10-12T04:14:39Z | sage | cutover preview unit installed | scripts/webui-service.sh install at 777ada59 with mosaic-preview.woltje.com, X-authentik-username, jason.woltje, --send; written and daemon-reload only, not enabled or started; status send on; ops-01 cleared the line against #337 2c24a629 (Mos sage-0071) +2026-10-12T13:18:52Z | sage | cutover ready, I1 review | verified rev-sol-01 R5 PASS on #337 at 2c24a629 and sent Mos ready at 13:16Z; reviewed Researcher's I1 survey, accepted with finding 1 corrected (forward-auth shipped), Jason's part sent to Mos as I1-1 to I1-4; AM standup updated; no unit touched