R-297: installer compares a local golden against the manifest before using it
Step 7 short-circuited on any local golden archive with no version compare, no digest and no warning, so the manifest sha256 was consulted only on the fetch path. Local discovery is newest-by-filename: correct by recency, never by verification. A box could reinstall from a stale archive and come back below the version where the offsite recovery screen exists. Digest first, then the baked controller tag. An auto-discovered mismatch re-fetches the vouched golden; an operator-named mismatch refuses. An unreadable manifest refuses rather than passing. Not published: installer-v1.26.0 is deliberately not cut until a fresh install has been observed taking a stale local golden on drill-r50. Also files R-295..R-298.
This commit is contained in:
@@ -1,3 +1,42 @@
|
||||
## felhom-host-install.sh v1.26.0 — an install takes the golden you approved (2026-08-10, R-297)
|
||||
|
||||
**Step 7 short-circuited on ANY local golden archive: no version compare, no digest, no warning.**
|
||||
`if [[ -n "$GOLDEN_VOLID" ]] && ! $FORCE_GITEA_GOLDEN; then log_skip "using local golden"; return 0`
|
||||
— so the manifest's sha256, whose entire purpose is to vouch from a **different trust root than the
|
||||
code host**, was consulted only on the fetch path. Local discovery is
|
||||
`pvesm list … | sort | tail -1`: correct by **recency**, never by verification.
|
||||
|
||||
**The sharp end:** a box with an old archive lying around reinstalls from it silently, and can come
|
||||
back below the version where the off-site recovery screen exists — unable to run the ceremony its
|
||||
own data depends on — and born below the update floor, whose auto-target is the floor and never the
|
||||
newest. Measured on a real host: three goldens sat on `demo-hp`, carrying controller **0.153.0** and
|
||||
**0.210.0**, and nothing compared either to the vouched version before using it.
|
||||
|
||||
**The row narrows itself and the narrowing holds:** on `--resume`, step 7 fetches correctly, because
|
||||
resume skips preflight and preflight is where local discovery sets the variable (`:2849`). The two
|
||||
paths disagreed and resume was the safe one.
|
||||
|
||||
`golden_local_matches_manifest()` now runs two comparisons, cheapest first:
|
||||
|
||||
1. **digest** — local sha256 == manifest sha256 ⇒ this IS the vouched artifact, certain;
|
||||
2. **version** — a locally BAKED golden is legitimately not byte-identical to the published file, so
|
||||
a digest mismatch alone is not proof of staleness. The controller tag baked into the archive
|
||||
(`/etc/felhom-controller-image`, what the bootstrap unit runs) is compared to the vouched version.
|
||||
|
||||
Neither matching ⇒ the archive is not what the operator approved. **An auto-discovered archive is
|
||||
then ignored and the vouched one fetched**, saying which check failed and why; **an archive the
|
||||
operator NAMED with `--golden` is REFUSED, never silently substituted**, and the refusal names the
|
||||
vouched version and the two routes (pass a matching archive, or `--force-gitea-golden`).
|
||||
|
||||
**Fail-safe:** an unreadable manifest is a REFUSAL, not a pass. "We could not look" must not resolve
|
||||
to "install whatever is lying around" — that is the finding restated.
|
||||
|
||||
**NOT YET OBSERVED FAILING, and deliberately not published.** The task asked that a fresh install be
|
||||
watched taking a stale local golden BEFORE the fix, on `drill-r50`. That observation was not made in
|
||||
this session, so this change is committed to `main` — which publishes nothing (R-110) — and the
|
||||
`installer-v1.26.0` tag is **deliberately not cut**. Publishing an unobserved change to the one
|
||||
artifact that runs as root on a virgin box is the failure this project keeps writing rules about.
|
||||
|
||||
## golden_currency_gate.py — a released controller must have a golden carrying it (2026-08-08, R-242)
|
||||
|
||||
**R-242 was filed the previous day as a rule with no mechanism and RECURRED WITHIN A DAY.** Controller
|
||||
|
||||
Reference in New Issue
Block a user