# 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`:** new `HostReport.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
  the `fp` from `EnsureLeaf` (the SAME value the LOADED/REGENERATED log reports) into every report, next
  to `Capabilities`.

## 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.
