# 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 1–4 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:223–241);
  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, :53–55, :153).
- **Local-API exposure:** binds the vmbr0 IP:8443 by default (host-install.sh:1546–1548) — 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 (:2040–2044 — 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 (:326–332), 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, :53–55, :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 — D1–D6 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 1–4 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

**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.