docs: GL-7 closeout — tester agreement + hub 0.36.0 CHANGELOG/REPORT/CONTEXT + GO-LIVE G7 done

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
This commit is contained in:
2026-07-09 08:44:21 +02:00
parent 02c748eb2a
commit 0efdc78d75
5 changed files with 337 additions and 58 deletions
+39 -7
View File
@@ -11,6 +11,7 @@ catalog `2ebe082a` · felhom.eu `1a1e42ad`/hub v0.35.0 · host-install v1.9.1 ·
**Updated 2026-07-08 (GL-5b shipped):** felhom-agent **v0.76.0** live + PUBLISHED (`9828c5f7…f50b`) — restore-test full-fidelity + mount parity (new G12); the manifest bump target is now 0.76.0.
**Updated 2026-07-08 (GL-8):** felhom.eu `18a556a5` · host-install **v1.12.0** — BYO coexistence: F3 (leaf guard narrowed to Felhom guests → no `--allow-new-leaf` on a populated BYO host), F6 (byo refuses a foreign `:53`, never mutates), F1 (uninstall purges config `.bak*`). F6 live-proven on felhom-pve; harness 36/36. **GL-7 unblocked** (Peti's command needs no workaround).
**Updated 2026-07-08 (GL-6 DRILL COMPLETE):** felhom.eu `87ba30ae` · host-install **v1.11.3** (F4 resume fix shipped mid-drill; v1.11.2 anon-fetch ruling). Two full destroy/rebuild cycles on felhom-pve; manifest confirmed vouching agent 0.76.0 + golden 0.103.0. G2/G4/G5/G6/G7 LIVE-VALIDATED; G1 DONE; key-pin legs 14 proven. Record: `DRILL-GL6-2026-07-08.md`.
**Updated 2026-07-09 (GL-7 SHIPPED):** felhom.eu `844fbfa7` · **hub v0.36.0** LIVE (ArgoCD synced/healthy) — operator customer page now (a) MASKS the retrieval passphrase (reveal/copy, never baked into a copyable command) and (b) carries an interactive install-command generator (vanilla JS, real v1.12.0 flags only, download-then-run, JS-off static fallback). Tester agreement written (`PETI-tester-agreement.md`). G9/G10/G11 closed to their pilot-ready state (G9/G11 = onboarding-time actions, documented). **GL-7 DONE.**
---
@@ -68,10 +69,10 @@ Status legend: ✔ DONE · ◐ PARTIAL · ○ OPEN · ⚠ BLOCKER
| **G6** | **Uninstaller gap-closure (customer offboarding).** SHIPPED in host-install v1.11.0 (GL-4, `f7cc6a72`): 4b4 self-update-artifact removal (wrapper, .prev/.new.* slots, rollback unit, limits drop-in — derived from the guarded script itself), per-drive unmounts under `/mnt/felhom-drives` (plain umount ONLY, busy = warn+guidance, root-bind guarded), the **KEPT-vs-WIPED statement** in BOTH modes (drives/PBS/hub record/escrow/vaulted recovery credential named as living on), guest-only drive note from the bind store. **LIVE-VALIDATED (GL-6): two real uninstalls** — busy-drive prop handled (warn+guidance, no `-l/-f`, statement=retry), KEPT/WIPED statement verbatim, host audit clean, **drive data intact ×3** (witness hash matched every time). Findings F1 (config `.bak` residue) + F2 (mount-unit residue) filed. | ✔ | DRILL-GL6 §Phase 1/5 |
| **G7** | **Demo-box drill****DONE 2026-07-08.** Two full destroy/rebuild cycles (byo + appliance) + two uninstalls on felhom-pve, Viktor gating every phase; F4 found+fixed+proven mid-drill (v1.11.3), C7 + armed-key chain live-validated, data intact ×3. | ✔ | DRILL-GL6-2026-07-08.md |
| **G8** | **DR bring-up bind-override fix** (agent). SHIPPED as **v0.75.0** (GL-5, `b3446213`, LIVE on felhom-pve) + **scratch-DR live-validated end-to-end** (9310 from a real 9201 archive: mp0 200G + mp1 50G restored with content, real mp8/mp9 binds, zero unusedN, clean auto-teardown; the same op failed outright on v0.74.0). **TWO live-discovered PVE rules beyond the spike:** explicit-params restore requires an explicit rootfs AND silently drops unlisted mountpoints — the full param set now derives from the archive's embedded config (`ExtractArchiveConfig`, 200 under the scoped token; bind LAYOUT stays the known constants). | ◐ | agent v0.75.0 @ `b3446213`; REPORT.md. **Remaining: the full customer-data DR drill (GL-6/S5). (The publish follow-up landed as 0.76.0 — GL-5b/G12.)** |
| **G9** | **Auth-on onboarding.** Auth + CSRF proven in campaign 2; remaining work is procedural: GL-6 confirmed the dashboard password is **operator-set via the hub config** (anti-F9 pipeline), NOT a customer-dashboard field — until set the public dashboard is OPEN (**G10 exposure**). Rehearsed the location; **password-set + geo-restriction deferred to GL-7 with Peti** (a GL-7 prerequisite). | | DRILL-GL6 §Phase 2b |
| **G10** | **Local-API posture documented + spot-verified.** Token→vmid binding is structural (server.go:23, :5355, :153 — verified this session); write it into the security notes, including the vmbr0-reachable surface and its TLS+token defense. One CC spot-check: a token minted for guest A is refused for a guest-B-scoped op (test exists? verify; add if hollow). | | localapi/server.go as cited |
| **G9** | **Auth-on onboarding.** Auth + CSRF proven in campaign 2; the dashboard password is **operator-set via the hub config** (anti-F9 pipeline), NOT a customer-dashboard field — until set the public dashboard is OPEN (**G10 exposure**). **DONE for GL-7:** the password-set + geo-restriction are now an explicit onboarding step in the tester agreement (§7 step 3), gated as "onboarding not complete until set". The action itself is performed with Peti at his day-0. | | PETI-tester-agreement.md §7 |
| **G10** | **Local-API posture documented + spot-verified.** Token→vmid binding is structural (server.go:23, :5355, :153). **DONE:** written into the tester agreement (§2 table + §3 — vmbr0:8443 LAN surface, TLS + per-guest bearer token, cross-guest refusal). | | PETI-tester-agreement.md §2/§3 |
| **G12** | **Restore-test full-fidelity verification** (GL-5b, agent **v0.76.0**). The restore-test had GL-5 finding #2's mirror image: its live-source-config override path tripped PVE's drop-unlisted-mountpoints rule, so it boot-verified scratch guests WITHOUT their storage mpN. Now: params derive from the ARCHIVE's embedded config (`drRestoreOverrides`, same as DR) + a **mount-parity assert** (restored mpN set vs the archive's; missing/mispathed/undersized/extra = FAIL naming the delta) so the rule can never regress into a green light. `MountParity`+`MountInventory` ride the hub wire record (additive). Honest cost, measured: **3m4s** on the local tier (the extraction adds ~2min over data-less; cheaper than the DR-derived ~7m estimate; PBS tier will run longer). Live-proven on felhom-pve: parity ok, inventory mp0 200G + mp1 50G + 2 throwaways; a rotated-out archive volid refuses up front. | ◐ | agent v0.76.0 (published `9828c5f7…f50b`); agent REPORT.md. Remaining: parity-on-real-drift (GL-6 family) + PBS-tier runtime |
| **G11** | **Pilot backup statement.** Assert local backups green on Peti's box at onboarding; the tester agreement states plainly: *no offsite copy yet a dead/stolen box or dead drive without a second local target loses data*. Honesty is the sovereignty pitch. | ○ | D3; agent CONTEXT.md v0.66/0.67 (retarget reverted; Tier-1/2 split pending) |
| **G11** | **Pilot backup statement.** **DONE:** the tester agreement states it plainly (§4 — *no offsite copy yet; a dead/stolen box or dead drive without a second local target loses data*; §7 step 5 asserts local backups green at onboarding). **⚠ carries the one open pilot question:** Peti's local backup TARGET (does his box have a second disk/pool?) — resolved into `--acl-storages` at onboarding (agreement §6). | ✔ | PETI-tester-agreement.md §4/§6/§7 |
**Non-gating / fast-follow (tracked, not blocking):** Impl-3 shared-box operator format gate
(existing wipe-binding + mkfs-guarded gates cover the dangerous core); `deviceRole`/`roleForMountPath`
@@ -91,7 +92,7 @@ BUNDLE cert/key/token migration item; hub-floor auto-update.
| **GL-5** DR bind-override | ✔ **DONE 2026-07-08** (agent v0.75.0, `b3446213`, live-validated) | felhom-agent | G8 | — |
| **GL-6** Demo-box drill | ✔ **DONE 2026-07-08** (`DRILL-GL6-2026-07-08.md`; F4 fix v1.11.3 mid-drill) | felhom.eu/scripts (v1.11.3) | G7 | GL-1, GL-2, GL-4 |
| **GL-8** BYO coexistence hardening | ✔ **DONE 2026-07-08** (v1.12.0, `18a556a5`; F3/F6/F1) | felhom.eu/scripts | F3/F6/F1 | GL-6 |
| **GL-7** Peti day-0 runbook + onboarding | **NEXT** (GL-6 green) | felhom.eu/documentation/pilot | G9, G10, G11 + findings F1/F2/F3/F6/F7 | GL-6 green |
| **GL-7** Peti day-0 runbook + onboarding | **DONE 2026-07-09** (hub v0.36.0 `844fbfa7`; `PETI-tester-agreement.md`) | felhom.eu (hub + pilot docs) | G9, G10, G11 + findings F1/F2/F3/F6/F7 | GL-6 green |
Recommended order: **GL-1 and GL-3 immediately** (operator-heavy, unblock everything), GL-2 next
(the biggest CC task), GL-5 in parallel (independent repo), then GL-4 → GL-6 → GL-7.
@@ -171,6 +172,33 @@ Recommended order: **GL-1 and GL-3 immediately** (operator-heavy, unblock everyt
GL-6 scenario). Harness 36/36 + red-proofs RP-F3/F6/F1; GL-2/GL-4 regression green. F2/F7 remain
open (non-blocking). **GL-7 unblocked.**
- 2026-07-09 — **GL-7 SHIPPED** (hub **v0.36.0**, felhom.eu `844fbfa7`; deploy `02c748eb`). Two
coupled changes to the operator customer page, security-first: **(1) passphrase hardening** — the
per-customer retrieval passphrase was rendered in cleartext twice (the visible `#retrieval-pw` node
and baked into the Option-3 debug curl `X-Retrieval-Password:` header). Now masked by default
(bullet run) with reveal + copy controls (value in `data-secret`, the existing model), and the
Option-3 command carries a `<YOUR-RETRIEVAL-PASSWORD>` placeholder instead of the secret. A
zero-secret-in-DOM reveal-on-demand fetch is a noted follow-up, deliberately NOT scoped here.
**(2) interactive install-command generator** — the three hard-coded `<code>` blocks became a
client-side builder (vanilla JS, no framework/CDN/network) that assembles a live install command
from form controls, emitting ONLY real host-install **v1.12.0** flags, download-then-run shape,
with a graceful JS-off static fallback and a CustomerID prefilled from the server. The control
surface is a curated subset (mode/cores/memory/vmid/node/acl/pubkey/preserve + skip/dry-run/
preflight/allow-new-leaf); the seven dangerous/operator-only flags (`--force`, `--rotate-recovery`,
`--enable-oob`, `--remove-golden`, `--uninstall`, `--adopt-pool`, `--rescope-acl`) are NEVER offered
as controls. Render tests `TestTemplates_PassphraseHardened` + `TestTemplates_InstallGenerator`
cover both (green gate passed on the committed source); the passphrase test red-proofs by reverting
the Option-3 block to the raw secret. Deployed via ArgoCD (Synced/Healthy, rollout confirmed, live
image `felhom-hub:0.36.0`, `Listening on :8080`). **Tester agreement written**
(`PETI-tester-agreement.md`): BYO trust boundary (break-glass/OOB/WG all off, non-root agent,
pool-scoped token), honest limitations (no offsite backup, physically-removable-drive caveat F2,
pool-reassert-bring-up-only F7, `:53`-must-be-free F6), exit rights (uninstall keeps data), Peti's
box facts (80c/128 GB → caps 12/32768, `sajatfelhom.hu` tunnel re-point), the byo install command,
and the onboarding sequence (preflight → install → G9 password-set → tunnel → backup-green). G9/G10
closed; G11 closed with the one open pilot question folded into the agreement's pre-install
checklist. Note: the hub UI is operator-password-gated (CC cannot log in) — verification is the
render tests + the deploy checks, per the repo's stated policy.
## 6. Open questions & operator actions
**Operator actions (Viktor):**
@@ -194,6 +222,10 @@ Recommended order: **GL-1 and GL-3 immediately** (operator-heavy, unblock everyt
tasks — paste it to CC with the next task so wrap-ups stop falling back to CONTEXT.md).
**Open questions:**
- G5: CPU/RAM cap values for Peti's guest (needed by GL-6/GL-7, not before).
- G11/GL-7: what is the local backup TARGET on Peti's box, given `felhom-pbs` is unreachable from
his LAN — second local drive via per-app cross-drive backup, or a local PBS/vzdump storage?
- G5: CPU/RAM cap values for Peti's guest **RESOLVED: 12 cores / 32768 MiB** (his 80c/128 GB box).
- G11/GL-7: the local backup TARGET on Peti's box, given `felhom-pbs` is unreachable from his LAN.
**Still open, but now owned by the tester agreement** (`PETI-tester-agreement.md` §6): the ONE
thing to confirm with Peti before finalising his install command is **whether his server has a
second disk/pool** — if yes it becomes the `--acl-storages` backup target (real local resilience);
if no, backups share the guest's pool (degraded — one drive failure loses both, must be stated to
him). Resolve at onboarding; it changes only the `--acl-storages` value, nothing structural.