# #027 Protokollansicht, CSV-Export, Syslog **Status:** erledigt **Meilenstein:** v0.5.0 **Labels:** ui, backend **Geschätzt:** 2 h **Tatsächlich:** 0 h 20 min ## Ziel Filterbare Ansicht, CSV, optionale Weiterleitung an Syslog. ## Aufgaben - [x] `/protokoll` statt Platzhalter, jede Rolle liest: Tabelle mit Zeitpunkt (TT.MM.JJJJ HH:MM:SS), Aktion (lesbar, farbig), Akteur, Host, Zielbenutzer, Fingerprint (gekürzt), Ergebnis; unter `md` Karten - [x] Zeile aufklappbar: Diff im Diff-Box-Stil, Details als Liste (Werte als JSON), Hash und Vorgänger-Hash - [x] Lesbare Texte für alle Aktionen in `src/lib/protokoll-aktionen.ts`, gruppiert (Anmeldung, Host-Key, Ausrollen, Schlüssel, Widerruf/Rotation, Zielkonto, Abgleich, Hosts, Personen und Vorlagen, Protokoll) - [x] Filter per GET: Zeitraum (Berliner Kalendertage), Aktionsgruppe, Akteur, Host, Ergebnis, Freitext (Fingerprint/Host/Benutzer) - [x] 50 je Seite, „Ältere laden“ hängt per Server Action an; Cursor über `id`, kein `OFFSET`; `?vor=` als Einstieg - [x] Kopfzeile mit Anzahl und Syslog-Ziel; „Kette prüfen“ (Server Action) mit Ergebnis-Zwischenspeicher für 5 Minuten, Warnung mit Link auf die erste fehlerhafte ID - [x] CSV-Export `/api/protokoll.csv`: eigene Rechteprüfung, gleiche Filter, gestreamt in Stapeln zu 500, Formel-Entschärfung über `src/lib/csv.ts`, Export selbst als `protokoll.exportiert` protokolliert - [x] Kein Lösch-/Bearbeitungsweg; struktureller Test gegen `protokoll.update/delete…` und `UPDATE/DELETE/TRUNCATE "Protokoll"` in `src/` - [x] Syslog nach RFC 5424 (`src/lib/syslog.ts`, UDP oder TCP mit Oktettzählung, ohne neue Abhängigkeit), eingehängt in `protokollieren()` nach dem Schreiben - [x] `.env.example` und `docker-compose.yml` (web und worker) um `SSHKV_SYSLOG_*` - [x] Tests: Query/Cursor/Filter, CSV-Route, Kettenprüfung, Syslog (Format, Escaping, Länge, UDP-/TCP-Empfänger), Aktionstexte, Struktur; E2E `tests/e2e/protokoll.spec.ts` - [x] Screenshots `protokoll-desktop.png` und `protokoll-mobil.png` ## Akzeptanzkriterien - [x] Jede `aktion: "…"` im Quellcode hat einen lesbaren Text (Test) - [x] Filter und „Ältere laden“ liefern weder Lücken noch Doppelte, auch wenn zwischendurch Einträge dazukommen - [x] CSV ohne Sitzung → 403; Kopfzeile `id;zeitpunkt;akteur;aktion;…;hash`; große Protokolle werden in Stapeln gelesen - [x] Manipulierte Zeile → Warnung mit ID; unversehrte Kette → „Hash-Kette unversehrt“ - [x] Ausgefallener Syslog-Server verhindert keine Aktion; Fehler höchstens einmal je Minute im Log - [x] 1440 und 390 px ohne Querscrollen ## Abhängigkeiten #005 ## Notizen / Entscheidungen - **Kettenprüfung nur auf Knopfdruck, 5 Minuten zwischengespeichert (je Prozess).** `protokoll_kette_pruefen()` rechnet SHA-256 über jede Zeile und wächst linear mit dem Protokoll; beim bloßen Seitenaufruf wäre das bei 100 000 Einträgen spürbar. Gleichzeitige Klicks teilen sich eine laufende Prüfung. Ein Bruch wird selbst als `protokoll.kette_beschaedigt` (FEHLER) protokolliert, damit er auch beim Syslog ankommt. - **CSV gestreamt** über einen `ReadableStream` mit `pull`: je Stapel 500 Zeilen (Cursor über `id`), der nächste Stapel erst, wenn der Client den vorigen abgenommen hat. Der Exporteintrag wird vor dem ersten Byte geschrieben – scheitert er, gibt es keinen Export. - **IDs sind nicht lückenlos** (Spalten-Default und Trigger ziehen beide aus der Sequenz); Cursor und Tests verlassen sich nur auf die Ordnung. - **Syslog:** RFC 5424, SD-ID `sshkv@32473`, Parameter id/akteur/aktion/ergebnis/host/zielbenutzer/fingerprint/hash (escaped nach §6.3.3, Steuerzeichen ersetzt, je Wert ≤ 120 Byte, Zeile ≤ 2048 Byte), MSGID = Aktion, Severity ERFOLG=notice, VERWEIGERT=warning, FEHLER=err, Facility standardmäßig `authpriv` (`SSHKV_SYSLOG_FACILITY`). Diff und Details gehen nie hinaus. Fire-and-forget nach dem `create`; innerhalb einer Transaktion kann ein späterer Rollback eine Syslog-Zeile ohne Gegenstück hinterlassen – das ist die harmlosere Richtung (ihr Hash fehlt dann in der Kette). - `--ok` nur für erfolgreiche Aktionen, die etwas ändern; Anmeldungen, Abrufe und Export bleiben neutral, Fehler/Verweigert immer `--danger`.