560f0d4451
Campaign 12 ranked this first of eight gating candidates. It is built BEFORE the fixes it finds, because last night an off-the-shelf tool for a neighbouring class (deadcode, for C6) was made to prove itself first and found NEITHER of the two defects it was meant for. A gate nobody has watched fail has not been shown to work. scripts/wire_contract_gate.py, registered in repo_gates.py as --fast (no network, no container, so it runs in BOTH the pre-push hook and CI — the R-29 constraint). THE TEST. For every json tag reachable from a declared wire ROOT, does that literal tag occur anywhere in the receiving repo's production Go or templates? A tag occurring nowhere cannot be decoded by any struct, named OR anonymous. That last clause is why a string test is used instead of comparing struct to struct: Campaign 12's first attempt paired types by shape and false-positived badly, because the hub decodes one report through several ad-hoc anonymous structs. RESULT ON TODAY'S TREE: 210 tags checked across 3 declared wires, 51 skipped (generic / opaque / allowlisted), 40 CONVICTED. Captured verbatim in documentation/tests/wire-contract-gate-2026-08-08/ BEFORE.md, which is deliverable 1 of this session. The prompt for this session said "465 emitted tags, eight unreachable". Checked against the repo rather than quoted: R-260's wording was "at least eight DECISION-BEARING facts", not eight tags in total. The real count on the three declared wires is 40, and R-260's own census already listed more than eight. Recorded because this prompt's own rule 6 says not to quote a document as source. TWO THINGS THE CONTROL CAUGHT, both before the gate was trusted: 1. A SUBSTRING FALSE NEGATIVE. `grep -F healed_at` also matches `privsep_healed_at`, so a genuinely dropped field read as received — and R-260 named healed_at, so its absence from the output was the tell. Now a whole-token regex; healed_at is convicted. 2. dr_recipe IS NOT WHOLLY OPAQUE. The hub stores each half as json.RawMessage and re-emits nested shapes verbatim, so the LEAVES are genuinely not on this wire. But the TOP-LEVEL SECTION KEYS are decoded by hostHalfShape/appHalfShape, and those are ALLOW-LISTS: a section an emitter adds is silently dropped until named in both. That already cost `offsite_restic` (R-122). So the gate is opaque BELOW depth 1, not opaque — the sections are checked and pass. Self-test: `--selftest` plants an unreachable tag on a real root in a throwaway copy and asserts conviction. Verified: exit 1, planted tag named. Blind spots are in the module docstring AND in the gate's own output, because Campaign 12's C1 guard turned out blind to one of the three shapes it was written for: generic tag names are not checked; reachability of a NAME is not use of a VALUE; only declared ROOTS are covered, and the hub's desired-state (served as raw stored JSON, no typed emitter) and the agent local API are NOT. Allowlist entries carry a stated reason. A quiet exclusion is a dropped field with paperwork. Not pushed alone: the fixes follow in the next commit so main is never red on this check.
Felhom — Documentation
Felhom is a managed home-server service for Hungarian households, built on a three-component model over Proxmox:
- Hub — operator backend on k3s (
hub.felhom.eu). Repo:felhom.eu/hub/. - Host agent — one per Proxmox host; operator-tier; owns all Proxmox interaction. Repo:
felhom-agent/. - In-guest controller — one per customer LXC; Docker-only; manages the customer's apps. Repo:
felhom-controller/.
This directory is the central, code-verified documentation home for all three components plus the platform and the security-audit record.
Sections
Controller (in-guest) — controller/
The Docker-only app-domain controller. Full per-area docs grounded in current source (v0.59.0).
→ controller/README.md: module map, deploy & stack lifecycle, backup
architecture, storage/monitoring/metrics, auth/hub/sync/integrations.
Host agent & platform — architecture/, proxmox-platform.md
The operator-tier agent and the Proxmox platform.
architecture/01-topology-and-trust.md— topology & trust modelarchitecture/03-host-agent.md— the host agent (Go; v0.29.1)architecture/04-control-plane-authorization.md— signing, escrow, authzarchitecture/02-controller-module-map.md— historical v0.33 planning map; the live map iscontroller/module-map.mdproxmox-platform.md— Proxmox platform reference
Hub (operator backend) — architecture/05
architecture/05-hub-architecture.md— hub architecture (v0.11.0)
Security audits & remediation — audits/
audits/deep-sweep-2026-06-13.md— cross-repo deep audit (controller + agent) with remediation statusaudits/bughunt-reconcile-2026-06-13.md— reconciliation of the v0.30.3 BUGHUNT against current code + merged fix list
Spike & test findings — tests/
Per-slice spike/validation findings (phases 0–5, slices 7–10). See tests/.
Conventions
- Code-verified, not memory-derived. Architectural claims here are checked against the actual current source; if a claim can't be verified it is omitted and flagged, not guessed.
- Per-repo operational working files (
CLAUDE.md,CONTEXT.md,CHANGELOG.md,BUGHUNT.md,REPORT.md,TASK.md) live in their own repos — they are operational, not published docs. - Authoritative versions at last refresh: controller v0.59.0, agent v0.29.1, hub v0.11.0.