Files
felhom.eu/REPORT.md
T

9.4 KiB

REPORT — Hub v0.85.0: the Network card (2026-07-31)

Overwritten per the standing rule. Pairs with agent v0.119.0 (see felhom-agent/REPORT.md); neither half is useful alone. Live evidence: documentation/audits/host-addresses-visible-2026-07-31.md.

The earlier v0.84.0 work this file previously described (break-glass Console access card) shipped, deployed and validated in the same session; its durable record is hub/CHANGELOG.md v0.84.0 plus CONTEXT.md ruling S-4 and documentation/backlog/ R-133.

0. Follow-up shipped the same session — hub v0.86.0 (Copy without reveal)

The operator hit a real defect in the v0.84.0 Console access card and it cost a login. Copy was disabled until a Reveal, so clicking it did nothing, silently; the clipboard kept its previous contents — another host's console password — which was pasted into demo-hp's PVE login. It failed with password check failed for user (root), which reads exactly like a stale credential and sends you diagnosing the wrong thing.

Diagnosis, read-only first: the vaulted password matched the box's /etc/shadow hash, the account was unlocked and non-expiring, no TFA, no pam_faillock — and then it minted a real PVE ticket (POST /api2/json/access/ticket → HTTP 200, root@pam, 367-char ticket). So the credential was always good; only the clipboard was wrong. That also closes the leg §7 of this report listed as operator-only — the capability-map row now records it.

v0.86.0 makes Copy work without revealing (the safer default — the secret never renders, so it cannot be shoulder-surfed or screenshotted) and closes three silent-failure branches in one eight-line function: the disabled no-op, a missing navigator.clipboard, and an ignored writeText() rejection that let the operator believe a refused write had succeeded. The success message now names the host, because the clipboard is fleet-wide and "copied" alone cannot say for which box.

Tests 566 → 568, both pinning the regression; red-proof: re-adding disabled reproduces the shipped bug. Deployed and live-verified (Synced/Healthy, image :0.86.0, button served without disabled, retrieval URL defined exactly once, all four outcome messages present). Commits 670ec35 + 80f4739.

1. Baselines

Repo main @ start of this half Version before → after
felhom.eu (hub) b4edc087fa9a hub v0.84.0 → v0.85.0
felhom-agent 6b5dade4dcc5 agent 0.118.1 → 0.119.0

2. The ask, and what it turned out to be

"Show the LAN and WireGuard IPs on the hosts page — it looks like it is not visible anywhere." Nearly exact, and the two halves were very different jobs:

  • WireGuard — the hub already had it (wg_peers.assigned_ip, GetWGPeerForHost, no UI consumer). It was visible in exactly one place, /offsite's peer table keyed by pubkey, so you could go peer→host and never host→peer.
  • LANnot renderable at all. HostReport/HostMetrics carried no address of any kind, so this needed a cross-repo agent release, not an edit. Confirmed against the struct and against a live box before proposing anything.

Operator chose: both together as one arc, with the addresses[] (iface + cidr) shape.

3. Files (hub half)

  • hub/internal/web/hosts.goparseHostAddresses, hostAddressView, hostNetworkView, hostNetwork, minAgentForAddresses, hostDetailData +1 key
  • hub/internal/web/templates/host_detail_body.html — the Network card
  • hub/internal/web/hosts_network_test.go (new)
  • hub/internal/api/testdata/host-report.golden.json — the cross-repo contract, moved in lockstep
  • hub/CHANGELOG.md, REUSE.md, manifests/hub.yaml
  • documentation/architecture/00-capability-map.md (new row), documentation/audits/host-addresses-visible-2026-07-31.md (new)

4. Commits pushed to main

Repo Commit What
felhom-agent 14642e3 v0.119.0 — the host report carries the box's addresses
felhom-agent 4663df7 REPORT
felhom.eu e07d90f hub v0.85.0 — Network card
felhom.eu 37f7ff6 manifests: hub 0.84.0 → 0.85.0

5. Tests + red-proofs (hub half)

Suite 559 → 566 (+7). go build ./... && go vet ./... && go test ./... rc=0, run separately from the commit per standing rule 1.

Test Asserts Result
TestNetwork_A_LANAddressRendered the LAN address + its interface reach the page PASS
TestNetwork_B_WireGuardAllocatedAndConfirmed WG shown once, marked confirmed, not duplicated as a plain row PASS
TestNetwork_C_AllocatedButBoxDoesNotHoldIt the drift case renders not confirmed by the box PASS
TestNetwork_D_OldAgentSaysUnknownNotNone an old agent renders UNKNOWN, never "no addresses" PASS
TestNetwork_E_NoPeerAllocated no peer → says so; the box's wg address is not silently dropped PASS
TestNetwork_F_NoReportYet never-reported host says "waiting", not "no addresses" PASS
TestParseHostAddresses_RealWire parses the real wire; empty/malformed degrade without panic PASS

The report fixture is the REAL wire — the addresses block copied out of felhom-agent --selftest=hub on demo-felhom running 0.119.0. A hand-written shape would have proved only that the parser matches my own idea of the format.

# Mutation Observed Reverted
A hostDetailData ships an empty hostNetworkView{} (the inert-seam shape) FAIL … the LAN address is not on the host page — the feature shows nothing yes
B WGConfirmed set unconditionally from the allocation FAIL … an allocated-but-unheld peer renders as healthy — the drift is invisible yes
D delete the AgentTooOld branch FAIL … an old agent's silence is not explained yes

Red-proof A took two attempts, and the first one proved nothing. The initial mutation (_ = network inside a map literal) did not compile, so the "failure" was a build error, not a test result. Recorded because a red-proof that fails to build is indistinguishable from one that lands if you only read the exit code.

6. Deployed

Image gitea.dooplex.hu/admin/felhom-hub:0.85.0 built on DooPlex and pushed; manifests/hub.yaml bumped in git; ArgoCD hard-refreshed and deliberately synced (never kubectl set image).

  • ArgoCD app felhom: Synced / Healthy
  • deploy/hub image: gitea.dooplex.hu/admin/felhom-hub:0.85.0
  • Rollout: deployment "hub" successfully rolled out (rc=0)
  • Startup log: 2026/07/31 08:50:57 [INFO] felhom-hub 0.85.0 starting

One sequencing note worth keeping: the first sync fired before ArgoCD had re-read git, so it reported Synced/Healthy while still running 0.84.0 — a green pair that meant nothing. The fix is to wait until .status.sync.revision equals the pushed commit before trusting the sync, which the final run did.

7. Live validation

Method: endpoint-level (no browser on DooPlex), against the deployed hub, cross-checked against ip addr read directly over SSH on both boxes.

Host Agent Network card, live Matches ground truth?
demo-felhom-8363b5 0.119.0 WG 10.77.0.2 confirmed; vmbr0 192.168.0.162/24, tailscale0 100.70.170.35/32 + ULA yes, exactly
demo-hp-bb76ea 0.119.0 WG 10.77.0.3 confirmed; vmbr0 192.168.0.87/24, tailscale0 100.76.96.79/32 + ULA yes, exactly
drill-r50-0a4f9a 0.113.0 WG 10.77.0.4 allocated; "agent (0.113.0) does not report its addresses — they are unknown, not absent. Needs 0.119.0 or newer." correct UNKNOWN rendering
sess-f-2670b5 old same UNKNOWN rendering correct

Correctly absent from every card: lo, vmbr9's 169.254.253.1 island literal, every fe80::.

A fifth host 404'd and it was not a bug. sess-g-e687c3 appeared in a host list I read 30 minutes earlier and returned 404 when I fetched its page; the concurrent session had deleted it as part of its scratch-customer cleanup. Chased to ground before reporting rather than filed as a defect.

8. Not yet validated / not covered

  • A box with two LAN bridges — handled by design (one row per interface) and unit-tested; no such box exists to observe.
  • A real WireGuard drift — the not confirmed branch is unit-tested and red-proofed but never seen in production, because no live peer is currently unapplied.
  • IPv4-only / IPv6-only hosts — every box here is dual-stacked via tailscale's ULA.

9. Teardown

This run provisioned nothing — no guest, no VM, no scratch customer, no external resource. The only mutations are two in-place agent upgrades (previous binaries retained as .bak-0.118.1 on both boxes), the Day-0 manifest agent vouch, and the hub image bump.

10. Backlog

  • Opened: none. Closed: none.
  • R-115 / R-121 touched, not closed. This release walked all three legs deliberately — deployed, published (round-trip verified) and vouched (read back) — so no new drift instance was created. The finding those rows record is that nothing notices when the legs diverge, which is unchanged. One small contribution: the Network card now surfaces "this host's agent is older than 0.119.0" per host, which is a per-field hint, not the installed-vs-vouched checker R-121 asks for.
  • Concurrent session: every path was staged explicitly; no foreign WIP was swept into any commit.