13 KiB
13 KiB
Clusev v1 — Konsolidierte Fix-Liste
Alle Punkte gegen die echten Dateien geprüft. Duplikate (Focus-States, Touch-Targets, KPI-Balken, Ringe, mobile CPU/RAM-Anzeige) sind zusammengeführt. Reine Bereitschafts-/Konventionshinweise ohne Datei-Defekt sind unter „Bewusst weggelassen" gelistet.
MUST-FIX (Regelverstoß / echter Bug / A11y-Blocker)
A11y — Tastatur-Fokus unsichtbar
- Dateien:
nav-item.blade.php,topbar.blade.php(Z. 3, 16),sidebar.blade.php(Z. 10, 19, 48),server-item.blade.php(Z. 5),livewire/dashboard.blade.php(Z. 69) - Änderung: Auf jeder interaktiven Basisklasse einen Token-Fokusring ergänzen:
focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/60 focus-visible:ring-offset-2 focus-visible:ring-offset-surface. Alternativ eine Base-Layer-Regel inapp.css:*:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px }. - Grund: Null Fokus-Styles im gesamten View-Layer (per grep bestätigt) — Tastaturbedienung auf der dunklen UI ist unmöglich.
A11y — Kontrast ink-3 unter WCAG AA
- Datei:
resources/css/app.css:36(--color-ink-3: #69757F) - Änderung: Auf ca.
#7E8A95aufhellen (≈4,6:1 auf surface). - Grund: 3,95:1 auf surface —
ink-3ist Default für fast jeden Sekundärtext (IPs, Subtitles, Unit-Labels, systemd-Beschreibungen) beitext-[11px]/text-xs, also gilt 4,5:1.
A11y — Kontrast ink-4 unter WCAG AA (für Text)
- Datei:
resources/css/app.css:37(--color-ink-4: #495159) - Änderung: Für Textnutzung auf ca.
#707B85(≈4,5:1) aufhellen, oderink-4strikt auf Hairlines/Nicht-Text beschränken und betroffene Textstellen (dashboard.blade.php:107,109,server-item.blade.php:13,19) auftext-ink-3umstellen. - Grund: 2,31:1 — fällt sogar unter AA-large (3:1), wird aber für echten Lesetext (Audit-Timestamps/Targets, CPU/RAM-Spaltenlabels) genutzt.
A11y — Off-Canvas-Drawer nicht aus Tab-Order entfernt
- Datei:
resources/views/components/sidebar.blade.php:2(<aside>) - Änderung: Geschlossenen Zustand mit
x-bind:inert="!nav"(plus:aria-hidden) binden, auflgimmer interaktiv halten; Fokus beim Öffnen auf den Schließen-Button setzen. - Grund: Nur
-translate-x-fullschiebt den Drawer aus dem Bild — Tastatur/Screenreader tabben weiter in unsichtbare Off-Canvas-Links.
R7 — Touch-Targets unter 44px
- Dateien/Änderungen:
topbar.blade.php:3und:16— Menü- und Glocken-Buttonh-9 w-9→min-h-11 min-w-11(gridplace-items-centerbehalten).sidebar.blade.php:10(Schließen) und:48(Abmelden-Link<a>) —h-9 w-9→min-h-11 min-w-11.livewire/dashboard.blade.php:69— „Hinzufügen"-Buttonmin-h-9→min-h-11.
- Grund: R7 fordert ≥44px; diese realen Tap-Ziele sind 36px (Switcher/Nav-Items nutzen bereits korrekt
min-h-11).
Bug — NaN-Guard greift an der falschen Stelle
- Datei:
resources/js/app.js:34-37(push()) - Änderung:
push(v) { const n = Number(v); if (!Number.isFinite(n)) return; this.last = n; this.points.push(n); if (this.points.length > this.max) this.points.shift(); } - Grund:
Number(e.cpu)bei fehlendem/falschem Key liefertNaN; die Klammer incoords()lässtNaNdurch →<polyline>wird ungültig (Sparkline verschwindet) und der Zähler zeigtNaN%.
Bug/Leak — Reverb-Channel wird nie abgebaut
- Datei:
resources/js/app.js:26-32(init()) - Änderung: Channel-Referenz halten und
destroy() { window.Echo?.leave('metrics'); }zum Alpine-Objekt hinzufügen;state_change-Handler ebenfalls per Referenz unbinden. - Grund: Kein
Echo.leave/unbindvorhanden (grep bestätigt). Heute durch Full-Reload maskiert, aber sobaldwire:navigatefür die geplanten Server/Dienste/Dateien-Seiten kommt, stapeln sich Subscriptions auf dem Singletonwindow.Echo.
R10 — KPI-Fortschrittsbalken ignoriert den Status-Triad
- Datei:
resources/views/components/kpi.blade.php:23 - Änderung: Balkenfarbe aus
$toneableiten, z. B.$barColor = ['ink'=>'bg-accent','online'=>'bg-online','warning'=>'bg-warning','offline'=>'bg-offline','accent'=>'bg-accent','cyan'=>'bg-cyan'][$tone] ?? 'bg-accent';undbg-accentersetzen. Width-Inline-Style bleibt (R4). - Grund: Balken ist hart
bg-accent; dietone-Prop färbt nur die Zahl — eine getonte KPI mitpctzeigt orangen Balken unter grüner/roter Zahl.
Datenintegrität — Ressourcen-Ringe zeigen hartkodierte Konstanten
- Datei:
resources/views/livewire/dashboard.blade.php:57-60 - Änderung: Ringe an echte Daten binden (mind. CPU/RAM aus denselben
$avgCpu/$avgMemwie die KPIs) und Ton schwellenwertgesteuert inx-ringsetzen (grün <75, amber 75–90, rot >90) statt fixemtoneje Metrik. - Grund:
:value="34/61/48"mit statischen Tönen — „Disk" rendert amber bei 48% nur wegentone="warning", irreführend in einem Monitoring-View und entkoppelt vom Datenstrom.
R7/UX — Keine Empty-/Loading-States in den Listen
- Datei:
resources/views/livewire/dashboard.blade.php(Server73-78, systemd82-93, Audit98-112) - Änderung: Jedes
@foreachzu@forelse … @emptymit zentrierter, gedämpfter DE-Empty-Zeile (z. B.<div class="px-5 py-8 text-center font-mono text-[11px] text-ink-3">Keine Server im Cluster</div>);wire:loading-Skeleton für die per SSH/Queue hydrierten Panels. - Grund: Bare
@foreachohne Fallback (grep: 0 forelse/@empty/wire:loading) — leere Daten rendern blanke Boxen.
NICE-TO-HAVE (Polish)
A11y — prefers-reduced-motion fehlt
- Datei:
resources/views/components/status-dot.blade.php:7 - Änderung:
animate-ping→motion-safe:animate-ping, oder Base-Layer-Regel inapp.css, die.animate-pingbei reduzierter Bewegung deaktiviert. - Grund: Dauerhafte Ping-Animation auf jedem Online-Dot ohne Reduced-Motion-Guard (grep: 0).
A11y — <nav> ohne zugänglichen Namen
- Datei:
resources/views/components/sidebar.blade.php:31 - Änderung:
<nav aria-label="Hauptnavigation" …>. - Grund: Generisches „navigation"-Landmark für Screenreader.
A11y — Live-Chart Disconnected-Zustand kaum wahrnehmbar
- Datei:
resources/views/livewire/dashboard.blade.php:46 - Änderung: Dot
aria-hidden="true"(Text daneben trägt die Info) und Disconnected-Farbebg-ink-4→bg-warning::class="connected ? 'bg-online' : 'bg-warning'". - Grund:
bg-ink-4(2,3:1) ist als Statusindikator praktisch unsichtbar.
R7/Responsive — Per-Server CPU/RAM auf Mobile komplett ausgeblendet
- Datei:
resources/views/components/server-item.blade.php:11 - Änderung: Kompakte Mono-Zeile nur
<smeinblenden (z. B.CPU 34% · RAM 61%), absmauf die Balken umschalten. - Grund:
hidden sm:flexlässt unter 375px die wichtigste At-a-glance-Metrik ersatzlos verschwinden.
R7 — Server-Item-Zeile ohne Mindesthöhe
- Datei:
resources/views/components/server-item.blade.php:5 - Änderung:
min-h-11zur<a>-Klasse ergänzen. - Grund: Nur
py-2.5, keine Mindesthöhe — in der einzeiligen<sm-Variante kann die Tap-Höhe unter 44px fallen.
R10 — Drei verschiedene Gauge-Track-Tokens
- Dateien:
kpi.blade.php:22(bg-inset),server-item.blade.php:14,20(bg-line),ring.blade.php:16(text-line) - Änderung: Ein einheitliches Track-Treatment wählen (
bg-insetliest als vertiefter Kanal am besten) für alle Progress-/Gauge-Hintergründe; Ring-Track ggf. mit kräftigeremline-strong. - Grund: Gleicher „Gauge-Hintergrund"-Begriff, drei verschiedene Tokens —
bg-line(rgba 0.10) ist als Track fast unsichtbar.
Polish — Ring-Cap bei 0% und kein Übergang
- Datei:
resources/views/components/ring.blade.php:17-18 - Änderung:
stroke-linecap="butt"bzw. den Wert-Kreis per@if($v > 0)schützen, Track-Stroke verstärken,transition-[stroke-dashoffset] duration-500ergänzen. - Grund: Bei Wert 0 malt
stroke-linecap="round"einen Streu-Punkt; Live-Updates springen ohne Transition.
Polish — Sparkline ohne Baseline/Marker, verzerrter Stroke
- Datei:
resources/views/livewire/dashboard.blade.php:36-45 - Änderung:
vector-effect="non-scaling-stroke"auf die Polylines (oderpreserveAspectRatio="none"entfernen), dezente Baseline/Gridline viaborder-line, Accent-Punkt am letzten Wert. - Grund:
preserveAspectRatio="none"streckt den 1,5px-Stroke ungleichmäßig; kein Bezugsrahmen/aktueller Wert auf der Linie.
Polish — Inkonsistentes Eyebrow-Tracking
- Dateien:
dashboard.blade.php:14(tracking-[0.2em]),kpi.blade.php:10(tracking-wider),sidebar.blade.php:32(tracking-widest);server-item.blade.php:13,19(kein Tracking) - Änderung: Alle uppercase-Mono-Mikrolabels auf einen Wert vereinheitlichen (
tracking-widest), arbitrarytracking-[0.2em]ersetzen; ggf.x-eyebrow-Helper. - Grund: Gleiche Rolle (Mono-Eyebrow), vier verschiedene Letter-Spacings.
Polish — Notifications-Dot kollidiert mit Brand-Accent
- Datei:
resources/views/components/topbar.blade.php:20 - Änderung: Unread-Dot von
bg-accent(orange) aufbg-cyanoderbg-warning. - Grund: Orange liest als „aktiv/Brand", nicht als „Aufmerksamkeit"; Token-Intent für Accent wahren.
API/R11 — server-item und Abmelden-Link hart href="#"
- Dateien:
server-item.blade.php:5,sidebar.blade.php:48 - Änderung:
$href-Prop ergänzen (@props([… 'href' => '#']),<a href="{{ $href }}">), später:href="route('servers.show', $s['id'])"übergeben. - Grund: Server-Liste nicht navigierbar und kein Slot für den von R11 geforderten UUID-Route-Key.
API — kpi-tone themt Widget nur halb
- Datei:
resources/views/components/kpi.blade.php:22-24 - Änderung: Identisch zum Must-Fix oben (Balkenfarbe aus
$tone). Hier separat als API-Konsistenz notiert. - Grund:
toneimpliziert das ganze Widget, färbt aber nur die Zahl.
Datenform — Mock divergiert vom MetricsTicked/SSH-Kontrakt
- Datei:
app/Livewire/Dashboard.php:28-50 - Änderung: Jedem Server eine
id(UUID) und ein verschachteltesmetrics => ['cpu','mem','disk','series']geben, damit Panel und Ringe aus$servers[$active]lesen undMetricsTicked.server1:1 auf eine Zeile mappt. - Grund: Globale
$metrics-Serie ohne Server-Key und Rows ohne stabile id überleben den Broadcast/SSH-Kontrakt nicht.
Security-Readiness — öffentlicher metrics-Channel
- Datei:
resources/js/app.js:20(+app/Events/MetricsTicked.php) - Änderung: TODO setzen; mit Auth auf
PrivateChannel('fleet.metrics')+routes/channels.php-Gate migrieren, inapp.jsaufwindow.Echo.private(...)umstellen. - Grund: Öffentlicher Channel (kein
routes/channels.php) — jeder Browser kann Flotten-CPU abonnieren; akzeptabel in der Mock-Phase, vor echten Daten zu flaggen.
R9-Klarheit — englische systemd-Beschreibungen im Mock
- Datei:
app/Livewire/Dashboard.php:36-40 - Änderung: Entweder Code-Kommentar „spiegelt reales Unit-
Description=" (zulässig unter §6) oder bis zur echten SSH-Schicht auf knappe deutsche Beschreibungen umstellen. - Grund: Handgeschriebene Mock-Copy rendert als sichtbarer Sekundärtext (
dashboard.blade.php:88) und kann als englische UI-Copy gelesen werden.
R3/R6-Sauberkeit — totes welcome.blade.php
- Datei:
resources/views/welcome.blade.php - Änderung: Datei löschen.
- Grund: Einzige Quelle roher Hex-Farben in
resources/views, nicht geroutet/referenziert — verschmutzt jedes R3-Audit.
Defensive Formatierung — x-text="last + '%'"
- Datei:
resources/views/livewire/dashboard.blade.php:51 - Änderung:
x-text="Math.round(last) + '%'"(nach dempush()-Guard). - Grund: Verhindert lange Dezimalstellen aus dem künftigen SSH-Poller; sichtbare Oberfläche des NaN-Bugs oben.
Optional — Progressbar-Semantik
- Dateien:
kpi.blade.php:22,server-item.blade.php(Balken) - Änderung:
role="progressbar" aria-valuenow="{{ $pct }}" aria-valuemin="0" aria-valuemax="100"am Balken-Wrapper. - Grund: Server-Item-Balken haben sichtbar keinen zugeordneten Zahlenwert; niedrige Prio, da KPI die Zahl textlich zeigt.
Bewusst weggelassen (kein Datei-Defekt)
- R1–R11 Architektur: Keine echten Verstöße gefunden (Routing, Livewire-3-Klassen, Token-only Farben, German Copy, Component-Kit alle verifiziert).
config/livewire.phpfehlt: Reiner Explizitheits-/Bootstrap-Hinweis — die Livewire-3-Defaults matchen die §4-Konvention; kein funktionaler Defekt.server-itemaria-valuenow / KPI-Progress-Semantik: Als optional behalten, nicht als Blocker (siehe oben).