REPORT: Part 5 FAILED — the package never creates /etc/felhom. NOT PUBLISHED

The Terminal-UI interactive install ran to completion from the release image and gave 3 of 4
required observables:
  1 package installed      PASS  ii felhom-bootstrap 1.26.0
  2 unit enabled           PASS  wants-symlink present; postinst enabled it from the chroot
  3 unit FIRED first boot  PASS  journal shows PAIRING mode, registering unclaimed appliance
  4 box wants a claim code FAIL

/etc/felhom/ does not exist on the installed system, so felhom-bootstrap.sh cannot write the
appliance token (:431) or the pairing code (:435), and the hub poll then 401s forever. The box can
never finish pairing and the customer never sees a claim code.

ROOT CAUSE, mine: stub-first-boot.sh opened with 'install -d -m 0755 /etc/felhom /usr/local/sbin'.
This task correctly dropped the env FILE from the package and dropped the DIRECTORY with it.
felhom-bootstrap.sh uses /etc/felhom for its runtime state (token, pairing code, .bootstrap-done).

WHY THE GATE MISSED IT: G9 proves the packaged script is byte-identical to HEAD, and it is. I
verified the payload files and never the directory the payload writes into — a check that proves
the thing present and not the thing it depends on. Added as G13.

The fix is one line and is deliberately NOT applied: a failing Part 5 stops the task, and proving a
fix needs both installs re-run.

Also recorded: 'qm set --scsi0 ... --boot order=scsi0;ide2' silently yields boot: order=net0;ide2,
so a COMPLETED install looked like a machine sitting in the installer. Set --boot separately.

Nothing uploaded; R2 credentials never read. Teardown complete: VMs purged, spike5 storage removed,
demo-hp back to 6.6G, drill-r50 and 9201 untouched. Hub-side: no appliance object was created
(searched /, /hosts, /configs for the hostname — zero hits), so R-131 gains no row.
This commit is contained in:
2026-07-31 18:16:20 +02:00
parent 246036605a
commit 4ea211f67f
+76 -19
View File
@@ -1,8 +1,9 @@
# REPORT — the universal ISO: built and gated, **NOT PUBLISHED** (2026-07-31)
> **Nothing was published.** Part 5 (prove it — two interactive installs) was not completed, and
> publication is gated on it. Per the task: *"If either fails, stop. Report it and publish nothing."*
> and *"Stopping is the good outcome."* This is that outcome, not a failure of the artifact.
> **Nothing was published. Part 5 FAILED**, and it failed on a real defect in the package this task
> created: the installed box cannot complete pairing because `/etc/felhom/` is never created, so the
> appliance token and the pairing code cannot be written and the hub poll 401s forever. Per the task:
> *"If either fails, stop. Report it and publish nothing."* — §6 is the finding.
>
> Written as `REPORT-iso-release.md`, not root `REPORT.md`, per the task and the shared-clone rule.
@@ -108,24 +109,68 @@ fetched at run time from the website's git-sync of `main` (R-94/R-110), so whate
carries, the script a box runs is always current. An assertion would invent a constraint. The comment
now states the independence, and `ISO_VERSION` is `1.26.0`.
## 6. Part 5 — **NOT COMPLETED. This is why nothing was published.**
## 6. Part 5 — **FAILED. A real defect in the package. Nothing was published.**
**What was proven:**
- The release image boots to the **branded two-entry menu** — screendumped: *"Felhom telepítés"* and
*"Felhom telepítés (szöveges mód)"*, the second selected, over the Felhom boot card.
- The **Terminal UI entry boots the stock PVE installer** and reaches the EULA screen.
### The Terminal UI entry — 3 of 4 observables pass, the fourth fails
**What was not:** neither install was carried through to completion, so **none** of the four required
observables was obtained on either entry — package installed, unit enabled, unit fired on first boot,
box asking for a claim code. The **Graphical** entry was created (VM 500) but never driven.
Normal manual install from the release image: own disk (`/dev/sda`, shown by the installer with its
data-loss warning), own password, own FQDN. Installed host `spikefive.felhom.eu`, `pve-manager/9.2.2`.
Completion signal: the installer wrote 7.0 GB to the disk and rebooted itself; the installed system was
then reached over SSH — not inferred from a changed artifact.
**Why:** each interactive install takes roughly fifteen further verified interaction rounds plus
install and boot time, and this session did not have room for two. Driving them half-way and reporting
partial observables would be exactly the `LastRun`-class error this arc has corrected three times.
| # | Observable | Result |
|---|---|---|
| 1 | the `.deb` is installed | **PASS**`ii felhom-bootstrap 1.26.0 all` |
| 2 | the unit is enabled | **PASS**`enabled`, wants-symlink present; postinst log confirms `enabled felhom-bootstrap.service via systemctl` from inside the installer chroot |
| 3 | the unit **fired on first boot** | **PASS**`activating`, and the journal shows it running: *"PAIRING mode (generic ISO, no baked customer/passphrase) — hub=https://hub.felhom.eu"**"registering unclaimed appliance at the hub"* |
| 4 | the box reaches the point of wanting a claim code | **FAIL** |
**What it would take:** ~90 minutes for both, using the driver already proven in Spikes 3 and 4. The
fixture is reproducible from committed source — `qm` VMs on a `spike5` dir storage, the ISO at the
recorded sha256.
### The defect, and it is mine
```
felhom-bootstrap.sh[1105]: /usr/local/sbin/felhom-bootstrap.sh: line 431: /etc/felhom/appliance-token: No such file or directory
felhom-bootstrap.sh[1067]: /usr/local/sbin/felhom-bootstrap.sh: line 435: /etc/felhom/appliance-pairing-code: No such file or directory
felhom-bootstrap.sh[1067]: felhom-bootstrap: poll returned HTTP 401 — still retrying
```
**`/etc/felhom/` does not exist on the installed system**, so the appliance token and the pairing code
cannot be written, and the poll then 401s forever because there is no token to authenticate with. The
box can never finish pairing, and the customer never sees a claim code.
**Root cause.** The old `stub-first-boot.sh` began with
`install -d -m 0755 /etc/felhom /usr/local/sbin` (`scripts/iso/stub-first-boot.sh`). §3 correctly
dropped the *env file* from the package — it is genuinely unnecessary — but dropped the **directory**
with it. `felhom-bootstrap.sh` uses `/etc/felhom/` for its runtime state: the appliance token
(`:431`), the pairing code (`:435`) and `.bootstrap-done` (the unit's `ConditionPathExists`).
**Why the gate did not catch it.** G9 asserts the packaged `felhom-bootstrap.sh` is byte-identical to
repo HEAD, and it is. I verified the *payload files* and never the *directory the payload writes
into* — the same shape as this arc's other misses: a check that proves the thing present and not the
thing it depends on. **The gate needs a criterion for it** (see below), and that is worth more than
the one-line fix.
**The fix** is one line — ship `/etc/felhom/` in the package (an empty dir at 0755), or `install -d`
it in the postinst under the existing guards. It is deliberately **not applied here**: a failing
Part 5 stops the task, and applying a fix would mean re-running both installs to prove it, which this
session no longer has room for.
### The Graphical entry — **not completed**
VM 500 booted the graphical entry from the same image and reached the installer: the KVM-support
dialog, the EULA, and the **Target Harddisk** screen showing `/dev/sda (20.00GiB, QEMU HARDDISK)` with
*"Please verify the installation target … All existing partitions and data will be lost"*. It was not
driven further: `Enter` on the Location screen lands in the Country field rather than on `Next`, and
the QEMU monitor's `mouse_move`/`mouse_button` did not move the guest cursor, so the GTK flow needs a
different driving method than the TUI's tab-order. Since Part 5 had already failed on the TUI entry,
finishing this one would not have unblocked publication.
### A fixture bug of mine, recorded because it cost a diagnosis
`qm set <vmid> --scsi0 … --boot order="scsi0;ide2"` silently produced `boot: order=net0;ide2` — PVE
processed `--boot` before `--scsi0` existed and substituted a default. Both VMs therefore netbooted,
failed, and fell through to the CD, so a **completed** install looked like a machine sitting in the
installer. Diagnosed from `qm config` and the 7.0 GB disk, not from the screen. Set `--boot` in a
**separate** `qm set` after the disk exists.
## 7. Part 6 — the gate, run against the built artifact
@@ -146,6 +191,7 @@ sha256 **`24977bafd24d73262745fc1b3040939469c9b23b87ead927a8af86de73044a90`**, 1
| **G10** | build inputs committed | `git status --porcelain`, HEAD vs origin | **PASS** — clean and pushed at build time |
| **G11** | published checksum + round trip | — | **NOT RUN** — nothing was published |
| **G12** | bucket stays private | — | **NOT RUN** — the bucket was never touched |
| **G13** | *(new, from Part 5's failure)* the package creates every directory its payload writes into | `/etc/felhom/` present after install | **would have FAILED** — see §6 |
**A gate refinement found by running it.** G7 also asked that the ISO's copy of the `.deb` sha256-match
the package built from source. It does not, and cannot: `dpkg-deb` embeds build timestamps, so two
@@ -179,7 +225,14 @@ the customer list and searching it — 0 spike-named objects, the same single pr
## 10. R-dispositions
**No new `R-n` rows.** Each candidate was grepped against the register first:
**One new row is warranted** (§6's defect), and it was grepped against the register first — no
existing row covers `/etc/felhom` or the package's directory set (`grep -rn 'etc/felhom' documentation/backlog/`
returns nothing about package contents). It is deliberately **not filed as a defect against shipped
code**, because the package has never shipped: it is a finding against this task's own unpublished
work, recorded in §6 and in the gate as **G13**. If the ISO work is picked up later and the fix is not
applied first, file it then.
Otherwise, no new rows. Each candidate was grepped against the register first:
- **R-128 — FIXED** here (§5).
- **R-155 — RESOLVED** here (§4): the guard is narrowed, not deleted.
- **R-154** (`[first-boot]` is automated-only and nothing in the tree says so) — **addressed in code
@@ -189,7 +242,11 @@ the customer list and searching it — 0 spike-named objects, the same single pr
## 11. What did not happen, and why
- **Part 5, both entries** — the reason publication is blocked. §6.
- **Part 5** — the TUI entry ran to completion and **failed** on observable 4 (§6). The Graphical
entry reached the Target-Harddisk screen and was not driven further, because Part 5 had already
failed and finishing it could not unblock publication.
- **The one-line fix** (ship `/etc/felhom/` in the package) — deliberately not applied: proving it
needs both installs re-run, which this session no longer had room for.
- **Part 7, publication** — gated on Part 5.
- **Part 8, documentation** — the release-gate runbook is committed (`e787391`); `day0-install.md`'s
ISO-vs-manual section, the `OPEN-ITEMS`/`ROADMAP` dispositions and the `scripts/CHANGELOG.md` entry