Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pg8ANF97SEeKYSN5Jxw3qJ
1.9 KiB
REPORT — agent reports served leaf fingerprint (hub re-key detection, Part A), v0.48.0
Task: the last self-health leg — the agent reports its served local-API leaf fingerprint so the
hub can detect an agent re-key fleet-wide (host_leaf_changed, hub v0.22.x). This repo = Part A.
Baseline: agent main @ 3844df7 (v0.47.0) → v0.48.0 @ bf8e3be, sha a3dad050….
Change
internal/hub/report.go: newHostReport.LeafFingerprint string(json:"leaf_fingerprint") — the SHA-256 of the leaf the agent currently serves. Empty when the local API is disabled (no leaf) → the hub treats "" as unknown, never an alert. Not a secret (the fp is public; the token is never reported).internal/hub/collect.go+cmd/felhom-agent/main.go:Collector.SetLeafFingerprint(fp)threads thefpfromEnsureLeaf(the SAME value the LOADED/REGENERATED log reports) into every report, next toCapabilities.
Tests (green: go build/vet/test ./...)
TestCollect_LeafFingerprint: the report carries the fp when set, and "" when unset (local API
disabled) — companion proving the threading is what populates it. The golden + contract + field-names
tests updated; the cross-repo golden mirrors leaf_fingerprint (byte-identical with the hub copy).
Live validation (felhom-pve) — PASS
Deployed 0.48.0 (leaf LOADED fp 60b5974d…, capabilities 45/45). The hub received the report with
leaf_fingerprint: 60b5974d… (confirmed in the hub DB), then — during the end-to-end re-key test — a
regenerated leaf (82078fab…) and its restore (60b5974d…) both rode the report stream and the hub
raised host_leaf_changed on the change (see felhom.eu/REPORT.md). Final state: leaf == pin
60b5974d…, capabilities 45/45, channel recovered.
NOT changed
The pin/transport, the token store, the sudoers/capability surface, the swap, the channel-health logic. Report contract + collector threading only.