# BAK-05 – Prüfprotokoll: Reconciliation / Konsistenzprüfung Storage vs. DB Voraussetzung BAK-01, BAK-02 (Welle 1) – erledigt, siehe eigene Protokolle. ## Grundsatzentscheidung: reine Funktion + zwei Quell-Adapter `internal/reconcile.Reconcile` ist eine reine Funktion ohne DB-/Storage- Zugriff (leicht ohne echte Infrastruktur testbar), die Ein- und Auslesen echter Systeme ist strikt in `sources.go` getrennt (`ListDBStorageKeys` gegen echtes Postgres, `ListStorageObjects` gegen echtes Dateisystem). Beide Seiten liefern nur SCHLÜSSEL – niemals Inhalt – dadurch bleibt BAK-05 sauber getrennt von BAK-08 (Inhalts-/Prüfsummen- verifikation, eigene Fehlerklasse, eigenes Ticket). Report-Format bewusst deterministisch: beide Ergebnislisten (`missing_in_storage`, `orphaned_in_storage`) nach `storage_key` aufsteigend sortiert, damit BAK-08 später dieselbe Objektliste als stabile Stichprobenquelle weiterverarbeiten kann, ohne selbst neu zu sortieren/filtern (Nutzervorgabe). Meldeweg über OPS-05 (wie später BAK-08) wurde als offene Design-Frage aufgeworfen, aber nicht zur Vorbedingung gemacht – hier bewusst noch nicht umgesetzt (kein OPS-05-Abhängigkeitseintrag im Board für BAK-05); Report wird aktuell nur als JSON auf stdout ausgegeben und per Exit-Code (1 bei Abweichungen) für systemd/Monitoring sichtbar gemacht. Anbindung an OPS-05 kann bei Bedarf nachgezogen werden, ohne `Reconcile` selbst zu ändern. ## Umsetzung - `internal/reconcile.Reconcile(dbEntries, storageKeys) Report` – reine Vergleichsfunktion, liefert `MissingInStorage`/`OrphanedInStorage`, `Report.IsClean()` als eindeutiges Sauber-Merkmal. - `internal/reconcile.ListDBStorageKeys` – liest `file_revisions` (DMS FDN-02) per direktem SQL aus derselben physischen Tenant-DB (Modell C, Core TEN-01) – kein Import von DMS-Go-Paketen möglich (eigenes Go-Modul), daher reiner SQL-Zugriff gegen das dokumentierte Schema. - `internal/reconcile.ListStorageObjects` – durchläuft den lokalen FDN-03-`LocalDriver`-Basisordner (`filepath.WalkDir`), liefert `nil, nil` bei fehlendem Verzeichnis statt Fehler (noch keine Objekte ist kein Fehlerzustand). - `cmd/reconcile-cli` – liest `NEXARCH_RECONCILE_TENANT_DSN` und `NEXARCH_RECONCILE_STORAGE_DIR`, gibt Report als JSON auf stdout aus, Exit-Code 1 bei Abweichungen. ## Prüfungen | # | Prüfung | Ergebnis | |---|---|---| | 1 | Datenbankeintrag ohne Storage-Objekt wird erkannt | **bestanden** — `TestReconcile_DetectsMissingInStorage` | | 2 | Storage-Objekt ohne Datenbankeintrag wird erkannt | **bestanden** — `TestReconcile_DetectsOrphanedInStorage` | | 3 | Lauf ohne Abweichungen liefert leeren, eindeutig sauberen Bericht | **bestanden** — `TestReconcile_CleanRunProducesEmptyReport` (zusätzlich `IsClean()`-Konsistenzprüfung) | Zusätzlich (Nutzervorgaben, nicht explizit im Ticket als Pflichtprüfung benannt, aber zentral für die Abgrenzung/Weiterverwendbarkeit): - `TestReconcile_ExistingButCorruptedObjectProducesNoFinding` – Nachweis, dass Reconcile AUSSCHLIESSLICH Existenz prüft, niemals Inhalt (Trennung von BAK-08). - `TestReconcile_DeterministicOrdering` – zwei Läufe mit identischer Eingabe liefern identische Reihenfolge, aufsteigend nach `storage_key`. - `TestListDBStorageKeys_ReadsRealFileRevisions` – liest echt gegen die gemeinsame Tenant-Testdatenbank `dms_tenant_test` (reales DMS-FDN-02- Schema, kein Mock). - `TestListStorageObjects_WalksRealDirectory` / `_MissingDirectoryReturnsEmpty` – echtes Dateisystem, kein Mock. ## Echte Verdrahtung auf 192.168.1.131 - `reconcile-cli` gebaut nach `/opt/nexarch-archive/bin/` - `/etc/nexarch/archive-reconcile.env` (0600): `NEXARCH_RECONCILE_TENANT_DSN` zeigt auf die gemeinsame Tenant-Testdatenbank `dms_tenant_test` (DMS selbst läuft auf 192.168.1.131 noch nicht als eigener systemd- Dienst mit persistenter Konfiguration – dies ist die real verfügbare Tenant-DB mit echtem FDN-02-Schema, dokumentierter bekannter Stand, kein stiller Mock); `NEXARCH_RECONCILE_STORAGE_DIR` zeigt auf `/var/nexarch-archiv/dms-objects` (persistentes ZFS-Dataset, NICHT `/var/nexarch-test/`). - Timer `nexarch-archive-reconcile.timer` installiert und aktiviert (täglich 05:00 UTC), `systemctl list-timers` bestätigt scharf. - `systemctl start nexarch-archive-reconcile.service` real ausgelöst: `status=0/SUCCESS`, Journal zeigt echten JSON-Report (`missing_in_storage: null, orphaned_in_storage: null` – Tenant-DB aktuell leer, daher sauberer Bericht, keine synthetische Ausgabe). ## Build/Test-Ergebnis (192.168.1.131, `make check`) ``` go build ./... -> clean go vet ./... -> clean golangci-lint run ./... -> 0 issues go test ./... -p 1 -count=1 -> 3/3 Pakete mit Tests ok (internal/backup, internal/objectbackup, internal/reconcile), 0 Fehlschläge ``` `internal/reconcile`-Tests separat mit gesetzter `TEST_TENANT_DSN` gegen `dms_tenant_test` verifiziert: 8/8 Tests bestanden (5 reine `Reconcile`-Tests + 3 `sources.go`-Integrationstests). ## Gesamtergebnis **Bestanden.** Alle drei Akzeptanzkriterien und alle Pflicht- sowie Nutzervorgaben-Prüfungen real erfüllt (echte Postgres-Instanz, echtes Dateisystem, echter systemd-Lauf). Zwei Testfehler während der Entwicklung (Schema-Abweichung `revision_number` NOT NULL in der realen `dms_tenant_test`-Tabelle; inkonsistente Fixture-Daten in `TestReconcile_DeterministicOrdering`) gefunden und korrigiert – beide waren Testautorenfehler, keine Fehler in `Reconcile` selbst.