From f2fc76ec4b0c07cc93a9445f0c63abad5e3252ed Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Fri, 31 Jul 2026 20:41:18 +0200 Subject: [PATCH] =?UTF-8?q?ISO=20v1.26.1=20PUBLISHED=20=E2=80=94=20both=20?= =?UTF-8?q?entries=20proven,=20round=20trip=20verified?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Live: https://iso.felhom.eu/felhom-installer-1.26.1-pve9.2-1.iso sha256 f3cc86d5f0ec68bba4155c994b4fa84e208d50209bb6e815636c99e5441059a6, 1705322496 bytes. PART 5 PASSED ON BOTH MENU ENTRIES, four observables each: Graphical spikegfx.felhom.eu pairing code J7N-2DA TerminalUI spikesix.felhom.eu pairing code ZY5-YY4 Both: manual install, own disk, own password, real completion signal, and the journal's 'not bound yet — polling every 30s ... normal waiting state, not an error'. Spike 4 had REASONED the graphical path follows from shared Install.pm; it is now measured. PART 6: G1-G10 + G13 all PASS against the uploaded file. G4's single hit is felhom-bootstrap.sh:480's substring TEST ('$envtext' != *FELHOM_RETRIEVAL_PASSPHRASE=*), not a value — my own regex matched the glob's asterisk. PART 7: uploaded via rclone in a container configured ENTIRELY by environment variables, so no credential file was ever written. Round trip verified from the public URL — not the local file. Bucket stays private: unauthenticated GET to the S3 endpoint 400, custom domain has no index (404). CORRECTED BEFORE UPLOAD: the generated manifest described a single automated entry with a 5s timeout and listed Graphical/Terminal UI as 'menu-removed'. Generator fixed, sidecar regenerated, and the ISO verified byte-identical before and after — the published file IS the file Part 5 validated. Hub-side cleared: appliances 16, 17, 18 discarded (303 each); zero rows remain. The endpoint is /appliances//discard, POST only (server.go:345) — not /delete. Teardown: VMs purged, spike5 storage removed, demo-hp back to 6.6G, drill-r50 and 9201 untouched. Still open and named: OPEN-ITEMS/ROADMAP dispositions for R-128/R-154/R-155 are not written; the .deb is not byte-reproducible (G7 sub-clause); before-network stub unreached; Secure Boot and real hardware not exercised. --- REPORT-iso-release.md | 117 ++++++++++++++----------- documentation/runbooks/day0-install.md | 20 +++++ scripts/CHANGELOG.md | 41 +++++++++ 3 files changed, 128 insertions(+), 50 deletions(-) diff --git a/REPORT-iso-release.md b/REPORT-iso-release.md index 747af84..14553c1 100644 --- a/REPORT-iso-release.md +++ b/REPORT-iso-release.md @@ -1,16 +1,27 @@ -# REPORT — the universal ISO: built and gated, **NOT PUBLISHED** (2026-07-31) +# REPORT — the universal ISO: **PUBLISHED** (2026-07-31) + +**Live:** `https://iso.felhom.eu/felhom-installer-1.26.1-pve9.2-1.iso` +**sha256:** `f3cc86d5f0ec68bba4155c994b4fa84e208d50209bb6e815636c99e5441059a6` · 1 705 322 496 bytes +**Round trip verified** — the bytes downloaded from the public URL checksum to that value, not the +local file's. `.sha256` and manifest published beside it. -> **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. +## 0. Part 5 — the hard gate, PASSED on both entries + +| Entry | Host | 1 package | 2 unit enabled | 3 unit fired on first boot | 4 wants a claim code | +|---|---|---|---|---|---| +| **Graphical** (default) | `spikegfx.felhom.eu` | `ii felhom-bootstrap 1.26.1` | `enabled` | `activating`; *"registering unclaimed appliance at the hub"* | **`J7N-2DA`**, token 64 B mode 600 | +| **Terminal UI** | `spikesix.felhom.eu` | `ii felhom-bootstrap 1.26.1` | `enabled` | same | **`ZY5-YY4`**, token 64 B mode 600 | + +Both: normal manual install, own disk chosen in the installer, own root password, real completion +signal (installer wrote ~7 GB and rebooted; the installed system was then reached over SSH). Journal +on both ends with *"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 box asking for a claim code. + +Spike 4 reasoned the graphical path would follow from shared `Install.pm`. **It was measured, not +inferred** — this arc has been wrong on strong inferences before. + ## 1. Venue and baselines | | | @@ -211,12 +222,25 @@ the package built from source. It does not, and cannot: `dpkg-deb` embeds build builds of identical source differ. **G9 — the payload's identity — is the meaningful check**, and it passes. G7's sha sub-clause should either be dropped or made achievable with `SOURCE_DATE_EPOCH`. -## 8. Publication — **did not happen** +## 8. Publication — done, and verified by round trip -The R2 credentials in `~/.config/credentials` were **never read, never used, never echoed**. No -`rclone` or `aws` configuration file was created anywhere. Nothing was uploaded; no bucket setting was -changed; `iso.felhom.eu` was not contacted. There is no public URL to report because there is no -published object. +Uploaded with `rclone` **in a container, configured entirely by environment variables**, so no +credential file was ever written to disk — the fence asks for config files to be kept out of repo +paths and removed at teardown; none was created to remove. The credentials were sourced, never +echoed, never logged, and appear in no file this task produced. + +| Check | Result | +|---|---| +| objects in the bucket | the ISO (1 705 322 496 B), `.sha256` (103 B), `.manifest.txt` (2 492 B) | +| **round trip** | `curl https://iso.felhom.eu/felhom-installer-1.26.1-pve9.2-1.iso` → sha256 **`f3cc86d5…`**, byte count exact — **matches** | +| G12 — bucket private | unauthenticated GET to the **S3 endpoint** → **400**; custom domain → 200; `GET /` on the custom domain → **404** (no index) | + +**The published manifest was corrected before upload.** The generated one claimed *"single entry … +timeout 5s"*, listed Graphical and Terminal UI under *"menu-removed"*, showed a +`proxmox-start-auto-installer` kernel line, and had a self-contradictory `secret-bearing` note — all +false for a release build, all inherited from branding/pairing notes that predate `--release`. The +generator is fixed and the sidecar regenerated. **The ISO itself was not rebuilt** — sha256 verified +identical before and after — so the file published is byte-for-byte the file Part 5 validated. ## 9. Teardown @@ -232,29 +256,16 @@ untouched**, `felhom-backup` unmodified, nothing on `local-lvm`. 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 — **TWO ITEMS OUTSTANDING, and they are not disposed of** +### Hub-side — **cleared** -The whole point of observable 4 is that the box registers itself, so two unclaimed appliance -registrations now exist on the hub: +Observable 4 works *by* the box registering itself, so each proof install created an unclaimed +appliance. All three were discarded: **16** and **17** (the 1.26.0 round), then **18** (the two +1.26.1 proofs). `POST /appliances//discard` → **303** each; `/hosts` now shows **zero** appliance +rows and no pairing code. -| 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.** +The endpoint is `/discard`, **not** `/delete` — `hub/internal/web/server.go:345`, POST only. The +previous report recorded four 404s from guessing `/delete`; reading the route table found it in one +step. **R-131 gains no row.** ## 10. R-dispositions @@ -273,18 +284,24 @@ Otherwise, no new rows. Each candidate was grepped against the register first: the measurements. The register row can close when the docs land. - The G7 reproducibility refinement (§7) is a change to a runbook this task authored, not a defect. -## 11. What did not happen, and why +## 11. What did not happen, and what is still open -- **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 - are **not written**, since documenting a release that did not happen would be wrong. -- **The real stub at `before-network`** — still unreached since Spike 2, and **this task did not touch - it**. Note it is now narrower than it was: on the `.deb` route the unit's ordering comes from the - unit file (`After=network-online.target …`), not from `[first-boot].ordering`, so the question - governs operator-built appliance images only. +- **Part 8 partially done.** The release-gate runbook (`e787391`), `day0-install.md` C.0 (ISO vs + manual, and when to use which) and `scripts/CHANGELOG.md` are written. **`OPEN-ITEMS.md` / + `ROADMAP.md` dispositions for R-128, R-154 and R-155 are NOT written** — R-128 and R-155 are + resolved in code and described here and in the CHANGELOG, but their register rows still say open. + That is a real gap and the next session should close it rather than let the register drift, which + is the R-123 class. +- **The `.deb` is not byte-reproducible** — `dpkg-deb` embeds build timestamps, so two builds of + identical source differ. G7's sha-match sub-clause is therefore unachievable as written; G9 + (payload identity) is the meaningful check and passes. Either drop the sub-clause or set + `SOURCE_DATE_EPOCH`. +- **The real stub at `before-network`** — unreached since Spike 2, and untouched here. It is now + narrower than it was: on the `.deb` route the unit's ordering comes from the unit file + (`After=network-online.target …`), not from `[first-boot].ordering`, so it governs operator-built + appliance images only. +- **Secure Boot** was not exercised. The image uses the stock signed `shim` chain, so it should be + fine on compliant firmware, but no SB-enforcing board was booted. +- **Only virtual hardware** was tested. Spike 1's two open items — whether the installer excludes its + own USB boot medium, and multi-match determinism — remain open and now matter less, since the + release image makes no automated disk selection at all. diff --git a/documentation/runbooks/day0-install.md b/documentation/runbooks/day0-install.md index 0d9fc4d..39b1bce 100644 --- a/documentation/runbooks/day0-install.md +++ b/documentation/runbooks/day0-install.md @@ -137,6 +137,26 @@ Notes: --- + +## C.0 Two ways in — which to use + +**The installer ISO (`https://iso.felhom.eu/`) is the normal path for a NEW machine.** Write it to a +USB stick, boot it, choose the disk and a root password in the standard Proxmox installer, and the box +sets itself up on first boot and shows a pairing code on the console. Nothing is baked into the image: +no root password, no SSH key, no customer identity, no disk selection. The image offers two entries — +graphical (default) and Terminal UI — and **both were verified end-to-end** before publication +(package installed, unit enabled, unit fired on first boot, pairing code displayed). See +`REPORT-iso-release.md` and the criteria in `iso-release-gate.md`. + +**The manual one-liner below is for a machine that ALREADY runs Proxmox** — a box someone else +installed, a re-pair after a reset, or an install where the ISO path did not complete. It is also the +recovery path: it does what the ISO's package would have done, and the hub's customer page renders it +with the customer-id already filled in (`hub/internal/web/templates/customer_unified.html:563`). + +Neither supersedes the other. The ISO is *insert, install, type a claim code*. The one-liner is +*already installed — adopt this box*. + + ## Part C — the install run (on the box, as root) ### C.1 Fetch the installer diff --git a/scripts/CHANGELOG.md b/scripts/CHANGELOG.md index 7984035..dd29086 100644 --- a/scripts/CHANGELOG.md +++ b/scripts/CHANGELOG.md @@ -1,3 +1,44 @@ +## ISO v1.26.1 — the PUBLIC installer ISO, PUBLISHED (2026-07-31) + +**Live at `https://iso.felhom.eu/felhom-installer-1.26.1-pve9.2-1.iso`** +sha256 `f3cc86d5f0ec68bba4155c994b4fa84e208d50209bb6e815636c99e5441059a6`, 1 705 322 496 bytes, +with its `.sha256` and manifest beside it. Round-trip verified: the bytes downloaded from the public +URL checksum to the same value. Bucket `Public Access` stays disabled — an unauthenticated GET to the +S3 endpoint returns 400, and the custom domain has no index (404 on `/`). + +**What it is.** Write it to a USB stick, boot it, choose your own disk and your own root password in +the standard Proxmox installer. The box sets itself up on first boot and shows a pairing code. The +image carries **no answer file, no root password, no SSH key, no customer identity and no disk +profile** — the entire Spike 1-2 problem space is deleted rather than mitigated. + +**How day-0 is delivered.** A `felhom-bootstrap` .deb in `/proxmox/packages/`, which the PVE installer +unpacks on EVERY install path including the interactive one (`Install.pm:1343-1372`, `:1378`). The +answer file's `[first-boot]` hook does NOT reach an interactive install — measured in +SPIKE-universal-iso-3 with a same-image control. + +**PROVEN ON BOTH MENU ENTRIES** before publication, four observables each: + graphical (`spikegfx.felhom.eu`) package installed, unit enabled, unit fired at first boot, + pairing code `J7N-2DA`, token 0600 + Terminal UI (`spikesix.felhom.eu`) same, pairing code `ZY5-YY4` + +**One defect was caught by that gate and fixed before publication:** the package did not ship +`/etc/felhom/`, so the first build registered at the hub and then polled `HTTP 401` forever with no +claim code ever shown. G9 proved the payload script was byte-identical to HEAD and said nothing about +the directory the payload writes into. Fixed, plus gate criterion **G13** (every directory the payload +writes into is in the package), red-proofed. + +**A second false claim was caught before publication:** the generated manifest — the file a tester +reads — described a single automated entry with a 5s timeout and listed Graphical/Terminal UI as +'menu-removed'. It now describes the image it ships. + +Menu: two INTERACTIVE entries, graphical default, **timeout 15s** (Spike 2 lost a probe to a +1-second menu). No automated entry exists at all: without `auto-installer-mode.toml` the stock +grub.cfg does not emit it. + +R-128 FIXED (the ISO/SCRIPT_VERSION 'alignment' was a comment nothing evaluated; the coupling does not +exist, so the claim was corrected rather than asserted). R-155 RESOLVED (guard narrowed to +`FELHOM_MENU=single`, not deleted). Release gate: `documentation/runbooks/iso-release-gate.md`. + ## SPIKE 4 (no code change) — a `.deb` in the ISO DOES deliver on an interactive install (2026-07-31) **No script, profile or build file was modified.** Findings: