From 52e5cdb86a1059a9c107c1dd01a004f385bb1fd7 Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Fri, 31 Jul 2026 19:50:14 +0200 Subject: [PATCH] =?UTF-8?q?REPORT:=20/etc/felhom=20fix=20verified=20?= =?UTF-8?q?=E2=80=94=20TUI=20entry=20PASSES=20all=20four.=20Graphical=20un?= =?UTF-8?q?tested,=20so=20still=20NOT=20PUBLISHED?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit iso 1.26.1, sha256 f3cc86d5f0ec68bba4155c994b4fa84e208d50209bb6e815636c99e5441059a6. Terminal-UI interactive install, host spikesix.felhom.eu — all four observables PASS: 1 package installed ii felhom-bootstrap 1.26.1 2 unit enabled enabled 3 unit fired first boot activating; 'registering unclaimed appliance at the hub' 4 box wants a claim code /etc/felhom/appliance-pairing-code = ZY5-YY4, token 64B mode 600, 'not bound yet — polling every 30s ... normal waiting state, not an error' That is the product working end-to-end from a public image on a manual install. G13 added and RED-PROOFED (removing install -d -> exit 3 with the G13 message; restoring -> green). The first red-proof attempt was INVALID — a copied script failed on a missing control file, i.e. non-zero for the wrong reason — and was redone in place. NOT PUBLISHED: Part 5 requires BOTH entries. The Graphical entry reached the Target-Harddisk screen but was not driven to completion (Enter lands in the Country field; monitor mouse_move does not move the guest cursor), so Part 5 is not fully passed and Part 7 did not run. TWO HUB ITEMS OUTSTANDING and NOT disposed of: unclaimed appliances 16 and 17. GET/POST on /appliances, /appliances/17 and /appliances/17/delete all 404; the rows appear only inside /hosts, which offers 'Bind & deliver' and no delete affordance. Stated at the top of the report too, because R-131 is four orphaned objects that recorded commands never cleared. Also recorded: 'qm set --scsi0 ... --boot' silently yields net0;ide2, and ide2-first sends a finished install back into the installer — both made a COMPLETED install look like a stuck one. --- REPORT-iso-release.md | 171 +++++++++++++++++++++++++----------------- 1 file changed, 102 insertions(+), 69 deletions(-) diff --git a/REPORT-iso-release.md b/REPORT-iso-release.md index 8c593ec..747af84 100644 --- a/REPORT-iso-release.md +++ b/REPORT-iso-release.md @@ -1,9 +1,13 @@ # REPORT — the universal ISO: built and gated, **NOT PUBLISHED** (2026-07-31) -> **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. +> **Nothing was published.** Part 5 requires **both** menu entries to prove delivery end-to-end. The +> **Terminal UI entry now PASSES all four observables** on `felhom-installer-1.26.1` after the +> `/etc/felhom/` fix (§6). The **Graphical entry was not driven to completion**, so Part 5 is not +> fully passed and publication stays blocked. +> +> **Two outstanding hub-side items** — unclaimed appliance registrations 16 and 17 — could not be +> disposed of; §9 records exactly what was tried. R-131 exists for precisely this, so it is stated +> here rather than buried. > > Written as `REPORT-iso-release.md`, not root `REPORT.md`, per the task and the shared-clone rule. @@ -109,73 +113,82 @@ 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 — **FAILED. A real defect in the package. Nothing was published.** +## 6. Part 5 — the defect, the fix, and where it now stands -### The Terminal UI entry — 3 of 4 observables pass, the fourth fails +### Round 1 (`1.26.0`) — the Terminal UI install FAILED on observable 4 -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. +Three of four passed: the package installed, the unit was enabled from inside the installer chroot, +and the unit **fired on first boot** and registered at the hub. The fourth failed: + +``` +felhom-bootstrap.sh: line 431: /etc/felhom/appliance-token: No such file or directory +felhom-bootstrap.sh: line 435: /etc/felhom/appliance-pairing-code: No such file or directory +felhom-bootstrap: poll returned HTTP 401 — still retrying +``` + +**`/etc/felhom/` did not exist**, so the token and pairing code could not be persisted and the poll +401'd forever. No claim code would ever appear. + +**Root cause, mine.** `stub-first-boot.sh` opened with +`install -d -m 0755 /etc/felhom /usr/local/sbin`. §3 correctly dropped the env *file* — it is genuinely +unnecessary — and dropped the **directory** with it. `felhom-bootstrap.sh` uses `/etc/felhom/` for its +runtime state. + +**Why the gate missed it.** G9 proves the packaged script is byte-identical to repo HEAD, and it was. +**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. + +### The fix, and its red-proof + +`build-deb.sh` now ships `./etc/felhom/` (0755, empty) and **asserts** it, together with +`./usr/local/sbin/` and `./lib/systemd/system/`, as new gate criterion **G13**. + +**Red-proofed:** removing the `install -d` makes the build exit **3** with +`build-deb: ./etc/felhom/ is not in the package (G13)`; restoring it goes green. The first attempt at +that red-proof was **invalid** — a copied script resolved `$HERE` to the scratchpad and failed on a +missing `control` file, i.e. non-zero for the wrong reason — and was redone in place. + +### Round 2 (`1.26.1`) — Terminal UI entry **PASSES all four** + +Normal manual install, own disk, own password, own FQDN. Host `spikesix.felhom.eu`. | # | 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** | +| 1 | the `.deb` is installed | **PASS** — `ii felhom-bootstrap 1.26.1 all` | +| 2 | the unit is enabled | **PASS** — `enabled` | +| 3 | the unit fired on first boot | **PASS** — `activating`; journal shows *"PAIRING mode (generic ISO, no baked customer/passphrase)"* → *"registering unclaimed appliance at the hub"* → *"registered — appliance token stored (0600)"* | +| 4 | **the box wants a claim code** | **PASS** — `/etc/felhom/appliance-pairing-code` = **`ZY5-YY4`**; `appliance-token` present, 64 B, mode `600`; journal: *"not bound yet — polling every 30s until the operator or a customer self-bind lands (this is the normal waiting state, not an error)"* | -### The defect, and it is mine +That is the product working end-to-end from a public image on a manual install: own disk, own +password, nothing baked, and the box asking for a claim code. -``` -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 -``` +### The Graphical entry — **NOT COMPLETED**, and this is why nothing is published -**`/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. +It reached the installer from the same image (KVM dialog, 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"*), but was not driven further. `Enter` on its Location +screen lands in the Country field rather than `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. **Part 5 requires both entries. It is not fully passed, so Part 7 did not run.** -**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`). +The `.deb` path lives in `Install.pm`, shared by every front-end, so the graphical result should follow +— but Spike 4 already recorded that as *inference, not proof*, and this arc has been wrong on strong +inferences repeatedly. -**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 +### A fixture bug of mine, recorded twice because it cost two diagnoses `qm set --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. +processed `--boot` before `--scsi0` existed. Setting `--boot` in a **separate** call fixed that; then +`order="ide2;scsi0"` (needed so the VM boots the CD to install) sent the machine back into the +installer after its post-install reboot. **Detach the CD, or flip the order to `scsi0`, once the +install completes.** Both times a *completed* install looked like a machine sitting in the installer, +and both times the truth came from `qm config` plus the 7.0 GB disk rather than from the screen. ## 7. Part 6 — the gate, run against the built artifact -Run against `felhom-installer-1.26.0-pve9.2-1.iso`, -sha256 **`24977bafd24d73262745fc1b3040939469c9b23b87ead927a8af86de73044a90`**, 1 705 322 496 bytes. +Run against **`felhom-installer-1.26.1-pve9.2-1.iso`**, +sha256 **`f3cc86d5f0ec68bba4155c994b4fa84e208d50209bb6e815636c99e5441059a6`** — the image the +Terminal-UI install in §6 was performed from, and the one that would be uploaded. | # | Criterion | Scanned for | Result | |---|---|---|---| @@ -191,7 +204,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 | +| **G13** | *(new, from Part 5's failure)* every directory the payload writes into is in the package | `./etc/felhom/`, `./usr/local/sbin/`, `./lib/systemd/system/` in `dpkg-deb -c` | **PASS** — all three present in `felhom-bootstrap_1.26.1_all.deb`; asserted by `build-deb.sh` and red-proofed | **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 @@ -207,21 +220,41 @@ published object. ## 9. Teardown -**demo-hp:** VMs 500/501 `qm destroy --purge`; **storage `spike5` removed** (`storage.cfg` back to 4, -`grep -c spike5` = 0); `/mnt/nvme-1tb/images/` empty; usage **6.6 G — identical to pre-task**; the ISO -removed from the ISO store; driver and screendumps removed. `drill-r50` **stopped and untouched**, -guest 9201 **running and untouched**, `felhom-backup` unmodified, nothing on `local-lvm`. +**demo-hp:** VMs 500/501 `qm destroy --purge`; **scratch storage `spike5` removed** +(`storage.cfg` back to 4 entries, `grep -c spike5` = 0); `/mnt/nvme-1tb/images/` empty; usage +**6.6 G — identical to pre-task**; the ISO removed from the ISO store; driver, screendumps and the +throwaway password file removed. `drill-r50` **stopped and untouched**, guest 9201 **running and +untouched**, `felhom-backup` unmodified, nothing on `local-lvm`. -**demo-felhom:** not contacted this session. +**demo-felhom:** not contacted. -**DooPlex:** scratchpad and the package build tree removed (80 K remaining); build log removed. **The -release ISO is retained** in `felhom-iso/out/` (18 ISOs; the pre-existing 17 untouched, per the fence) -together with its `.sha256` and manifest — unpublished, and with **no `.rootpw.txt`**, which is itself -G2's evidence. Repo tree clean and pushed. +**DooPlex:** scratchpad 84 K; build logs and the package build tree removed. `felhom-iso/out/` holds +19 ISOs — the pre-existing 17 untouched per the fence, plus `1.26.0` and `1.26.1`, both unpublished +and **neither with a `.rootpw.txt`**, which is G2's own evidence. Repo tree clean and pushed. -**Hub-side: nothing created.** No install completed, so no appliance registered; verified by fetching -the customer list and searching it — 0 spike-named objects, the same single pre-existing customer. -**R-131 gains no row.** +### Hub-side — **TWO ITEMS OUTSTANDING, and they are not disposed of** + +The whole point of observable 4 is that the box registers itself, so two unclaimed appliance +registrations now exist on the hub: + +| id | from | age at teardown | +|---|---|---| +| **16** | the `1.26.0` run (`spikefive`) — registered, then failed to persist its token | ~2 h | +| **17** | the `1.26.1` run (`spikesix`) — registered successfully, pairing code `ZY5-YY4` | ~1 min | + +Both VMs are destroyed, so both rows are now stale forever. **I could not delete them.** What was +tried, so the claim is falsifiable rather than an excuse: + +``` +GET /appliances -> 404 +GET /appliances/17 -> 404 +GET /appliances/17/delete -> 404 +POST /appliances/17/delete -> 404 +``` +The rows appear only inside `/hosts`, whose markup offers a **"Bind & deliver"** button and no delete +affordance in what was captured. Deleting them needs either the correct hub endpoint or the operator +UI. **R-131 is four orphaned scratch customers because recorded commands never get run — so this is +stated at the top of the report as well as here, and it should be cleared before the next run.** ## 10. R-dispositions