Files
felhom-agent/REPORT.md
T
admin 4bb84fc3ca
gates / gates (push) Successful in 12s
REPORT: v0.120.0 + golden 3.0.0 — built and proven at the bake, NOT proven on a box
States the scope reduction first: Phases 6-7 (reinstall both demo boxes and
prove one end to end) were NOT done, nothing was wiped, and the golden is
deliberately left unvouched as a result. Filed as R-178.

Also records the two instrument errors this session: a census truncated by
head -10 that gave the wrong answer about --sysdata-grow (the installer does
pass it), and a wait gated on a marker the bake prints before publishing.
2026-08-03 07:15:29 +02:00

190 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# REPORT — v0.120.0 + golden 3.0.0: one data volume (R-165 · D-a · V-c), 2026-08-03
**Overwritten** per the standing rule. The prior contents (R-168, CI) have their durable record in
`CHANGELOG.md`.
**Outcome: the merge is BUILT, PROVEN AT THE BAKE, and NOT YET PROVEN ON A BOX.** Everything through
Phase 5 is shipped and green. **Phases 67 — reinstalling the two demo boxes from the merged golden
and proving one end to end — were NOT done**, and the golden is deliberately left **unvouched** as a
result. That is a scope reduction against what was approved at the STOP and it is stated here first
rather than at the end. Remaining work: **R-178**.
---
## 1. Baselines — all three matched §1, re-read on arrival
| Repo | §1 | found | match |
|---|---|---|---|
| `felhom-agent` | `587dbb43fe97`, v0.119.0, script 2.1.0 | same | **yes** |
| `felhom-controller` | `d5be67b91363`, v0.191.2 | same | **yes** |
| `felhom.eu` | `1806dfa8e9f6`, hub v0.89.0 | same | **yes** |
Highest register ID **R-177**; `R-178` grepped free before minting.
## 2. Phase 0 — the two probes (full detail: `felhom.eu/documentation/audits/SPIKE-r165-phase0-2026-08-03.md`)
**P1 — PASS.** A real pre-merge archive (`mp0+mp1`, confirmed from its own vzdump log, not assumed)
restore-tested on demo-hp: `pass: true`, `mount_parity: "ok"`, 84 s, inventory listing `mp0=50G` and
`mp1=20G`. **`mountParity` was not relaxed.** Limit stated: it ran with the pre-merge agent because the
merged one did not exist yet; the comparison is archive-vs-its-own-restore and never consults the host
layout, so it carries — and it is one command to re-run against v0.120.0.
**P2 — all three variants mechanically clean; the deciding fact was not in the task's table.** Each
built as a throwaway LXC with the golden's own `daemon.json`, then measured at first boot and after
**each of three reboots**.
| | V-a | V-b | **V-c (chosen)** |
|---|---|---|---|
| dockerd + `docker run`, reboots | 3/3 | 3/3 | **3/3** |
| ONE filesystem, ONE free figure | yes | yes | **yes** |
| container `statfs("/")` = merged volume | yes | yes | **yes** |
| container's view of `/mnt` | 8.0K | **17.9M — all of Docker** | **8.0K** |
| customer data inside Docker's data-root | **YES** | no | **no** |
**The ordering risk that motivated the probe did not materialise** — an `/etc/fstab` bind is ordered
under `local-fs.target`, before `docker.service`. What separates them is which documented guarantee
they break. **V-c was probed because both named variants broke one**, and it is offered/chosen as the
shape that breaks neither. **The operator ruled V-c at the STOP.**
**P3 — 8 checks, 8 passed.** Every retargeted golden assertion was run against a **deliberately wrong
shape** (a real split-layout guest and a real archive of it) and shown to reject it, and against a
right shape and shown to accept it. Guest and archive torn down.
## 3. Files changed and commits
| Repo | Commit | Subject |
|---|---|---|
| `felhom-controller` | `4be6467` | v0.192.0 — the capture floor replaces the bulkhead (B2) |
| `felhom-agent` | `cd6e267` | v0.120.0 — one data volume (V-c), golden 3.0.0 |
| `felhom.eu` | `7406ac7` | audits: R-165 Phase 0 |
| `felhom.eu` | `e3525e6` | host-install: one data volume, derived from the disk |
Agent files: `configs/build-golden.sh` (2.1.0 → **3.0.0**), `internal/reconcile/bringup.go`,
`internal/reconcile/bringup_test.go`, `cmd/felhom-agent/main.go`, `CHANGELOG.md`.
## 4. The variant, and the golden bake as evidence
```
[golden] build-golden.sh v3.0.0 — baking controller …felhom-controller:0.192.0
[golden] wiring the single data volume (R-165 variant V-c): /var/lib/felhom/{docker,sys_drive} -> binds
docker OK (overlay2; data-root /var/lib/docker)
/var/lib/docker is a real mount: /dev/mapper/pve-vm--9100--disk--1[/docker] ext4
/mnt/sys_drive is a real mount: /dev/mapper/pve-vm--9100--disk--1[/sys_drive] ext4
both paths are ONE filesystem: /dev/mapper/pve-vm--9100--disk--1 23317576
INFO: including mount point rootfs ('/') in backup
INFO: including mount point mp0 ('/var/lib/felhom') in backup <-- and NO mp1 line at all
INFO: archive file size: 619MB
```
Published: registry **HTTP 200**, `felhom-golden/0.192.0`, sha `54e2a4c431daf580d2807b82d810be36…`.
Build guest 9100 destroyed; scratch scripts and credential file removed from the host.
**Baked on `felhom-pve`, not DooPlex.** The historical bake fixture is DooPlex's nested drill VM, and
this task forbids DooPlex outright — so it ran on a Tier-0 demo host, which the task names as the
target. demo-hp was avoided for the probes and bake because `target-selection.md` records its
`local-lvm` as an over-subscribed thin pool backing a live guest, and it carries no template.
## 5. Provisioning — and a census that changed the answer
**`--sysdata-grow` is FOLDED IN, not removed.** The task's rule was to remove it unless something
outside the repo passes it. **My first census said nothing did — and it was wrong, because I truncated
it with `head -10` and the output was exactly 10 lines.** That is §9.11's own trap
("an instrument that can silently drop results is not a measurement") and this project's own recorded
lesson. Re-run without truncation: **`felhom.eu/scripts/felhom-host-install.sh:2621` passes it.**
So: the flags stay accepted (removing them would fail every install on an unknown flag), and their GiB
are **added** to the single volume's grow rather than dropped — dropping them would silently shrink
every appliance an older installer builds by 42 of 250 GiB. The existing test was **retargeted** to pin
the fold, and it caught the behaviour change before I did.
**§8.2 — the single volume's size IS derived from the physical disk, and already was.** The same
census found `felhom-host-install.sh:1776 step_grows` reading the thin pool's real free space; the
merge only collapsed its 80/20 split into one total (`226` = the previous `184+42`), so **a standard
appliance keeps exactly its 250 G**. An unflagged install does **not** get the golden's 24 G. No row
needed to be filed for this.
## 6. The floor's constants, and the proof it sits below the warning band
**97% used or 1 GiB free**, whichever binds first — `fillwatch`'s two-term shape, which proved live on
2026-08-02 when the critical alert fired on the free-byte term at 91% used. **Deliberately beyond
fillwatch's critical band (95% / 2 GiB)**, so the chain is warn (85/5) → critical (95/2) → refuse
(97/1) and the customer is always warned before a refusal. `TestFloorSitsBelowTheCriticalWarningBand`
pins the ordering on **both** terms; a red-proof setting the floor equal to the critical band fails it.
1 GiB is a **reserve, not a working budget**: §7.5 measures a DB-backed unit at up to ~2× its data, so
no fixed number guarantees a capture fits. What it guarantees is the bulkhead's actual job — that a
capture cannot consume the last of the space the container runtime needs.
## 7. Tests and red-proofs
Controller **1184 → 1191**; agent suite green; all gates green in all three repos.
| # | mutated | result |
|---|---|---|
| C | the **whole** floor block removed | 3 tests FAIL |
| D | headroom predicate → per-unit cap (`UsedGB > 20`) | 2 tests FAIL |
| E | floor set **equal** to fillwatch's critical band | 1 test FAILS |
| P3 | 4 retargeted shell assertions vs a wrong shape | **8/8 rejected/accepted correctly** |
**One fixture was hollow and was strengthened mid-red-proof.** `TestFloor_TheOld20GCeilingIsGone` sat
at exactly 20 GB, so it **survived** a literal `UsedGB > 20` cap — it passed the very shape it forbids.
Raised to 120 GB; the mutation now fails it. Reported rather than quietly fixed, per §9.10's rule that
a mutation must remove every guard a test covers.
## 8. Deployed versions
| what | where | version |
|---|---|---|
| controller | guest 9201 (felhom-pve) | **0.192.0**, healthy |
| agent | felhom-pve | **0.120.0**, `active` |
| agent | demo-hp | **0.120.0**, `active` |
| golden script | repo | **3.0.0** |
| golden archive | registry | **0.192.0**, HTTP 200 — **UNVOUCHED on purpose** |
Prior agent binaries backed up in place as `/root/felhom-agent.pre-0.120.0.bak` on both hosts.
## 9. WHAT WAS NOT DONE — Part 4, and why
**Neither demo box was reinstalled, and nothing was wiped.** I stopped before the destructive phase
because the remaining session budget could not confidently cover a wipe **plus** its end-to-end proof
**plus** the second box, and a half-reinstalled box is worse than an untouched one. Both demo boxes are
running normally on the split layout.
**Consequently the golden is deliberately UNVOUCHED.** Vouching is what makes a fresh install pick a
golden up; vouching one no box has been proven from would put an unproven disk layout in front of the
next install anywhere. **Prove first, then vouch** (`CONTEXT.md` S-14). The golden being published but
unvouched is a safe, reversible state — nothing consumes it.
**Nothing in the field is affected.** No box has the merged layout, nothing assumes it at runtime
(§8.5), and agent v0.120.0 folds the retired grow so an older installer still produces the same
capacity. **The work is filed as R-178** with the ordering (demo-hp first, proven, then demo-felhom).
## 10. Teardown — all three layers
| layer | evidence |
|---|---|
| **machine** | probe guests 9401/9402/9403 destroyed; P3 guest 9410 destroyed; golden build guest 9100 destroyed; P1's scratch 990000 torn down by the restore-test itself. `pct list` on both hosts shows only their own `9201` |
| **host** | felhom-pve `local-lvm` 112398205 → 107204406 KiB (**5.19 GB returned**) after the probes; P3's archive freed with `pvesm free`; `/root/{build-golden.sh,.regcred.env,p2-probe.sh,p3-assertions.sh}` and `/tmp/p*.log` removed |
| **hub** | **none created, verified not assumed** — no probe ran a controller or claimed a box. Registers hold the same 5 customers and 4 hosts as before. The reinstalls that would have produced NEW host records did not happen, so no old records needed disposing |
## 11. Register rows
**Opened:** R-178. **Closed:** R-163 (the ceiling it records no longer exists), R-175 (§7.5 fixed in
the same pass). **Updated:** R-165 → SHIPPED-not-yet-proven-live; R-176 → (a) answered by P1, (b)
**withdrawn** because every node is reinstalled rather than migrated.
## 12. CI and `--no-verify`
**`--no-verify` NOT used** — every push ran `.githooks/pre-push` and passed. CI run ids are recorded
in `felhom.eu/REPORT.md`.
## 13. Observations — noticed, NOT acted on
- **I gated a wait on `DONE. golden archive volid`, which the bake prints BEFORE publishing**, and
briefly reported the publish as failed. It had not failed; a 649 MB upload was still running. No harm
(the archive is on disk and the guest destroy did not touch it), but it is the same class as the
truncated census: **a marker that is not a completion marker.** Worth a `[golden] publish OK` line at
the true end of the script — not added here, out of scope.
- The `felhom-golden` package listing endpoint returns a shape my query did not expect; the direct
artifact URL is the reliable check.