scripts v1.18.0 — R-21 slice B: firmware loader option --loader shim|mkimage (F1)

Closes N100 F1 (HIGH): cheap AMI (AN3PLUS 0.01-class) UEFI firmware can't
relocate the ISO's stock signed GRUB from USB (relocation 0x0). The run's live
grub-mkimage workaround is now a first-class pipeline mode.

- build-felhom-iso.sh: --loader shim|mkimage (default shim, byte-for-byte
  unchanged; profile-settable FELHOM_LOADER; --loader wins). Loud banner +
  manifest loader:/grub-mkimage: fields + -mkimage filename suffix.
- mkimage-surgery.sh (new): post-prepare-iso, in the assistant container. Builds
  a monolithic grub-mkimage loader from the ISO's own GRUB (module set from its
  grub.cfg; embedded search --fs-uuid -> configfile the real menu). Swaps it into
  the ISO9660 tree (real lowercase path) + the efi.img ESP; xorriso re-master
  preserves BIOS-hybrid + UEFI + GPT-ESP, drops only Apple HFS+/APM. Recipe from
  the N100 run evidence, not re-derived.
- Dockerfile.assistant: grub-common + grub-efi-amd64-bin + mtools + dosfstools.
  profiles/n100.profile (new, mkimage + SB-off note).
- Validated on nested VM 311 (RUNBOOK-B legs): leg1 shim boots+installs under
  OVMF SB-enforcing + SeaBIOS; leg2 mkimage boots+installs under SB-off; leg3
  (red-proof) mkimage under SB-enforcing FAILS Access Denied (unsigned -> SB must
  be OFF); leg4 surgery byte-identical payload. bash -n + shellcheck clean.
  Physical N100 closure folds into the rehearsal (n100-safety match-nothing ISO
  built + sha-recorded, unbooted). PXE stays a deferred R-21 note.
This commit is contained in:
2026-07-17 14:28:10 +02:00
parent d86d2699c3
commit 3172df1927
11 changed files with 439 additions and 58 deletions
@@ -31,6 +31,7 @@
|---|---|---|---|---|
| Appliance day-0 install: golden image → first boot → auto-confirm (zero clicks) → claimable box | installer, agent, hub, golden | **PROVEN-LIVE** (nested VM) | `DRILL-day0-vm-2026-07-12`, `DRILL-day0-take2-2026-07-12` | First firing on real customer hardware pending → R-1 |
| BYO install: `--mode byo`, mandatory caps, host-mutation disclosure, coexistence guards | installer v1.15+, agent | **PARTIAL** | `DRILL-GL6-2026-07-08` (demo box); GL-8 coexistence fixes | Peti clean-slate reinstall on proxmox2 is the first real BYO run of the current path → R-1 |
| Bare-metal Felhom ISO (blank hardware → zero-touch auto-install → first-boot `host-install`), + selectable UEFI loader | scripts v1.18.0 (`scripts/iso/`) + assistant container | **PARTIAL** (nested VM 310/311) | slice A `SPIKE-baremetal-iso-2026-07-16` (build gate, disk-filter fail-safe, stub→public-channel host-install fetch); slice B RUNBOOK-B legs (2026-07-17): shim boots + installs under OVMF **SB-enforcing** + SeaBIOS; **`--loader mkimage` boots + installs under OVMF SB-off**; mkimage under SB-enforcing **FAILS** (`Access Denied`); surgery byte-identical payload | **F1 loader caveat:** `--loader mkimage` fixes cheap AMI (`AN3PLUS`-class) firmware that can't USB-boot the stock GRUB — but the loader is **UNSIGNED → the target board's Secure Boot must be OFF**; default `shim` keeps Secure Boot working on compliant firmware. Physical boot on the real N100 board still pending → supervised rehearsal (R-1). ISO is secret-bearing (slice C de-secures) → R-21 |
| Customer claim: one-time emailed code → customer sets own password (bcrypt, operator never sees it) | controller v0.122, hub v0.50 | **PROVEN-LIVE** (drill VM) | `DRILL-day0-vm-2026-07-12` §10/F-4 (gate ON via real edge; claimed, code consumed) | Never executed by a non-Viktor human → R-3. (Dropped mis-cited `CAMPAIGN-4` F-C — that is the escrow-claim 502, not password claim) |
| Escrow ceremony: customer-facing wizard, one-shot R claim, operator zero-knowledge | controller v0.127, agent v0.88/0.89 | **PROVEN-LIVE** (drill VM, endpoint-exact) | agent v0.88.0 REPORT (ceremony ~4s, one-shot claim 200→410, R absent from every payload); `SPIKE-controller-escrow-2026-07-13` | Endpoints driven on the drill VM; customer-facing **browser wizard** leg not yet live-validated. First supervised ceremony with a real customer pending → R-1. **agent v0.89.0:** `/escrow/preflight` `pbs_storage_id` row now live-reloads (reads current agent.json) — a pbsdr convergence that seeds the id flips it green with NO service restart. **hub v0.60.0 (data-first retention):** a re-escrow with a DIFFERENT sealed passphrase no longer destroys the old blob — the hub RETAINS it (`host_escrow_superseded`), so a previous passphrase stays recoverable with its recovery code (turns the reinstall-orphan incident from "history destroyed" into "history recoverable"). Guided-recovery flow = R-26. Red-proof `TestSaveHostEscrow_RetainsSuperseded`. **hub v0.60.1 — custody survives the host lifecycle:** host deletion (with the escrow ack) DEMOTES the current blob to retained custody (moved into `host_escrow_superseded`, never destroyed; existing superseded rows spared); the customer Danger-zone Delete is the one true purge point (cascades both escrow tables incl. already-deleted hosts). No operator path through host lifecycle can lose a blob. Red-proofs `TestDeleteHost_DemotesEscrowNeverDestroys` + `TestDeleteCustomer_PurgesEscrowCustody` |
| DR tier by default: PBS + WireGuard base infra on every install, hub-controlled activation | installer v1.15, agent v0.86, hub v0.51 | **IMPLEMENTED** | `DRILL-day0-take2-2026-07-12` §2 (WG enabled both modes, PBS-DR descriptor auto-provisioned ~1s after WG registration, zero operator steps); ships installer v1.15/agent v0.86/hub v0.51 | Live only on demo/drill fleet. (Cited spike was slice-0 mechanics — shipped nothing; corrected. Candidate upgrade to PROVEN-LIVE — see REPORT.) **agent v0.89.0 closes the F4 non-default-storage-id gap (R-22) — PROVEN-LIVE 2026-07-17:** the reconcile self-grants the ACL through the root wrapper on a pre-check 403 instead of dead-locking. Reproduced F4 on the demo (marker moved aside = reinstall fresh-state + felhom-offsite ACLs revoked) → next reconcile tick `pbsdr: pre-check 403 … self-granting … (R-22)``converged state=adopted` in ~3 s, ACLs self-restored, `pvesm status felhom-offsite`=active, zero operator action. No more one-shot `pveum` grant |