webui: Console pinned copy, update step and service hardening (#1571)

Row 77, round 3 (round 2 rebased onto row 95). Rocko built it. This
covers row 75's N1-N5 and Vikunja 146 and 147. `install --copy ID`
refuses unless every ExecStart path of the bus unit, read from
`systemctl --user show` so drop-ins count, lies inside that copy. It
also refuses when the unit isn't loaded, no unit is loaded, ExecStart
has no path, or systemctl fails. COPY_PATHS gains packages/tasks/src and
packages/tasks/fields.json. Every copy directory is 0555. TOOLS.md and
the webui README give the removal command and the rollback floor.

Candidate manifest d9880f4c92d1d976027562a03cc5dd07512954e86f49f1da0ebb34e642a955f5
(10 paths, 8 applied by the patch, 2 packet files already committed),
base 2e26fbe1, packet agents/rocko/work/queue-77/r2b/. Approvals on round
3: Darkwing 27979 and Filbert 27985 (Filbert round 2: 27898). Sage's
gate rerun 22:32:51Z-22:35:12Z on 459c4fc6 plus the patch (row 92
included), manifest 10/10: webui 101, control-board 124, and every
scripts/test-*.sh exited 0 (test-release 4, Docker cases skipped at a
dead socket).

Live at the next Console install and restart (decision 109). Mos makes
that call.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-12 17:35:26 -05:00
co-authored by Claude Opus 5.5
parent cca5f23eaf
commit 0d10cf0798
8 changed files with 921 additions and 94 deletions
+19
View File
@@ -110,6 +110,25 @@ system config at start: without it serve refuses with `--send needs the bus
configured` and exits 2, which the unit doesn't restart. `status` says
whether the installed unit sends.
The unit runs a read-only pinned copy of the Console's paths, not the
working checkout (row 77). `scripts/webui-service.sh copy COMMIT` makes
one from a commit on `refactor`, and `install --copy ID` points the unit
at it, with serve's `--checkout` naming the checkout, where the queue read
still runs, so the queue view isn't pinned and shows the queue as it is
now. The update step is `copy`, stop, `install --copy ID` with the same
flags, start; rollback is the same with the earlier id (one at or after
row 77's landing, since an older `cli.mjs` refuses `--checkout`), and
copies are kept (they are read-only, files and directories; remove one
with `chmod -R u+w DIR && rm -rf DIR`). `install --copy ID` refuses unless
the bus unit runs from the same copy, because the bus accepts a human
proof only from its own `human-cli.mjs`. The bus still runs from the
checkout, so the update step can't be used until a later row puts the bus
on the copy. The stop and start are Jason's or Mos's: `install` and
`uninstall` refuse while the unit runs. With `--auth-header
X-authentik-uid` the allowed user must be the 64-character Authentik uid
(lead decision 101). `status` names the copy and whether `refactor` has
moved past it.
## Message a role (row 76, #1570)
```sh