- Migration 20260924120000_dashboard_image_drop_data: Schutzpruefung
(bricht ab, solange eine Zeile ohne storagePath existiert; row_security
aus, damit ein Eigentuemer ohne BYPASSRLS nicht still 0 Zeilen sieht),
dann NOT NULL, DROP COLUMN data, DROP POLICY system_read_policy
- Dienst: Bootstrap-Umzug samt forSystem() und Selbstheilung aus data
entfernt; Upload vergibt die UUID selbst, Zeile gleich mit Pfad
- FORSYSTEM_ALLOWED_CALL_SITES, Tests, Zugriffsklassifikation (per
Gate-Schleife gemessen: 61/213/6) nachgezogen
- Betriebshandbuch Kap. 4: Hinweis und Wiederherstellungsweg bei Abbruch
- Todo 2026-09-22 nach completed/
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Beim Rundgang aufgefallen: nach dem Umzug zeigt eine Zeile auf eine Datei,
die es auf diesem Server nicht gibt — lokal, weil der Umzug am Host lief und
der Container ein eigenes Volume hat. Derselbe Zustand entsteht im Betrieb,
wenn jemand einen `pg_dump` von vor dem Umzug zurueckspielt: die Bytes
stecken noch in der Spalte `data`, das getrennt gesicherte Volume
`user-files` ist aber leer.
`getBytes` schreibt die Datei in diesem Fall aus `data` neu und liefert sie
aus, statt 404 zu melden. Fehlt beides, bleibt es bei 404. Nach dem
Entfernen der Spalte (eigenes Todo) faellt der Zweig ersatzlos weg.
api-Tests 1186 -> 1188, type-check und lint unveraendert gruen.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Bytes liegen unter user-files/dashboard-images/<userId>/<id>.<ext>, die
Zeile haelt nur noch storagePath (Muster User.avatarPath)
- Dateiname immer servergeneriert: UUID der Zeile + Endung aus dem
ERKANNTEN Mime-Typ, originalName kommt in keinem Pfad vor (T-HK4-01)
- Migration 20260922120000: storagePath dazu, data wird NULLbar, kein DROP
(zweistufig, T-HK4-03); system_read_policy fuer den Umzug
- onApplicationBootstrap zieht Altbestand automatisch um: systemgebunden
lesen, je Zeile mandantengebunden schreiben (Muster DKV-Planer)
- Upload nimmt die Zeile bei fehlgeschlagenem Schreiben zurueck, Loeschen
entfernt die Datei mit, fehlende Datei -> 404 (T-HK4-04)
- 11 neue Dienst-Tests gegen ein echtes Temp-Verzeichnis (kein fs-Mock)
- Zugriffsklassifikation: Stand system-gebunden, Zahlen nachgemessen
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Prisma-Modell DashboardImage (bytea) mit Migration 20260921120000: Tabelle,
Indizes, RLS ENABLE/FORCE und tenant_isolation_policy mit Benutzerdimension
- dashboard-image-rules.ts: detectImageMime ueber Magic Bytes (PNG/JPEG/GIF/
WebP), Grenzen 5 MiB je Datei und 30 je Benutzer
- DashboardImagesService: list/upload/getBytes/remove, je Methode
forTenant(prisma, tenantId, userId); Besitz = Mandant UND Benutzer, sonst 404
- DashboardImagesController unter dashboard/images: GET, POST (FileInterceptor
image, 5 MiB, eine Datei), GET :id mit Content-Type aus dem erkannten Typ,
Cache-Control private, nosniff, Content-Disposition inline ohne Dateinamen,
CSP sandbox; DELETE :id
- CreateWidgetDto kennt 'picture-frame'
- Klassifikationsdokument: neues Paar dashboard-images.service.ts/
dashboardImage; Bereichs- und Summenzeilen nachgemessen (dashboard 12->18,
settings 3->4 und bug-reports waren in der Summe nie mitgezaehlt)
- Befund: Prisma-Bytes verlangt Uint8Array<ArrayBuffer>, multers Buffer wird
ohne Zusicherung abgelehnt - Kopie per new Uint8Array(buffer) statt Cast
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>