golden 0.203.0 baked + published; runbook acceptance markers fixed (R-233)
gates / gates (push) Successful in 13s

Bake evidence: documentation/tests/golden-0.203.0-2026-08-06/ (bake.log + README).
sha256 3039c6ffa7a5a8b2d959daddb2895c58b44de70f8d4f4a7e12ad4b1c0d61dc88, verified
by an independent round-trip download and by reading /etc/felhom-controller-image
out of the published archive itself. NOT vouched — the hub still serves 0.201.0.

R-233: RUNBOOK-manual-build.md §4.1 named three pass markers, two of which the
script cannot print (`overlay2 OK` does not exist; `mp1` stopped existing in
build-golden.sh v3.0.0 under R-165), and a 404 pre-gate URL with the wrong
filename, which would 404 for the wrong reason and pass even when the version
already existed. A grep for an impossible string reads 0 forever and 0 is
indistinguishable from failure. Markers re-captured from the real log; token
handling moved off the command line into an in-VM runner script; a positive
control is now required on the token-leak grep; the vouch step rewritten as the
three-field change it is (golden_version + agent_version + min_agent).
This commit is contained in:
2026-08-06 13:23:22 +02:00
parent 0c4411e54b
commit 1c47e3b6fd
4 changed files with 468 additions and 8 deletions
+49 -8
View File
@@ -139,27 +139,68 @@ qemu-system-x86_64 -enable-kvm -cpu host -smp 4 -m 8192 \
0600), then run it as a transient unit so it survives a session close, reading the token from the
file **inside** the VM so it never reaches a command line:
Put the invocation in a **runner script inside the VM** that reads the token itself, and launch
that. The older `--setenv=GITEA_TOKEN=$GT` form put the value on a command line and into the
transient unit's properties, where `systemctl show` prints it:
```bash
GT=$(cat /root/.gitea-token); systemd-run --unit=golden-bake --collect \
--setenv=GITEA_USER=admin --setenv=GITEA_TOKEN=$GT \
--setenv=REGISTRY_USER=admin --setenv=REGISTRY_TOKEN=$GT \
bash -c "/root/build-golden.sh 9100 local:vztmpl/<template> local-lvm local vmbr0 \
gitea.dooplex.hu/admin/felhom-controller:<VER> > /root/bake.log 2>&1"
cat > /root/bake-run.sh <<'EOS'
#!/bin/bash
GT=$(cat /root/.gitea-token)
export GITEA_USER=admin GITEA_TOKEN="$GT" REGISTRY_USER=admin REGISTRY_TOKEN="$GT"
exec /root/build-golden.sh 9100 local:vztmpl/<template> local-lvm local vmbr0 \
gitea.dooplex.hu/admin/felhom-controller:<VER>
EOS
chmod 0700 /root/bake-run.sh
systemd-run --unit=golden-bake --collect bash -c "/root/bake-run.sh > /root/bake.log 2>&1"
```
Confirm the value went nowhere: `systemctl show golden-bake -p Environment -p ExecStart |
grep -c -F "$(cat /root/.gitea-token)"` must be `0`. Copy the token in **file → file** (`scp`), so
it never crosses a shell on either side.
`CONTROLLER_IMAGE` is a **required** argument (a hand-bumped default rotted twice) and
`GOLDEN_VERSION` is derived from it — the golden's version IS the controller it bakes.
**The script is the publisher**: it uploads to Gitea and prints `GOLDEN_VERSION` + `GOLDEN_SHA256`.
Pass markers: `overlay2 OK`, `including mount point` for rootfs **and mp0 and mp1** with no
`excluding`/`FATAL`, `upload OK (HTTP 201)`. The 404 pre-gate applies to the package URL.
Pass markers, **each captured from a real log rather than paraphrased** — two of the three named
here until 2026-08-06 could not match anything the script prints (see the note below):
`docker OK (overlay2`, `including mount point` for rootfs **and mp0** — there is no mp1 — with no
`excluding`/`FATAL`, `upload OK (HTTP 201)`. The 404 pre-gate applies to the package URL, which is
`…/generic/felhom-golden/<VER>/golden.tar.zst` — the filename is `golden.tar.zst`, **not**
`felhom-golden-<VER>.tar.zst`.
<!--
2026-08-06, R-233: this line listed `overlay2 OK` and demanded `including mount point` for `mp1`.
The script prints neither. The storage-driver line it means is ` docker OK (overlay2; data-root
/var/lib/docker)`, and mp1 stopped existing in build-golden.sh v3.0.0 (R-165 collapsed the two data
volumes into one). A reader following this literally greps for a string that can never appear and
reads 0 — the "an instrument that can silently drop results is not a measurement" class, aimed at the
bake's own acceptance check. The real guard was never weak: the script's own
`[ "$drv" = "overlay2" ] || { echo FATAL; exit 1; }` is fail-closed. The DOCUMENT was the broken part.
-->
4. Teardown: `pct destroy 9100 --purge`, `shred -u` the token/script/log **after** copying the log out
for evidence, `poweroff`, wait for qemu to exit, `qemu-img snapshot -a virgin`. Token-leak grep on
the saved log = `grep -c -F "$(cat ~/.gitea-token)"` (the literal value — a broad `[a-f0-9]{40}`
pattern false-hits image shas).
pattern false-hits image shas). **A `0` is only evidence once the grep is shown to work**: append
the token to a throwaway copy of the log, grep that (must be `1`), `shred -u` the copy, and only
then believe the `0`. Grep the copy that gets **committed**, not just the one in the VM.
5. Hub → Configuration → Day-0 artifacts: pick the new Golden, Save. **The R-120 gate lives on this
save** (`hub/internal/web/configs.go:1165`) and REFUSES a golden older than the newest controller
the fleet reports. It does **not** run on a controller image deploy — it is not a general drift net.
**Vouching is a THREE-field change, not one.** `golden_version` alone ships a controller onto an
older agent than it declares it needs. Read the golden's controller `CHANGELOG.md` header — it
carries `MinAgent <X>` — and move all three together:
`golden_version` → the new golden, `agent_version` → ≥ that `MinAgent`, `min_agent` → that
`MinAgent`. The `min_agent` field is what the hub HOLDS a box's floor against; blank means an
uncoupled release with no gating. Setting `min_agent` **above** the vouched agent is the R-216
shape and hub v0.97.0 now HOLDS it rather than serving past it.
**Vouching is reversible**: re-select the previous values and Save. The old golden's package is
never deleted by a bake (the publish step's pre-delete targets only its own version), so rolling
back is a form submission, not a rebuild.
A golden is only needed when a publish train wants fresh installs current — demo deploys never need it.
The full 0.188.0 run, with the observables: `documentation/audits/tester-gate-golden-0.188.0-2026-07-31.md`.