Assessor_2.0/docs/POSTGRESQL.md

133 lines
6.0 KiB
Markdown

# PostgreSQL-Persistenz
## Architekturstand
Phase 11 ergänzt `PostgresAssessorRepository` als produktiven Adapter hinter
dem bestehenden `AssessorRepository`. React, API, Importengine und
Vergleichslogik kennen weder SQL noch den PostgreSQL-Treiber.
Relationale Spalten und Fremdschlüssel sichern Identitäten und Beziehungen.
Das vollständige versionierte Fachobjekt bleibt zusätzlich als JSONB erhalten.
Damit können neue Scannerfelder verlustfrei aufgenommen werden, ohne die
Integritätsregeln für Projekt, Assessment, Scan-Lauf, Datei und Finding zu
umgehen.
## Lokale Datenbank starten
1. `.env.postgres.example` nach `.env.postgres` kopieren.
2. Ein langes, nur lokal verwendetes Passwort eintragen.
3. `npm run db:up` ausführen.
4.
pm run start:local oder
pm run serve:local starten. Das Startskript lädt .env.postgres automatisch und bildet daraus die lokale Loopback-Verbindung.
```text
ASSESSOR_DATABASE_URL=postgresql://assessor:<passwort>@127.0.0.1:5432/assessor
ASSESSOR_DATABASE_SSL=disable
ASSESSOR_DATABASE_POOL_SIZE=10
```
5. `npm run serve:local` starten.
Ohne `ASSESSOR_DATABASE_URL` startet ASSESSOR bewusst im flüchtigen
In-Memory-Entwicklungsmodus. Ist eine URL gesetzt und PostgreSQL nicht
erreichbar, bricht der Serverstart ab; er fällt nicht still auf Arbeitsspeicher
zurück. Dadurch kann ein Konfigurationsfehler keine scheinbar erfolgreichen,
aber nicht dauerhaften Importe erzeugen.
`ASSESSOR_DATABASE_SSL=disable` ist ausschließlich für die Loopback-Verbindung
auf dem Entwicklungsrechner vorgesehen. Für entfernte Datenbankziele ist TLS
standardmäßig erforderlich. Die spätere Firmenkonfiguration benötigt eine
vertrauenswürdige interne Zertifikatskette.
## Migrationen
Migrationen liegen versioniert unter `server/postgres/migrations`. Beim Start
mit PostgreSQL:
1. nimmt der Prozess einen PostgreSQL-Advisory-Lock,
2. prüft Version und SHA-256-Prüfsumme jeder bekannten Migration,
3. führt jede neue Migration in einer eigenen Transaktion aus,
4. dokumentiert sie in `assessor_schema_migrations`,
5. verweigert den Start, wenn eine bereits angewandte Migration verändert wurde.
Angewandte Migrationen dürfen niemals nachträglich editiert werden. Änderungen
erhalten stets eine neue, aufsteigend nummerierte SQL-Datei.
## Schema und Suche
Das Schema besitzt unter anderem:
- Primär- und Fremdschlüssel mit kontrollierten Löschregeln
- eindeutige Scan-Reihenfolgen pro Assessment
- optimistische Review-Revisionen
- eine globale Repository-Revision für konkurrierende Importtransaktionen
- B-Tree-Indizes auf Fremdschlüsseln und Filterspalten
- gespeicherte `tsvector`-Dokumente und GIN-Indizes für Findings
- einen GIN-JSONB-Index für spätere strukturierte Zusatzfeldabfragen
Importdaten werden zunächst im Prozess gestagt. Der Commit öffnet genau eine
Datenbanktransaktion auf genau einer Poolverbindung, sperrt die
Repository-Revision, schreibt alle Entitäten, validiert das vollständige
kanonische Assessment-Modell und führt danach den Commit aus. Fehler erzeugen
ein Rollback ohne Teilimport.
## Import-Fingerprints
Migration `002_import_fingerprints.sql` ergänzt `assessor_import_fingerprints`. Der SHA-256-Wert ist Primärschlüssel; gespeichert werden außerdem Dateiname, Größe, letzter Dateiänderungszeitpunkt, erster und letzter Importzeitpunkt sowie ein Wiederholungszähler.
Der Abschluss eines bestätigten Batchimports verwendet `commitCanonicalImport`. Der PostgreSQL-Adapter schreibt neues Projekt, Assessment, Scan-Lauf, kanonische Importdaten und Fingerprints auf derselben Poolverbindung innerhalb derselben Transaktion. Die Repository-Revision wird dabei genau einmal erhöht. Ein Validierungs-, Auswahl- oder Datenbankfehler erzeugt ein vollständiges Rollback.
## Backup
Vor Migrationen, Updates und größeren Löschvorgängen ist ein logisches Backup
zu erstellen. Bei installiertem PostgreSQL-Client:
```text
pg_dump --format=custom --no-owner --file=assessor-YYYYMMDD.backup "$ASSESSOR_DATABASE_URL"
```
Das Backup muss außerhalb des Datenbankcontainers, zugriffsgeschützt und gemäß
der später festzulegenden Aufbewahrungsfrist abgelegt werden. Regelmäßig muss
ein Restore in eine getrennte Testdatenbank durchgeführt werden; ein Backup
ohne geprüften Restore gilt nicht als belastbar.
## Restore
Ein Restore ersetzt Daten und darf nur nach exakter Prüfung der Zieldatenbank
erfolgen. Empfohlen wird zunächst eine neue leere Datenbank:
```text
createdb assessor_restore_test
pg_restore --no-owner --exit-on-error --dbname=assessor_restore_test assessor-YYYYMMDD.backup
```
Danach werden Migrationstabelle, Projektanzahl, Assessments, Scan-Läufe,
Findings, Reviews und Stichprobenexporte geprüft. Erst nach erfolgreicher
Validierung darf ein betriebliches Umschalten geplant werden.
## Löschung
Projektlöschung verlangt weiterhin die exakte Projekt-ID und `cascade: true`.
PostgreSQL entfernt abhängige Assessments, Scan-Läufe, Dateien, Tabellen,
Vorkommen, Evidenz, Diagnosen, Reviews, Regeln und Vergleiche innerhalb einer
Transaktion. Nicht mehr verwendete Finding-Definitionen werden anschließend
bereinigt. Datenbank-Backups bleiben davon unberührt und benötigen ein eigenes
Aufbewahrungs- und Löschkonzept in Phase 14.
## Verifikation
Neben Schema- und Migrationsläufertests existiert ein echter Integrationstest
gegen PostgreSQL 16. Er prüft idempotente Migrationen, atomare Mehrlaufimporte,
Volltextsuche, optimistische Reviewkonflikte, Vergleiche, Export,
Parallelkonflikte, kanonische Batchimporte, dauerhafte Fingerprint-Zähler und kaskadierende Projektlöschung. Der Test verwendet
`ASSESSOR_TEST_DATABASE_URL` und darf niemals auf eine produktive Datenbank
zeigen.
## Technische Referenzen
- PostgreSQL: https://www.postgresql.org/docs/current/ddl-constraints.html
- PostgreSQL-GIN: https://www.postgresql.org/docs/current/gin.html
- PostgreSQL-Volltextsuche: https://www.postgresql.org/docs/current/textsearch.html
- node-postgres-Transaktionen: https://node-postgres.com/features/transactions
- node-postgres-Parameter: https://node-postgres.com/features/queries