v0.169.0: disk-health card + degradation notification (Lemezek állapota)

Consumes the agent v0.94.0 smart payload (MinAgent floor unchanged; feature-detect
by presence). One pure verdict fn agentapi.DiskVerdictFor shared by the dashboard
card and the 6h check. Card via a 60s /disks TTL cache (anti-smartctl-storm);
unreachable agent -> Nincs adat, page never blocks. disk-health-check (6h) emits
disk_health_degraded on a degradation only vs an in-memory baseline (first run
silent, recovery/UNKNOWN never notify, multi-attr -> one event). No global banner
(deliberate). Pairs with the hub allowlist bump.

Tests: verdict table (>=90 red-proof), notifier emit, check first-run-silent
(red-proof), degradation-once, recovery-silent, UNKNOWN-excluded, FAILING-critical,
nil-smart card, TTL cache.
This commit is contained in:
2026-07-24 21:27:16 +02:00
parent e164fef70c
commit c97975c1df
16 changed files with 741 additions and 5 deletions
+28
View File
@@ -7,6 +7,7 @@ import (
"io"
"log"
"net/http"
"strings"
"sync"
"time"
@@ -428,6 +429,33 @@ func (n *Notifier) NotifyAppStartFailures(apps []AppRunState) {
}
}
// DiskHealthDetails is the event-detail payload for disk_health_degraded.
type DiskHealthDetails struct {
Disk string `json:"disk"`
Attributes []string `json:"attributes,omitempty"`
Critical bool `json:"critical"`
}
// NotifyDiskHealthDegraded fires a disk_health_degraded hub event on a disk-health DEGRADATION only
// (the controller's 6h check owns the transition logic — never first-run/recovery/UNKNOWN). severity
// is warn for a Figyelmeztetés, critical for a Hiba (FAILING). The hub applies its own per-event-type
// cooldown. NOTE: the event type "disk_health_degraded" MUST be in the hub's allowedEventTypes (else
// the hub 400s the POST) — added in the hub's v0.x bump alongside this.
func (n *Notifier) NotifyDiskHealthDegraded(label string, attrs []string, critical bool) {
severity := "warn"
var msg string
switch {
case critical:
severity = "critical"
msg = fmt.Sprintf("Lemez állapot romlás: %s — a lemez SMART önellenőrzése hibát jelez. Kérjük, mentse az adatait, és vegye fel velünk a kapcsolatot.", label)
case len(attrs) > 0:
msg = fmt.Sprintf("Lemez állapot romlás: %s — romló érték: %s. Javasolt figyelemmel kísérni.", label, strings.Join(attrs, ", "))
default:
msg = fmt.Sprintf("Lemez állapot romlás: %s — a lemez állapota romlott. Javasolt figyelemmel kísérni.", label)
}
n.emit("disk_health_degraded", severity, msg, DiskHealthDetails{Disk: label, Attributes: attrs, Critical: critical})
}
// emit sends an event through the test seam if set, else the real async PushEvent.
func (n *Notifier) emit(eventType, severity, message string, details interface{}) {
if n.pushFn != nil {