MAP-04: pruefprotokoll
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
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
CI / Web (pdf-viewer) (pull_request) 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 (shl) (pull_request) Canceled after 0s
Core-Schnittstellen-Vertragstests / contract-tests (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
Core-Pflichttest-Gate / pflichttest-gate (pull_request) Canceled after 0s
RBAC-Rollenhierarchie-Pflichtgate / rbac-policy-invariant (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

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
patrickandClaude Sonnet 5 committed 2026-10-14 21:56:06 +00:00
1 parent 3f579ec330
commit 90f35f59a8
1 file changed
+48
+48
View File
@@ -0,0 +1,48 @@
# MAP-04 Prüfprotokoll – User-Migration-Map & Freigabe-Workflow
Datum: 2026-10-14
Umgebung: Host 204 (`root@192.168.1.204`), echter Postgres-Testcluster via `TEST_ADMIN_DSN` aus `/etc/nexarch-dev/core-dev.env` (Werte nie im Klartext ausgegeben, nur per `set -a && source ... && set +a` eingespeist). Alle Testdaten synthetisch (`*.example.invalid`-E-Mails, selbst erzeugte Test-Hashes), keine echten archivmail-/archivdms-Kundendaten.
## Umsetzung
- Neues Paket `internal/usermigrationapproval` (Store, `Entry`, `AuditEntry`), 1:1 nach dem Muster von MAP-02 (`internal/tenantapproval`), eine Ebene tiefer (Benutzer statt Tenant):
- `InsertCandidates` legt `usermatch.Candidate`-Zeilen (MAP-03) als `status='pending'` in `user_migration_map` an (einseitige Kandidaten ohne jede Quelle werden verworfen).
- `Pending()` / `Approved()` / `Get()` als Lesezugriffe; `Approved()` ist exakt der Filter, den COR-02 (`internal/migrationuser.MapStore.Approved`, `WHERE approved_at IS NOT NULL`) bereits nutzt.
- `Approve(id, approvedBy, note)` / `Reject(id, rejectedBy, note)` protokollieren jede Entscheidung transaktional in `user_migration_map_audit` (Zeitpunkt `performed_at`, handelnde Person `performed_by`).
- Migration `migrations/0025_user_migration_map_approval.{up,down}.sql`: erweitert die bestehende `user_migration_map` (COR-02-Tabelle aus 0020/0023) additiv um `status`/`rejected_by`/`rejected_at` plus Check-Constraints, analog zu `0024_tenant_migration_map_approval.up.sql` (MAP-02). Neue Tabelle `user_migration_map_audit`. Keine bestehende Spalte verändert oder entfernt — COR-02 liest weiterhin unverändert `approved_at IS NOT NULL`.
- Keine UI gebaut: MAP-02 (direktes Vorbild) hat ebenfalls keine Freigabe-Oberfläche implementiert, nur den Store/CLI-Zugriffspfad (`cmd/map03-user-match` liest `tenantapproval.Approved()` direkt). MAP-04 hält sich an denselben Umfang — die "Technische Grundlage: Freigabe-Oberfläche" bleibt wie bei MAP-02 ein nicht ticketierter Folgeschritt, hier dokumentiert statt stillschweigend übersprungen.
- COR-02 (`internal/migrationuser`) nicht verändert: sein Lesezugriff (`approved_at IS NOT NULL`) ist bereits exakt der einzige, über den freigegebene Benutzer übernommen werden (Akzeptanzkriterium 3 war durch COR-02 bereits erfüllt, MAP-04 liefert jetzt den davorliegenden Freigabe-Workflow, der diese Spalte überhaupt kontrolliert befüllt).
## Tests (real gegen Postgres ausgeführt, `go test ./internal/usermigrationapproval/... -v`)
| Test | Prüft | Ergebnis |
|---|---|---|
| `TestApprove_RequiresExplicitDecisionAndLogsIt` | AK1: explizite, protokollierte Freigabe (Status, `approved_by`, `approved_at`, Audit-Log-Eintrag mit Zeitpunkt+Person) | PASS |
| `TestUnapprovedMerge_StaysRejectedWhileBothAccountsRemainSeparatelyMigratable` | AK2 / sicherheitskritische Prüfung 1: Zusammenführungs-Kandidat ohne Freigabe wird vom COR-02-Downstream-Filter nachweislich nicht erfasst; nach `Reject` bleiben beide Konten als zwei einseitige, unabhängig freigebbare Kandidaten migrierbar statt fälschlich zusammengeführt | PASS |
| `TestApproved_LiefertNurFreigegebeneEintraege` | AK3: `Approved()` liefert ausschließlich freigegebene Zeilen, nie pending/rejected | PASS |
| `TestApproved_StichprobeVon10GegenQuellenGeprueft` | Prüfung 3: Stichprobe von 10 freigegebenen Zuordnungen 1:1 gegen die ursprüngliche Kandidatenliste (archivmail-/archivdms-ID, Tenant, Name) verglichen | PASS |
| `TestInsertCandidates_DiscardsCandidatesWithoutSource` | Robustheit: Kandidat ganz ohne Quelle wird nicht als Map-Zeile angelegt | PASS |
Lauf-Ergebnis:
```
ok gitea.perlbach24.de/scripte/nexarch/internal/usermigrationapproval 0.470s
```
Regressionslauf angrenzender Pakete (unverändert, real gegen Postgres):
```
ok gitea.perlbach24.de/scripte/nexarch/internal/tenantapproval 0.440s
ok gitea.perlbach24.de/scripte/nexarch/internal/usermatch 0.079s
ok gitea.perlbach24.de/scripte/nexarch/internal/migrationuser 3.627s
```
`go build ./...` und `go vet ./...` über das gesamte Repo: fehlerfrei.
## Migrations-Prüfung (Prüfung 2 sinngemäß: Protokoll vollständig und nachvollziehbar)
Migration `0025_user_migration_map_approval` real gegen eine Wegwerf-Datenbank (`map04_sqltest`, danach gelöscht) nach vollständiger Vorkette (`0001`, `0019`, `0020`, `0023`, `0024`) angewendet:
- `up.sql`: `ALTER TABLE`/`CREATE TABLE`/`CREATE INDEX` fehlerfrei.
- `down.sql`: vollständiger Rollback (`DROP TABLE`, `ALTER TABLE ... DROP COLUMN/CONSTRAINT`) fehlerfrei.
## Nicht Bestandteil dieser Kachel
- Freigabe-Oberfläche (UI) — wie bei MAP-02 nur als Store/API vorbereitet, kein Frontend gebaut (konsistent mit dem direkten Vorbild).
- Anpassung von MAP-03 (`cmd/map03-user-match`), um `usermigrationapproval.InsertCandidates` statt/zusätzlich zu `WriteCandidatesCSV` aufzurufen — MAP-03 ist laut Ticket bereits fertig und liefert die CSV als "bisherige dünne Schnittstelle"; die Verdrahtung zu einem schreibenden Aufruf wäre ein eigener Integrationsschritt und nicht Teil des MAP-04-Scopes (Freigabe-Workflow selbst).