Commit Graph

3 Commits (feat/v1-foundation)

Author SHA1 Message Date
boban 265136fc42 Metric history fix, service-failure audit trail, alert channels + secret-retarget hardening
Metric history: the per-minute sampler (clusev:sample-metrics) now reads
cpu/mem/disk from the `servers` DB row — the same source the live gauges read,
shared via MariaDB — instead of a cross-container Redis cache the poller may
not share in prod. It gates on last_seen_at freshness (skip offline/unpolled)
and keeps `load` as a best-effort cache read. History now fills whenever the
gauges have data, independent of the cache driver or container split — the
prod detail page no longer shows "Noch keine Verlaufsdaten" after hours.

Service-action failures are persisted: a failed systemctl start/stop/restart
writes a red service.<op>.failed AuditEvent with the FULL systemctl reason in
meta['output'] (mb_scrub-ed, 4000-cap), shown expandable in the audit log — a
truncated, ephemeral toast is no longer the only trace. The failure toast is a
short pointer to the audit log, level=error, and error toasts now linger 9s.

Alert delivery: a warning banner appears on the alerts page when NO channel
would reach anyone (no SMTP + no safe webhook + no Gotify). A new Gotify push
channel (server URL + encrypted app token) posts title/message/priority with
the token in X-Gotify-Key; a self-hosted LAN Gotify is allowed (scheme-checked,
not private-range-blocked like the SSRF-guarded webhooks) — a real push when a
service goes down, no e-mail needed.

Secret-retarget hardening (Codex-found class): changing a target while leaving
its secret blank could send the OLD secret to the NEW endpoint. Closed for the
Gotify token, the SMTP password (save + test-send + the runtime mailer), and
the host-terminal SSH credential (username/port change) — each drops/forbids
the stale secret before the new target is stored. Setting::uncached() reads the
security-sensitive keys DB-direct so a cache-repopulation race can't re-pair an
old secret with a new target. Three Codex rounds, clean; 778 tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 22:21:54 +02:00
boban 4d349eebb9 fix: alert mail on queue, SMTP reset, cert/uptime auto-probe, pill heights, XSS
Batch of user-reported fixes + two findings from the nav-split audit.

Bugs:
- Alerts never e-mailed. AppServiceProvider::applyMailSettings() ran only
  at boot; the long-lived QUEUE worker booted once, so SMTP configured
  after worker start (the normal case) meant queued alert/reset mail used
  the stale/log mailer. Re-apply the DB SMTP config before every job
  (Queue::before) so queued mail always sends with the current settings.
- SMTP could not be fully reset. Add Email::clearConfig() (+ a Reset
  button + Setting::forget) that removes every mail_* setting, reverting
  the panel to the safe default (log) mailer.
- New cert endpoint / uptime check showed no validity/status until a
  manual refresh. Certs\Index::addEndpoint + Health\Index::addCheck now
  probe the just-added row immediately.

Audit findings (096ba3c..HEAD):
- HIGH stored/DOM XSS: the per-server Terminal tab rendered the server
  name inside an Alpine x-text JS sink (`x-text="title || '{{ name }}'"`);
  Blade escaping does not protect that context. Move the fallback to a
  data-attribute read as a plain string (server-terminal + the host
  terminal for consistency).
- LOW: /terminal is now admin-only, but the command-palette `g t` leader
  key still sent every role there → 403. Drop it from the static map;
  render it as a role-filtered nav entry (admins only).

UI:
- status-pill is h-8 now (the small-button height) so a status pill and
  the action buttons in the same row line up (Services/Certs/Docker/…).

748 tests (new clearConfig test); R12-verified (uniform pill/button
heights). Marketing docs at ~/clusev-site reworded to remove the
contradictory domain/CLUSEV_DOMAIN install note.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 19:46:46 +02:00
boban 73eecd03e0 feat(mail): SMTP configuration in Settings (encrypted password, runtime override, test-send)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 23:42:19 +02:00