From 8334a52331dc47733e23ca45ac1ad00c34042b34 Mon Sep 17 00:00:00 2001 From: Jason Woltje Date: Sun, 11 Oct 2026 17:17:35 -0500 Subject: [PATCH] docs: lead decision 94, dogfood cutover rows, Jason starts the Console (#1569, #1570) Decision 94 records Q94 yes and Mos's sage-0054/0055 directions: no broker row (the Console already reads as the human), Jason starts the Console, nine rows deferred, S7's line amended, Gate E partial pass on the dogfood day, no rollback hostname. New brief for the Console service row and the send-to-a-role row. Row 74's start line and S7's request line amended. Co-Authored-By: Claude Opus 5.5 --- docs/plans/2026-09-26_lead-decisions.md | 45 +++++++ docs/plans/2026-10-04_slice-1.md | 4 +- docs/plans/2026-10-11_dogfood-cutover.md | 147 +++++++++++++++++++++++ docs/plans/2026-10-11_webui-preview.md | 12 +- 4 files changed, 202 insertions(+), 6 deletions(-) create mode 100644 docs/plans/2026-10-11_dogfood-cutover.md diff --git a/docs/plans/2026-09-26_lead-decisions.md b/docs/plans/2026-09-26_lead-decisions.md index e6bf3fc4e..f12190f7e 100644 --- a/docs/plans/2026-09-26_lead-decisions.md +++ b/docs/plans/2026-09-26_lead-decisions.md @@ -1999,3 +1999,48 @@ which stay with him. Each item names who decided it and what happened. likely X-authentik-uid. The Console check stays generic (one header name, one user id, from flags). Jason's Q93, on the Authentik token, gates ops-01's application, not the Console's landing or install. + +94. **Dogfood on mosaic.woltje.com within 24 hours; Jason starts the + Console (2026-10-11).** Jason, relayed by Mos (sage-0053): "I want the + system online and us able to dogfood in the next 24 hours." Q94, his + yes to Sage's reading (sage-0055): "Yes, but the old build didn't work + anyway. Rollback is likely not a desirable action." Mos's directions + are in sage-0054 and sage-0055. + - The Console already reads the bus as the human. Its bus reads run + the human transport (`packages/webui/src/bus.mjs`, `humanCall`), so + the broker binds a human capability after `verifyHuman`, and only + Console code limits it to the reads in `packages/bus/src/views.mjs`. + A send from the browser needs a Console route, not new broker + authority. The broker row Sage proposed in the sage-0053 reply (row + A) is dropped. Q95, web write authority, is a ruling on that route. + - The process that starts the Console holds human authority. An agent + that starts it through `systemd-run` or a user unit gets a clean + environment and an ancestry the proof accepts: the detachment gap + decision 62 names, which T3 seats must not use. So Jason starts the + Console himself, the 03:00Z read-only fallback included. This + replaces decision 93's "Sage starts the preview"; the row 74 brief + says so (amended line, re-pinned). Agents may install and render the + unit and read its status, never start, stop or restart it. + - New rows, brief `docs/plans/2026-10-11_dogfood-cutover.md`: the + Console user service (owner Rocko, reviewer Filbert), which starts + now ahead of rows 72 and 73; and a human message to a role from the + Console (owner Dewey after row 74, reviewers Darkwing and Filbert), + blocked on Q95. + - Deferred until after cutover, each moved to blocked with that + reason: rows 49, 61, 63, 64, 65, 66, 69, 70 and 71. Rows 58, 59, 60, + 67, 72 and 73 continue around the cutover reviews. + - S7 (row 42): Jason's five requests may come from the WebUI or the + CLI; the brief's one line is amended and re-pinned. S7 runs with + the cutover, and his first five requests to the PM are its pieces. + - Gate E (row 5): the dogfood day is its demonstration for the scope + that exists, the managed PM on the bus. Jason's ruling on that day + records a partial pass. The all-seat part stays open and row 5 + stays waiting on Jason; it isn't called passed. + - No rollback hostname. The old build isn't a rollback target, so + ops-01 builds no rollback name or flip-back. Its data is kept until + Jason rules on deleting it. The live cutover still needs his + approval at the time. + - The tradeoff: no agent can restart the Console. After a crash the + unit's `Restart=on-failure` brings it back; after a reboot, or a + logout without linger, it waits for Jason. Deferring nine rows + pushes the skills, routing and hygiene work back by about two days. diff --git a/docs/plans/2026-10-04_slice-1.md b/docs/plans/2026-10-04_slice-1.md index c8dfaee06..bba077263 100644 --- a/docs/plans/2026-10-04_slice-1.md +++ b/docs/plans/2026-10-04_slice-1.md @@ -596,8 +596,8 @@ The PRD's acceptance can only be shown end to end. ### What ships -Five one-sentence requests from Jason in the CLI, each carried to a -closed, reviewed task. For each: the trail in `mosaic trail` and the +Five one-sentence requests from Jason, sent from the WebUI or the CLI +(lead decision 94), each carried to a closed, reviewed task. For each: the trail in `mosaic trail` and the WebUI, the decisions that reached Jason (gated only), and the event counts from the bus. Those counts are the first measures (REQ-EVT-1). diff --git a/docs/plans/2026-10-11_dogfood-cutover.md b/docs/plans/2026-10-11_dogfood-cutover.md new file mode 100644 index 000000000..1b124173a --- /dev/null +++ b/docs/plans/2026-10-11_dogfood-cutover.md @@ -0,0 +1,147 @@ +# Dogfood cutover: the Console as a service, then sending to a role (2026-10-11) + +Status: written by Sage, lead. It follows `docs/plans/BRIEF-TEMPLATE.md`. +Two rows, from Mos's sage-0054 (lead decision 94). The service row starts +now. The send row is briefed only; it starts after Jason answers Q95 +(web write authority), and is amended first if his answer narrows it. +Q94, the cutover reading, is answered yes. + +What the code already does, and why there is no broker row. The Console +reads the bus as the human. `packages/webui/src/bus.mjs` runs the S4 +human transport (`packages/bus/src/human-cli.mjs`) as a child, so the +broker binds a human capability (`bindHuman`, `via: 'cli'`) after +`verifyHuman` checks the process and its ancestry +(`packages/bus/src/human.mjs`). The Console limits itself to the read +verbs in `packages/bus/src/views.mjs`; the broker doesn't. So a send from +the browser needs no new broker authority, only a Console route, and the +Q95 ruling is about that route. It also means the process that starts +the Console decides whether it holds human authority. A Console started +from an agent's shell, detached through systemd, passes the ancestry +check: the gap lead decision 62 names. So Jason starts it himself. + +## Console as a user service + +### Problem + +Row 74 cut the service script to make the 10-12 date. Daily use can't run +on a transient unit, which a reboot or a logout without linger ends and +nobody reviewed as a file. The bus has `scripts/bus-service.sh`; the +Console has nothing. + +### Owner and reviewer + +Owner: Rocko. Reviewer: Filbert. Rocko has no Gitea token; Sage runs the +review request as jarvis. + +### Files owned + +- `scripts/webui-service.sh` (new) +- `packages/webui/systemd/mosaic-webui.service.in` (new) +- `packages/webui/tests/service.test.mjs` (new) +- `docs/TOOLS.md`, the new script's entry only (row 70, the other row + editing it, is deferred) +- `agents/rocko/work/queue-/` + +Not `packages/webui/README.md` or any `src/` file: row 74 owns them. The +README pointer to the script is a line Sage adds after both rows land. + +### What ships + +- `scripts/webui-service.sh render|install|uninstall|status` on the + `bus-service.sh` pattern and exit codes (0 ok, 1 failed, 4 usage): + `render` prints the unit; `install [--dir DIR] [--no-reload]` writes it + to a temp file, renames it and runs `systemctl --user daemon-reload`; + `uninstall` refuses while the unit is active; `status` prints the unit + state and the result of `GET /healthz` on its port. +- No start, stop, enable or restart verb. The script header and the + TOOLS.md entry say why: the Console holds the human's capability, so + Jason starts it from his own shell with + `systemctl --user enable --now mosaic-webui`. +- `render` and `install` take `--port N` (default 7332), `--business ID`, + `--board URL`, and row 74's `--public-host NAME --auth-header HEADER + --allow-user ID`, all three or none, as `serve` takes them. Each value + is held to a plain character set the unit can carry (systemd expands + `%` and splits on spaces) and refused otherwise. None is a secret. +- `mosaic-webui.service`: one instance, `WorkingDirectory` and `PATH` + filled in as the bus unit does, `ExecStart` running + `node @REPO@/packages/webui/src/cli.mjs serve` with the rendered flags, + `Restart=on-failure`, `RestartPreventExitStatus` for usage and config + exits, `NoNewPrivileges=yes`, `WantedBy=default.target`. It sets no + `MOSAIC_*`, `CLAUDE*`, `CODEX*` or `PI_*` variable. +- Tests: render with and without the preview flags; a partial preview + set refused; a value with a space, `%` or newline refused; the rendered + unit names none of the agent markers in `packages/bus/src/human.mjs`; + install into `--dir` with `--no-reload` writes the file whole; + uninstall refuses while active (a stand-in `systemctl` on `PATH`). + +### Out of scope + +Starting the unit; the board's service; any `src/` change; a container. +If the unit can't run `serve` as written, stop and tell Sage. + +### Gate + +Filbert approves on the row's issue naming the candidate manifest. The +webui node suite and every `scripts/test-*.sh` green on Sage's gate rerun. + +## Console sends a message to a role + +### Problem + +For dogfooding, Jason has to ask the PM for work from the browser. Tasks +don't need their own path: the PM creates and assigns them (S3). One write +covers it, a human `message.send` to a role. The Console refuses every +POST in preview mode (row 74), and outside it has no bus write at all. + +### Owner and reviewer + +Owner: Dewey, after row 74. Reviewers: Darkwing and Filbert. + +### Files owned + +- `packages/webui/src/` (serve, bus, cli and the page assets under + `public/`), `packages/webui/README.md` and `packages/webui/tests/` +- `agents/dewey/work/queue-/` + +### What ships + +- A `--send` flag on `serve`, off by default, accepted only with the + three preview flags. Without it the Console behaves as after row 74. +- `POST /api/bus/message` with JSON `{to, body, in_reply_to?}`, at most + 16 KiB. With `--send` it is the one POST preview mode allows. It + requires the auth header equal to the allowed user on every request, + loopback included, an Origin equal to the request's own origin, and + `Content-Type: application/json`. It calls `message.send` through the + same human transport the reads use, with exactly those keys. `to` and + the body limits are the broker's to refuse; its codes map to HTTP the + way `busStatus` maps the reads'. +- `outcome-unknown` is shown as unknown, with no resend: the page says + the message may have been sent and points at the trail. Nothing retries + automatically. +- One log line per send on stdout (time, allowed user, `to`, message id + or error code), never the body. +- On the page: a role picker from the agents read, a text box and Send. + The receipt shows the message id and links its trail; replies show in + the inbox as today. A draft survives the periodic refresh. +- Tests: each refusal (no `--send`, missing or wrong header, a loopback + request without the header, bad Origin, wrong type, oversize, an extra + key), a send through a stand-in transport with exactly the allowed + keys, `outcome-unknown` reported and not retried, and every other POST + still 403 `read-only`. +- The README states what `--send` grants: anyone the proxy lets through + as the allowed user, and any local process that reaches the port and + sets the header, can send a human instruction. The second is the same + class of exposure as running the human CLI directly (lead decision 62). + +### Out of scope + +Decisions from the browser (seen, resolve, withdraw) stay in the CLI +(REQ-DEC-3); message classes other than the default; corrections; any +bus or broker change; conversations with T3 seats (CHAT-07). + +### Gate + +Darkwing and Filbert approve on the row's issue naming the candidate +manifest. The webui, bus, control-board and cli node suites and every +`scripts/test-*.sh` green on Sage's gate rerun. Jason's Q95 answer is +recorded before the row starts. diff --git a/docs/plans/2026-10-11_webui-preview.md b/docs/plans/2026-10-11_webui-preview.md index 59fd510f2..1fe76f320 100644 --- a/docs/plans/2026-10-11_webui-preview.md +++ b/docs/plans/2026-10-11_webui-preview.md @@ -99,10 +99,14 @@ exactly as today, and the existing tests show it. - A container image, CI deploy, or changes to the bus unit. - A service script and unit template (`scripts/webui-service.sh` on the `bus-service.sh` pattern). That is a follow-up row. -- Starting it on dragon-lin. After the row lands, Sage starts the preview - as a transient user unit (`systemd-run --user`, loopback port 7332; - 7330 holds the operator's own Console). The edge reaches it once - rev-sol-01 passes ops-01's route. +- Starting it on dragon-lin. The Console reads the bus through the human + transport, so whoever starts it holds the human's capability. An agent + starting it, even detached through systemd, works around the human + proof (lead decisions 62 and 94). After the row lands, Jason starts it + from his own shell as a transient user unit (`systemd-run --user`, + loopback port 7332; 7330 holds the operator's own Console), with the + command Sage gives him. The edge reaches it once rev-sol-01 passes + ops-01's route. - The group check. Authentik and the proxy limit sign-in to Jason's group; the Console checks the header against the one user id.