Files
nexarch/docs/VAL-01-PRUEFPROTOKOLL.md
patrickandClaude Sonnet 5 628be89c9a
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (push) Canceled after 0s
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (pull_request) Canceled after 0s
CI / Core-Modul (Build/Vet/Test) (push) Canceled after 0s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (push) Canceled after 0s
Core-Schnittstellen-Vertragstests / contract-tests (pull_request) Canceled after 0s
Core-Pflichttest-Gate / pflichttest-gate (pull_request) Canceled after 0s
RBAC-Rollenhierarchie-Pflichtgate / rbac-policy-invariant (pull_request) Canceled after 0s
CI / Connect Security-Test-Gate (QA-01 AC4, Merge-Gate) (push) Canceled after 0s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (push) Canceled after 0s
CI / Web (dms-browser) (push) Canceled after 0s
CI / Web (pdf-viewer) (push) Canceled after 0s
CI / Web (shl) (push) Canceled after 0s
Supply-Chain-Scan (Go) / govulncheck (push) Canceled after 0s
CI / Core-Modul (Build/Vet/Test) (pull_request) Canceled after 0s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (pull_request) Canceled after 0s
CI / Connect Security-Test-Gate (QA-01 AC4, Merge-Gate) (pull_request) Canceled after 0s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (pull_request) Canceled after 0s
CI / Web (dms-browser) (pull_request) Canceled after 0s
CI / Web (pdf-viewer) (pull_request) Canceled after 0s
CI / Web (shl) (pull_request) Canceled after 0s
Supply-Chain-Scan (Go) / govulncheck (pull_request) Canceled after 0s
Supply-Chain-Scan (npm) / npm-audit (pull_request) Canceled after 0s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (push) Canceled after 0s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (pull_request) Canceled after 0s
VAL-01: zeilenzahl-abgleich-kerntabelle
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-14 20:07:29 +00:00

7.0 KiB
Raw Permalink Blame History

VAL-01 – Pruefprotokoll: Zeilenzahl-Abgleich je Kerntabelle

Auftrag

Automatisierter Abgleich der Zeilenzahl je migrierter Kerntabelle (Benutzer, Dokumente, Nachrichten) alt vs. neu, je Tenant, abzueglich bewusst nicht migrierter Kategorien. Reines Lese-/Zaehlwerkzeug (QA-Verifikation), kein neuer Migrationsschritt.

Gelesener Migrationscode (Voraussetzung)

  • internal/migrationuser/map.go, migrate.go (COR-02): Quellzahl der Benutzer-Kerntabelle ist die Anzahl freigegebener Zeilen in user_migration_map (approved_at IS NOT NULL), je nexarch_tenant_id. Zielzahl ist COUNT(*) FROM users in der physischen Tenant-Datenbank (Modell C).
  • dms/internal/migrationdocument/migrate.go (DOK-01): Zielzahl der Dokument-Kerntabelle ist COUNT(*) FROM documents in derselben physischen Tenant-Datenbank. Die Quelle ist das Source-Interface (Documents(ctx)), das archivdms per SQL-Export liest — eine konkrete Produktiv-Implementierung existiert in diesem Repository noch nicht (nur Testfixtures), da archivdms ein eigenes System auf Host 131 ist.
  • mail/internal/messagemigration/messagemigration.go (MAI-02): Es gibt im Ziel keine Postgres-Metadatentabelle fuer Nachrichten — Metadaten liegen ausschliesslich im Manticore-Suchindex (mail/internal/search). Die Quelle ist ebenfalls ein Source-Interface (Messages(ctx)), analog zu DOK-01.

Architekturentscheidung

dms und mail sind eigene Go-Module (eigene go.mod, keine Abhaengigkeit auf das Root-Modul oder umgekehrt) — ein direkter Import der Source-Interfaces aus internal/migrationverify (Root-Modul) ist daher nicht moeglich, ohne diese Modultrennung aufzubrechen. Das waere keine "kleinste Loesung" fuer ein reines QA-Werkzeug.

Entscheidung: internal/migrationverify ist ein generischer Vergleichsmotor (CountProvider-Schnittstelle, TenantCounts, TableReport, Run, RenderBericht) ohne Abhaengigkeit auf dms/mail. Konkrete Zaehl-Adapter:

  • Benutzer-Quelle: RegistryApprovedUserCountProvider — echte Postgres-Abfrage gegen user_migration_map (Registry-DB).
  • Benutzer-/Dokument-Ziel: PostgresTenantCountProvider — echte Postgres-Abfragen COUNT(*) FROM users / COUNT(*) FROM documents in der physischen Tenant-DB.
  • Dokument-/Nachrichten-Quelle: wird ueber eine JSON-Datei eingespeist (--source-counts), die das jeweilige Migrationsmodul (dms bzw. mail, in deren eigenem Go-Modul) aus seinem eigenen Source.Documents()/Source.Messages() ableitet und exportiert. Das haelt die Modultrennung ein und macht die Quelle des Zaehl-Schritts explizit nachvollziehbar.
  • Nachrichten-Ziel: in dieser Kachel bewusst nicht an Manticore angebunden (keine Manticore-Testinstanz in diesem Lauf verfuegbar); die Schnittstelle (CountProvider) ist aber bereits so geschnitten, dass ein search.Client-basierter Zaehl-Adapter (SELECT COUNT(*) FROM mail_documents WHERE tenant_slug = ..., analog zum bestehenden EnsureSchema-Pfad) ohne Aenderung am Kernmotor nachgezogen werden kann. Offener Punkt fuer eine Folge-Kachel, siehe unten.

Erklaerte Abweichungen (bewusst nicht migrierte Kategorien, z.B. abgelaufene Freigabelinks, abgeschlossene Workflow-Instanzen) werden als Explanation{TenantSlug, Table, Count, Reason} je Tenant/Tabelle eingespeist (--explanations). Eine Differenz gilt nur dann als "erklaert", wenn ihre Summe exakt der Differenz entspricht — jede nicht vollstaendig erklaerte Differenz ist ein offener Befund (Akzeptanzkriterium 2).

Implementierung

  • internal/migrationverify/report.go — TableReport, Diff(), OffenerBefund().
  • internal/migrationverify/verify.go — CountProvider, MapCountProvider, CombineUsers, Run.
  • internal/migrationverify/postgres.go — echte Postgres-Adapter (PostgresTenantCountProvider, RegistryApprovedUserCountProvider).
  • internal/migrationverify/render.go — deutschsprachiger Markdown-Bericht (RenderBericht), OffeneBefunde.
  • cmd/val01-zeilenzahl-abgleich/main.go — CLI-Wrapper: laedt Tenants aus der Registry, verbindet je Tenant-DB, schreibt den Bericht nach --out oder stdout, Exit-Code 2 bei offenen Befunden.

Tests (je Akzeptanzkriterium mindestens einer, real ausgefuehrt)

Alle Tests real ausgefuehrt gegen den echten Postgres-Testcluster auf Host 204. Zugangsdaten nie im Klartext ausgegeben — Variablennamen per grep -o '^[A-Z_]*=' /etc/nexarch-dev/*.env, Werte ausschliesslich per set -a && source /etc/nexarch-dev/*.env && set +a im selben SSH-Befehl eingespeist.

Test Deckt ab Ergebnis
TestRun_ErklaerteUndOffeneAbweichungen AC 1 (Bericht je Tenant/Tabelle), AC 2 (erklaert vs. offener Befund) PASS
TestRun_UnbekannterTenant Fehlerpfad: Tenant ohne hinterlegte Zahlen PASS
TestCombineUsers Zusammenfuehren Benutzer-Quelle + Dokument-/Nachrichten-Quelle PASS
TestOffeneBefunde Filterung auf offene Befunde fuer den Bericht PASS
TestZeilenzahlAbgleich_DreiTenantsMitEingefuegterAbweichung (echter Postgres-Cluster, Host 204, TEST_ADMIN_DSN) Pruefung 1 (>= 3 Test-Tenants, Bericht erzeugt) UND Pruefung 2 (absichtlich eingefuegte Zeilenzahl-Abweichung bei mandant-b/documents, 2 Dokumente im Ziel fehlen, ohne Erklaerung — wird als OFFENER BEFUND erkannt; die uebrigen Tenants/Tabellen sind unauffaellig OK) PASS, 4.4–4.7s Laufzeit

Lauf (Beispiel):

go test ./internal/migrationverify/... -v
=== RUN   TestZeilenzahlAbgleich_DreiTenantsMitEingefuegterAbweichung
--- PASS: TestZeilenzahlAbgleich_DreiTenantsMitEingefuegterAbweichung (4.42s)
=== RUN   TestRun_ErklaerteUndOffeneAbweichungen
--- PASS: TestRun_ErklaerteUndOffeneAbweichungen (0.00s)
=== RUN   TestRun_UnbekannterTenant
--- PASS: TestRun_UnbekannterTenant (0.00s)
=== RUN   TestCombineUsers
--- PASS: TestCombineUsers (0.00s)
=== RUN   TestOffeneBefunde
--- PASS: TestOffeneBefunde (0.00s)
PASS

go build ./... und go vet ./internal/migrationverify/... ./cmd/val01-zeilenzahl-abgleich/... fehlerfrei. gofmt -l liefert keine Treffer.

Datenschutz

Alle Testfixtures sind synthetisch (fiktive Tenant-Namen mandant-a/b/c, fiktive E-Mail-Adressen unter example.invalid, selbst erzeugte UUIDs). Keine echten archivdms-/archivmail-Daten verwendet oder angefasst. Keine Zugangsdaten im Code — ausschliesslich ueber --registry-dsn/Umgebungsvariablen zur Laufzeit.

Offene Punkte fuer Folge-Kacheln

  1. Echter Nachrichten-Ziel-Zaehl-Adapter gegen Manticore (search.Client.CountByTenant o.ae.), sobald eine Test-Manticore- Instanz fuer diesen Zweck zur Verfuegung steht.
  2. Konkrete, produktive Source-Implementierungen fuer migrationdocument.Source/messagemigration.Source (SQL-Export gegen archivdms/archivmail) existieren noch nicht in diesem Repo; bis dahin bleibt die Dokument-/Nachrichten-Quellzahl fuer dieses Werkzeug eine extern angelieferte JSON-Datei (--source-counts).

Branch / Commits / Push

  • Branch: feature/val-01-zeilenzahl-abgleich-kerntabelle
  • Commit-Nachricht: VAL-01: zeilenzahl-abgleich-kerntabelle
  • Kein Merge, kein Deploy.