What the audit is worth keeping, and where

Five passes produced a working document that said on its first line it was
temporary. This is it being spent rather than abandoned.

CLAUDE.md gains eleven paragraphs, each a thing that had shipped looking
correct: a handler bound to a shared variable rather than its own socket,
a script the base template already loads being loaded again, a control
that stays clickable while it awaits permission, "is this name taken?"
asked about visibility instead of ownership, root running a file the
service account can write, sourcing anything under $PREFIX, a read-only
command name that is not a read-only command, 0.0.0.0 being this machine,
a folder that is not a label, a file that is not deleted by the row that
named it, and a measuring harness that measured an unstyled page and
reported a dramatic finding that was entirely an artefact.

PLAN.md carries the seven things the audit found and deliberately did not
fix, each with why: they change what something does rather than fix what
it claims to do, which is not an audit's job.

deploy/README.md says why root runs a copy, and that a host installed
before this keeps the old wiring until the installer is re-run -- the
button cannot fix it, because the button runs the old unit.

docs/notes/audit-0.9.md is deleted, having been all three.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-07 15:25:44 +02:00
parent 3d51ba061e
commit 656bea2b20
+27 -6
View File
@@ -95,19 +95,40 @@ The button is opt-in, and the reason is a boundary rather than caution:
INSTALL_UPDATE_HELPER=1 SITE_HOST=chat.example ./deploy/install.sh INSTALL_UPDATE_HELPER=1 SITE_HOST=chat.example ./deploy/install.sh
``` ```
That installs `lembas-update.path` and `lembas-update.service`. The web That installs `lembas-update.path` and `lembas-update.service`, and puts a
**root-owned copy** of `update.sh` at `/usr/local/lib/lembas/update.sh`. The web
interface writes `$PREFIX/data/update-requested`; the path unit notices and the interface writes `$PREFIX/data/update-requested`; the path unit notices and the
service runs `update.sh` **as root**, on the configured channel. service runs that copy **as root**, on the configured channel.
**Why a copy.** The unit used to point inside the checkout, and `install.sh`
clones the checkout *as the service user* — so root was executing a file the
unprivileged account could rewrite, and one that every update replaces with
whatever the branch contained. Either turns a compromise of the web application
into root, and the second needs no compromise at all. The cost is that changing
`update.sh` needs the installer re-run; the script tells you when its copy has
fallen behind, and says so loudly if it finds itself running from inside the
checkout.
**If you installed the helper before 1.0.0, re-run the installer.** The old
wiring stays until you do, and the update button cannot fix it — the button runs
the old unit.
**What that grants.** Anybody who can administer this web interface can then **What that grants.** Anybody who can administer this web interface can then
deploy whatever is on the configured branch and restart the service. That is the deploy whatever is on the configured branch and restart the service. That is the
point of it, and it is why it is not the default. point of it, and it is why it is not the default.
**What it deliberately does not grant.** The request file carries nothing that **What it deliberately does not grant.** The request file carries nothing that
reaches a command line — no ref, no branch, no channel, no arguments. Both are reaches a command line — no ref, no branch, no channel, no arguments, and its
baked into the unit at install time, so the button is always "deploy the channel *contents* are never read at all. Both are baked into the unit at install time,
this host was configured with" and never "deploy something else". Re-running the installer without the flag removes both units and the so the button is always "deploy the channel this host was configured with" and
marker, and the page goes back to printing the manual command. never "deploy something else". Re-running the installer without the flag removes
both units, the marker and the root-owned copy, and the page goes back to
printing the manual command.
A re-run **keeps the channel this host already follows** rather than resetting it
to `stable`: the channel is declared in `lembas.env` and in the unit, a re-run
keeps the first while rewriting the second, and an installer that silently moved
one half was causing exactly the mismatch the Updates page detects.
Without the helper the page says so and shows `sudo …/deploy/update.sh`, which is Without the helper the page says so and shows `sudo …/deploy/update.sh`, which is
the same honest degradation the SSH and search extras have. the same honest degradation the SSH and search extras have.