Feedback on the new feature pages: buttons were oversized and Docker showed an empty list where
containers exist.
- Buttons: the new pages (groups, alerts×2, commands×2, certs, health) plus settings/login-protection
used size="lg" (h-11) on inline form-submit buttons, dwarfing the h-9 inputs and the surrounding
pills. Drop to the default `sm` (h-8) — matching every other form in the app (e.g. the e-mail save
button). The auth full-width CTAs keep size="lg" (their intended use); x-ring size="lg" is unrelated.
- Docker "empty" bug: DockerService::containers used `docker ps --format '{{json .}}'` (needs a modern
Docker AND depends on JSON key casing) and returned [] on ANY failure — so a daemon/permission/
rootless-socket error read as "no containers". Switched to a tab-separated `--format` (portable to
much older Docker, state derived from the Status text) and it now THROWS the real error on failure;
the page shows that reason instead of a misleading empty state (so the actual cause is visible).
- Patch rows: the pending/security/up-to-date pills now match the action button height (h-8) so the
row reads cleanly.
DockerServiceTest updated (tab-parse + state-from-status + throws-real-error). 742 tests green, Pint,
vite build clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Uptime monitoring for the services the fleet hosts: HTTP and TCP probes with a live up/down status
board. Completes the monitoring trio (alerts, certs, uptime).
- HealthService::probe(check): native — Laravel HTTP client (withoutRedirecting; reports only the
status code + latency, never the response body → no internal-content exfil) for http, a PHP TCP
stream for tcp. No SSH, no shell, so the target is never interpolated into a command. 2xx/3xx = up;
a 4xx/5xx means "answered but unhealthy"; a connect error = down.
- Health\Index page (route /health, `operate`-gated: route + mount + per-method). Add/remove checks
(http target validated as a real http(s) URL; tcp target as a hostname/IP + a required port). Lazy
per-check probe, each guarded. Up/total summary. Delete via signed ConfirmToken + R5 modal.
Add/delete audited.
- lang/{de,en}/health.php + audit.php health.check_* + shell.nav_health (de/en parity). No emoji.
11 new tests: service (http 2xx up / 5xx down / connection-error down, tcp refused-port down),
component (route gating, add http + audit, reject non-url http target, tcp requires host+port,
reject missing port, scan probes each check, delete via confirmed token). 742 tests green, Pint,
lang parity, self-reviewed. A PUBLIC (unauthenticated) status page is a documented future.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>