# REPORT — SPIKE 4: can a `.deb` in the ISO deliver the stub on an interactive install? (2026-07-31)

> Written as `REPORT-universal-iso-spike.md`, not `REPORT.md`: the shared file belongs to today's hub
> v0.85.0 session and the second session in a shared clone never touches it. Supersedes this file's
> Spike 1–3 contents.

**Class: Spike.** Findings only — no production file changed, no release ISO built, nothing published.
Evidence: `documentation/audits/SPIKE-universal-iso-4-2026-07-31.md`.

## The answer is yes, and it was measured with the negative control in the same box

One ISO, 15 GRUB entries, a trivial probe `.deb` injected into `/proxmox/packages/`. Two VMs on
demo-hp built with `qm` so the run was visible in the web console: **400 interactive**, **401
automated control**.

On the **interactive** install (`spikefour.felhom.eu`):

- the package is installed — `ii felhom-spike4-probe 0.0.1`
- its **postinst ran** — marker file present, content intact
- it **enabled a systemd unit**, and **that unit fired on first boot** (uptime 7.98 s, `pid1: systemd`)
- and on **that same machine**, `proxmox-first-boot` is not installed and `/var/lib/proxmox-first-boot`
  does not exist — Spike 3's negative reproduced, not assumed

So the two delivery mechanisms are independent, and the one that survives the path we are actually
shipping is the `.deb`. **The product — insert the stick, install Proxmox normally choosing your own
disk and password, box sets itself up and waits for a claim code — is now measured rather than hoped
for.** With one honest caveat: what was measured is a trivial probe package, not Felhom's real stub.
Packaging the real stub and confirming pairing end-to-end is the last step before a spec (~60 min).

## What a postinst may and may not do

Identical on both paths: `pid1 = unconfigured.sh`, **no running systemd**, `/proc` and `/sys` mounted,
and **`systemctl enable` succeeds** (it wrote the symlink). Network and DNS *happened* to be up —
inherited from the installer's own DHCP.

Four constraints for the real postinst, so they get written against rather than discovered:

1. Never `systemctl start` or `daemon-reload` — there is no systemd running. `enable` is the only verb.
2. **Never require the network**, despite it being present here. A box installed with the cable out
   gives a postinst no route, and a failing postinst breaks the customer's install.
3. Never fail — guard everything, `exit 0`.
4. Do the real work in the unit at first boot, where systemd, network and a booted kernel exist.

## Two smaller results

**The repack preserves the `.deb`, but not naively.** `xorriso … -boot_image any replay` fails with
*"Overlapping MBR partition entries"* — and `iso-repack.sh:270-292` already documents that exact
failure and its fix. Mirroring it produced a working image (19 El Torito entries; the `.deb` extracted
back out is byte-identical). So this is an insertion into an extract→modify→re-master cycle our repack
already performs, not a new build stage.

**Q3:** `iso-repack.sh:100-106` refuses an ISO without `auto-installer-mode.toml`. It is a guard, not
a structural requirement, and its reasoning is sound for the shape it was written for — already R-155,
cited exactly here. With no mode file the stock grub.cfg does not emit the Automated entry at all; with
a mode file but no answer, that entry aborts safely and loudly.

## A correction I owe you from last session

**R-153 is retracted.** The register grep this task mandated shows R-94 already carries it verbatim at
`OPEN-ITEMS.md:15`, status `READY (XS)`, with leg (b) being precisely "the gate fails today and is
invoked by nothing" — and R-29, the class, says in terms *"do not mint a new ID for a new instance."*
Spike 3 filed a duplicate.

**And the substantive half of that Spike 3 claim was wrong.** I wrote that the drift left the customer
page's install-command generator "targeting a flag surface three minor versions stale." R-94 explicitly
retracts exactly that reading: the constant selects no script — it renders as a text label, and the
command beneath it fetches the script the website git-syncs from `main`, so **1.22.0 is what every
install already gets**. It is a wrong number on your screen and nothing more. I overstated it.

## Still unknown

**The real stub has not been packaged** — that is the one thing between here and a build spec.
Also unproven: `dpkg --configure -a` ordering for a package with dependencies; an ISO that never went
through `prepare-iso` (blocked by R-155, which this spike was fenced from changing); and the Graphical
installer, where the result should hold *a fortiori* since the `.deb` path is in `Install.pm`, shared
by all front-ends — but that is inference, not measurement.

**Spike 3's Q3** — the real stub at `before-network` — **this session did not touch it.** Note it is
now partly superseded: on the `.deb` route the unit's ordering comes from the unit file, not from
`[first-boot].ordering`.

## R-rows

**None opened.** Each candidate was grepped against the register first: the delivery result is a
positive finding, the postinst constraints belong in the build spec, and the repack guard is already
R-155. **R-153 retracted** into R-94 leg (b) / R-29.

## Teardown

All three layers plus the scratch storage, verified positively. demo-hp: VMs 400/401 purged, **storage
`spike4` removed** (`storage.cfg` back to 4, `grep -c spike4` = 0), `/mnt/nvme-1tb/images/` empty,
**disk usage 6.6 G — identical to pre-spike**, probe ISO and driver removed, 0 loop devices,
`drill-r50` stopped and untouched, 9201 running, `felhom-backup` unmodified, nothing on `local-lvm`.
DooPlex: workspace scratch **4.8 GB removed**, scratchpad **3.3 GB → 88 K**, both throwaway passwords
destroyed, 17 ISOs in `out/` untouched, no production file modified. **Hub-side: nothing created** —
the VMs took LAN DHCP leases but never ran `felhom-host-install.sh` or contacted the hub; verified by
fetching and searching the customer list. Nothing published.
