docs(quick-260922-hk4): Changelog, Betriebsanleitung und Todo zur data-Spalte
- Changelog unter Unveroeffentlicht -> Geaendert: Bilder liegen im Dateibereich, vorhandene ziehen beim ersten Start automatisch um - Betriebsanleitung Kap. 6: user-files nennt die Bilderrahmen-Bilder und haelt fest, dass pg_dump allein sie nicht mehr enthaelt - Todo fuer Stufe 2 (DROP data, storagePath NOT NULL) mit Vorbedingung, Migrationsname und den Nacharbeiten an Spec und Klassifikation Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,82 @@
|
|||||||
|
---
|
||||||
|
created: 2026-09-22
|
||||||
|
title: DashboardImage — Spalte "data" entfernen und "storagePath" auf NOT NULL setzen (Stufe 2 der Umstellung aus quick-260922-hk4)
|
||||||
|
area: apps/api/prisma
|
||||||
|
severity: cleanup
|
||||||
|
trigger: erst wenn alpha UND live je einmal mit einer Version >= der Freigabe nach 1.3.0 gelaufen sind — dann hat der Bootstrap-Umzug auf beiden Servern gearbeitet und die Bytes liegen im Dateibereich.
|
||||||
|
relates_to: quick-260922-hk4 (.planning/quick/260922-hk4-bilderrahmen-bilder-auf-die-festplatte/)
|
||||||
|
---
|
||||||
|
|
||||||
|
## Worum es geht
|
||||||
|
|
||||||
|
Die Bilder des Bilderrahmen-Widgets sind mit `quick-260922-hk4` aus der
|
||||||
|
Datenbank in den Dateibereich gezogen (`user-files/dashboard-images/
|
||||||
|
<userId>/<id>.<ext>`, Pfad in der Spalte `storagePath`). Die Umstellung ist
|
||||||
|
BEWUSST ZWEISTUFIG:
|
||||||
|
|
||||||
|
- **Stufe 1, ausgeliefert** (Migration `20260922120000_dashboard_image_to_disk`):
|
||||||
|
`storagePath` dazu (NULLbar), `data` wird NULLbar — aber NICHT gelöscht.
|
||||||
|
Der Umzug der vorhandenen Zeilen passiert beim ersten Start automatisch
|
||||||
|
(`DashboardImagesService.onApplicationBootstrap()`).
|
||||||
|
- **Stufe 2, dieser Zettel:** `data` löschen, `storagePath` auf NOT NULL.
|
||||||
|
|
||||||
|
Warum nicht sofort: `prisma migrate deploy` läuft VOR dem Anwendungsstart.
|
||||||
|
Ein sofortiges `DROP COLUMN "data"` hätte die Bytes vernichtet, bevor der
|
||||||
|
Umzug beim Start sie lesen konnte (T-HK4-03).
|
||||||
|
|
||||||
|
## Was zu tun ist
|
||||||
|
|
||||||
|
1. **Vorbedingung prüfen** (auf BEIDEN Servern, alpha und live):
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT count(*) FROM "DashboardImage" WHERE "storagePath" IS NULL;
|
||||||
|
```
|
||||||
|
|
||||||
|
Muss überall `0` sein. Ist sie es nicht, ist der Umzug dort noch nicht
|
||||||
|
gelaufen (Server noch auf einer älteren Version) — dann NICHT ausliefern.
|
||||||
|
|
||||||
|
2. **Neue Migration** `20260922120100_dashboard_image_drop_data`:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
ALTER TABLE "DashboardImage" ALTER COLUMN "storagePath" SET NOT NULL;
|
||||||
|
ALTER TABLE "DashboardImage" DROP COLUMN "data";
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Schema** `apps/api/prisma/schema.prisma`: Feld `data Bytes?` entfernen,
|
||||||
|
`storagePath String?` → `storagePath String`.
|
||||||
|
|
||||||
|
4. **Dienst** `apps/api/src/dashboard/dashboard-images.service.ts`:
|
||||||
|
`onApplicationBootstrap()` samt `forSystem()`-Aufruf entfernt sich damit
|
||||||
|
— der Umzug hat seine Arbeit getan. Danach:
|
||||||
|
- Eintrag `apps/api/src/dashboard/dashboard-images.service.ts` aus
|
||||||
|
`FORSYSTEM_ALLOWED_CALL_SITES` in `apps/api/src/prisma/rls-access-inventory.spec.ts`
|
||||||
|
wieder ENTFERNEN (die Liste ist ein „genau", ein veralteter Eintrag
|
||||||
|
macht die Spec rot).
|
||||||
|
- In `docs/mandantentrennung-zugriffsklassifikation.md` den Stand der Zeile
|
||||||
|
`dashboard-images.service.ts`/`dashboardImage` von `system-gebunden`
|
||||||
|
zurück auf `gebunden` setzen und die Zahlen der Bereichszeile
|
||||||
|
`dashboard` sowie die Summe neu messen (Gate-Schleife, nicht
|
||||||
|
abschreiben).
|
||||||
|
- Die Tests 18, 21, 22 und 23 der Dienst-Spec (Zeile ohne `storagePath`,
|
||||||
|
Bootstrap-Umzug) entfallen mit dem Umzug.
|
||||||
|
- Die Regel `system_read_policy` auf `"DashboardImage"` (angelegt in
|
||||||
|
20260922120000) kann bleiben oder mit `DROP POLICY` fallen — bleibt sie,
|
||||||
|
gehört sie in der Klassifikation erwähnt; fällt sie, ist die
|
||||||
|
Aufzählung „fünf/sechs Tabellen" dort nachzuziehen.
|
||||||
|
|
||||||
|
5. **Prüfen**, dass die Datenbank kleiner wird:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT pg_size_pretty(pg_total_relation_size('"DashboardImage"'));
|
||||||
|
```
|
||||||
|
|
||||||
|
(Nach dem DROP zusätzlich `VACUUM FULL "DashboardImage";`, sonst gibt
|
||||||
|
PostgreSQL den Platz nicht ans Dateisystem zurück.)
|
||||||
|
|
||||||
|
## Was passiert, wenn es liegen bleibt
|
||||||
|
|
||||||
|
Nichts Schlimmes: die Spalte steht leer herum und kostet je neuer Zeile
|
||||||
|
nichts. Der Gewinn der Umstellung (kleiner `pg_dump`) ist bereits da, weil
|
||||||
|
neue Uploads keine Bytes mehr in die Zeile schreiben. Nur die Bytes der
|
||||||
|
ALTEN Bilder bleiben bis dahin doppelt vorhanden — einmal in der Datei,
|
||||||
|
einmal in der Spalte.
|
||||||
@@ -4,6 +4,10 @@ Diese Liste beschreibt in einfachen Worten, was sich von Version zu Version an T
|
|||||||
|
|
||||||
## Unveröffentlicht
|
## Unveröffentlicht
|
||||||
|
|
||||||
|
### Geändert
|
||||||
|
|
||||||
|
- Bilderrahmen: hochgeladene Bilder liegen jetzt im Dateibereich des Servers statt in der Datenbank — die Datenbanksicherung bleibt dadurch klein; vorhandene Bilder ziehen beim ersten Start automatisch um
|
||||||
|
|
||||||
## 1.3.0 – 2026-09-22
|
## 1.3.0 – 2026-09-22
|
||||||
|
|
||||||
### Neu
|
### Neu
|
||||||
|
|||||||
@@ -283,8 +283,11 @@ Restores stattfinden.
|
|||||||
- **Verschlüsselungsschlüssel** `TESSERA_ENCRYPTION_KEY`: liegt nur in `.env` auf
|
- **Verschlüsselungsschlüssel** `TESSERA_ENCRYPTION_KEY`: liegt nur in `.env` auf
|
||||||
dem Host, **nicht** im Datenbank-Dump. Getrennt sichern (siehe Kapitel 2/3) – ohne
|
dem Host, **nicht** im Datenbank-Dump. Getrennt sichern (siehe Kapitel 2/3) – ohne
|
||||||
ihn sind alle per `pg_dump` gesicherten verschlüsselten Zugangsdaten wertlos.
|
ihn sind alle per `pg_dump` gesicherten verschlüsselten Zugangsdaten wertlos.
|
||||||
- **Hochgeladene Dateien** (Avatare unter `user-files/avatars/`, generierte
|
- **Hochgeladene Dateien** (Avatare unter `user-files/avatars/`, Bilder des
|
||||||
DKV-Exporte unter `user-files/`, siehe `apps/api/src/user/user.controller.ts` und
|
Bilderrahmen-Widgets unter `user-files/dashboard-images/<Benutzerkennung>/`,
|
||||||
|
generierte DKV-Exporte unter `user-files/`, siehe
|
||||||
|
`apps/api/src/user/user.controller.ts`,
|
||||||
|
`apps/api/src/dashboard/dashboard-images.service.ts` und
|
||||||
`apps/api/src/dkv/dkv-export.service.ts`): Diese Dateien liegen im benannten
|
`apps/api/src/dkv/dkv-export.service.ts`): Diese Dateien liegen im benannten
|
||||||
Docker-Volume `user-files`, gemountet auf `/app/user-files` im Dienst `api`. Der
|
Docker-Volume `user-files`, gemountet auf `/app/user-files` im Dienst `api`. Der
|
||||||
Mount ist in `docker-compose.yml` und `docker-compose.prod.yml` eingetragen:
|
Mount ist in `docker-compose.yml` und `docker-compose.prod.yml` eingetragen:
|
||||||
@@ -296,7 +299,11 @@ Restores stattfinden.
|
|||||||
user-files:
|
user-files:
|
||||||
```
|
```
|
||||||
|
|
||||||
Damit überstehen Avatare und DKV-Exporte ein `--force-recreate` von `api`. Wie bei
|
Damit überstehen Avatare, Bilderrahmen-Bilder und DKV-Exporte ein
|
||||||
|
`--force-recreate` von `api`. Seit den Bilderrahmen-Bildern (Version nach 1.3.0)
|
||||||
|
gehört dieses Volume zwingend zur Sicherung: `pg_dump` allein enthält diese
|
||||||
|
Bilder nicht mehr — genau das ist der Zweck der Umstellung, der
|
||||||
|
Datenbank-Abzug bleibt dadurch klein. Wie bei
|
||||||
`pgdata` zeigt `docker volume ls` das Volume mit vorangestelltem Projektnamen an
|
`pgdata` zeigt `docker volume ls` das Volume mit vorangestelltem Projektnamen an
|
||||||
(`<projekt>_user-files`). Gesichert werden die Dateien weiterhin mit
|
(`<projekt>_user-files`). Gesichert werden die Dateien weiterhin mit
|
||||||
`docker compose cp api:/app/user-files ./user-files-backup`, alternativ über eine
|
`docker compose cp api:/app/user-files ./user-files-backup`, alternativ über eine
|
||||||
|
|||||||
Reference in New Issue
Block a user