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
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:
1 parent
3f579ec330
commit
90f35f59a8
1 file changed
+48
@@ -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).
|
||||
Reference in new issue
Block a user