# REPORT — build-golden.sh v2.0.0: golden 0.98.3 rebuild (drill B5 + B1) **Date:** 2026-07-03 · **Class:** implementation + clean-room drill (script-only — no Go code, no binary, **no agent version bump**; docs-only precedent) · **Source findings:** `felhom.eu/documentation/audits/DRILL-day0-cleanroom-2026-07-03.md` B5/B1 + the stale backlog note `FOLLOWUP-golden-default-controller-tag.md` (now resolved). Full drill evidence: **`felhom.eu/documentation/audits/DRILL-golden-098-2026-07-03.md`**. ## Baselines & commits | What | Value | |---|---| | Base | `c9f963d` | | Script commit | `ceca355` — configs/build-golden.sh v2.0.0 + CHANGELOG | | Docs commit | (this one — REPORT/CONTEXT) | | felhom.eu | guide/ledger/backlog/evidence-doc push (see that repo's REPORT) | | Controller tag baked | **0.98.3** (reconfirmed current: CHANGELOG top + manifest HTTP 200 pre-bake) | ## What changed (configs/build-golden.sh only) 1. **B5 — CONTROLLER_IMAGE (arg 6) MANDATORY**: no default; missing → die with usage naming the convention. Rationale in-file: the hand-bumped default rotted twice (0.43.0 → 0.85.1 → stale again); a required arg cannot rot; auto-"latest" could bake an unvouched tag. **Red-proof:** the no-arg invocation exits 1 with the usage BEFORE any `pct` op (run locally + in the drill VM). 2. **B1 — baked `felhom-controller-bootstrap.path`** (`PathExists=/etc/felhom-bootstrap/bootstrap.json`, enabled, `WantedBy=multi-user.target`): starts the Condition-gated oneshot service when the agent back-half hot-plugs the bootstrap mount into the RUNNING guest. Service unchanged (`RemainAfterExit=yes` prevents re-trigger loops; the enabled service still covers the plain boot case). The mp0/mp1 vzdump-inclusion guards untouched. 3. `GOLDEN_SCRIPT_VERSION=2.0.0` + `[golden]` provenance line (script version + baked tag) opening every bake transcript. Gates: `bash -n` clean; usage renders. ## Clean-room validation (drill VM on 192.168.0.180, virgin-restored per scenario) | Scenario | Result | |---|---| | A — bake integrity | PASS: provenance line; controller 0.98.3 + infra images baked; `docker logout` + config.json removal before archive (line present, ran); vzdump **including mp0 AND mp1**; archive 583 MB, sha256 `b9a02ef1b6f02b9b58babc4c6aad9cf6c053ebdfba116c78c8e7830de757fd01`; guest 9100 destroyed | | B — isolated hot-plug (STOP gate) | PASS: fresh restore w/o mount → service `inactive (dead)` condition-unmet, path `active (waiting)`; back-half-identical `pct set -mp9 …,mp=/etc/felhom-bootstrap,ro=1` on the RUNNING guest → service SUCCESS ~1 s later, controller `Up (healthy)` 0.98.3, `uptime -s` unchanged (**no reboot**) | | C — local-golden Day-0 (publish gate) | PASS: served installer v1.9.1, canonical command w/o `--force-gitea-golden` → `[SKIP] using local golden` (resolution order); **first boot controller 0.98.3, NO D.1b**; `selfupdate/check` → `update_available:false` (self-manages); selftest all-OK incl. pool read; bentopdf deployed via the dashboard endpoint → 200 via traefik; hub rows: agent 0.63.0 / controller 0.98.3 | | Publish | PUT `…/felhom-golden/0.98.3/golden.tar.zst` → **201**; round-trip GET sha **matches** (publish-agent.sh pattern mirrored) | | Vouch | operator vouched golden **0.98.3** in the Day-0 manifest (agent 0.63.0 already vouched — the v0.63.0 follow-up is DONE); confirmed via `/api/v1/artifacts` | | D — published-artifact Day-0 | PASS: virgin box, no local golden → `fetching golden v0.98.3 from Gitea` → `verified sha256 b9a02ef1… matches the hub manifest` → SUCCESS; first boot 0.98.3; up-to-date. The exact fresh-customer path | Cleanup: all drill-1 hub rows deleted (8 tables, counts 0; demo-felhom/peti-felhom intact); drill VM reverted to `virgin` and kept; bake credential env (0600) removed. Registry read-cred handled via env only — never logged/committed. ## Deviations & observations - **Premature publish (caught + corrected):** the script's opt-in publish block triggers on the same `REGISTRY_*` vars the pull needs — the Scenario A bake published immediately, before the Scenario C gate. Package DELETEd (204, anon 404 verified) and re-published only after C passed. Candidate cleanup (not done — no-"while-here" rule): a separate `GOLDEN_PUBLISH=1` opt-in. - **SECURITY (operator follow-up):** the pull credential — the demo customer's `git.token`, i.e. what every customer box holds — turned out to be a Gitea **admin token with package-WRITE** (the premature publish proved it). Scope down to read-only + rotate. - Installer v1.9.1's post-provision reboot is now a redundant belt (the path unit deploys first) — removal recorded as a candidate installer cleanup, kept for now. - Drill-env: `dhcpstart=10.0.2.30` + explicit `hostfwd…-10.0.2.15:22` on the QEMU command removes the prior drill's slirp IP-collision quirk entirely. - Guide follow-through (felhom.eu): **D.1b retired** to a one-line version check; troubleshooting row covers pre-0.86.0 goldens; ledger B1/B5 FIXED; backlog note resolved.