The SSE stream already carried health.changed, health.stale, signal.raised,
signal.resolved and coverage.unmonitored, but two of the places that render
health never listened for them.
- The Fleet table refreshed only on entity.*, so its Health column sat at
whatever it was when the page mounted while the map view beside it — which
did listen — updated live. Health arrives on its own events, not entity.*.
Coalesced on a 400ms timer because health.stale fires once per entity during
a sweep, and refetching the whole fleet per event would mean a burst of
identical requests.
- The entity detail window loaded health, signals and monitoring once on open
and never again, so a window left on screen kept showing the health it had
at mount. That is the same staleness this whole change set has been about,
reproduced one window at a time. Now scoped by entity_id, and re-reads only
what a health or signal event can actually change rather than re-running the
full 11-request load().
Verified against live prod: flipping lxc:apps healthy -> degraded -> healthy
updated the Fleet table and an open detail window together, without a reload.
Co-Authored-By: Claude <noreply@anthropic.com>