Commit Graph

54 Commits

Author SHA1 Message Date
admin 770eeb6fee docs(scripts): felhom-poke.sh v1.0.0 CHANGELOG entry 2026-07-16 23:03:11 +02:00
admin eb227486d0 hub v0.59.0: Direction-2a agent-plane immediate-sync poke sender + ep0 felhom-poke surface
- internal/poke: pinned-host-key SSH poke sender (wgsync sibling) + fire-and-forget Notifier (PokeHost/PokeAllHosts). Poke refuses non-WG targets pre-dial; contentless via ep0 forced command to the box WG /32:51822.
- wiring: Server.SetPoke; applyPBSDR pokes the host after each descriptor gen-bump; handleSetArtifacts (MinAgent floor) pokes all hosts. main.go env POKE_SSH_KEY_FILE (reuses peersync endpoint/hostkey).
- scripts/felhom-poke.sh (non-root forced command) + offsite-endpoint.md §11; manifests/hub.yaml Secret/agent-poke + POKE_SSH_KEY_FILE (image tag bump follows the build).
2026-07-16 22:48:15 +02:00
admin 1fa3250aa3 feat(iso): R-21 slice A — bare-metal Felhom ISO pipeline + first-boot bootstrap
scripts/iso/: a DooPlex pipeline (build-felhom-iso.sh + Dockerfile.assistant) that
turns the official PVE ISO into a Felhom auto-install ISO whose first-boot stub
installs a retry-forever felhom-bootstrap unit which unattended-fetches
felhom-host-install.sh from the public felhom.eu/scripts channel and runs it until the
host is enrolled + a guest provisioned. host-install is UNMODIFIED (invoked only).

- build gates the answer on validate-answer OUTPUT text, never $? (spike S1 exit-0 trap)
- stub is from-iso, fully-up, exactly-once; retry unit owns all network work (S8a)
- retry-vs-resume encoded once: plain first, --resume when install state exists (v1.11.3)
- secret-bearing (embeds the retrieval passphrase): supervised/single-use; env shredded on success

Validated on VM 310: build gate + red-proof, disk-filter fail-safe, chain + retry,
resume-decision, exactly-once, no-net retry+recovery. Terminal host-install rc-0 success
operator-gated (drill customer needs the password-gated create-UI). scripts v1.16.0;
ROADMAP R-21 -> in-progress. Detail in REPORT.md.
2026-07-16 13:47:08 +02:00
admin 375cb082e2 host-install v1.16.0 (FELHOM_ESCROW via canonical sudoers fetch; hub hostInstallVersion synced, no deploy) + RUNBOOK-escrow-ceremony rewrite: controller wizard PRIMARY, CLI operator fallback, F1 threat-model paragraph (R over CF tunnel accepted 2026-07-13), stale-blob/supersede/void semantics 2026-07-13 19:01:46 +02:00
admin 8e69e5edda docs: scripts CHANGELOG - manifest_bearer_gate.py entry (incl. the .gitignore *secret* un-tracking gotcha) 2026-07-13 15:11:46 +02:00
admin 3682303131 scripts: manifest bearer gate lands as manifest_bearer_gate.py (the .gitignore *secret* pattern silently un-tracks any 'secret'-named gate file - the previous commit's gate never made it into git); references updated 2026-07-13 14:59:31 +02:00
admin 5d66c62bd6 hub: F-16 — inline two-step confirm partial replaces every native confirm() (offsite/PBS re-issue, freeze, telemetry reset, dismiss-all, regen-password, claim-resend, block/delete, geo-disable); hub_confirm_gate.py enforces zero
Claude-Session: https://claude.ai/code/session_01GzammAMzsJTgpQHqxwM2bC
2026-07-13 08:19:54 +02:00
admin 007946faf4 installer v1.15.0: DR-tier-by-default sweep (F-7 pbs-apply, F-10 age, F-9 wg default-on, F-1 single version + hub const, F-2 dry-run auth, F-8 rotation pointer, ACL felhom-pbs kept) + hostinstall_gates.py
Claude-Session: https://claude.ai/code/session_01NptTCFtu7dz2Ru89qHRagN
2026-07-12 19:52:56 +02:00
admin 0d73ca579b CAMPAIGN-3 Task A: agent v0.85.0 boot/recovery plane docs + host-install deployment_mode (--mode gates node self-heal)
network-storage-nas.md gains Boot-ordering (F12), reassert-hardening (F11/F10/F9),
F13 limitation, and Node self-heal (appliance) sections. host-install v1.14.0
templates deployment_mode from --mode + byo assert. Live matrix: host reboot x2 =
0 ordering-cycle lines (F12 dead); appliance self-heal recovered attempt 1.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_017CDMFpFx84pfviCTVuGGhf
2026-07-12 08:26:55 +02:00
admin 27e2fb05c0 host-install v1.13.0: systemd-journal group for the agent user + NAS feature doc
The NAS verify pipeline (agent v0.81.0) reads mount-unit journals unprivileged
— group membership, NO sudoers grant. Fixes the v1.11.0/1.12.0 header drift.
New authoritative feature doc documentation/controller/network-storage-nas.md
(verify pipeline, §8 truth table, Q4 error taxonomy, retry=0, Route A recipes
incl. the chmod-persists nuance).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-11 10:10:16 +02:00
admin 32ca1f60a7 tenantsync v1.0.0 live fix (client json is {data:[...]}-wrapped) + hub image bump 0.44.0
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-10 20:59:55 +02:00
admin ce6a56691e hub v0.44.0: PBS DR tier SLICE 1 — felhom-tenantsync surface (script+client) + hub provisioning flow (consume-once host secret, pbs_dr desired-state descriptor, fail-closed + idempotent, re-issue)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-10 20:49:48 +02:00
admin 18a556a514 GL-8: BYO coexistence hardening (host-install v1.12.0) — F3/F6/F1
F3: the populated-host leaf guard now fires only when a FELHOM guest exists
(felhom_guests, not `pct list`) — a fresh byo install on a host running only
the OWNER's guests proceeds without --allow-new-leaf; the pin protection for
real Felhom guests is unchanged (guard still fires on a Felhom guest).

F6: byo preflight REFUSES (never mutates) when a foreign resolver is bound
to :53, with remediation — Felhom needs the guest reachable by name and will
not stop/mask the owner's DNS (the dnsmasq analog of the break-glass rule).
Viktor's ruling: refuse+instruct only, no stop/mask path. ss failure degrades
to a warn. Appliance mode untouched (the agent's lan_resolver owns :53).

F1: uninstall now purges the agent config's .bak* siblings (one GL-6 residue
held a live hub api_key), not just agent.json; WIPED statement updated.

Harness +GL8-F3/F6/F1 static + GL8-F1b behavioural + GL8-F6 live (byo
preflight refuses on felhom-pve's leftover dnsmasq — the real F6 scenario).
Red-proofs RP-F3/F6/F1 each fail their invariant. 36/36 on felhom-pve;
shellcheck clean; GL-2 Scenario-A + GL-4 Scenario-D regression green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-08 19:37:49 +02:00
admin 98bf5a434f GL-6 F4 fix: v1.11.3 — --resume repopulates producer-step outputs
Live-found in the GL-6 drill: `should_skip X || step_X` fully skips a
completed step on --resume, but token/enroll/grows produce IN-MEMORY
outputs (pve token; hub host_id/api_key; volume grows) that later steps
consume — agent_config writes them into the config, provision passes the
grows as flags. A resume that had completed token/enroll but not
agent_config wrote a config missing hub.host_id/proxmox.token (daemon
crash-loop, "hub.host_id is required"); a resume past grows passed
`-rootfs-grow ""` (flag parse error). step_token even had an internal
resume-guard the `|| step_token` dispatch defeated.

Fix: token/enroll/grows now run every pass (all idempotent — token
reuses-or-rotates from the on-disk config, enroll is mint-once-reuse,
grows is a pure recompute); the guard uses _state_has (no misleading
SKIP log). golden's GOLDEN_VOLID is re-derived from the local archive in
the resume block so provision never gets an empty -archive. Harness
+GL6-F4 invariant; 27/27; shellcheck clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-08 13:01:33 +02:00
admin 0640aa06ea GL-6 Gate-0 ruling (G3): v1.11.2 — anonymous artifact fetch supported
Operator ruling at the GL-6 drill's Gate 0: the Felhom artifacts are
world-readable by design; an EMPTY git.username/git.token in the customer
config now WARNS and fetches anonymously instead of dying at step 5/8
(the hub-vouched sha256 stays the integrity root; a configured credential
is still used when present; curl auth args are conditional because -u with
an empty token 401s even on public content). All 12 installer fetch
targets validated 200 anonymously before shipping. Harness: +GL6-ANON
shape case; GL4-C2 assertion updated for the v1.11.1 pinned constants
(the benign overrides-notice is not a die). Drill record carries the
deviation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-08 12:28:51 +02:00
admin bd97bc3474 pin operator public keys (key ceremony) 2026-07-08 11:27:50 +02:00
admin f7cc6a720e GL-4: uninstaller gap-closure + operator-key day-0 fold (host-install v1.11.0)
Uninstall: NEW 4b4 removes the self-update artifacts (guarded wrapper,
.prev/.new.* A/B slots, rollback unit, limits drop-in — derived from
configs/felhom-selfupdate-guarded); enrolled drives under /mnt/felhom-drives
unmounted plain-umount-only (busy = warn+guidance, never -l/-f; root bind
guarded); both modes end with a KEPT-vs-WIPED statement (drives/PBS/hub
record/escrow/vaulted recovery credential live on); guest-only mode prints
the vmid's bind-store drives.

Key-pin: OPERATOR_KEY_* constants (empty until the operator ceremony) +
--operator-pubkey-file (argv-validated; comment=key_id required; file
overrides constants) -> authz.signers per the agent SignerKey schema;
no-keys-resolved KEEPS preserved signers; verify reports armed/dormant WARN.

Harness: +13 static cases + GL4-D parity + GL4-INV + PVE-tier GL4 H-U
(full-uninstall dry transcript vs live 9201). 28/28 on felhom-pve;
red-proofs RP-1..3 run->fail->revert. GO-LIVE-PACKAGE.md ABSENT AGAIN ->
status in CONTEXT.md. Live teardown/armed-pin = GL-6.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-08 08:14:07 +02:00
admin 02d63ed070 GL-2: --mode appliance|byo install profile (host-install v1.10.0) + harness
Mandatory install profile (no default): byo = a host the operator does not
own. Break-glass gated OFF at its call site in byo (root@pam never touched),
mandatory --cores/--memory, argv-time refusals (--enable-oob/--rotate-recovery,
non-9.x PVE, missing --acl-storages), host-mutation disclosure + typed-hostname
ack, byo config asserts (lan_resolver/wg_tunnel/oob off; byo flips the
lan_resolver write default to off), pool+ACL verify asserts in BOTH modes (R2),
--preflight-only (no state, PASS/FAIL verdict), resume mode-mismatch refusal,
FELHOM_INSTALL_STATE_DIR harness override.

NEW scripts/hostinstall-mode-harness.sh: static refusal matrix C1-C4 + grep
invariants + PVE tier (C5 + A/B dry transcripts). 16/16 PASS on felhom-pve
(C5 live); red-proofs RP-1..RP-3 run->fail->revert. shellcheck clean at
severity=warning. Docs: day0-install SC.5 byo section + trust model; REUSE row;
CONTEXT + REPORT. Live drill = GL-6 (supervised); STOP honored (no non-dry run).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-07 20:26:32 +02:00
admin 61f4898d30 docs(H1): doc06 §4.5/§4.6 amendment + endpoint runbook §9 + scripts CHANGELOG + REPORT + CONTEXT
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-05 23:03:33 +02:00
admin ccb378060d feat(install): --enable-oob installs felhom-sshd + static belt (H1 Part 5)
install_oob: /etc/felhom-sshd tree + dedicated host key + felhom-op user + scoped
sudoers + RuntimeDirectory-guarded felhom-sshd.service (enable-not-start; agent
renders config) + static felhom_oob nft table + boot loader. Uninstall removes all.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-05 22:34:06 +02:00
admin f1d3922fcc docs(G1): REPORT + scripts CHANGELOG for break-glass (hub v0.34.1 live-validated)
Auto-heal drill (agent stopped) healed /run/sshd in 30.0s; mgmt_plane_healed
warning fired end-to-end; break-glass vault→retrieve→PVE-ticket proven.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-05 19:22:51 +02:00
admin 05d81810d4 feat(hub,install): break-glass recovery vault + mgmt_plane surfacing (TASK G1)
Hub half of the management-plane break-glass (prereq for felhom-sshd/H1; agent
half = felhom-agent v0.71.0). Closes SPIKE-felhom-sshd §8/#9.

- store.host_recovery + methods: per-host root@pam console password, at-rest,
  operator-retrievable (the PVE-web-console fallback when sshd + auto-heal both fail).
- API: PUT /hosts/{id}/recovery-credential (self-scoped, day-0 vaults) + GET
  /admin/hosts/{id}/recovery-credential (global key only). Secret never logged
  (red-proofed).
- monitor/host_mgmtplane: parses the agent mgmt_plane stanza, raises
  mgmt_plane_healed WARNING on a new privsep_healed_at (recurring clobber surfaces
  before lockout; complements host_staleness).
- host-install: step_break_glass generates a strong root@pam password (openssl
  rand, never logged/filed — stdin to chpasswd + curl), vaults via host key;
  idempotent unless --rotate-recovery. Installs the G1 host artifacts (tmpfiles +
  agent-independent watchdog timer), RuntimeDirectory-guarded; uninstall removes them.

Hub v0.34.0. Non-hollow tests + red-proofs; full suite green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-05 19:03:18 +02:00
admin b6bad953b5 feat(host-install)+docs: D1 — install self-update artifacts on day-0 + architecture §11 self-update (implemented)
felhom-host-install.sh installs felhom-selfupdate-guarded (sh -n), the rollback
unit + the [Unit] start-limit drop-in (daemon-reload) so day-0 boxes get
operator-signed self-update from birth; non-fatal on pre-D1 agent repos.
03-host-agent.md §11 updated to the shipped mechanism (signed op, A/B wrapper,
OnFailure rollback, tuned start-limit backstop).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-05 15:36:15 +02:00
admin 76ee25e5e8 docs: 06-doc S3 SHIPPED (agent v0.64.0) + agent-side revocation semantics + CONTEXT/REPORT
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-04 08:58:44 +02:00
admin 265f46c0e7 docs: S2 shipped — hub v0.33.0 CHANGELOG, peersync v1.0.1, 06 §3.2 wire shape + S2 status, CONTEXT, REPORT
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-04 01:20:10 +02:00
admin 30d762d520 scripts: felhom-peersync v1.0.1 — strip out of process substitution (exit-swallow fix)
<(wg-quick strip ...) hid the strip exit code: a corrupt head file could feed
syncconf partial input that wipes the live peer set with exit 0 (S1 REPORT
finding). Strip now writes a temp file; its failure aborts before wg runs.
Sandbox red-proof: pre-fix shape invoked wg with rc=0 despite strip exit 1;
fixed shape never reaches wg.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-04 00:49:25 +02:00
admin 740cc42734 docs: S1 shipped — hub v0.32.0/0.32.1 CHANGELOG, peersync v1.0.0, 06 S1 status, CONTEXT, REPORT
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-04 00:14:35 +02:00
admin 6f5fb19a64 scripts+manifests: S1 felhom-peersync.sh v1.0.0 + hub wg-endpoint-ssh deploy surface
Peersync script: validate-first (jq contract check before ANY state change),
head-file + generated-peers conf model, syncconf-from-tmp then atomic mv (live
conf never diverges in the failure direction), zero-peer payload valid (wipe).
hub.yaml: 0.32.0 image + WG_ENDPOINT_SSH_* env + optional Secret mount so the
pod starts before the runbook's step-6 Secret exists.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-03 23:42:12 +02:00
admin 7fb20d5fb0 docs: architecture Part 06 — offsite-connectivity design-of-record (slice roadmap S1-S6)
Records the settled transport decisions (plain WG, host-side agent-managed pilot,
one hub-driven endpoint VM running WG+PBS, hub source-of-truth over WireDesiredState,
one datastore + per-customer namespaces, relay-through-DooPlex rejected). Grounded
at file:line vs felhom.eu@bf099f6 + felhom-agent@4ba1b14. Backlog line resolved to
cite spike + design doc. Docs-only; slices are separate future tasks.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-03 23:02:31 +02:00
admin bf099f6a10 docs: SPIKE — offsite-backup connectivity: plain WireGuard wins the ladder (transport decision made)
P0-P7 probe ladder on real ends (demo-felhom PVE host <-> throwaway Hetzner).
Verdict: GO at H1 — plain host-side WG, box-dials-out to a small public endpoint;
Headscale is a separable fleet layer, not a traversal necessity. Line is plain-NAT
(not CGNAT) with zero IPv6 — recorded honestly; CGNAT vantage deferred to Peti VM 110.
Real 2 GiB worst-case PBS backup over the tunnel at the full home uplink, pin intact.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-03 22:04:51 +02:00
admin 3d7f0505b0 skills: NEW felhom-app-catalog (4th skill) — catalog authoring workflow, proven on SparkyFitness
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-03 19:48:53 +02:00
admin 7ad111cfb5 docs: golden 0.98.3 live — D.1b retired, drill B1/B5 fixed, backlog note resolved + evidence doc
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-03 18:38:28 +02:00
admin 2e33a8b86b docs: D.1b narrowed + drill B2/B3 marked FIXED (agent v0.63.0)
Restart-the-agent step in day0-install.md is now conditional on agent <
v0.63.0 (reload-on-miss shipped; Day-0 manifest still vouches 0.62.0).
Troubleshooting row + drill ledger + go/no-go item 8 updated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-03 17:27:39 +02:00
admin 0fa79cd90d Go-live package: Day-0 install runbook + clean-room drill + host-install v1.9.1
- documentation/runbooks/day0-install.md (NEW): operator Day-0 guide, every
  command drill-executed verbatim (Parts A-F incl. the mandatory one-time
  controller update D.1b and the OQ-3 prereq checklist).
- documentation/audits/DRILL-day0-cleanroom-2026-07-03.md (NEW): nested-PVE
  clean-room drill evidence D0-D6, residue tables, OQ-1/2/3 answers, findings
  ledger (B1-B5), go/no-go for Peti (GO).
- scripts/felhom-host-install.sh v1.9.1: residue-free uninstall (agent config,
  shared-parent unit/script/mount, mkfs wrapper, hook snippet, dnsmasq
  snippets; zero-residue diff proven) + post-provision guest reboot (R6) +
  header/version sync.
- CONTEXT.md, REPORT.md, scripts/CHANGELOG.md updated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-03 15:14:47 +02:00
admin 639a57ee8b felhom-host-install.sh v1.9.0 — Pool.Audit in FelhomAgentGuest (audit A1)
Companion to felhom-agent v0.62.0: the stale-lock reaper reads GET /pools/felhom
as its ownership registry. Pool.Allocate does NOT satisfy the read (spike T2).
Idempotent upgrade via --rescope-acl (_ensure_role modifies to the exact set).
Rescope FIRST, agent second. + REUSE §2 errata: gitea-creds is NOT out-of-band
(committed in felhom.secret.yaml, live-consumed — rotation pending).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-03 13:26:26 +02:00
admin 5e3dfcb714 docs: SPIKE — A1 pool-membership read for the stale-lock reaper
Live-probed on felhom-pve under the PRODUCTION scoped token vs root:
enumeration IS pool-filtered (T1: token sees [9201] of 4 guests); pool read
403s naming Pool.Audit (T2); Pool.Audit@/pool/felhom alone suffices (T3,
throwaway identity, torn down); /cluster/resources withholds the pool field
without Pool.Audit (T7); local ownership records all partial (T5).

Recommendation for the A1 impl spec (now unblocked): Pool.Audit added to
FelhomAgentGuest + GET /pools/felhom cross-check in staleLockController,
fail-safe skip on read failure. Appendix: committed-secrets rotation
micro-runbook (operator follow-up).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-03 13:00:00 +02:00
admin 9282d60f96 docs+skills: felhom-{build-deploy,ui-design,testing} skills + install_skills.py (junction); CLAUDE.md refresh (version-free); consolidated REPORT
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-03 11:27:48 +02:00
admin d331eb26d1 docs: REUSE.md introduced — reuse map (hub+website+scripts+manifests) + reuse_refs_check.py gate + consolidated cross-repo REPORT
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-03 09:40:39 +02:00
admin bed8675930 D3 Part 2: index + kapcsolat on design system v2
- Both pages: Google Fonts links + preconnects removed; ONE stylesheet
  (/assets/site.css?v=1); embedded <style> blocks deleted; body classes
  page-index/page-kapcsolat; canonical nav/footer (active marker per
  page; index's #szolgaltatasok href normalized to /#szolgaltatasok);
  all emoji -> sprite icons (feature tiles = .ico-tile 48px bg-2
  squares; headings .ico-lg; inline .ico) or plain text.
- kapcsolat: the contact form is functionally frozen — every field
  name/id, the submit JS, and the /api/contact endpoint byte-identical;
  only the visual layer changed (upload/paperclip + file-type icons as
  sprite refs in JS strings, the x button as &#215;, status-message
  emoji prefixes dropped).
- site.css: CSS-generated marks (content '✓'/'✗'/'⚠'/'★ …') replaced by
  currentColor mask-based marks / plain text (emoji-free stylesheet;
  gate now scans it too); .ico-tile is svg-as-tile (immune to container
  display rules), .ico-lg added.
- Gates: zero failures for the two converted pages; the remaining five
  convert in Part 3.
2026-07-02 22:06:27 +02:00
admin dd54e4cdf6 D3 Part 1: shared website assets + site gates (pages untouched)
- website/assets/site.css: ONE stylesheet for all seven pages — vendored
  @font-face (4 faces, latin+latin-ext, /assets/fonts/ paths), the
  design-system v2 :root token block verbatim, a hand-written shared
  base (reset, nav, two-tone heading as solid blue-bright, section/page
  headers, buttons, card, footer, hamburger + mobile menu, icon-tile,
  reduced-motion), and per-page sections mechanically converted from
  the seven embedded style blocks (tokens renamed, radii → 2px,
  box-shadows/text-gradients/hover-lifts removed, greens → blue per
  exception-color) scoped under .page-<name> body classes.
- website/assets/fonts/: the 4 woff2 files copied byte-identical from
  felhom-controller (self-hosted — removes the Google Fonts CDN / GDPR
  exposure once the pages switch over).
- website/assets/icons.svg: 70-symbol Lucide sprite (the D0 30 + 40
  marketing icons) for <use href="/assets/icons.svg?v=1#i-name">.
- scripts/site_gates.py: 8 gates (BOM bytes, Python-codepoint emoji,
  nav/footer consistency after active-marker normalization, analytics
  presence, no-CDN, banned legacy tokens, zero <style> blocks,
  ?v= cache-busting). Baseline against the unconverted pages: 84
  problems, 182 emoji — goes green with the page conversion commits.
- Live site unaffected: nothing references the new assets yet.
2026-07-02 22:00:01 +02:00
admin 7ea36bccad host-install v1.8.0: install the guarded-mkfs wrapper (Impl-1 Part B)
step_agent_install now fetches configs/felhom-mkfs-guarded.sh (bash -n validated)
and installs it 0755 root to /usr/local/sbin/felhom-mkfs-guarded BEFORE the
sudoers (which — from agent v0.54.0 — allowlists only the wrapper, not raw mkfs,
plus read-only pvs/zpool). Live-validated on felhom-pve. bash -n + shellcheck clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 16:59:37 +02:00
admin 457a5cdf2d host-install v1.7.0: 3b-fix — Datastore.Audit box-wide (restore drive visibility)
v1.6.0 put Datastore.Audit in the per-storage Store role, hiding the enrolled
drives (felhom-usb/felhom-flash) from the agent's storage enumeration → false
detach alerts. Move Datastore.Audit (read-only) to box-wide Base; keep write
privs (Allocate/AllocateSpace) per-storage → visibility restored, write
containment unchanged. apply_scoped_acl reordered Base-before-Store (gap-free
re-apply). Live-repaired felhom-pve (role modify, no agent stop): drives back,
alerts cleared, write-containment + guest-403 re-confirmed. bash -n + shellcheck
clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 13:26:52 +02:00
admin 741f322d6a host-install v1.6.0: pool-scoped token ACL (3-role) + --rescope-acl retrofit
step_token now grants 3 scoped roles (Guest@/pool/felhom incl. Pool.Allocate,
Store@each PVE_STORAGES incl. felhom-pbs, Base=Sys.Audit+SDN.Use@/) to both user
and token, pool-before-token, and removes any pre-3b broad / grant. New
--rescope-acl migrates existing installs (add-before-remove; supervised).
--uninstall removes both scoped + old shapes. Post-provision pool_add_guest
dropped (agent restore --pool owns membership, v0.53.0). Validated dry-run on
felhom-pve; bash -n + shellcheck clean. LIVE rescope+swap is the supervised STOP.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 12:46:08 +02:00
admin 482dbec913 host-install v1.5.0: felhom pool by default + --adopt-pool + uninstall teardown
Every managed guest joins a dedicated `felhom` pool (fleet uniformity; foundation
for the later pool-scoped ACL). All pool ops run as root@pam from the installer —
NO agent/token/ACL change (PVE_PRIVS untouched). step_provision creates the pool
+ adds the guest; new --adopt-pool retrofits existing guests non-destructively
(ours-checked, membership-only); --uninstall deletes the pool only if empty.
Confirmed pveum pool / /pools syntax live; validated dry-run + SAFE live adopt of
9201 on felhom-pve. bash -n + shellcheck clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 11:48:19 +02:00
admin f7905b78b5 host-install v1.4.0: appliance CPU/RAM cap passthrough (--cores/--memory)
Optional --cores N / --memory M (MiB) passed through to the agent's
--selftest=provision as -cores/-memory ONLY when set (0/unset = golden default;
avoids unknown-flag death on an agent < v0.52.0). Pre-flight soft WARN when a cap
exceeds host nproc/MemTotal. Validated dry-run on felhom-pve. bash -n + shellcheck
clean. Deploy dependency: hub artifact manifest must serve agent >= v0.52.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 08:13:15 +02:00
admin 6db68f4e45 host-install v1.3.0: --uninstall (clean revert) + pre-flight guards
Colleague-safety batch #1+#2 (script-only). Adds a guarded, dry-run-aware
--uninstall local host teardown (guest -> agent -> pveum(ACL,token,user,role)
-> golden(opt-in) -> state file), with ours-check on the /etc/felhom-bootstrap
mount, typed vmid confirm, other-Felhom-guests safe-skip, and idempotent
tolerate-absent. Records customer_id + provisioned_vmid into the install state
(_state_put/_state_get) so uninstall resolves its target automatically. Adds
three provision pre-flight guards: multi-node (--node required), archive-storage
exists, and a RAM-floor WARN. Validated dry-run-only on felhom-pve.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 07:47:34 +02:00
admin b77df3c761 host-install: bump header comment to v1.2.0 (matches SCRIPT_VERSION)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 06:46:35 +02:00
admin 562c0dfeb6 hub v0.28.0 + host-install v1.2.0: settings→Configuration, online install, vmid auto-detect
Part A (hub): move the global-floor + Day-0-artifacts cards from the Customers
page to the Configuration tab; routes → /configuration/{global-floor,artifacts};
redirects + flashes to /configuration. Customers page back to list + Add.

Part B: online setup command on the customer page (download-then-run, passphrase
at prompt, not templated); serve /scripts/ from the website (sparse-checkout +
nginx location) so felhom.eu/scripts/felhom-host-install.sh resolves; script
passphrase prompt reads < /dev/tty (works for pipe-to-bash too).

Part C (script): --vmid auto-detect — default 9201 in use + no --force → pick the
next free id from pct+qm and confirm; explicit --vmid stays die-unless-force.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 06:43:29 +02:00
admin fdcbc04d82 host-install: seed agent backup.local_backup_retention=3 (vzdump keep-last default)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HxLA1mZurFq9kt8hneFeCs
2026-06-30 19:44:08 +02:00
admin a69e06354e host-install: --preserve-state-from + populated-host leaf guard (prevention B.2)
--preserve-state-from DIR carries the prior local-api.{crt,key}+local-tokens.log into the agent
state dir (validates the leaf parses) so the pinned fp stays stable across a reinstall — no
re-bootstrap. Populated-host guard: refuse to proceed leaf-less when the host already has guests
unless --preserve-state-from or --allow-new-leaf is given (converts the 2026-06-28 silent footgun
into a hard stop). bash -n clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pg8ANF97SEeKYSN5Jxw3qJ
2026-06-29 21:46:45 +02:00