installer v1.23.0 — publishing becomes an act, not a side-effect (R-110, R-183)
gates / gates (push) Successful in 8s

Two channels moved off main in the same change, because either one left behind
makes the other cosmetic.

Channel 1 — the served script. webpage.yaml git-synced /scripts/ from
--branch=main every 30s and nginx served that tree, so pushing this file WAS
publishing it: within half a minute it was what every new machine downloaded and
ran as root, with no staging and no rollback but another push. The sync is now
SPLIT: the website keeps tracking main at the same cadence (a copy edit must
never need a release) and /scripts/ tracks the tag installer-v<SCRIPT_VERSION>.

PROVEN before the manifest was touched: git-sync v4.4.0 follows a tag AND
notices a MOVED one — measured on a throwaway sync against this repo,
"update required ... local:<old> remote:<new>" -> "updated successfully",
within one period. The moved-tag half is what the publish model rests on.

Channel 2 — the sixteen files fetched at run time. fetch_raw pulled from
$AGENT_REPO/raw/branch/main; it now pulls raw/tag/v$ART_AGENT_VER. That is a
correctness fix, not only a channel one (R-183): a fresh install fetched the
vouched agent BINARY while taking its unit file, sudoers and guarded wrappers
from whatever main held. Two refs, one install, nothing compared them. Their
correct ref was never SCRIPT_VERSION — they do not live in this repo.

No fallback to a branch: a vouched version whose tag is missing fails loudly
rather than quietly serving main.

Channel 3 — the URL — needed no change, recorded rather than left silent:
https://felhom.eu/scripts/felhom-host-install.sh never carried a ref, so both
producers follow the tag with no edit. No hub change, no hub version bump.

Gate 6 in hostinstall_gates.py pins all three structurally with no network, so
it stays in --fast and runs in CI. It deliberately does NOT assert "a tag exists
for the current SCRIPT_VERSION": that would go red on the very push that bumps
the version, before publishing — and publishing being separate is the ruling.
This commit is contained in:
2026-08-03 12:08:37 +02:00
parent 8360f940bf
commit bee6848458
4 changed files with 209 additions and 6 deletions
+48
View File
@@ -1,3 +1,51 @@
## v1.23.0 — the installer is published, not pushed (2026-08-03, R-110 + R-183)
**Two channels moved off `main` in the same change, because either one left behind makes the other
cosmetic.**
**Channel 1 — the served script.** `manifests/webpage.yaml` git-synced `/scripts/` from
`--branch=main` on a 30 s period and nginx served that working tree, so **pushing this file WAS
publishing it**: within half a minute it was what every new machine downloaded and ran as root, with
no staging and no rollback but another push. The sync is now **split in two**: the website keeps
tracking `main` at the same cadence (a copy edit must never need a release), and `/scripts/` tracks
the tag **`installer-v<SCRIPT_VERSION>`**. Publishing is moving that tag; rolling back is moving it
back.
**PROVEN, not assumed:** git-sync v4.4.0 follows a tag *and* notices a **moved** one — measured on a
throwaway sync against this repo, `update required … local:<old> remote:<new>``updated
successfully`, within one period (~20 s). The moved-tag half is what the whole publish model rests
on, so it was measured before the manifest was touched.
**Channel 2 — the sixteen files the installer fetches while it runs.** `fetch_raw` pulled from
`$AGENT_REPO/raw/branch/main`. It now pulls from **`raw/tag/v$ART_AGENT_VER`** — the agent version the
hub has vouched and whose binary sha this script already verifies.
**That is a correctness fix, not only a publish-channel one (→ R-183).** These are the AGENT's
configs — its systemd unit, its sudoers, its guarded wrappers — and a fresh install was fetching the
**vouched binary** while taking its configs from **whatever `main` held**. Two refs, one install, and
nothing compared them. The right ref for them was never this script's `SCRIPT_VERSION`: they do not
live in this repo and have no relationship to its version line.
**No fallback to a branch.** A vouched version whose tag is missing fails loudly rather than quietly
serving `main` — a silent fallback is the appearance of control with none of it. `felhom-agent`
carries `v<version>` tags from now on, `release-agent.sh` creates them, and `agent_gates.py` fails if
the vouched version is not downloadable.
**Channel 3 — the URL — needed no change, and that is worth recording rather than leaving as a
silence.** `https://felhom.eu/scripts/felhom-host-install.sh` never carried a ref: the ref lives in
the manifest. So both producers of that URL (`scripts/iso/felhom-bootstrap.sh`, the hub's day-0
command) follow the tag with no edit — **and no hub change, so no hub version bump.**
**Gate 6 in `hostinstall_gates.py`** pins all three structurally, with no network so it stays in
`--fast` and runs in CI on every push: no `raw/branch/` ref anywhere in the installer; `fetch_raw`
still pins to `$ART_AGENT_VER`; the manifest still syncs `/scripts/` from an `installer-v…` tag and
the website still from `main`.
**It deliberately does NOT assert "a tag exists for the current SCRIPT_VERSION".** That gate would go
red on the very push that bumps the version, before publishing — and publishing being a separate
deliberate act is the entire ruling. A gate that fails on the normal path is one people learn to
ignore.
## docs — v1.22.0 exercised end to end on two real reinstalls (2026-08-03, R-178) — **no script change**
**Nothing shipped.** `felhom-host-install.sh` stayed at **v1.22.0**; the published copy at