Files
felhom-agent/REPORT.md
T

4.2 KiB

REPORT — the golden bakes EVERY infra image, asked from the controller (2026-07-19)

Scope: configs/build-golden.sh only (v2.0.0 → v2.1.0). No agent version bump — this is build tooling, not the binary. Effective at the NEXT golden build; the current golden was deliberately NOT rebuilt for this.

The bug

Enabling Megosztás on a fresh box pulled felhom-samba from the registry with zero feedback — minutes of silent nothing. Observed live, twice.

The cause was not the pull. It was that the golden should already have carried the image, like the other infra stacks, and did not. build-golden.sh held its own hand-maintained array of three image tags, with a comment instructing the reader to keep it in sync with the controller's internal/infra constants:

INFRA_IMAGES=(
  "traefik:v3.6.7"
  "cloudflare/cloudflared:2026.6.0"
  "gtstef/filebrowser:1.3.3-stable"
)

That comment is the whole failure mode. When felhom-samba was added as the fourth infra stack (R-7 slice 1), the controller learned about it and this list did not. The golden baked 3 of 4.

The fix — structural, not a fourth copy

The list now comes from the controller image the bake has just pulled:

docker run --rm --entrypoint /usr/local/bin/felhom-controller "$CONTROLLER_IMAGE" --print-infra-images

backed by infra.Images(), which derives from the pins themselves. The golden therefore bakes exactly what that controller version will request, and the two cannot disagree by construction. Adding a fifth infra stack is now two edits in one file (internal/infra/infra.go) and zero here.

On the controller side a test parses the const block out of the source with go/ast and fails if a *Image const exists that Images() does not return — a hand-written expected list would need the same edit and would rot the same way. Red-proofed: removing SambaImage from Images() fails it with the exact drift message.

The ordering bug this exposed

docker logout + rm -f /root/.docker/config.json ran immediately after the controller pull, before the infra loop. That was fine while all three infra images were public Docker Hub images. felhom-samba lives on gitea.dooplex.hu — the same private registry as the controller — so the new loop would have 401ed on it.

The logout moved to after the loop, and gained a hard assertion that no credential remains in the guest before it is archived:

pct exec "$VMID" -- bash -c '[ ! -s /root/.docker/config.json ]' \
  || { echo "[golden] FATAL: registry credential still present in the guest — refusing to archive"; exit 1; }

The credential is still never baked; the guarantee is now checked rather than assumed.

Fallback, loudly

A controller older than v0.147.0 has no --print-infra-images. The bake falls back to the historical three-image list and prints three WARN lines saying felhom-samba will not be baked and Megosztás will pull at runtime. The fallback is the drift-prone thing this change removes, so it announces itself rather than passing silently.

Verification

  • bash -n configs/build-golden.sh — clean.
  • The seam was exercised against the real published image on the live demo guest:
$ docker run --rm --entrypoint /usr/local/bin/felhom-controller \
    gitea.dooplex.hu/admin/felhom-controller:0.147.0 --print-infra-images
traefik:v3.6.7
cloudflare/cloudflared:2026.6.0
gtstef/filebrowser:1.3.3-stable
gitea.dooplex.hu/admin/felhom-samba:1.0.0

All four, from the image the golden would bake. The flag is config-free by design (no controller.yaml, no data dir, no settings) precisely so a bare docker run can ask it.

  • Not run: a full golden bake. The task scoped this to "effective at the next golden build, do not rebuild the golden for this alone", so the loop itself has not executed end-to-end on a real bake. The parts that could be verified without one were.

Follow-up

documentation/backlog/ROADMAP.md pre-invite checklist records that golden ≥ 0.147.x carries all four infra images. Until the next bake, a fresh box still pulls felhom-samba at enable time — which controller v0.147.0's progress card now at least explains rather than leaving silent.