Vergleich mit InvenTree, Snipe-IT, Grocy, Shelf.nu, Resgrid, KP Front, FleetMS, HiOrg-Server ergibt neue Kacheln (ASSET-010 Custody, FILE-008 Hash-Audit-Journal, FILE-009 Notizen, NOTIF-003, MAINT-007 Tankbuch, ZUST-003 Standort-Scoping, FOUND-007 Import/Export, FOUND-008 Fristen-Dienst, READY-006 Statistik-Dashboard, UI2-006..010) sowie Referenz-Ergänzungen bei bestehenden Lücken. Alle Design- Entscheidungen (Datenmodell, Sicherheitsanforderungen bei ASSET-010) geklärt. Neues Epic 23 (Flutter-Begleit-App, Sondierungs-Prototyp FLUT-001) inkl. geklärtem TLS-Blocker (Domain mabea.perlbach-edv.de mit Let's-Encrypt-Zertifikat statt selbstsigniertem Server-Zertifikat). Alle Kacheln bleiben offen/ungeplant, nur ausgearbeitet, keine Implementierung. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
236 lines
12 KiB
Markdown
236 lines
12 KiB
Markdown
# 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.
|