# Epic 01 — Foundation Details zu FOUND-001 … FOUND-008. FOUND-007/008 ergänzt am 2026-09-09 aus HiOrg-Server-Vergleich, offen/ungeplant. Übersichtstabelle mit allen FOUND-Kacheln (auch die noch nicht detaillierten) siehe `00_index.md`. --- ## FOUND-001 — Repo & Projektstruktur - **Modul:** Foundation - **Ziel:** Einheitliche, nachvollziehbare Code-Basis, auf der alle weiteren Kacheln aufbauen. - **Beschreibung:** Verzeichnisstruktur Backend/Frontend, Namenskonventionen, Formatierungs-/Lint-Regeln, Basis-README. - **Benutzerwert:** Keiner direkt (Entwickler-Infrastruktur), aber Voraussetzung für alles. - **Abhängigkeiten:** keine - **Datenmodell:** keins - **Backend:** Grundgerüst (App-Einstiegspunkt, Router-Registrierung leer) - **Frontend:** Grundgerüst (Build-Tooling, leere Startseite) - **Mobile:** noch nicht relevant - **QR-Code:** nein - **Seriennummer:** nein - **Inventarnummer:** nein - **Akte:** nein - **Rechte:** keine (noch kein Auth) - **Audit:** nein - **Akzeptanzkriterien:** Repo klont sich, Backend startet, Frontend baut, Lint läuft ohne Fehler. - **Tests:** Smoke-Test „App startet" - **DoD:** lauffähiges leeres Grundgerüst, dokumentiert im README. ## FOUND-002 — DB-Grundgerüst + Migrationen - **Ziel:** Versionierte, reproduzierbare Datenbankstruktur. - **Beschreibung:** PostgreSQL-Anbindung, Migrationstool (z.B. Alembic), erste leere Migration. - **Benutzerwert:** indirekt (Datenintegrität/Nachvollziehbarkeit für alle Module). - **Abhängigkeiten:** FOUND-001 - **Datenmodell:** Migrations-Metatabelle (vom Tool selbst verwaltet) - **Backend:** DB-Session-Handling, Connection-Pool - **Frontend:** — - **Mobile:** — - **QR-Code / Seriennummer / Inventarnummer / Akte:** nein - **Rechte:** keine - **Audit:** nein - **Akzeptanzkriterien:** Migration lässt sich anwenden und zurückrollen, DB-Verbindung aus App funktioniert. - **Tests:** Migrations-Up/Down-Test gegen Testdatenbank. - **DoD:** Migration reproduzierbar auf frischer DB, CI führt sie aus. ## FOUND-003 — Authentication - **Ziel:** Sichere Anmeldung als Basis für jede weitere Rechteprüfung. - **Beschreibung:** Login mit Passwort (gehashed), Token-Ausgabe (JWT o.ä.), Token-Validierung. - **Benutzerwert:** Jeder Nutzer kann sich anmelden — Grundvoraussetzung für alles Weitere. - **Abhängigkeiten:** FOUND-002 - **Datenmodell:** `benutzer` (login, passwort_hash, aktiv) - **Backend:** POST /auth/login, Token-Decode-Dependency - **Frontend:** Login-Seite - **Mobile:** gleicher Login-Flow - **QR-Code/Seriennummer/Inventarnummer:** nein - **Akte:** nein - **Rechte:** noch keine Rollen, nur „angemeldet/nicht angemeldet" - **Audit:** Login-Fehlversuche protokollieren (Brute-Force-Erkennung, optional P2) - **Akzeptanzkriterien:** korrektes Passwort → Token; falsches Passwort → 401; abgelaufener Token → 401. - **Tests:** Login erfolgreich/fehlgeschlagen, Token-Ablauf. - **DoD:** Login funktioniert clientseitig und serverseitig, Passwort niemals im Klartext gespeichert/geloggt. ## FOUND-004 — Authorization-Grundgerüst - **Ziel:** Zentrale Stelle, an der jeder Endpunkt Rechte prüfen kann. - **Beschreibung:** Rollen-Modell (fest, kein granulares System — das kommt erst in Personnel/Readiness-Phase oder eigener späterer Kachel), Dependency/Middleware für Rollenprüfung. - **Benutzerwert:** Schützt sensible Aktionen (z.B. nur Materialwart darf Material anlegen). - **Abhängigkeiten:** FOUND-003 - **Datenmodell:** `rolle`, `benutzer_rolle` - **Backend:** require_roles()-Dependency - **Frontend:** Rollenbasiertes Ein-/Ausblenden von UI-Elementen - **Mobile:** gleiches Prinzip - **Akte/QR/SN/Inv:** nein - **Rechte:** dies IST das Rechte-Grundgerüst - **Audit:** Rollenänderungen protokollieren - **Akzeptanzkriterien:** Endpunkt ohne passende Rolle → 403; mit passender Rolle → 200. - **Tests:** je Rolle ein Zugriffstest. - **DoD:** mind. 2 Rollen (z.B. Administrator, Helfer) funktionieren nachweisbar unterschiedlich. ## FOUND-005 — API-Grundgerüst - **Ziel:** Konsistente API für alle künftigen Module. - **Beschreibung:** Einheitliches Fehlerformat, Versionierungs-Präfix (`/api/v1`), OpenAPI-Dokumentation automatisch. - **Benutzerwert:** indirekt — konsistente, vorhersehbare API für Frontend/Mobile/ Drittsysteme. - **Abhängigkeiten:** FOUND-002 - **Datenmodell:** keins - **Backend:** Fehler-Handler, Health-Endpoint - **Frontend:** generischer API-Client mit einheitlicher Fehlerbehandlung - **Mobile:** gleicher Client - **Akte/QR/SN/Inv:** nein - **Rechte:** keine (Health-Endpoint öffentlich) - **Audit:** nein - **Akzeptanzkriterien:** `/health` antwortet 200, ein absichtlich provozierter Fehler liefert einheitliches JSON-Fehlerformat. - **Tests:** Health-Check-Test, Fehlerformat-Test. - **DoD:** OpenAPI-Doku ist unter `/docs` erreichbar. ## FOUND-006 — Logging & Audit-Grundgerüst - **Ziel:** Jede sicherheits-/fachlich relevante Aktion muss später nachvollziehbar sein. - **Beschreibung:** Zentrale Audit-Tabelle (append-only), generische Log-Funktion (wer/wann/was/alter Wert/neuer Wert). - **Benutzerwert:** Nachvollziehbarkeit für Zugführer/Administrator, Vertrauenswürdigkeit des Systems. - **Abhängigkeiten:** FOUND-002 - **Datenmodell:** `audit_log` (id, zeitpunkt, benutzer_id, ereignistyp, entitaet_typ, entitaet_id, alter_wert, neuer_wert) - **Backend:** log()-Service-Funktion, von anderen Modulen aufrufbar - **Frontend:** Änderungslog-Ansicht (rudimentär, volle UI evtl. später eigene Kachel) - **Mobile:** — - **Akte/QR/SN/Inv:** nein direkt, aber Grundlage für FILE-005/007 - **Rechte:** Lesen nur privilegierte Rollen - **Audit:** ist selbst das Audit-System - **Akzeptanzkriterien:** eine Testaktion erzeugt einen Log-Eintrag mit korrektem Vorher/Nachher-Wert. - **Tests:** Log-Eintrag wird bei simulierter Aktion erzeugt und ist abrufbar. - **DoD:** mind. ein reales Ereignis (z.B. Login) wird bereits geloggt. ## FOUND-007 — CSV/XLS-Import/Export für Objekt- und Materialstammdaten (P2, neu, Scope geklärt 2026-09-09) - **Ziel:** Massenpflege von Objekt- UND Materialstammdaten statt Einzelanlage per UI. - **Scope (entschieden 2026-09-09):** beide Ebenen — `Objekt` (Behälter-Stammdaten: Rucksack/Fahrzeug/Standort) UND `GeraetInstanz` (Einzelgeräte mit Seriennummer darin). Passt zum Ursprungsfall Excel-Rucksackliste, wo beide Ebenen typischerweise in einer Tabelle stehen. - **Beschreibung:** Export bestehender Objekte+Geräteinstanzen als CSV, Import mit Validierung (Duplikat-Erkennung über Inventarnummer/Seriennummer, Fehlerliste bei ungültigen Zeilen statt Alles-oder-Nichts-Abbruch). Ein Import-Vorgang kann beide Ebenen in einer Datei abdecken (verschachtelte Struktur: Objekt-Zeile + zugehörige Geräte-Zeilen) oder zwei getrennte Dateien — Implementierungsdetail, nicht mehr Scope-Frage. - **Benutzerwert:** Direkter Nutzen für den Ursprungsfall von MABEA — Migration bestehender Excel-Rucksacklisten in Massenpflege statt Zeile für Zeile manuell nacherfassen, inklusive der darin enthaltenen Einzelgeräte. - **Abhängigkeiten:** ASSET-003, `GeraetInstanz`-Modell - **Datenmodell:** keins neu (nutzt bestehende Objekt-/GeraetInstanz-Tabellen) - **Backend:** `POST /objekte/import` + `POST /geraete/import` (oder kombinierter Endpunkt, je nach gewählter Dateistruktur), jeweils Dry-Run-Modus + Commit-Modus; `GET /objekte/export` + `GET /geraete/export` - **Frontend:** Upload-Dialog mit Fehlerliste-Anzeige vor endgültigem Import, Export-Button in Objektliste UND Geräte-/Materialansicht - **Mobile:** nein (Desktop-Verwaltungsaufgabe) - **QR-Code/Seriennummer/Inventarnummer:** Duplikat-Prüfung läuft darüber - **Akte:** nein direkt - **Rechte:** Administrator/Materialverantwortlicher - **Audit:** Import als Sammel-Ereignis geloggt (nicht jede Zeile einzeln) - **Akzeptanzkriterien:** Import mit teilweise fehlerhaften Zeilen zeigt genau welche Zeilen fehlschlugen, gültige Zeilen werden trotzdem übernommen (kein Alles-oder- Nichts); Export re-importierbar (Round-Trip-Test), sowohl für Objekte als auch für Geräteinstanzen; Geräte-Zeilen ohne zugehöriges Objekt werden abgelehnt (referenzielle Konsistenz). - **Tests:** Round-Trip-Test (Export→Import ergibt identischen Bestand) für beide Ebenen, Fehlerzeilen-Test (gemischt gültig/ungültig), Test für Objekt+zugehörige-Geräte in einem Import-Vorgang. - **DoD:** offen. **Referenz (HiOrg-Server-Vergleich 2026-09-09):** HiOrg bietet Import/Export für praktisch alle Datentypen (CSV/XLS/vCard/iCal) — MABEA hat dafür aktuell keinen erkennbaren Mechanismus außer direkter API-Nutzung. ## FOUND-008 — Generischer Fristen-Dienst (P3, neu, Schnittstelle geklärt 2026-09-09) - **Ziel:** EINE Berechnungslogik für „läuft etwas bald ab/wird etwas bald fällig" statt mehrfach separat implementiert. - **Beschreibung:** MABEA hat Ablauf-/Fälligkeitslogik aktuell an drei Stellen unabhängig voneinander gebaut: Chargen-Ablaufdatum (INV-005), Qualifikations- Ablaufwarnung (PERS-007), Wartungsfälligkeit (MAINT-002/NOTIF-003). Ein gemeinsamer `Fristen`-Dienst (Interface: „gib mir alle Objekte mit Frist-Typ X, die den Dringlichkeitsgrad Y erreicht haben" — siehe Schnittstelle unten) würde die Berechnungslogik einmal statt dreimal pflegen. - **Benutzerwert:** Kein direkter Nutzerwert (reines Refactoring), aber weniger Wartungsaufwand/Inkonsistenz-Risiko bei künftigen Fristen-Arten (z.B. Vertrags- laufzeiten, TÜV-Termine). - **Abhängigkeiten:** INV-005, PERS-007, MAINT-002 (bestehende Implementierungen als Migrationsbasis) - **Datenmodell:** keins neu, gemeinsame `FristTyp`-Enum als Kategorisierung (`charge_ablauf`/`qualifikation_ablauf`/`wartung_faellig`/...) - **Schnittstelle (entschieden 2026-09-09, korrigiert 2026-09-10):** „Tage bis fällig" als gemeinsamer Nenner funktioniert NICHT für km/Betriebsstunden-Fristen — MABEA verfolgt keine Verbrauchsrate über Zeit (nur den aktuellen Zählerstand), eine Tage-Schätzung wäre erfunden/unbegründet. Stattdessen: gemeinsame `FristTreffer`-Struktur mit **Dringlichkeits-Ampel** statt einheitlicher Zeiteinheit — `{objekt_id, frist_typ, bezeichnung, dringlichkeit: enum (ok/bald/kritisch/ueberfaellig), rest_anzeige: str}`. `rest_anzeige` bleibt je Typ in seiner nativen Einheit (z.B. „in 12 Tagen" bei Datum-Fristen, „noch 340 km" bei Kilometer-Fristen, „noch 15 Bh" bei Betriebsstunden) — nur die Ampel-Einstufung (ok/bald/kritisch/überfällig) ist typübergreifend einheitlich vergleichbar, die Restanzeige selbst bleibt nativ und ehrlich statt einer erfundenen Tage-Umrechnung. Jede der drei Implementierungen bringt ihre eigene Schwellenwert-Logik mit (z.B. „< 10% der Sollstrecke übrig" = kritisch bei km), `fristen.py` normalisiert nur auf die gemeinsame Ampel, nicht auf eine gemeinsame Zeiteinheit. - **Backend:** `app/services/fristen.py` als gemeinsame Schnittstelle, bestehende drei Implementierungen (`app/services/dashboard.py`, `app/services/akte.py`, `app/services/personal.py`, `app/services/wartung.py:faellige_wartungen_fuer_objekt`) schrittweise darauf umstellen (nicht big-bang) — jede liefert intern weiter ihre Rohdaten, `fristen.py` übernimmt nur die Normalisierung auf `FristTreffer`. - **Frontend:** keine Änderung sichtbar (reines Backend-Refactoring) - **Mobile:** keins - **QR-Code/Seriennummer/Inventarnummer:** nein - **Akte:** nein direkt - **Rechte:** keine Änderung - **Audit:** keine Änderung - **Akzeptanzkriterien:** alle drei bestehenden Fristen-Arten liefern nach Umstellung identische Ergebnisse wie vorher (Regressionstest), neue Fristen-Art ohne Duplikation der Kernlogik hinzufügbar. - **Tests:** Regressionstests der drei bestehenden Fristen-Berechnungen gegen die neue gemeinsame Implementierung. - **DoD:** offen, **P3 — reines Refactoring, kein MVP-Bestandteil**. Schnittstelle geklärt (2026-09-09), bereit für Implementierung. **Referenz (HiOrg-Server-Vergleich 2026-09-09):** HiOrg berücksichtigt Qualifikations-Ablauf generisch bei der Diensteinteilung — technische Entsprechung wäre bei MABEA ein gemeinsamer Fristen-Mechanismus statt drei getrennter Implementierungen. --- **MABEA-Ist-Stand-Abgleich:** FOUND-001…006 sind in MABEA vollständig vorhanden (FastAPI-Grundgerüst, Alembic-Migrationen, JWT-Login, `require_roles()`-Dependency, einheitliches Fehlerformat + `/docs`, `historie`-Tabelle als Audit-Log). FOUND-007…012 (Konfiguration/Docker/CI/Backup/Tests/Doku) ebenfalls größtenteils vorhanden (`app_settings.py`, `.env`, Gitea-CI `ci.yml`, `pytest`, README/DEVLOG) — kein Nachholbedarf in diesem Epic.