channelhealth: controller->agent channel health-check (periodic probe + classified operator alert) v0.90.0
New internal/channelhealth Checker: ~60s probe via the PRODUCTION memoized client (Server.ProbeAgentChannel, GET /storage), classifies failures (spike Q1 map), debounces transient reasons (N>=2; construction error latches distinctly), seeds first obs, alerts operator+dashboard on transition. Notifier.NotifyAgentChannelDown/Recovered (English, operator-only), AlertManager dashboard banner (Hungarian). No agent/hub change. Spike-proven. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EPZ4GJ8L5Jqf8UiPwbn1kt
This commit is contained in:
@@ -1,5 +1,33 @@
|
||||
## Changelog
|
||||
|
||||
### v0.90.0 — Controller→agent channel health-check (periodic probe + classified operator alert) (2026-06-29)
|
||||
- **What:** the next self-health slice — a ~60s scheduler job that proves the controller↔agent
|
||||
local-API channel, classifies failures, and alerts the operator + dashboard on a state change.
|
||||
Closes the gap the R1 pin-mismatch incident exposed (the channel was only checked once at startup and
|
||||
only logged). Spike-proven: `felhom.eu/documentation/audits/SPIKE-controller-agent-channel-health-2026-06-29.md`.
|
||||
- **`internal/channelhealth` (NEW):** a `Checker` over two seams — a `Probe` (the channel call) and a
|
||||
`Sink` (dashboard + operator notify). Each run classifies the result into `up | down:<reason>` by the
|
||||
spike Q1 error-substring map (`pin_mismatch` / `unauthorized` / `unreachable` / `timeout` /
|
||||
`misconfigured` / `construction_error` / `unknown`). **Debounce:** transient reasons (refused/timeout)
|
||||
require **N≥2 consecutive** down-probes before alerting — so the ~1s agent-restart socket gap (spike
|
||||
Q2) does NOT page; pin/401/DNS/construction alert on the first down observation. First scheduler
|
||||
observation **seeds** state without notifying (mirrors host_staleness/host_capability). A
|
||||
construction error (`agentClient()` can't build — latches via `sync.Once`) is surfaced **distinctly**.
|
||||
- **Probe via the PRODUCTION memoized client (`Server.ProbeAgentChannel`):** GET /storage through
|
||||
`s.agentClient()` — NOT a fresh `agentapi.New` per probe. Per the spike, the memoized client
|
||||
self-heals after an agent restart, reflects exactly what the disk UI sees (zero divergence), and
|
||||
avoids the per-call transport leak the singleton fixed.
|
||||
- **Operator alert + dashboard:** `Notifier.NotifyAgentChannelDown/Recovered` relay an **English,
|
||||
operator-only** event (the customer can't act on "the agent re-keyed"; the event type isn't a
|
||||
customer toggle, same as the host_* events) on a **transition** (up→down, down→up, or reason-change),
|
||||
with the existing hub 1h cooldown. `AlertManager.SetAgentChannelAlert` shows a short Hungarian
|
||||
banner whenever the channel is down (state-based, idempotent — a born-down channel shows even though
|
||||
it's seeded silently). **No customer email.** No agent or hub change (the hub relays the new event
|
||||
types generically).
|
||||
- Tests: classifier per-reason, transitions (up→down once, no duplicate, recovered, reason-change
|
||||
re-alerts), first-obs seed, and the **debounce red-proof** (one refused → no alert; two consecutive →
|
||||
exactly one). Version `0.89.0 → 0.90.0`.
|
||||
|
||||
### v0.89.0 — App-email: plaintext-only listener (:2526) + split-From mapping (2026-06-29)
|
||||
- **What:** closes the two relay gaps from `FINDING-app-email-rollout-2026-06-29.md` so the
|
||||
opportunistic-STARTTLS clients (cal.com, nextcloud) can use the relay.
|
||||
|
||||
Reference in New Issue
Block a user