Commit Graph

7 Commits (ec1516184e4966e92fb22e210fd6b3fd329e8cdb)

Author SHA1 Message Date
boban ec1516184e i18n: complete DE/EN localization (modals, shell, backend) + v0.3.0
- modals: wire 5 hard-coded views + 10 components to lang/{de,en}/modals.php
- shell: command-palette (incl. app.js cmdk(nav,actions) refactor), server-item,
  toaster fallback
- backend: new lang/{de,en}/backend.php; localize Hardening/Firewall/Fail2ban/
  Maintenance services, OsProfile, plus FleetService + CredentialVault errors
- fix: localized page <title> on Dashboard/Servers index+show (->title(), the
  Livewire-3 way; the stray title() methods were never auto-called)
- fix: topbar inline @php() was swallowed by Blade's raw-block precompiler up to a
  later @endphp -> 500 on every authed page; converted to block @php ... @endphp
- versions: localize changelog section labels via a canonical heading map
- translation-quality pass: Unlock, Add credentials, clearer auth/notify copy

Bump 0.2.1 -> 0.3.0; CHANGELOG.

Verified: Pint clean; npm build OK; R12 all routes HTTP 200 + 0 console errors in
BOTH locales (titles/nav/labels switch language); 589 used keys resolve in de+en
with full group parity; Codex review clean; adversarial DE/EN audit (0 high).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 23:27:42 +02:00
boban 2c533bf821 feat(ux): command palette (Strg/⌘-K) + keyboard shortcuts
A global command palette and keyboard shortcuts, mounted once in the persistent
layout with a single global keydown listener.

- Strg/⌘-K opens the palette: fuzzy-filter nav targets (German, from the sidebar) +
  "Server hinzufügen"; ↑/↓ to move, Enter to run, Esc to close. Navigation uses
  window.Livewire.navigate (SPA-fast).
- Leader "g" + key: d=Dashboard, s=Server, i=Dienste, f=Dateien, l=Audit-Log,
  e=Einstellungen, y=System, v=Version.
- "/" focuses the page search ([data-page-search] on services/servers/audit) — but
  only consumes the key when such a field exists, so the browser quick-find still
  works elsewhere.
- "?" shows a shortcut-help overlay.
- Typing guard: shortcuts never fire inside inputs/textarea/select/contentEditable.
- Alpine destroy() removes the navigation listener (no leak across wire:navigate);
  topbar gains a "Strg K" trigger button. New icons: command, corner-down-left.

R5/R3/R9 respected: the palette only navigates or opens the existing (R5) create-server
modal — zero direct destructive actions; tokens-only styling, German, no emoji.

Pint clean; Codex review clean (destroy cleanup + slash-passthrough hardened); R12 —
verified in-browser: Ctrl-K opens, filter works, Esc closes, g+f navigates, ? help,
HTTP 200, 0 console errors.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 20:38:22 +02:00
boban b9b0f62d78 feat(ssh): wire real fleet data over SSH (FleetService + live poller)
Replace the page mock data with real reads from the target host via the
phpseclib SSH layer. New FleetService parses raw command output into the exact
shapes the Livewire pages already consume; all parsing forces LC_ALL=C and reads
/proc to stay locale-independent.

- app/Services/FleetService.php: metrics (cpu via two /proc/stat samples, mem via
  /proc/meminfo, disk via df), full snapshot (identity/specs incl. virt+disk_gb,
  volumes, interfaces from ip+/proc/net/dev, sshd/fail2ban/ufw hardening, authorized
  keys), systemd units + journal, and an ls-based directory listing. One compound
  command per read; connect/parse failures bubble up.
- clusev:poll-metrics command replaces the mock emitter in the dev supervisor:
  polls every credentialed server, persists cpu/mem/disk/status, broadcasts
  MetricsTicked(server) — unreachable boxes flagged offline, loop never dies.
- Pages wired with graceful failure (offline state, never a 500):
  Dashboard (live cached metrics + notable units), Services (real units+journal),
  Files (real listing + dir navigation via open/go/up), Server-Details (live
  snapshot persisted onto the row + offline banner).
- WithFleetContext prefers a credentialed, non-offline server as the default.
- dualChart filters ticks by server name so the chart tracks the active host.

Verified live against a real Debian 13 box: metrics/services(91)/journal(25)/
files(navigable)/snapshot(5 ifaces, real hardening, real key) all parse correctly.
Credentials are stored encrypted in the vault — never in source.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 21:34:13 +02:00
boban 688e9e7866 feat: reference-depth dashboard (sparkline KPIs + live dual chart + table)
Align the dashboard to the BASTION reference (clusev-template) — the active
server's detail view:
- x-metric: KPI tiles with sparklines + trend (CPU/Memory/Disk/Load).
- live dual-series chart (CPU+MEM, grid + Y/X axes + legend) as a dualChart
  Alpine island; MetricsTicked + clusev:mock-metrics now broadcast CPU+MEM.
  Static SSR paths remain as the no-JS fallback.
- systemd services as a table.
Tokens/currentColor only — no inline styles; Y-axis via utilities.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 14:44:11 +02:00
boban 47eae61371 fix: apply v1 UI review (a11y, contrast, live-chart robustness)
- Focus-visible token ring + prefers-reduced-motion guard (app.css).
- Lift ink-3/ink-4 to WCAG-AA text contrast.
- Touch targets >=44px (topbar, sidebar, dashboard buttons).
- Off-canvas drawer removed from tab order when closed (breakpoint-aware inert)
  + sidebar aria-label.
- Live chart: NaN guard on incoming cpu; Echo.leave('metrics') + unbind on
  destroy (no subscription leak under wire:navigate).
- KPI progress bar follows the tone (status triad), not always accent.
- Resource rings bound to real server data with threshold-based tone.
- docs/v1-ui-review.md: full adversarial review.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 06:16:52 +02:00
boban 8df4456108 feat: live metrics over Reverb (mock emitter)
- MetricsTicked broadcast event (channel 'metrics', as 'tick') + a
  clusev:mock-metrics command (dev placeholder for the SSH MetricsPoller),
  broadcasting a rolling CPU value every 2s.
- Echo + pusher-js client in app.js with an env-driven Reverb connection
  (VITE_REVERB_*). metricsChart Alpine island seeds from server data, appends
  each tick and redraws the sparkline; the indicator reflects the real WS state.
- Published config/reverb.php + config/broadcasting.php.
- Backend verified: the queue processes MetricsTicked every 2s with no errors.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 01:23:10 +02:00
boban 53f7309c0b feat: scaffold — Dockerized Laravel 13 + Livewire 3 + Tailwind 4 + Reverb
Working dev stack on :80 (Freigabe step 5: app boots, page renders, Vite HMR runs):
- Multi-stage Dockerfile (php8.3-fpm + nginx + supervisor + node). Dev runs
  php-fpm + nginx + vite in ONE app container; prod target bakes vendor + assets.
- docker-compose.yml (dev, bind-mount) + docker-compose.prod.yml (GHCR image).
  Env-driven ports/UID (APP_PORT, VITE_PORT, REVERB_HOST_PORT, DB_PORT,
  HOST_UID/HOST_GID) — nothing hardcoded. MariaDB only on 127.0.0.1:3306.
- Laravel 13, Livewire 3.8 (class-based, no Volt), wire-elements/modal 2,
  phpseclib 3, laravel/reverb 1. composer platform pinned to php 8.3.
- Tailwind v4 @theme tokens ("Tactical Terminal") in app.css; Vite remote HMR
  (host 0.0.0.0, hmr.host 10.10.90.136).
- Dashboard as a full-page Livewire route (/) in layouts/app; §5 folder skeleton.
- Docs: rules.md R1-R11 (incl. R11 UUID-in-URLs) + CLAUDE.md updated for
  Laravel 13, clusev/ root, port 80, vite-in-app, env-driven config.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 00:31:50 +02:00