Polymorphes akte_notiz-Modell (gleiches entitaet_typ/entitaet_id-Muster wie
Dokument/Historie/Mangel), CRUD-Endpunkte, NotizenPanel im Akte-Grid. Löschen
nur durch Autor oder Administrator.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
CI schlug fehl (ERESOLVE): @vitejs/plugin-react@4.7.0 kennt nur Vite
bis v7 als Peer-Dependency, lief lokal nur weil node_modules bereits
force-aufgelöst war. v6.1.1 unterstützt Vite 8 nativ, sauberes
npm install ohne --force jetzt möglich, 0 vulnerabilities.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
Schließt alle 6 gemeldeten Schwachstellen (esbuild-Dev-Server-CVE,
GHSA-67mh-4wv8-2f99), betraf nur den lokalen Dev-Server, kein
Produktions-Impact. Vite 5->8, vitest 2->5, vite-plugin-pwa 0.20->1.3.
tsc/build/vitest lokal geprüft, 0 vulnerabilities.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
Neue Tabelle person (Migration 0034, Backfill bestehender Benutzer 1:1
per Zeilennummer, keine Datenverluste). Benutzer.person_id optional -
Login kann bestehende Person verknüpfen oder legt automatisch eine neue
an (Rückwärtskompatibilität zum bisherigen Anlegen-Flow). /personen-CRUD
(admin-only), neue PersonSection.tsx im Personal-Tab, BenutzerSection
um Personen-Auswahl erweitert.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
Neue Stammdaten-Tabelle nummernschema (Migration 0032): Präfix + Stellenzahl
einmal je Objekttyp festlegen statt bei jeder Objekt-Anlage manuell
einzutippen (Fehlerquelle - Tippfehler, uneinheitliche Schreibweise,
falsches Präfix für den Typ). GET /objekte/naechster-code akzeptiert jetzt
objekttyp_id als Alternative zu praefix; ohne konfiguriertes Schema bleibt
der bisherige manuelle Präfix-Weg nutzbar (Rückwärtskompatibilität).
Admin-UI: Nummernschema-Pflege direkt in der Objekttyp-Verwaltung
(ObjekttypSection). ObjektAnlegenFormular versucht zuerst das Schema des
gewählten Objekttyps, fällt bei 404 auf manuelles Präfix zurück.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
Neue Stammdaten-Tabelle einsatzfunktion (Migration 0031), benutzer bekommt
optionales einsatzfunktion_id-Feld - analog zu einheit_id modelliert, eine
Person hat im Regelfall genau eine primäre Einsatzfunktion. Bewusst
getrennt von den technischen App-Rollen (RolleTyp), die nur steuern, was
jemand in MABEA tun darf, nicht welche Funktion er im Einsatz hat.
CRUD-Endpunkt /einsatzfunktionen nach Kategorie-Muster, Duplikat-Prüfung
vorab (Projekt-Konvention). Admin-UI: Auswahl + Inline-Neuanlage in der
Benutzerverwaltung (BenutzerSection).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
POST /objekte/{id}/code-neu-vergeben und /objektpositionen/{id}/code-neu-
vergeben (admin-only) - z.B. bei beschädigtem/verlorenem Etikett. Alter
Code bleibt über die bestehende Audit-Infrastruktur (Historie-Tabelle,
Prompt 13) nachvollziehbar statt eine eigene Versions-Tabelle zu brauchen:
GET /historie?entitaet_typ=objekt&entitaet_id=... zeigt alter_wert/
neuer_wert des Codes. Duplikat-Prüfung explizit vorab (Projekt-Konvention,
siehe geraet_instanz.py::erstelle).
Frontend: "Code neu vergeben"-Aktion in der Objektakte (nur Admin), inline
statt window.prompt (Accessibility-Vorgabe aus dieser Session).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
Testsuite-get_db-Override macht kein Rollback bei Exceptions (dokumentierter
Fund 2026-09-05) - ein Flush-Fehlschlag über IntegrityError hinterlässt die
geteilte Test-Session im PendingRollbackError-Zustand für jeden folgenden
Request im selben Test. Projekt-Konvention laut geraet_instanz.py::erstelle
ist deshalb explizites Vorab-Prüfen statt Verlassen auf den DB-Constraint -
hier nachgezogen.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
Neue Tabellen hersteller/modell (Migration 0030), CRUD-Endpunkte
(/hersteller, /modelle) nach bestehendem Kategorie-Muster, inkl. 409 bei
Duplikaten (IntegrityError abgefangen wie in personal.py). geraet_instanz
bekommt optionales modell_id-Feld - verknüpft eine konkrete Geräteinstanz
(mit Seriennummer, IDENT-004) mit ihrem Hersteller/Modell.
Ergänzt Material.hersteller (bleibt unverändert als Freitext) um eine
normalisierte Variante gezielt für Geräte mit Seriennummer - keine
Datenmigration bestehender Freitext-Werte (Scope dieser Kachel).
Bewusst kein neues Admin-UI-Screen für die Pflege (Scope-Grenze der
Kachel) - Hersteller/Modell aktuell nur über die API verwaltbar.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
Neues Feld ist_original (Boolean, Migration 0029) - explizit beim Upload
und beim Ersetzen (DOC-003) setzbar, kein Default in eine Richtung erraten.
Wird beim Ersetzen bewusst NICHT vom Vorgänger übernommen (neue Version
könnte ein nachgereichtes Original sein, das eine bisherige Kopie ersetzt,
oder umgekehrt). Frontend: Checkbox "Original (nicht nur Kopie/Scan)" im
Upload-Formular, "Original"-Badge in der Dokumentenliste.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
Postgres legt für FK-Spalten selbst KEINEN Index an (nur für die
referenzierte PK-Seite) - grep über alle Models ergab 0 explizite Indizes
im gesamten Schema trotz 86 Fremdschlüsseln. Ohne Index braucht jede
Lookup-Query von der "viele"-Seite (z.B. "alle Fehlbestände zu diesem
Objekt", "alle Kontrollen zu diesem Benutzer") einen Sequential Scan -
bei aktueller Datenmenge unauffällig, würde mit wachsendem Bestand aber
zum Problem.
5 Spalten ausgelassen, weil bereits über eine UniqueConstraint als
führende Spalte indiziert (Postgres nutzt den führenden Teil eines
zusammengesetzten Unique-Index für Einzelspalten-Lookups genauso):
objektposition.objekt_id, bestand.lagerplatz_id, beladungsvorlage.
objekttyp_id, vorlagenposition.vorlage_id, benutzer_qualifikation.
benutzer_id. dokument.vorgaenger_id hatte bereits einen Index (Migration
0027).
Fund beim Abgleich gegen die database-optimization-Checkliste aus
ai-coding-starter-kit.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
Dokument-Versionierung: vorgaenger_id verkettet Versionen (Migration 0027),
POST /dokumente/{id}/ersetzen legt neue Version an statt zu überschreiben,
alte Fassung bleibt als Historie erhalten. GET /dokumente/{id}/versionen
liefert die Kette (neueste zuerst), respektiert DOC-005-Zugriffsrechte.
Liste zeigt nur die jeweils aktuelle Version. Löschen der aktuellen Version
gibt automatisch den Vorgänger als neue "aktuelle" frei. Frontend:
"Ersetzen"-Button + aufklappbare Versionshistorie im DokumentePanel.
QR-Code-Etiketten: bisher nur Code128-Barcode möglich. generiere_qr_label_pdf
(reportlab-eigenes QR-Widget, keine neue Abhängigkeit) als Alternative,
?format=qr|code128 an /objekte/{id}/label.pdf und /objektpositionen/{id}/
label.pdf. AktePage bekommt "Etikett (Barcode)"/"Etikett (QR)"-Buttons
(vorher gab es dafür noch gar keinen UI-Zugang im Web-Frontend).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
FOUND-012 (Dokumentationsgerüst) war laut Backlog-Abgleich offen - kein
README im Projektwurzelverzeichnis. Fasst zusammen, was MABEA kann
(Digitale Akte, Kontrolle, Fehlbestandsmanagement, Warehouse, Wartung,
Dokumente, Suche, Dashboard, PWA/Offline, ...), Techstack und wie man
Backend/Frontend lokal startet.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
test_liste_kann_nach_dokumenttyp_gefiltert_werden lief als Mitarbeiter,
einer der beiden Testtypen war "rechnung" - die DOC-005-Einschränkung
(diese Session) blendet Rechnungen für Mitarbeiter jetzt aus, Test lief auf
Materialverantwortlicher-Login um.
chore: drei Original-Excel-Rucksacklisten aus dem Repo genommen (waren nur
Referenzmaterial aus der Konzeptphase, gehören nicht ins Code-Repo) und
*.xlsx in .gitignore aufgenommen.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
Rechnungen sind finanziell sensibel - nur Materialverantwortliche/
Leitungsverantwortliche/Administration dürfen sie in der Liste sehen und
herunterladen (403 bei direktem Downloadversuch), Mitarbeiter nicht.
Hochladen bleibt für alle offen (z.B. Wareneingang direkt scannen). Andere
Dokumenttypen bleiben unverändert für jeden mit Aktenzugriff sichtbar - die
werden im Feldeinsatz gebraucht. EINGESCHRAENKTE_DOKUMENTTYPEN als zentrale
Stelle für künftige weitere Einschränkungen.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
Neues Pflichtfeld dokumenttyp (Enum: Prüfprotokoll/Wartungsbericht/
Bedienungsanleitung/Rechnung/Zulassungsdokument/Sonstiges, Migration 0026)
- macht Dokumente kategorisier- und filterbar statt nur per Freitext-
Beschreibung auffindbar zu sein. Backend: Pflichtfeld beim Upload, optionaler
Query-Filter bei GET /dokumente. Frontend: Auswahl-Dropdown beim Upload,
Typ-Badge + Filter-Dropdown in der Liste (DokumentePanel).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
GHSA-wrjc-x8rr-h8h6 + GHSA-337j-9hxr-rhxg betrafen die gesamte 6.x-Reihe,
kein gepatchtes 6.x verfügbar - v7 war die einzige Lösung. Projekt nutzt
nur den klassischen Declarative-Router (BrowserRouter/Routes/Route,
useNavigate/useParams/useSearchParams), keine Data-Router-APIs
(loaders/actions) - v7 ist dafür API-kompatibel, keine Code-Änderung nötig.
Typecheck/Build/alle 16 Vitest-Tests grün, npm audit --omit=dev jetzt 0
Vulnerabilities.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
Per SSH-Debug auf dem Server (Wegwerf-Testdatenbank, echte pytest-Ausführung
- hier lokal ohne venv nicht möglich): erstelle_vorlage() legt für den
Freitext-Fachnamen einer Vorlagenposition bereits automatisch ein Fach an
(services/vorlagen.py). Der Test versuchte danach nochmal explizit ein Fach
mit fast demselben Namen anzulegen ("Reizverschlussfach Gross") - das
kollidierte case-insensitiv mit dem bereits automatisch erzeugten
("Reizverschlussfach gross") und schlug mit 409 fehl, worauf der Rest des
Tests mit falschen Annahmen weiterlief (KeyError 'id').
Fix: das automatisch angelegte Fach wird jetzt per Query als Ziel verwendet
statt nochmal angelegt zu werden. Komplette Suite (164 Tests) läuft auf dem
Server jetzt vollständig grün.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV