diff --git a/agents/bushroot/work/queue-198/DESIGN.md b/agents/bushroot/work/queue-198/DESIGN.md index 60f8e441a..d9524eadb 100644 --- a/agents/bushroot/work/queue-198/DESIGN.md +++ b/agents/bushroot/work/queue-198/DESIGN.md @@ -4,13 +4,27 @@ Gitea #1696. Brief `docs/plans/2026-10-20_retire-control-board.md` (blob 11977a5 call mos-1019). Owner Bushroot, reviewer Webby, gate owner Sage. Inventory: `agents/bushroot/work/queue-198/INVENTORY.md` (004f133bd, sha256 76b630ce...877). -Note on base: brief commit a31f1a0f8 is local to the canonical checkout and is not on origin. This branch -does not contain it. I read the brief from that commit with `git show`. Sage, please push a31f1a0f8 or -confirm that the brief text is what the reviewers read. +Base: brief commit a31f1a0f8 is on origin `refactor` (head aa1bd209e). This branch rebases on `refactor` after +row 192 lands (Sage's sequencing, ruling 4). + +## Revision 3 (Sage rulings sage-1372, on rev 2 80fd45521) + +- Ruling 1: `/api/seen` goes under `--send`, the same as `/api/reply`. Mos agrees (mos-1023 item 5). Both POSTs sit + above `serve.mjs:558` (decision 5). +- Ruling 2: the board context keeps the writer's read-only fleet default (decision 9). +- Ruling 3: a rollback to a copy with no recorded `--board` falls back to 7331, which is dark, as it is today (decision 8). +- Ruling 5: loopback stays read-only. No new gate in this row. The cross-uid loopback gate is row 196's. Sage took + this to Mos (sage-1370). If Mos rules otherwise, Sage says so and this design changes. +- Ruling 6, correction: neither the live pointer nor the live unit carries `--board`. Sage checked the live + `ExecStart`: `cli.mjs serve --checkout /mnt/storage/src/mosaic-stack --port 7332 --public-host mosaic.woltje.com + --auth-header X-authentik-username --allow-user jason.woltje --send --tester-port 7333`. Rev 2 said otherwise, and + that was wrong. Decisions 6 and 8 are rewritten. The B2 guard stays. `webui-service.sh` lines 44, 71, 110 and 163 + still take and emit `--board`, so they are in the retirement. +- Ruling 7: base. Brief commit a31f1a0f8 is on origin `refactor` at aa1bd209e. ## Revision 2 (Webby REVIEW.md, origin/webby/reviews 9afb947c7) -Rev 1 was c8fe23a37. This revision answers B1-B3 and N1-N5. Changes are marked where they land. +Rev 1 was c8fe23a37. Rev 2 answered B1-B3 and N1-N5 (80fd45521). Changes are marked where they land. - **B1** (pinned copy): fixed. `packages/control-board/src` and `tools/tmux/agent-send.sh` join `COPY_PATHS`. The copy test starts the Console from a fresh copy and expects 200 on `/api/board`. See decision 7. @@ -44,37 +58,38 @@ Rev 1 was c8fe23a37. This revision answers B1-B3 and N1-N5. Changes are marked w runs. In loopback mode, `--send` cannot be set at all (`:479`). So both POST branches go after the header and origin checks (`:493-516`), beside `/api/bus/message` (`:550`) and chat (`:554`), and require `send !== null && named`. The result: `/api/reply` is the first board write the live Console has ever allowed. - Mos ruled it in (mos-1019). In loopback mode, reply and mark-seen refuse with 403 `read-only`. Board reads still - work there. `/api/seen` is gated too (Webby's ruling, and mine). It writes marks under the data root, and without the - gate it would be the only preview-mode POST that passes without `--send`. -6. **The live unit's `--board` flag goes.** The installed unit passes `--board http://127.0.0.1:7331`. With the - flag refused, the next restart from the old unit exits 2. The unit restarts only on exit codes other than 2 - (`RestartPreventExitStatus=2`), so it stays down. The re-render and restart are a human step (Jason or Mos). - This row changes the template and the script. It does not touch the installed unit. + Mos ruled it in (mos-1019), and mos-1023 item 5 confirms `/api/seen` too. In loopback mode, reply and mark-seen + refuse with 403 `read-only`. Board reads still work there. `/api/seen` writes marks under the data root, and without + the gate it would be the only preview-mode POST that passes without `--send`. +6. **The retirement removes `--board` from the Console scripts.** No installed unit or live pointer carries `--board` + (Sage checked, rev 3). So no live unit needs a flag change to start. The flag goes from `packages/webui/src/cli.mjs` + (`:14`, `:18`, `:32`) and `scripts/webui-service.sh` (lines 44, 71, 110, 161-163). An old `--board` argument refuses + with the usage error (exit 2). A re-pin with the flag removed is an ordinary re-pin. Cutover needs no unit edit. 7. **The pinned copy carries the board code (B1).** The live Console runs from `copies/`. `COPY_PATHS` in `scripts/stack-copy.sh` (lines 23-33) lacks `packages/control-board/src` and `tools/tmux`. Without them a Console from a copy fails at import, and `reply` cannot find `agent-send.sh`. Both paths join `COPY_PATHS`. `tools/tmux` goes in whole, the same way `packages/plugins` does, because `agent-send.sh` may load its own siblings. The `control-board/src` closure is `conversation/src`, `discord/src` and `seat/src`, and those are already in the list. -8. **Re-pin and rollback handle `--board` (B2).** The live pointer records `--board http://127.0.0.1:7331` in - `P_CONSOLE` (`stack-release.sh:128`). `:676` copies it to `RUN_CONSOLE`, and `:459` passes it to `webui-service.sh install`. - Rule: keep `--board` only when the target's `packages/webui/src/cli.mjs` still parses it. Otherwise drop it and - report the drop in the plan. That is the same shape as `console_for_target` and `--tester-port` (`:667`, `:687-690`). - Rollback to an older copy that parses `--board` keeps the flag as the pointer recorded it. An older copy with no - recorded flag falls back to its own default, 7331. That is the state today, and the board view stays dark, as it is now. +8. **Re-pin and rollback drop `--board` when the target cannot parse it (B2 guard).** The pointer's console flags + (`P_CONSOLE`, `stack-release.sh:128`) pass through `:676` into `RUN_CONSOLE`, and `:459` passes them to + `webui-service.sh install`. The live pointer has no `--board` (rev 3), so this is a guard for a pointer that + carries one, such as an older pointer or a rollback target. Rule: keep `--board` only when the target's + `packages/webui/src/cli.mjs` parses it. Otherwise drop it and report the drop in the plan. That is the same shape + as `console_for_target` and `--tester-port` (`:667`, `:687-690`). Rollback to a copy that parses `--board` keeps + the recorded flag. A copy that does not parse it gets the flag dropped, and falls back to its own default, 7331. + That default is dark, the same as today (Sage ruling 3). 9. **The board context uses the writer's default fleet source (N1).** `--fleet` defaults to `~/.mosaic/fleet/agents`, as the writer did (`cli.mjs:14`). The Console reads it and never writes it. Whether the fleet is retired and the default becomes `none` is a later decision. This row keeps the board's contents unchanged. ## Open points for Sage and Mos -- **Auth on loopback.** Mos's item says "every board route sits behind the Console's auth." The Console has - two modes. In preview mode, a named request needs the proxy header and proof, and the board routes inherit - that. In loopback mode (no `--public-host`), there is no sign-in at all. Today `/api/board` is open to any - local process in that mode, and so is every other Console read. This design makes the board routes follow - the same rule as every other read. If Mos wants loopback board reads gated too, that is a Console-wide - change and needs a ruling. I will not invent one. +- **Auth on loopback (Sage ruling 5, taken to Mos as sage-1370).** The Console has two modes. In preview mode, a named + request needs the proxy header and proof, and the board routes inherit that. In loopback mode (no `--public-host`), + there is no sign-in. Loopback stays read-only with no new gate in this row. Board reads stay open to any local + process, as they are today. Reply and mark-seen cannot run there, because `--send` needs preview mode. The + cross-uid loopback gate is row 196's. If Mos rules otherwise, Sage says so and this design changes. - **Row 192 overlap (Launchpad, SSO on `webui/src/serve.mjs`).** My edits touch these regions of `packages/webui/src/serve.mjs`: - lines 12-27 (`DEFAULT_BOARD`, `boardURL`) @@ -86,8 +101,10 @@ Rev 1 was c8fe23a37. This revision answers B1-B3 and N1-N5. Changes are marked w I do not edit the preview and proof gate (lines ~486-505) or the auth-header checks. The board branches go after those checks, in the same order as the bus and chat branches. Sage should sequence 192 and 198 so the second one rebases on the first. I will not touch the SSO code. -- **Cutover.** The Console restart is a human step (`console-holds-human-authority`). It needs the re-rendered - unit without `--board`. The live unit stays up until then. +- **Cutover.** The new Console code reaches the live Console through a copy and re-pin. The restart is a human + step (`console-holds-human-authority`). No unit flag changes (decision 6). The live unit stays up until then. +- **Sequencing (ruling 4).** Sage sequences 198 after 192. I rebase once, onto the tree with 192 landed, and rerun + the board route tests there. ## File-by-file @@ -208,15 +225,13 @@ Dead-board fixture files (16 webui plus `tester-fixture.mjs`) match Webby's coun Mutant runs use single test files, which run freely. Any suite (control-board, webui, cli, every `scripts/test-*.sh`) needs Sage's slot. -## Gate - Webby approves INVENTORY.md (already sent), then this DESIGN.md, then the manifest. Sage's gate runs the control-board and webui suites, the cli suite and every `scripts/test-*.sh`. All must be green, and mutants -M1-M9 killed. +M1-M13 killed. ## Stop points -- If Mos rules that loopback board reads need a gate, this design changes. I stop and report. +- If Mos rules that loopback board reads need a gate, this design changes. Sage tells me, and I stop and report. - If the Console's auth model changes under row 192, the board block in section "Console" changes with it. - The Console restart and unit re-render are Jason's or Mos's steps. I do not run them.