13af252907
R-38 flips to SHIPPED with the live-canary evidence. Two new items registered from tonight's work: R-45 (unified async-job feedback — five one-off progress surfaces now exist and agree on nothing; the two lessons any framework must encode are "probe the terminal state, never infer it" and "a source reporting nothing is normal, not broken") and R-46 (verification copies are now visible but still cannot be browsed and never expire — the invisible-result gap and the disk-lifecycle gap, designed together because they are the same object). Pre-invite checklist gains the golden note: build-golden v2.1.0 makes goldens >= 0.147.x carry all four infra images; no rebuild for this alone. REPORT-<topic>.md per the parallel-session rule — another session is writing in this clone tonight, so the shared REPORT.md is left alone. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nn3VgQk9iwEGgyx6QJ2NvE
120 lines
7.4 KiB
Markdown
120 lines
7.4 KiB
Markdown
# REPORT — ISO boot branding + single-entry GRUB menu (R-38) · website grid restored (2026-07-19)
|
||
|
||
> `REPORT-<topic>.md` per this repo's parallel-session rule: another session was writing in this
|
||
> clone tonight (CAMPAIGN 7 / `DIAG-immich-restore-2026-07-19.md`), so the shared `REPORT.md` is left
|
||
> untouched.
|
||
|
||
Parts 1 and 2 of the polish train. Parts 3 and 4 landed in `felhom-agent` and `felhom-controller`;
|
||
see their own `REPORT.md`.
|
||
|
||
---
|
||
|
||
## Part 1 — scripts v1.22.0: GRUB branding + single-entry safety (R-38)
|
||
|
||
### What shipped
|
||
|
||
Every ISO is now **repacked** after `prepare-iso`. `mkimage-surgery.sh` → **`iso-repack.sh`**:
|
||
branding and the slice-B loader swap need the same extract → modify → re-master cycle, so they share
|
||
one pass instead of re-mastering twice. **The mkimage recipe is untouched.**
|
||
|
||
**The safety half — the one that matters.** The stock PVE menu offers *Graphical*, *Terminal UI*, a
|
||
serial variant, and an **Advanced Options** submenu holding two `nomodeset` entries, three debug
|
||
entries, *Rescue Boot*, memtest and *UEFI Firmware Settings*. Every one of those reaches the
|
||
**manual** installer, whose first question is which disk to wipe. They are **not emitted** — not
|
||
hidden, not password-gated. What ships is one entry, „Felhom telepítés", default, 5 s.
|
||
|
||
**Boot behavior is unchanged.** The `linux`/`initrd` lines are lifted **verbatim at repack time**
|
||
from the ISO's own *Install Proxmox VE (Automated)* entry rather than frozen into a copy in this
|
||
repo, so a PVE bump that moves the kernel path or edits the append line tracks automatically. The
|
||
build **fails** if they cannot be found, if the append line has lost `proxmox-start-auto-installer`,
|
||
or if `auto-installer-mode.toml` is absent — that last one because without it the single
|
||
Felhom-labelled entry would boot a *manual* installer, i.e. exactly what this change prevents.
|
||
|
||
**Gates, then a re-check against the shipped artifact.** The rendered menu is asserted to have
|
||
exactly 1 `menuentry`, 0 `submenu`s and no *live* reference to
|
||
`proxtui`/`proxdebug`/`nomodeset`/`Rescue Boot`/`memtest`/`fwsetup` (comments are stripped first —
|
||
the template's header names the dropped entries deliberately). Then the menu and theme background
|
||
are read back **out of `final.iso`**, not out of the extract tree.
|
||
|
||
**The boot card.** `grub/generate-grub-background.sh` letterboxes `website/assets/og-image_2.png`
|
||
onto a 1024×768 gfxterm canvas at repack time (ImageMagick added to the assistant image), so the boot
|
||
screen has **one source** and not a second pre-rendered PNG to drift. The card's own subtle grid
|
||
(measured: 4px lines of `#0D131A` on `#0D1117`, pitch 131px) is continued across the letterbox fill
|
||
**phase-locked** to where the card's grid lands, so the fill is seamless instead of a 500px square of
|
||
grid floating in flat navy. The generator refuses a source whose geometry no longer matches the
|
||
measured constants — a swapped asset would misplace every line, and that only shows up on a boot
|
||
screen nobody re-checks. Menu positioning needs a gfxmenu theme (plain `background_image` cannot move
|
||
the menu off the wordmark), so `grub/felhom-theme.txt` puts it in the lower third the layout leaves
|
||
empty, optically centered (measured off a canary screenshot; the comment records the measurement).
|
||
|
||
### Live validation — nested canary, UEFI/OVMF, PVE 9.2-1
|
||
|
||
Booted the built canary ISO under QEMU with OVMF and captured the framebuffer.
|
||
|
||
| Check | Result |
|
||
|---|---|
|
||
| GRUB renders the Felhom card | **PASS** — background + grid visible at 1024×768 |
|
||
| Exactly one entry, selected | **PASS** — „Felhom telepítés" only |
|
||
| Hungarian accents under gfxterm | **PASS** — „telepítés", „Indítás … másodperc múlva" render correctly |
|
||
| Countdown visible and counting | **PASS** — 5 → 0 |
|
||
| Auto-fires at 0 | **PASS** — serial shows ``Booting `Felhom telepítés'`` |
|
||
| Unattended install proceeds | **PASS** — „Fetching answers for automatic installation" → auto installer |
|
||
| Same abort as v1.21.0 | **PASS** — `ERROR: Installation failed: filter did not match any device` → `Installation aborted`; no disk touched |
|
||
|
||
A first build **correctly failed closed**: the banned-entry gate matched the template's own
|
||
explanatory header. Fixed to strip comments before matching (a comment naming a removed entry is the
|
||
point; a directive using one is the bug), which is a gate behaving as designed.
|
||
|
||
### Artifacts (rebuilt on 180, `/mnt/5_hdd/felhom.eu/felhom-iso/out/`)
|
||
|
||
| ISO | sha256 | bytes |
|
||
|---|---|---|
|
||
| `felhom-pve-9.2-1-v1.22.0-n100-generic-mkimage.iso` (safety) | `ff6f06ba1dbfe10f27d703afc29516001000349147426b43c9a424a0ea28bdbf` | 1 704 482 816 |
|
||
| `felhom-pve-9.2-1-v1.22.0-n100-demo-generic-mkimage.iso` (real) | `494db0ddf859b6b152cad4d0e0d9e9cefd27255cde07e2b41aba3ac12a217888` | 1 704 482 816 |
|
||
| `felhom-pve-9.2-1-v1.22.0-nested-canary-generic.iso` (validation) | `83c61c0413c84e27b26a37bb5dfaed2fcd44fd25e3e571c7310142bd305f2f9d` | 1 705 338 880 |
|
||
|
||
Both shipping ISOs: `embedding 60 modules`, `El Torito boot images=2`, fs-uuid preserved, and the
|
||
post-re-master verification confirming 1 entry + theme background inside the finished image.
|
||
|
||
**Deliberately not done** (per the task): no squashfs/initrd rebranding — post-GRUB screens are still
|
||
Proxmox-branded; no disk-setup or answer-generation change; the pairing banner is untouched.
|
||
|
||
---
|
||
|
||
## Part 2 — website: the index grid background, restored
|
||
|
||
**Archaeology.** Not a deliberate removal. The grid lived as a fixed `body::before` in
|
||
`index.html`'s inline `<style>` block and was dropped in **`bed8675`** ("D3 Part 2: index + kapcsolat
|
||
on design system v2"), the commit that migrated the page onto the shared `assets/site.css`.
|
||
`dd54e4c`, which *created* `site.css`, has no `body::before` at all — it was a porting omission and
|
||
nothing took its place. `ccbb13a` (the other five pages) never had it. No asset was lost: the
|
||
mechanism was pure CSS (two stacked `linear-gradient`s), which is why nothing looked missing in the
|
||
worktree.
|
||
|
||
**Restoration, not redesign.** Same 50px cells, same 1px lines, same 3% opacity, same
|
||
`position:fixed` / `z-index:-1`. One deliberate difference: the accent is the v2 `--blue` `#0083D8`
|
||
instead of the retired legacy `#0088cc`, which `site_gates.py` bans. Scoped to `body.page-index`,
|
||
because index is the only page that ever had it. `site.css` cache-bust bumped `?v=1` → `?v=2` across
|
||
all seven pages (nginx caches 7 days); BOM preserved on every file.
|
||
|
||
**Live verification** (felhom.eu, after git-sync deploy):
|
||
|
||
- Desktop: grid renders behind the hero, at its original subtlety.
|
||
- **376px viewport** (via a same-origin iframe — the browser window would not resize in this
|
||
environment, so the narrow case was exercised for real rather than asserted): grid renders, mobile
|
||
layout unchanged, `scrollWidth === clientWidth` so **no horizontal overflow**.
|
||
- Computed style confirmed live: `linear-gradient(rgba(0,131,216,0.03) 1px, …)`, `50px 50px`,
|
||
`position: fixed`, `z-index: -1`, `pointer-events: none`.
|
||
- `python scripts/site_gates.py` — **OK** (BOM, no legacy tokens, no `<style>` blocks, cache-busted).
|
||
|
||
---
|
||
|
||
## Docs
|
||
|
||
- `scripts/CHANGELOG.md` — v1.22.0 entry.
|
||
- `website/CHANGELOG.md` — grid restoration entry.
|
||
- `documentation/backlog/ROADMAP.md` — **R-38 flipped to SHIPPED**; **R-45** (unified async-job
|
||
feedback) and **R-46** (verification-copy browse + expiry) added; pre-invite checklist gained the
|
||
"golden ≥ 0.147.x carries all four infra images" line.
|
||
- Capability map: **untouched** — no capability moved. These are UX and packaging.
|