Files
felhom.eu/REPORT.md
T

54 lines
3.2 KiB
Markdown

# felhom.eu — task reports
> **Overwrite** this file with a summary of the most recent task only (uniform with the other repos; not cumulative). The cumulative hub history lives in [hub/CHANGELOG.md](hub/CHANGELOG.md).
---
# REPORT — hub v0.24.0: dispatcher routes `critical` (NAS A2, "Part 0")
**Date:** 2026-06-30
**Task:** `TASK.md` Part 0 — the hub dispatcher fix that ships alongside NAS Part A2 (controller work is in
the felhom-controller repo, v0.92.0).
## Baseline
| | value |
|---|---|
| Hub before | v0.23.0 |
| Hub after | **v0.24.0** — code `0ff1d3c`, manifest bump `87f0794` |
| Live image | `felhom-hub:0.24.0` (ArgoCD `felhom` Synced/Healthy) |
## What changed
- **`internal/notify/dispatcher.go` `ProcessEvent`:** the severity gate was `!= "warning" && != "error"`
a `critical`-severity event was **silently dropped** (never emailed). Now routes **warning / error /
critical** (`severityNotifies`); `info` stays an intentional non-notify; an **unrecognized** severity is
**logged** (`[WARN] Dispatcher: unrecognized severity …`), never silently dropped.
- **`internal/monitor/host_disk.go`:** `host_disk_critical` now emits its **natural `critical` severity**
(was forced to `error` to survive the old gate); `FormatOperatorEmail` styles `critical` 🔴 like `error`.
- **Latent crash guard:** `processCustomer` dereferenced `GetNotificationPrefs`, which returns `(nil, nil)`
for a customer with no notification row — an event for such a customer would have **panicked the dispatcher
goroutine and crashed the hub**. Now guards `prefs == nil`.
- **Seam:** `sendEmailFn` so routing is unit-tested without real HTTP.
- Verified safe first (§9 rule 5): grep confirmed **no** event currently emits `critical` (all controller
events are info/warning/error; the hub's only would-be `critical` emitter is `host_disk`) → no surprise
alert volume.
## Tests — `go build ./... && go vet ./... && go test ./...` GREEN
`severityNotifies` (warning/error/critical notify; info/unknown don't) + **companion red-proof** (the pre-fix
`warning||error` predicate drops `critical`); ProcessEvent routes `critical` to the operator; an unknown
severity is logged not dropped; `info` is silent and not mis-logged.
## Deploy + validation
Deployed via the GitOps manifest path (image build+push; `manifests/hub.yaml` 0.23.0→0.24.0; ArgoCD
hard-refresh → OutOfSync → sync → **Synced/Healthy**), per the repo convention (not bare `kubectl set
image`). Startup clean; the `host_disk` checker re-seeded `1 ok` (the demo host root is at 24% after the
prior task's prune). The critical-routing fix is unit-validated; not re-fired live (the demo disk is below
threshold). The downstream A2 NAS live e2e (add → jellyfin reads → kill → unreachable warning, no cascade →
recover → remove) was validated against an isolated sim NAS — see `felhom-controller/REPORT.md`.
## Observations / follow-ups
- Per-storage `StorageTargets` worst-fill alerting remains the easy follow-on to `host_disk`.
- Part B (restic-over-SFTP NAS backup target) still pending — separate task.
No secrets committed. Operator email address is the operator's own; the Resend key stays injected from
`Secret/resend-api`.