Files
felhom.eu/documentation/pilot/GO-LIVE-PACKAGE.md
T

236 lines
27 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.
# GO-LIVE PACKAGE — first external tester (Peti)
> Tracking doc for the pilot go-live: gating items, statuses, decisions, task sequence.
> Lives at `felhom.eu/documentation/pilot/GO-LIVE-PACKAGE.md`. Update per task completion.
> Created 2026-07-07 (project-Claude, source-verified). Operator: Viktor.
**Baselines at creation (verified live):** agent `ced60dd`/v0.74.0 · controller `59eb3bea`/v0.103.0 ·
catalog `2ebe082a` · felhom.eu `1a1e42ad`/hub v0.35.0 · host-install v1.9.1 · golden 0.98.3.
**Updated 2026-07-07 (GL-2 shipped):** felhom.eu `02d63ed0` · host-install **v1.10.0** + `scripts/hostinstall-mode-harness.sh`.
**Updated 2026-07-08 (GL-4 + GL-5 shipped):** felhom.eu `f7cc6a72` · host-install **v1.11.0** (uninstall gap-closure + key-pin plumbing) · felhom-agent **v0.75.0** (DR bind overrides, live on felhom-pve).
**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.**
---
## 1. Pilot definition & locked decisions (2026-07-07)
| # | Fork | Decision |
|---|------|----------|
| D1 | Pool model | **One shared `felhom` pool.** No multi-tenant boxes yet; the pool separates Felhom guests from the host owner's own workloads. Effort goes to preflight pool-membership assertion + local-API per-guest token scoping (verified structural, see G10). |
| D2 | Pilot topology | **BYO host.** Peti installs Felhom onto his OWN Proxmox server, already running his own LXCs. This reframes containment: not customer-vs-customer, but *Felhom-as-a-guest on a host the operator does not own*. See §2. |
| D3 | Backup posture | ~~Local-only for the pilot; `wg_tunnel.enabled` and `oob.enabled` stay FALSE.~~ **SUPERSEDED 2026-07-12 (DR-tier-by-default, decisions 1/5):** every install ships the full DR plumbing with `wg_tunnel.enabled=true` — WG is BASE infrastructure (outbound-only, like the CF tunnel; also the future OOB transport); activation of the PBS-DR tier is the hub's per-customer flag (default ON). `oob.enabled` stays FALSE on BYO. Consent moves to the installer's typed disclosure ack + the tester-agreement WG disclosure line (§2). |
| D4 | Uninstall drill | **Full provision → uninstall → re-provision drill on the demo box BEFORE Peti's day-0.** Peti's box is never the first live test of anything destructive. |
| D5 | DR bind-override | **Fix now** (small, spike-validated known-constant override per `SPIKE-dr-bindmount-source-2026-07-07.md`), not deferred to the intermediary-mount re-architecture. |
| D6 | Packaging | **This one tracking doc + a sequenced set of CC tasks** (GL-1…GL-7). |
---
## 2. The trust-model reframe (BYO host) — load-bearing
Everything so far was designed for the **appliance model**: Felhom-owned hardware, Viktor is the
root-holding operator, the customer is a UI user. Peti's pilot is the **BYO-host model**: Peti is
root on his own PVE box; Felhom is a *guest system* there (one LXC + a non-root agent + narrow
sudoers + a pool-scoped token). Consequences, each source-verified:
- **Break-glass inverts.** `step_break_glass` (host-install.sh:1186, step 4b/8, NOT flag-gated)
sets root@pam via `chpasswd` and vaults it to the hub. Right for appliances; on a BYO host it
silently changes the owner's root password and hands the operator root on hardware he doesn't
own — a consent, trust, and data-sovereignty violation. **Must be profile-gated (G2).**
- **Host-wide artifacts need coexistence review**, not just installation: dnsmasq snippets under
`/etc/dnsmasq.d/felhom-*.conf` + `systemctl restart dnsmasq` (and the installer installs the
dnsmasq package) can collide with the owner's existing DNS; the mgmt watchdog + tmpfiles heal
`/run/sshd` on *his* sshd (additive, likely benign — verify); felhom-sshd/OOB stays off (D3).
- **Already good citizens (verified):** VMID selection collision-safe (default 9201, auto-next-free
over the union of `pct`+`qm` ids, explicit `--vmid` dies unless `--force` — host-install.sh:223241);
uninstall targets only guests carrying the `/etc/felhom-bootstrap` bind mount and refuses
non-Felhom guests (:337, :472); stale-lock reaper is pool-intersected (agent v0.62.0);
local-API requests are authorized strictly against the caller-token's own guest
(localapi/server.go:23, :5355, :153).
- **Local-API exposure:** binds the vmbr0 IP:8443 by default (host-install.sh:15461548) — on a BYO
host that's reachable from the owner's LAN and his other guests. Defense = TLS + per-guest bearer
token. Acceptable for the pilot; documented in G10.
---
## 3. Gating items (must be green before Peti's day-0)
Status legend: ✔ DONE · ◐ PARTIAL · ○ OPEN · ⚠ BLOCKER
| ID | Item | Status | Evidence / gap |
|----|------|--------|----------------|
| **G1** | **Publish + vouch chain current & self-update alive.** ARTIFACTS PUBLISHED (RUNBOOK GL-1, felhom.eu `a63cc715`): agent **0.74.0** sha `1ec3f588…76af05` (the exact live-proven felhom-pve bytes, hash independently re-verified anonymously) and golden **0.103.0** sha `8481e8a1…6026e` (clean-room bake on the virgin drill VM, controller 0.103.0 baked, both split volumes in the vzdump). **Key-pin day-0 PLUMBING SHIPPED in GL-4** (v1.11.0: `OPERATOR_KEY_*` constants empty-by-default + `--operator-pubkey-file``authz.signers`; preserved-signers never clobbered; verify reports armed/dormant). **DONE (GL-6):** hub Day-0 manifest confirmed vouching agent **0.76.0** + golden **0.103.0** (fetched via the box API at Phase 0); the key CEREMONY is complete (real op/rec keys pinned in v1.11.1, fingerprints box==repo==manager, ARMED from first boot); and the **pinned operational key authorized a real signed `agent_update` round-trip** end-to-end (0.76.0→0.76.1→0.76.0). Published chain consumed live via anonymous fetch (v1.11.2 ruling). | ✔ | DRILL-GL6-2026-07-08.md §Phase 3; RUNBOOK-GL1 |
| **G2** | **BYO-host install profile.** SHIPPED as `--mode appliance\|byo` (mandatory, no default; the flag was repurposed from the retired `provision\|dr``dr` stub seam preserved). byo: break-glass gated OFF at its single call site (:20402044 — root@pam never touched, nothing vaulted), caps mandatory, `--enable-oob`/`--rotate-recovery` refused, host-mutation disclosure + typed-hostname ack, post-write config asserts (`lan_resolver`/`wg_tunnel`/`oob` must be off — asserts run BEFORE `_state_mark agent_config`, so `--resume` re-asserts). Red-proofs RP-1..3 run→fail→revert. Appliance flow unchanged. **LIVE-VALIDATED (GL-6):** byo install on real hardware — disclosure printed, Viktor typed the hostname ack, NO 4b/chpasswd/vault, config asserts held, signers armed. | ✔ | DRILL-GL6 §Phase 2 |
| **G3** | **`git.token` scope-down + rotate — UNBLOCKED, and now coupled to a visibility ruling.** Gate 3c (GL-1): both generic packages are **anonymously world-readable**, so rotating the customer token to read-only cannot break fresh-install fetches; the empty-creds die on demo-felhom is the installer's `resolve_git_creds` precondition (:326332), not a Gitea requirement. **NEW FINDING (project-Claude probe, 2026-07-08): the ENTIRE Gitea instance is anonymously readable — all nine repos `private=False`, including `homelab-manifests` (k3s manifests — audit for raw Secret objects) and personal repos (`work`, `revfulop-calendar`). Only the geo-fence (HU/DE/US) limits reach.** Coupling warning: if the reaction is to lock the instance ("require sign-in"), the anonymous day-0 package fetch dies and read-scoped tokens become MANDATORY — retest the fetch path with a token before any visibility change. | ○ ⚠ | GL-1 record §Gate 3c; anonymous `repos/search` probe 2026-07-08 |
| **G4** | **Preflight guards (refuse-to-provision gate).** SHIPPED in v1.10.0: byo dies on non-9.x PVE (unless `--force`) and on missing `--acl-storages` entries (named); `:53` DNS info line + existing-guest count; `--preflight-only` runs the full mode-aware checks with a PASS/FAIL verdict and **zero state marks** (live-proven on felhom-pve, incl. the FAIL verdict on a bogus storage). Verify asserts pool membership + all scoped-ACL grants in BOTH modes. **LIVE-VALIDATED (GL-6): C7 fired** — an induced pool-membership drop made `step_verify` `log_error` + WITH-WARNINGS, read-only; `--preflight-only` also proven live. | ✔ | DRILL-GL6 §Phase 4 (C7) |
| **G5** | **LXC caps mandatory on BYO hosts.** SHIPPED: byo refuses to run without explicit `--cores` AND `--memory` (:947, fires before the passphrase prompt); existing cap-sanity warns retained. Appliance unchanged (optional). **LIVE-VALIDATED (GL-6):** byo install ran with `--cores 4 --memory 8192` (Viktor's N100 values); the guest's `pct config` shows cores 4 / memory 8192. | ✔ | DRILL-GL6 §Phase 2 |
| **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 — SUPERSEDED by the customer-claim model (2026-07-12, controller v0.122.0 + hub v0.50.0).** The operator-set-password premise was found NEVER to exist in shipped code (DRILL-day0-vm F-4). Replaced by a customer-owned password set via a **one-time claim code the hub emails to the registered address**: an unclaimed box serves ONLY the claim page (no open window), which closes the CT-log first-visit race that motivated G9. Reset rides the same code engine. Live-proven on the drill box 2026-07-12 (gate ON via the real edge; claim page / 401 on API). | ✔ | DRILL-day0-vm-2026-07-12.md; controller/hub CHANGELOGs |
| **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.** **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`
unification refactor; Tier-1/Tier-2 offsite split + production WG endpoint; CGNAT true-sim retest;
BUNDLE cert/key/token migration item; hub-floor auto-update.
---
## 4. Task sequence
| Task | Type | Repo(s) | Covers | Depends on |
|------|------|---------|--------|------------|
| **GL-1** Publish/vouch/key-pin chain | ◐ **artifacts published 2026-07-08** (`a63cc715`); manifest bump + key pin = operator | felhom-agent, felhom.eu (hub manifest), operator UI | G1 | — |
| **GL-2** BYO-host profile + preflight + mandatory caps | ✔ **DONE 2026-07-07** (`02d63ed0`, validated) | felhom.eu/scripts | G2, G4, G5 | — |
| **GL-3** git.token rotate + scope-down | Operator (small) | Gitea admin + config template | G3 | — |
| **GL-4** Uninstaller gap-closure + key-pin fold | ✔ **DONE 2026-07-08** (host-install v1.11.0, `f7cc6a72`) | felhom.eu/scripts | G6 + G1-plumbing | GL-2 |
| **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 | ✔ **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.
---
## 5. Decision log
- 2026-07-07 — D1D6 locked by Viktor (see §1). BYO-host reframe adopted; break-glass step
identified as a BYO blocker (G2); G1 stale-vouch chain identified as item #1; G3 security O1
promoted into the gating list. Catalog healthcheck sweep confirmed CLOSED (live, `2ebe082a`).
- 2026-07-07 — **GL-2 SHIPPED** (host-install v1.10.0, felhom.eu `02d63ed0`), CC report validated
against source at file:line. Two spec corrections adopted, both verified at baseline: (a) `--mode`
already existed as the retired `provision|dr` — repurposed to `appliance|byo` with a guiding die
for `provision` and the `dr` stub seam preserved; (b) the installer's config write defaulted
`lan_resolver.enable: true` (baseline :1592) — the spec's "default-off" claim was agent-side only;
byo now defaults it OFF and the post-write assert still catches a `--preserve-from` carrying true
(appliance keeps historical default-on). The byo skip line intentionally avoids the literal
"4b/8" (the spec's Scenario B forbade the string). Harness runs red-proofs on scratch copies;
every invocation uses a throwaway `FELHOM_INSTALL_STATE_DIR` (new env override, spec-permitted).
- 2026-07-08 — **GL-1 EXECUTED** (felhom.eu `a63cc715`, felhom-agent `4c408467`), validated: agent
0.74.0 published from the exact running felhom-pve bytes (sha independently re-verified via
anonymous fetch, byte-exact); golden 0.103.0 baked clean-room on the virgin drill VM and
published (612MB, rootfs+mp0+mp1 all in the vzdump); drill environment restored to `virgin`.
Deviations sound: debian-13 template pveam-downloaded in-VM; bake detached via `systemd-run`.
Gate 3c: packages anonymously readable → G3 rotation unblocked. **Follow-on probe found the
whole Gitea instance anonymously readable (all repos public)** — operator ruling required
(see G3 + operator actions).
- 2026-07-08 — **GL-4 SHIPPED** (host-install v1.11.0, felhom.eu `f7cc6a72`): G6 uninstall
gap-closure (self-update artifacts, per-drive plain-umount with busy-warn, KEPT-vs-WIPED
statement both modes, guest-only bind-store drive note) + the G1 key-pin day-0 PLUMBING
(`OPERATOR_KEY_*` constants empty-by-default + `--operator-pubkey-file``authz.signers`;
no-keys-resolved KEEPS preserved signers — a pinned box is never silently un-pinned). Harness
28/28 on felhom-pve incl. a full-uninstall DRY transcript vs live 9201; red-proofs RP-1..3.
Statuses: **G6 → implemented-awaiting-GL-6; G1 key-pin plumbing → done, ceremony pending.**
- 2026-07-08 — **GL-5 SHIPPED** (agent v0.75.0, `b3446213`, live on felhom-pve): G8 DR bind
overrides + 4d real-bind swap, **scratch-DR live-validated** (see G8). The spike's
known-constants verdict held for the bind LAYOUT but PVE's all-or-nothing explicit-params
restore forced two live corrections (explicit rootfs; full storage-mpN pass-through from the
archive's embedded config — without it the DR guest boots WITHOUT its data volumes, a
data-loss restore that looks green). NOTE: no host-loss DR runbook exists yet to simplify
(the GL-5 spec assumed one) — the DR procedure doc is GL-6/S5 material. Follow-ups recorded:
publish agent 0.75.0 (the published 0.74.0 lacks working DR); restore-test has the same
dropped-mountpoint exposure in reverse (boot-verifies without mp0/mp1 — candidate: reuse
`drRestoreOverrides`); DR selftest KeepMAC=true duplicates a live source's MAC briefly.
- 2026-07-08 — **GL-5b SHIPPED** (agent v0.76.0, `b1697874`, live + PUBLISHED `9828c5f7…f50b`):
new **G12** — the restore-test now verifies FULL fidelity (archive-derived params via
`drRestoreOverrides` + a mount-parity assert; the old live-source-config path deleted with its
tests). Live run: parity ok, inventory mp0 200G + mp1 50G + 2 throwaways, **3m4s local tier**
(measured — cheaper than the DR-derived ~7m estimate); a rotated-out archive volid refuses up
front (good failure mode). **0.75.0 superseded unpublished; the ONE manifest bump goes straight
to 0.76.0.** Scenario-B red-proof run→fail→revert; bringup.go zero line changes (DR re-run
trigger not fired).
- 2026-07-08 — **GL-6 DRILL COMPLETE** (supervised, Viktor gating; `DRILL-GL6-2026-07-08.md`,
felhom.eu `87ba30ae`). Two full destroy/rebuild cycles on felhom-pve (byo #2 + appliance #6) +
two clean uninstalls; abort-path (local+PBS backup, restore-test parity ok) verified before any
destroy. **Key-pin legs 14 all green** (box==repo==manager fingerprints; armed from first boot;
the pinned operational key authorized a real signed `agent_update` round-trip 0.76.0→0.76.1→0.76.0).
**C7 live-validated** (verify's pool assert fired on induced drift). **F4 (resume-correctness,
HIGH) found + FIXED mid-drill (host-install v1.11.3) + live-proven** (the appliance install then
ran single-shot). Gate-0 ruling shipped **v1.11.2** (empty customer git creds → anonymous artifact
fetch; all 12 fetch targets 200-anon-verified). New findings F1/F2/F3/F6/F7 filed for a small
installer follow-up (none block Peti). G2/G4/G5/G6/G7 → LIVE-VALIDATED; G1 → DONE; G9 → deferred
to GL-7; G10 (open dashboard until operator password) → GL-7 prerequisite.
- 2026-07-08 — **GL-8 SHIPPED** (host-install **v1.12.0**, felhom.eu `18a556a5`): BYO coexistence
hardening from the GL-6 findings — **F3** leaf guard narrowed to `felhom_guests` (Peti's fresh
install on his populated box needs no `--allow-new-leaf` — the reason GL-8 shipped BEFORE GL-7),
**F6** byo preflight REFUSES a foreign `:53` with a remediation message (**Viktor's ruling: refuse
+ instruct, NO stop/mask — Felhom does not mutate a DNS service on a host it doesn't own**; the
break-glass analog), **F1** uninstall purges the config `.bak*` siblings (a GL-6 residue held a
live hub api_key). F6 **live-proven** on felhom-pve (byo preflight refuses at :53 — the exact
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
**Provisioning-checklist items (every fleet box, bench prep):**
- **BIOS "restore on AC power" = ON** (power-outage audit F8, 2026-07-22): a site power blip must not
become a half-day outage waiting for someone to press the button. Set + attest per box (not
OS-verifiable). Both current demo boxes done (Viktor, 07-22).
**Operator actions (Viktor):**
- **Hub manifest bump — DONE** (confirmed at GL-6 Phase 0: the manifest vouches agent `0.76.0` +
golden `0.103.0`). No action.
- **Installer findings — F1/F3/F6 FIXED in host-install v1.12.0 (GL-8, `18a556a5`).** F3: leaf guard
narrowed to `felhom_guests` (fresh byo install on a populated host needs no `--allow-new-leaf`).
F6: byo preflight REFUSES a foreign `:53` with remediation (Viktor's ruling — no stop/mask; live-
proven on felhom-pve). F1: uninstall purges config `.bak*` siblings. **Still open (none block
Peti):** F2 (per-drive `mnt-*.mount` units survive uninstall), F7 (pool re-assert is bring-up-only
— no continuous heal; `--adopt-pool` repairs). A later small pass, or fold into a future task.
- **Gitea visibility ruling** (new, see G3): decide deliberately — (a) keep felhom repos public
as an open-source posture, but audit + privatize `homelab-manifests` and the personal repos;
or (b) lock the instance, which REQUIRES first proving the day-0 package fetch with a
read-scoped token (the anonymous path dies). Recommendation: (a) — it preserves the working
day-0 path; do the homelab-manifests secrets audit either way.
- G3 token work: mint the scoped read-only token, rotate out the package-WRITE one, fill the
demo customer's empty `git.username`/`git.token` in the hub-served config.
- **Operator-key pin ceremony** on felhom-pve (+ the small day-0 follow-up — candidate GL-4 fold).
- Commit THIS doc to `felhom.eu/documentation/pilot/GO-LIVE-PACKAGE.md` (still absent after two
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 — **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.