chore(seed/docs): production safety, scripts audit, documentation
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 17m48s
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 17m48s
This commit is contained in:
247
docs/backup-und-seeding.md
Normal file
247
docs/backup-und-seeding.md
Normal file
@@ -0,0 +1,247 @@
|
||||
# Backup & Seeding — Betriebsnotiz Lageplan
|
||||
|
||||
> Stand: 2026-05-20
|
||||
> Autor: Automatisch generiert nach Produktionsvorfall
|
||||
|
||||
## Inhalt
|
||||
|
||||
1. [Wichtige Regeln](#wichtige-regeln)
|
||||
2. [Backup-Strategie](#backup-strategie)
|
||||
3. [Seed-Skripte](#seed-skripte)
|
||||
4. [Post-Deploy Prüfung](#post-deploy-prüfung)
|
||||
5. [Notfall-Recovery](#notfall-recovery)
|
||||
6. [Docker-Build Hinweise](#docker-build-hinweise)
|
||||
|
||||
---
|
||||
|
||||
## Wichtige Regeln
|
||||
|
||||
### Nie löschen
|
||||
|
||||
- **Keine** `deleteMany()`, `DELETE FROM`, `TRUNCATE` oder Cascade-Resets in Production
|
||||
- **Nie** direkt in `icon_assets`, `icon_categories`, `tenant_symbols`, `features`, `projects` löschen
|
||||
- Alle Seed-Skripte müssen **idempotent** sein (`upsert` statt `delete` + `create`)
|
||||
- Vor jedem Seed/Repair in Production: **Databasus-Backup erstellen**
|
||||
|
||||
### Databasus Backup
|
||||
|
||||
- Databasus ist als GUI-Backup eingerichtet
|
||||
- Backups werden gespeichert unter: `/volume1/docker/backups/databasus`
|
||||
- **Nie** das Docker-Volume unter `/volume1/@docker` als einzige Backup-Strategie verwenden
|
||||
|
||||
### Container-Informationen
|
||||
|
||||
| Service | Container-Name |
|
||||
|---------|---------------|
|
||||
| PostgreSQL DB | `lageplan-db-1` |
|
||||
| Web App | `lageplan-web-1` |
|
||||
| DB-Name | `lageplan` |
|
||||
| DB-User | `lageplan` |
|
||||
|
||||
---
|
||||
|
||||
## Backup-Strategie
|
||||
|
||||
### Automatisch (Databasus)
|
||||
|
||||
1. Databasus GUI öffnen
|
||||
2. Datenbank `lageplan` auswählen
|
||||
3. "Backup Now" klicken
|
||||
4. Backup wird unter `/volume1/docker/backups/databasus` abgelegt
|
||||
|
||||
### Manuell (pg_dump)
|
||||
|
||||
```bash
|
||||
# In der NAS-Shell (oder im DB-Container)
|
||||
docker exec lageplan-db-1 pg_dump -U lageplan -d lageplan \
|
||||
--no-owner --no-privileges \
|
||||
> /volume1/docker/backups/databasus/lageplan-manual-$(date +%Y%m%d-%H%M%S).sql
|
||||
```
|
||||
|
||||
### Wiederherstellen
|
||||
|
||||
```bash
|
||||
# 1. Backup-Datei prüfen
|
||||
ls -la /volume1/docker/backups/databasus/
|
||||
|
||||
# 2. App stoppen
|
||||
docker stop lageplan-web-1
|
||||
|
||||
# 3. DB zurückspielen (ACHTUNG: überschreibt aktuelle Daten!)
|
||||
docker exec -i lageplan-db-1 psql -U lageplan -d lageplan \
|
||||
< /volume1/docker/backups/databasus/lageplan-backup-YYYYmmdd-HHMMSS.sql
|
||||
|
||||
# 4. App starten
|
||||
docker start lageplan-web-1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Seed-Skripte
|
||||
|
||||
### Übersicht
|
||||
|
||||
| Skript | Zweck | Sicherheit | Aufruf |
|
||||
|--------|-------|-----------|--------|
|
||||
| `prisma/seed.js` | Vollständiger Seed (Tenant, Users, Icons, HoseTypes, Demo-Projekt) | ✅ Idempotent, nur `upsert` | `npm run db:seed` oder `node prisma/seed.js` |
|
||||
| `prisma/seed-icons-only.js` | Nur Icons aus `public/signaturen/*.svg` | ✅ Idempotent, nur `upsert` | `npm run db:seed:icons` oder `node prisma/seed-icons-only.js` |
|
||||
| `prisma/seed.ts` | Legacy-TypeScript-Seed (korrigiert, aber nicht der Primary) | ✅ Korrigiert | Nicht direkt aufrufen |
|
||||
| `prisma/seed-symbol-templates.ts` | Erstellt `SymbolTemplate`-Einträge | ✅ Nur `findFirst` + `create` (skip if exists) | `npx tsx prisma/seed-symbol-templates.ts` |
|
||||
| `prisma/migrate-tenant-symbols.ts` | Migriert bestehende `TenantSymbol` zu neuem Schema | ✅ Nur `findFirst`, `create`, `update` | `npx tsx prisma/migrate-tenant-symbols.ts` |
|
||||
| `prisma/recover-symbols.js` | Recovery: Icons + TenantSymbols wiederherstellen | ✅ Dry-Run/Apply Modus | `npm run recover:symbols:dry-run` / `npm run recover:symbols:apply` |
|
||||
| `prisma/repair-features.js` | Repariert kaputte `iconId`-Referenzen in Features | ✅ Dry-Run/Apply Modus + Backup | `npm run repair:features:dry-run` / `npm run repair:features:apply` |
|
||||
| `prisma/migrate.js` | DB-Migrationen (Raw SQL, idempotent) | ✅ Keine Deletes auf User-Daten | Wird automatisch beim Container-Start ausgeführt |
|
||||
|
||||
### Empfohlene Seed-Strategie
|
||||
|
||||
1. **Neue Umgebung** (erstmalig):
|
||||
```bash
|
||||
node prisma/seed.js
|
||||
```
|
||||
|
||||
2. **Nur Icons aktualisieren** (z.B. nach SVG-Update):
|
||||
```bash
|
||||
node prisma/seed-icons-only.js
|
||||
```
|
||||
|
||||
3. **Recovery nach Icon-Verlust**:
|
||||
```bash
|
||||
# 1. Erst Databasus-Backup erstellen!
|
||||
# 2. Dann:
|
||||
node prisma/recover-symbols.js --dry-run # Analyse
|
||||
node prisma/recover-symbols.js --apply # Anwenden
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Post-Deploy Prüfung
|
||||
|
||||
### 1. SVG-Dateien im Container
|
||||
|
||||
```bash
|
||||
docker exec -it lageplan-web-1 sh -c 'find /app/public/signaturen -type f -name "*.svg" | wc -l'
|
||||
```
|
||||
**Erwartung:** ca. 117
|
||||
|
||||
### 2. Icons seeden
|
||||
|
||||
```bash
|
||||
docker exec -it lageplan-web-1 node prisma/seed-icons-only.js
|
||||
```
|
||||
**Erwartung:**
|
||||
```
|
||||
✅ 10 icon categories upserted
|
||||
✅ FKS Signaturen: X created, Y updated (117 total SVGs)
|
||||
```
|
||||
|
||||
### 3. Datenbank-Prüfung
|
||||
|
||||
```bash
|
||||
docker exec -it lageplan-db-1 psql -U lageplan -d lageplan -c "
|
||||
SELECT 'icon_categories' AS table_name, COUNT(*) AS count FROM icon_categories
|
||||
UNION ALL
|
||||
SELECT 'icon_assets' AS table_name, COUNT(*) AS count FROM icon_assets
|
||||
UNION ALL
|
||||
SELECT 'tenant_symbols' AS table_name, COUNT(*) AS count FROM tenant_symbols
|
||||
UNION ALL
|
||||
SELECT 'features' AS table_name, COUNT(*) AS count FROM features
|
||||
UNION ALL
|
||||
SELECT 'projects' AS table_name, COUNT(*) AS count FROM projects;
|
||||
"
|
||||
```
|
||||
|
||||
### 4. Logs prüfen
|
||||
|
||||
```bash
|
||||
docker logs --tail=100 lageplan-web-1
|
||||
```
|
||||
**Keine** der folgenden Fehler sollen auftreten:
|
||||
- `404` für `/signaturen/*.svg`
|
||||
- `Prisma error` wegen `tenant_symbols.categoryId`
|
||||
- `Seed failed`
|
||||
|
||||
---
|
||||
|
||||
## Notfall-Recovery
|
||||
|
||||
### Szenario: Symbole sind verschwunden (404)
|
||||
|
||||
**Ursache:** `IconAsset`-Einträge wurden gelöscht (z.B. durch altes Seed-Skript mit `deleteMany`)
|
||||
|
||||
**Lösung:**
|
||||
|
||||
```bash
|
||||
# 1. Backup erstellen (Databasus GUI oder pg_dump)
|
||||
|
||||
# 2. Container-Status prüfen
|
||||
docker exec -it lageplan-web-1 sh -c 'ls -la /app/public/signaturen/ | head -5'
|
||||
# → Sollte SVG-Dateien anzeigen
|
||||
|
||||
# 3. Icons neu seeden (idempotent, sicher)
|
||||
docker exec -it lageplan-web-1 node prisma/seed-icons-only.js
|
||||
|
||||
# 4. Tenant-Symbols wiederherstellen (falls auch gelöscht)
|
||||
docker exec -it lageplan-web-1 node prisma/recover-symbols.js --dry-run
|
||||
docker exec -it lageplan-web-1 node prisma/recover-symbols.js --apply
|
||||
|
||||
# 5. Prüfen
|
||||
docker exec -it lageplan-web-1 node -e "
|
||||
const {PrismaClient} = require('@prisma/client');
|
||||
const p = new PrismaClient();
|
||||
p.iconAsset.count({where:{isSystem:true}}).then(c=>console.log('System-Icons:',c));
|
||||
p.tenantSymbol.count().then(c=>console.log('TenantSymbols:',c));
|
||||
"
|
||||
```
|
||||
|
||||
### Szenario: Features haben kaputte iconId-Referenzen
|
||||
|
||||
**Ursache:** Alte `iconId`-UUIDs in `Feature.properties` zeigen auf gelöschte `IconAsset`s
|
||||
|
||||
**Lösung:**
|
||||
|
||||
```bash
|
||||
# 1. Dry-Run: Analyse
|
||||
docker exec -it lageplan-web-1 node prisma/repair-features.js --dry-run
|
||||
|
||||
# 2. Apply: Reparatur (erstellt automatisch JSON-Backup)
|
||||
docker exec -it lageplan-web-1 node prisma/repair-features.js --apply
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Docker-Build Hinweise
|
||||
|
||||
### public/signaturen muss im Image sein
|
||||
|
||||
- `public/signaturen/*.svg` muss im Git-Index sein (`.gitignore` erlaubt es explizit)
|
||||
- `.dockerignore` darf `public/signaturen/` **nicht** ausschliessen
|
||||
- `Dockerfile` kopiert `public/` in die Runtime-Stage:
|
||||
```dockerfile
|
||||
COPY --from=builder /app/public ./public
|
||||
```
|
||||
|
||||
### Next.js standalone
|
||||
|
||||
- `next.config.js` hat `output: 'standalone'`
|
||||
- Der Build erzeugt `.next/standalone/` (minimaler Server)
|
||||
- `public/` wird explizit in die Runtime-Stage kopiert
|
||||
|
||||
### Multi-Stage Build
|
||||
|
||||
1. **deps**: `npm ci` (nur Dependencies)
|
||||
2. **builder**: `npm run build` (inkl. Prisma Generate)
|
||||
3. **runner**: Runtime-Image mit `public/`, `.next/standalone/`, Prisma-Client
|
||||
|
||||
---
|
||||
|
||||
## Änderungshistorie
|
||||
|
||||
| Datum | Änderung |
|
||||
|-------|----------|
|
||||
| 2026-05-20 | `.gitignore` korrigiert: `Signaturen/` → `/Signaturen/` (Root-only), `public/signaturen/*.svg` erlaubt |
|
||||
| 2026-05-20 | 117 SVG-Dateien force-added zum Git-Index |
|
||||
| 2026-05-20 | `.dockerignore` korrigiert: `Signaturen` → `/Signaturen/` |
|
||||
| 2026-05-20 | `package.json`: `db:seed` zeigt jetzt auf `prisma/seed.js` statt broken `seed.ts` |
|
||||
| 2026-05-20 | `seed.ts` korrigiert: Role-Enums + stabile IDs für `iconCategory.upsert` |
|
||||
| 2026-05-20 | Alle Seed-Skripte auf `deleteMany`-Freiheit geprüft |
|
||||
| 2026-05-20 | Dokumentation `docs/backup-und-seeding.md` erstellt |
|
||||
@@ -15,9 +15,12 @@
|
||||
"db:seed": "node prisma/seed.js",
|
||||
"db:studio": "prisma studio",
|
||||
"postinstall": "prisma generate",
|
||||
"db:seed:icons": "node prisma/seed-icons-only.js",
|
||||
"db:seed:safe": "node prisma/seed.js",
|
||||
"repair:features:dry-run": "node prisma/repair-features.js --dry-run",
|
||||
"repair:features:apply": "node prisma/repair-features.js --apply",
|
||||
"recover:symbols": "node prisma/recover-symbols.js"
|
||||
"recover:symbols:dry-run": "node prisma/recover-symbols.js --dry-run",
|
||||
"recover:symbols:apply": "node prisma/recover-symbols.js --apply"
|
||||
},
|
||||
"dependencies": {
|
||||
"@dnd-kit/core": "^6.1.0",
|
||||
|
||||
Reference in New Issue
Block a user