hub v0.102.0 — refuse to vouch a version that cannot be installed (R-273)

The guard owed since Friday morning. Agent v0.128.0 was published as a package
and never git-tagged; it was vouched here; and because felhom-host-install.sh
fetches an agent's configs from raw/tag/v<version>/configs/, every fresh install
and reinstall died at step 5 of 8, as root, on a virgin machine, for most of a
day. handleSetArtifacts is the sole UI path to SetArtifactManifest, so the check
belongs here and nowhere else.

TWO LEGS, because both failed inside two days: the TAG (missing, R-273) and the
PACKAGE (pruned from under a still-tagged version, R-287). Either alone catches
one of them.

It asserts configs/felhom-mkfs-guarded.sh -- the FIRST of the installer's sixteen
fetch_raw calls and literally the file whose 404 broke Friday. A test pins the
constant, because probing a path that merely exists is how it stayed invisible.
The golden gets the package leg only: it has no config tree, so a tag probe would
assert something the installer never does.

"Could not verify" refuses too, with its own message. No override -- the registry
is the operator's own server, so if it is unreachable the vouch can wait.

ORDERING IS LOAD-BEARING AND A FAILING TEST FOUND IT. The probes run before
resolveArtifactSHA, whose flash conflates "missing", "unreachable" and "bad sha".
Probing first means an unreachable registry is reported as unreachable.

Five scenarios each naming the wrong outcome; three red-proofs, mutations asserted
applied and reverted. With the tag check removed, scenario A reports artifacts_set
-- Friday's exact defect returns.
This commit is contained in:
2026-08-09 19:13:45 +02:00
parent 6088afcbed
commit b55fc17d82
5 changed files with 428 additions and 0 deletions
@@ -50,6 +50,18 @@
{{if eq .Flash "golden_behind_fleet"}}
<div class="flash flash-error"><strong>Refused: that golden is older than the controller the fleet already runs.</strong> A fresh install would land on stale application code — which is R-120, where new boxes shipped a controller that told customers the wrong thing about a missing backup drive. Manifest unchanged. Re-bake the golden on the current controller, publish it, then vouch it here.</div>
{{end}}
{{if eq .Flash "artifact_tag_missing"}}
<div class="flash flash-error"><strong>Refused: that version has no usable git tag.</strong> The installer fetches an agent's config files from <code>raw/tag/v&lt;version&gt;/configs/</code>, so a version published without its tag makes <em>every</em> fresh install and reinstall fail at step 5 of 8 — as root, on a virgin machine. That is exactly what happened on 2026-08-09. Manifest unchanged. Fix it by pushing the tag for that release: <code>git tag -a v&lt;version&gt; &lt;released-commit&gt; &amp;&amp; git push origin v&lt;version&gt;</code>, then vouch it here again.</div>
{{end}}
{{if eq .Flash "artifact_pkg_missing"}}
<div class="flash flash-error"><strong>Refused: that version's artifact is not downloadable.</strong> The version is tagged but its package is not in the registry, so a box would 404 fetching the binary itself. Manifest unchanged. Publish it — <code>bash scripts/release-agent.sh &lt;version&gt;</code> for the agent, or re-bake and publish the golden — then vouch it here again.</div>
{{end}}
{{if eq .Flash "artifact_unverifiable"}}
<div class="flash flash-error"><strong>Refused: could not verify — this does not mean anything is missing.</strong> The registry did not answer, so the hub cannot tell whether that version is installable. It refuses rather than saving with a warning, because a warning beside a success reads as a success. Manifest unchanged. Check that Gitea is up, then try again. There is deliberately no override: the registry is on your own server, so if it is unreachable the vouch can wait.</div>
{{end}}
{{if eq .Flash "artifact_sha_missing"}}
<div class="flash flash-error"><strong>Refused: no checksum for a chosen version.</strong> The hub records the sha256 it reads from Gitea, and that lookup came back empty — so saving would vouch bytes nobody verified. Manifest unchanged.</div>
{{end}}
{{if eq .Flash "pw_changed"}}
<div class="flash flash-success">Login password changed. It is already in effect — use it next time you sign in. Existing sessions stay logged in.</div>
{{end}}