Files
felhom.eu/REPORT.md
T

139 lines
7.6 KiB
Markdown

# 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**.
## 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.
- **LAN** — **not 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.go``parseHostAddresses`, `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.