clusev/app/Livewire
boban 0472b3531a feat(alerts): threshold alerting + notifications (feature 2/8)
Turns the existing metrics into an ops tool: rules that fire when a server crosses a
threshold and resolve when it recovers, with e-mail + webhook notifications. The event
sink later features (cert-expiry, uptime-down, patch-available, posture-drop) plug into.

- alert_rules (metric cpu|mem|disk|load|offline, comparator gt|lt, threshold, scope
  all|group|server) + alert_incidents (firing|resolved, FK cascade).
- AlertEvaluator — per-server state machine: opens ONE firing incident on a fresh breach
  (notifies), resolves on recovery (notifies), dedups a sustained breach (one breach = one
  alert). Numeric metrics skip a truly-offline server (stale reading); the `offline` rule
  fires only on offline, not a reachable "warning".
- AlertNotifier — best-effort e-mail (queued Mailable to configured recipients, falls back
  to admin e-mails) + generic webhook JSON POST (Slack/Discord/Mattermost/custom; only http(s)
  URLs). Every channel is wrapped so a broken SMTP/unreachable hook is logged, never thrown.
- PollMetrics evaluates after each poll (online, fresh status) and on a failed poll (offline),
  each guarded so an alerting error can never kill the poll loop.
- Alerts\Index page, manage-panel (admin): route can:-mw + mount() + per-method gate() on every
  mutation. Rule delete via signed ConfirmToken + R5 modal (no double audit). Scope group/server
  resolves a client UUID to an id server-side (never trusts a client id). Channels saved to
  Settings. Sidebar "Alarme" nav + firing-incident badge (cached 60s).
- lang/{de,en}/alerts.php + audit.php alert.* + shell.nav_alerts (de/en parity). No emoji.

Codex review raised three MEDIUMs, all fixed here:
- Webhook SSRF: strict http(s) scheme + reject hosts resolving to loopback/private/link-local/
  reserved ranges (blocks the 169.254.169.254 cloud-metadata classic), validated at save AND send,
  redirects disabled — so an admin-configured hook can't be pointed at an internal service.
- Incident dedup is now a DB invariant: a unique `firing_key` ("{rule}:{server}" while firing,
  null on resolve) means two concurrent poll ticks can't both open a duplicate incident (the loser
  hits a unique violation, caught → no-op).
- `load` is float-safe: threshold + incident value are decimal, compared as floats, so load 1.5 vs
  threshold 1 fires (it used to truncate to 1 > 1 = false).

31 new tests: evaluator (fire/resolve/dedup, offline vs warning, scope all/group/server, disabled,
fractional-load, firing_key unique, key-freed-on-resolve), notifier (email/fallback/webhook/
non-http-ignored/failure-swallowed/SSRF-reject/public-accept), component (RBAC route gating, rule
CRUD, uuid→id scope resolve, offline→threshold 0, toggle, delete via token, channels, unsafe-webhook
rejected, incidents render). 669 tests green, Pint, lang parity, Codex-reviewed (fixes applied).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 20:07:54 +02:00
..
Alerts feat(alerts): threshold alerting + notifications (feature 2/8) 2026-07-05 20:07:54 +02:00
Audit fix(rbac,honeypot): gate audit-retention + email sendTest; honeytoken scans JSON body 2026-07-05 02:28:13 +02:00
Auth feat(auth): drop password complexity — minimum is now just 6 characters 2026-06-26 06:29:33 +02:00
Concerns perf(fleet,wg) + i18n(dashboard,update) + a11y(btn): re-audit design/perf cleanups 2026-07-05 17:10:19 +02:00
Files fix(security): close file-read RBAC gap + fail2ban arg-injection + update/HMAC hardening 2026-07-05 16:05:16 +02:00
Help feat(wg): WireGuard help topic (registration + DE/EN content + test) 2026-06-20 22:46:04 +02:00
Modals fix(security): close file-read RBAC gap + fail2ban arg-injection + update/HMAC hardening 2026-07-05 16:05:16 +02:00
Onboarding feat(onboarding): first-run spotlight tour — dimmed backdrop, sidebar highlights, relaunchable 2026-07-02 20:00:19 +02:00
Release refactor(release): single stable channel — cut internal release candidates (-rc), remove all beta wording 2026-07-05 13:13:09 +02:00
Servers feat(fleet): server groups — organise the fleet + filter (feature 1/8) 2026-07-05 19:36:17 +02:00
Services feat(rbac): gate service + file mutations behind operate (viewer read-only) 2026-07-05 01:06:06 +02:00
Settings fix(rbac,honeypot): gate audit-retention + email sendTest; honeytoken scans JSON body 2026-07-05 02:28:13 +02:00
System feat(rbac): gate fleet, host terminal + domain/TLS actions (manage-fleet/operate/manage-panel) 2026-07-05 01:01:24 +02:00
Terminal feat(rbac): gate fleet, host terminal + domain/TLS actions (manage-fleet/operate/manage-panel) 2026-07-05 01:01:24 +02:00
Threats harden honeypot/ban path: close evasions, unmask & audit-DoS vectors 2026-07-05 15:05:35 +02:00
Versions feat(rbac): gate network + panel actions (manage-network/manage-panel) 2026-07-05 00:52:09 +02:00
Wireguard perf(fleet,wg) + i18n(dashboard,update) + a11y(btn): re-audit design/perf cleanups 2026-07-05 17:10:19 +02:00
Dashboard.php i18n: complete DE/EN localization (modals, shell, backend) + v0.3.0 2026-06-13 23:27:42 +02:00
ServerSwitcher.php fix(ui): keep the sidebar server-switcher in sync with the viewed server 2026-06-14 19:24:56 +02:00