# 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 |
