Files
craftvia/docs/KONZEPT-backup-target.md
msolarczekandClaude Opus 5 c8e6f30a27
CI / build-and-check (push) Canceled after 0s
CI / audit (push) Canceled after 0s
CI / sbom (push) Canceled after 0s
Basis: Certvia dev@a48c5fb als Fundament für Craftvia
Unveränderter Stand von certvia/dev (a48c5fb) plus Craftvia-Spezifikation
und Brandbook unter docs/craftvia/. ISMS-Module werden im Folgecommit entfernt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 11:05:39 +02:00

5.1 KiB

Konzept — Konfigurierbarer Backup-Zielspeicher (Backend + Lokal) (certvia)

Status: Konzept/Entscheidungsvorlage (kein Code). Produkt: certvia. Folge-Feature der Backup-Lane. Ziel: den Zielspeicher für Backup-/DSGVO-Artefakte im Betreiber-Portal konfigurierbar machen und lokale (persistente) Speicherung als vollwertige Option anbieten — nicht nur über Env.

1. Ist-Zustand (src/server/storage/backup-store.ts)

  • Es gibt bereits eine BackupStore-Abstraktion (put/get/list/remove) mit zwei echten Implementierungen: S3BackupStore (MinIO/S3) und LocalBackupStore (echte Byte-Persistenz).
  • Aber: Die Wahl trifft createBackupStore() einmalig beim Prozessstart, rein Env-basiert: alle S3_* gesetzt → S3, sonst lokaler Ordner (BACKUP_LOCAL_DIR bzw. <cwd>/.backups). Exportiert als statisches Singleton backupStore.
  • Nur 3 Nutzer: src/server/backup/export.ts, restore.ts, ops.ts.
  • Schwächen: (a) nicht im Backend wählbar; (b) der lokale Ordner liegt im Container → beim Redeploy flüchtig; (c) S3-Config nur als Env, nicht pro Betreiber pflegbar.

2. Zielbild

  • Betreiber wählt im Portal das Ziel: Lokal oder S3/MinIO, inkl. Config, mit „Verbindung testen".
  • Lokal ist persistent (gemountetes Volume), nicht flüchtig.
  • Env bleibt als Fallback funktionsfähig (Rückwärtskompatibilität).

3. Datenmodell (PlatformSetting, Singleton erweitern)

Aktuell nur mfaRequired. Ergänzen:

  • backupTarget String @default("local") — local | s3
  • backupLocalDir String? — Pfad des lokalen Ziels (muss auf ein gemountetes Volume zeigen)
  • backupS3Endpoint / backupS3Bucket / backupS3Region / backupS3AccessKey String?
  • backupS3SecretKeyEnc String? — S3-Secret verschlüsselt at-rest über src/server/secret-crypto.ts (encryptSecret/decryptSecret, Schlüssel MFA_ENC_KEY/AUTH_SECRET) — nie Klartext in der DB.

Migration additiv (nullable, Default local). Kein Backfill nötig.

4. Store-Factory umbauen

  • backupStore-Singleton → getBackupStore(): Promise<BackupStore>: liest PlatformSetting, baut den passenden Store, entschlüsselt den S3-Key.
  • Präzedenz: DB-Config (wenn backupTarget gesetzt/vollständig) → sonst Env (S3_* / BACKUP_LOCAL_DIR) → sonst lokaler Default .backups. So bleibt bestehendes Env-Deployment lauffähig.
  • Caching + Invalidierung: Store memoisieren, bei Änderung der Backup-Settings invalidieren (Version/Timestamp aus PlatformSetting.updatedAt).
  • Die 3 Call-Sites (export.ts, restore.ts, ops.ts) von backupStore auf await getBackupStore() umstellen.
  • Fail-secure: unvollständige S3-Config → klarer Fehler (nicht still auf lokal fallen, wenn backupTarget=s3 gewählt wurde).

5. Betreiber-UI

  • Neue Seite im Plattform-Portal, z. B. /admin/backup (oder Abschnitt in den Plattform-Einstellungen).
  • Gated: requirePlatformFullAdmin + MFA-Step-up (assertPlatformStepUp) — Betreiber-Config mit Credentials.
  • Felder: Ziel-Radio (Lokal/S3), je nach Wahl die Config; „Verbindung testen" (Probe-put+get+remove eines winzigen Test-Keys) mit klarer Rückmeldung; Speichern über eine Action analog setPlatformMfaRequired (platformSetting.upsert, S3-Secret vor dem Schreiben verschlüsseln).

6. Persistenz für „Lokal" (Compose)

  • In docker-compose.coolify.yml ein persistentes Volume ergänzen (analog pgdata/miniodata): backups: und in app + worker unter dem Pfad aus backupLocalDir mounten (z. B. /app/.backups). Ohne Mount bleibt Lokal flüchtig.
  • Doku-Hinweis: backupLocalDir muss innerhalb des gemounteten Pfads liegen.

7. Sicherheit

  • S3-Secret nur verschlüsselt in der DB (secret-crypto).
  • Config-Bearbeitung nur Full-Admin + Step-up, auditiert.
  • BACKUP_ENC_KEY (Artefakt-Verschlüsselung, src/server/backup/crypto.ts) bleibt getrennt vom Zielspeicher — Verschlüsselung des Inhalts ≠ Wahl des Speicherorts.
  • Umgebungs-Secret-Kohärenz (Restore) unverändert: BACKUP_ENC_KEY/PASSWORD_PEPPER/MFA_ENC_KEY sind Env, nicht Artefakt (siehe KONZEPT-backup-restore.md §9).

8. Tests

  • scripts/test-backup-* erweitern: Store-Auflösung aus DB-Config (local & s3), Präzedenz DB→Env→Default, „Verbindung testen"-Pfad, Fail-secure bei unvollständiger S3-Config.
  • Export→Restore end-to-end gegen beide Backends.

9. Sofort testbar (ohne Umbau)

Schon heute: ohne S3_* fällt der Store auf lokal zurück → Export/Restore/DSGVO laufen (Artefakte im Container-.backups, flüchtig). Für einen schnellen Funktionstest genügt: backup-worker + Redis (vorhanden) + BACKUP_ENC_KEY (Fallback AUTH_SECRET). Der Umbau macht das Ziel wählbar und persistent.

10. Offene Entscheidungen

  • Eigene Seite /admin/backup vs. Abschnitt in bestehenden Plattform-Einstellungen.
  • Mehrere Ziele/Profile (Primär + Offsite) — jetzt 1 Ziel, Mehrfachziele als Phase 2.
  • Ob der lokale Pfad frei wählbar ist oder auf den gemounteten Volume-Pfad festgelegt wird (empfohlen: fest, um Fehlkonfiguration zu vermeiden).