# Changelog Alle nennenswerten Änderungen an FLORIAN. Format nach [Keep a Changelog](https://keepachangelog.com/de/1.1.0/), Versionierung nach [Semantic Versioning](https://semver.org/lang/de/). Die Regeln dazu stehen in [docs/VERSIONIERUNG.md](docs/VERSIONIERUNG.md). ## [Unveröffentlicht] Nächster Schritt ist Phase 2 (Wartungs- und Prüfmanagement). ### Hinzugefügt - **Formular zum Anlegen und Bearbeiten eines Geräts** (`/geraete/neu` und `/geraete//bearbeiten`). Damit ist die letzte offene Lücke aus Phase 1 geschlossen: Ein Neuzugang lässt sich einzeln erfassen, ohne den Umweg über eine Importdatei. - Die Lagerung wird als Umschalter geführt statt als zwei Auswahlfelder, die man versehentlich beide füllen kann. - Prüftermin und Lebensdauerende werden schon beim Tippen ausgerechnet und angezeigt — mit denselben Funktionen, mit denen der Server anschließend rechnet. - Ist nur ein Standort angelegt, wird er vorbelegt. - 7 weitere Playwright-Tests zum Formular (nun 58 statt 44, zwei davon unter Touch-Emulation begründet übersprungen). ### Behoben - **Das Formular stürzte beim ersten Rechnen ab.** Die Vorgabewerte lagen in einem `"use client"`-Modul und wurden von einer Server-Komponente importiert; dort kommt nur eine Client-Referenz an, kein Objekt. Das Spreaden davon ergab lauter `undefined`. Die Werte liegen jetzt in einem eigenen Modul ohne `"use client"`. - **Das Sternchen an Pflichtfeldern wurde vorgelesen.** Eine Sprachausgabe nannte das Feld „Bezeichnung Stern". Das Sternchen trägt jetzt `aria-hidden`; dass ein Feld ausgefüllt werden muss, sagt das `required`-Attribut. - Fehlermeldungen in Formularen sind eindeutig ansteuerbar (`data-testid`) — Next.js hängt einen eigenen Routen-Ansager mit derselben Rolle in jede Seite. ## [0.2.0] — 2026-09-03 Phase 1: Stammdaten. Ab hier führt die Wehr ihren Bestand in FLORIAN — mit Standorten, Fahrzeugen samt Beladeordnung, Gerätetypen als Vorgabe und Geräten, die per QR-Code am Regal auffindbar sind. ### Hinzugefügt **Datenmodell** - `Standort` (Gerätehaus, Lager, Außenstelle, Werkstatt) mit PostGIS-Punkt für die Karte ab Phase 6. - `Geraeteraum` — die Fächer am Fahrzeug (G1 bis G6, Heck, Dach, Mannschaftsraum), in Beladereihenfolge sortierbar. - `Geraetetyp` als Vorgabe für Prüfintervall, Prüfvorschrift und Lebensdauer. Ein einzelnes Gerät darf davon abweichen; sonst gilt der Typ. - `Qualifikationstyp` und `Qualifikation` mit Gültigkeitsdauer und eigener Vorwarnzeit je Typ. - `Fahrzeug` erweitert um Fahrgestellnummer, DIN-Typkurzzeichen, Erstzulassung, Sitzplätze, Tankinhalt, Gesamtmasse und die UVV-Frist. - `Geraet` erweitert um Gerätetyp, Lebensdauerkategorie, errechnetes Lebensdauerende, Anschaffungspreis und die Lagerung. **Regeln in der Datenbank** - Ein Gerät steht entweder an einem Standort oder ist auf einem Fahrzeug verlastet — eine Prüfbedingung setzt das durch, ein Trigger stellt zusätzlich sicher, dass ein angegebener Geräteraum auch zum angegebenen Fahrzeug gehört. - Row Level Security auf allen neuen Tabellen. - Trigram-Indizes für die Volltextsuche über Geräte, Fahrzeuge und Personen. **Funktionen** - Geräteliste mit Volltextsuche, Statusfilter, serverseitiger Sortierung, Blättern und Spaltenauswahl. Die Spaltenauswahl bleibt je Browser gespeichert. - Massenbearbeitung: Status mehrerer Geräte auf einmal setzen, Geräte umlagern. Jede Änderung erzeugt einen eigenen Protokolleintrag am jeweiligen Gerät. - QR-Code je Gerät. Der Code zeigt auf `/g/` und führt nach der Anmeldung direkt zur Gerätedetailseite. - Etikettenbogen als PDF über Gotenberg: DIN A4 mit 65 Etiketten (38,1 × 21,2 mm). Der Druck kann an einer beliebigen Position beginnen, damit angebrochene Bögen weiterverwendet werden können. - QR-Scan über die Kamera im Browser, mit Eingabefeld als Rückfallweg. - Import aus CSV und Excel: Spalten werden nach den Überschriften automatisch zugeordnet, die Vorschau zeigt Zeile für Zeile, was übernommen würde und was daran nicht stimmt. Geschrieben wird erst nach Bestätigung. - Gerätehistorie und Fahrzeughistorie, gerendert aus dem Audit-Log. - Qualifikationen mit Ablaufwarnung, gerechnet mit der Vorwarnzeit des jeweiligen Typs. - Fahrzeugdetail zeigt die Beladung nach Geräteräumen statt alphabetisch. **Daten und Tests** - Der Seed legt jetzt zusätzlich 3 Standorte, 20 Geräteräume, 14 Gerätetypen mit echten Prüfvorgaben (DGUV, DIN, vfdb), 49 Geräte und 107 Qualifikationen an. Fristen sind bewusst gestreut, damit die Ampeln etwas zeigen. - 104 Vitest-Tests (vorher 32), davon 40 zum Import und 32 zu QR und Fristen. - 44 Playwright-Tests (vorher 10) über Desktop und Tablet. ### Geändert - **Fristenrechnung auf UTC-Kalenderarithmetik umgestellt.** Vorher wurde über `startOfDay` aus date-fns gerechnet, das die Zeitzone des Servers verwendet. Ein Prüfdatum kommt aus der Datenbank als UTC-Mitternacht und wurde dabei auf den Vortag zurückgeschoben — Fristen wären einen Tag zu früh fällig geworden. - `CardTitle` rendert eine echte Überschrift statt eines `div`. Wer mit einer Sprachausgabe arbeitet, springt von Überschrift zu Überschrift; Karten tauchten in dieser Navigation vorher gar nicht auf. - Die Entwicklungsanzeige von Next.js ist abgeschaltet, damit sie nicht in den Bildern der Anleitung mitläuft. ### Sicherheit - Der Etikettendruck wird protokolliert (`EXPORTIERT`) — damit ist nachvollziehbar, wann welche Aufkleber erzeugt wurden. - Der Import übernimmt keine Werte, die der Browser geschickt hat: die Datei wird beim Übernehmen erneut serverseitig eingelesen und geprüft. Sonst ließe sich die Vorschau umgehen. ## [0.1.0] — 2026-09-03 Phase 0: das Fundament. Ab hier steht ein lauffähiger Stack mit Mandantentrennung, Anmeldung, Dateiablage und lückenloser Protokollierung. ### Hinzugefügt **Betrieb** - `docker-compose.yml` mit Traefik, App, Worker, PostgreSQL 17 + PostGIS, Redis, MinIO und Gotenberg. - `docker-compose.override.yml` für die Entwicklung: ohne Traefik, mit Mailpit als SMTP-Auffangkorb und Adminer für den Blick in die Datenbank. Host-Ports bewusst abseits der Standardwerte (3100, 5442, 6389, 9010/9011), damit FLORIAN neben anderen lokalen Stacks laufen kann. - Mehrstufiges `docker/Dockerfile`: eigener Benutzer `florian` (UID 1001, kein root), `tini` als PID 1, Healthcheck gegen `/api/health`, Standalone-Build von Next.js. - `docker/entrypoint.sh` wendet ausstehende Migrationen an — nur im App-Container, nicht im Worker. - `docker/postgres/10-init-app-role.sh` legt beim ersten Start die Rolle `florian_app` (`NOBYPASSRLS`) samt Vorgabeprivilegien an. - `.env.example` mit einem Kommentar zu jeder einzelnen Variable. **Datenmodell** - Prisma-Schema mit `Organisation`, `Person`, `Rolle`, `Berechtigung`, `RolleBerechtigung`, `PersonRolle`, `AusweisToken`, `AuditLog`, `Datei`. - `Fahrzeug` und `Geraet` bereits schmal angelegt, damit der Seed eine realistische Wehr aufbauen kann. Phase 1 erweitert beide. - Migration `20260902000100_rls_policies`: Row Level Security auf allen mandantenpflichtigen Tabellen, Funktion `aktuelle_organisation()`, Append-only-Trigger auf `audit_log`. - Migration `20260902000200_audit_bereinigung`: `UPDATE` auf `audit_log` bleibt dauerhaft gesperrt, `DELETE` ist nur im gekennzeichneten Aufbewahrungslauf möglich. **Anwendungskern** - `lib/env.ts` — Zod-Validierung der gesamten Umgebung beim Start. - `lib/db.ts` — getrennte Verbindungen für Anwendung (RLS aktiv) und System (RLS-frei), `fuerOrganisation()` als einziger Weg zu Fachdaten. - `lib/authz.ts` — 9 Rollen, 38 Einzelrechte, zentrale Prüffunktionen. - `lib/storage.ts` — MinIO, presignte Up- und Downloads, SHA-256-Prüfsumme. - `lib/audit.ts` — Protokolleinträge mit Vorher/Nachher-Vergleich, entfernt Geheimnisse vor dem Schreiben. - `lib/auth.ts` — Auth.js mit OIDC gegen authentik, lokalem Passwort-Login und Terminal-Anmeldung über PIN oder RFID. - `lib/warteschlange.ts` und `src/worker/` — BullMQ-Gerüst mit den Auftragsarten für Fristen, Erinnerungen, PDF und Aufbewahrung. - `lib/integrations/` — Mail, Telegram und LLM hinter abschaltbaren Schnittstellen. - tRPC v11 mit den Prozedurarten `oeffentlich`, `angemeldet` und `mitRecht(...)`. **Oberfläche** - Basis-Layout mit Seitenleiste, heller und dunkler Darstellung (Systemvorgabe als Standard) und durchgängig deutschen Texten. - Anmeldeseite, die genau die eingerichteten Anmeldewege zeigt. - Übersicht mit Kennzahlen und dem Sicherheitshinweis zur analogen Atemschutzüberwachung. - Farbwelt in OKLCH mit festen Statusfarben für Gerätezustände. **Daten und Tests** - Seed mit einer vollständigen Beispielwehr: 15 Personen mit Rollen und Terminal-Ausweisen, 3 Fahrzeuge, 40 Geräte mit gemischten Prüffristen. - Vitest: 32 Tests, darunter acht, die die Mandantentrennung gegen eine echte Datenbank prüfen. - Playwright: 10 Tests über Desktop und Tablet. - `npm run screenshots` erzeugt die Bilder für die Anleitung. **Dokumentation** - README mit Schnellstart in sechs Zeilen. - Anleitung, Roadmap, Aufwandsschätzung, Devlog und Versionierungsregeln.