docs(16-05): add plan summary, close PERM-02, log open verification items

- 16-05-SUMMARY.md documents the two-task plan (sync-report wiring,
  grants-matrix internal-name fallback).
- PERM-02 marked complete in REQUIREMENTS.md: all five Phase-16 success
  criteria are code-complete across plans 16-01..16-03; this plan
  delivered the last missing visibility layer (D-05/D-06) and the
  third D-04 display site.
- WINDOWS.md #6: this plan's own manual browser walkthrough (sync
  report three-line render, amber default-marker line, grants-matrix
  two-name search) not executed — no browser tool in this session.
This commit is contained in:
2026-08-06 16:40:43 +02:00
parent fac152af74
commit a0c5e470c3
3 changed files with 201 additions and 5 deletions
@@ -0,0 +1,183 @@
---
phase: 16-ad-gruppen-synchronisation
plan: 05
subsystem: ui
tags: [nextjs, next-intl, ldap, groups, module-grants, vitest, tailwind]
# Dependency graph
requires:
- phase: 16-ad-gruppen-synchronisation (Plan 16-03)
provides: "LdapSyncResult erweitert um groupsAdopted, groupsRenamed, groupsDeleted, defaultMarkerMoved; groupMembershipsAdded/Removed seit D-21"
- phase: 16-ad-gruppen-synchronisation (Plan 16-04)
provides: "internalName ?? name Fallback-Muster in Gruppenliste/GroupFormModal als Vorbild fuer die Matrix-Spaltenkoepfe"
provides:
- "SyncResult (Frontend) additiv um sechs Zahlenfelder erweitert — keine vom Backend gelieferte Sync-Zahl bleibt unangezeigt"
- "syncRequestError-Zustand: ein insgesamt fehlgeschlagener Sync-Request zeigt eine sichtbare Fehlerzeile statt eines Null-Berichts"
- "Bedingte Amber-Zeile fuer defaultMarkerMoved > 0 (D-06-Sichtbarkeitsmassnahme fuer den in D-05 akzeptierten Zugriffsverlust)"
- "Group.internalName im Frontend-Typ von admin/modules/grants/page.tsx; Spaltenkoepfe der Freigabe-Matrix zeigen internalName ?? name als Text und Tooltip; Spaltensuche matcht beide Namen (dritte und letzte D-04-Anzeigestelle)"
affects: []
# Actuals (#2632)
actuals:
tokens: 1884
tasks: 2
commits: 2
# Tech tracking
tech-stack:
added: []
patterns:
- "Additive Sync-Report-Erweiterung: Backend-LdapSyncResult und Frontend-SyncResult wachsen im selben Schritt um dieselben Feldnamen (schliesst den D-21-Wiederholungsfall aus 16-03-Decisions)"
- "Sync-Request-Fehler und Sync-Ergebnis sind getrennte States (syncRequestError vs. syncResult) statt eines gemeinsamen Drei-Null-Fallback-Objekts — verhindert, dass ein nie gelaufener Sync als erfolgreicher No-Op erscheint"
key-files:
created: []
modified:
- "apps/web/src/app/(portal)/admin/ldap/page.tsx"
- "apps/web/src/app/(portal)/admin/modules/grants/page.tsx"
- "apps/web/src/messages/de.json"
- "apps/web/src/messages/en.json"
key-decisions:
- "PERM-02 in REQUIREMENTS.md auf [x] gesetzt: alle fuenf Phase-16-Erfolgskriterien (Auswahl-Import, keine OU-weite Automatik, Rename-Nachzug, Loesch-Nachzug samt Mitgliedschaften/Freigaben, unberuehrte lokale Gruppen) sind durch die kombinierte Arbeit der Plaene 16-01 bis 16-03 bereits code-vollstaendig; dieser Plan liefert die laut Plan-Vertrag zuletzt fehlende Sichtbarkeitsschicht (D-05/D-06-Massnahme) und die dritte D-04-Anzeigestelle."
- "Die A1/A2-Live-Pruefung gegen ein echtes Active Directory (RESEARCH.md-Annahmen, WINDOWS.md #4) bleibt trotz PERM-02-Abschluss ausdruecklich offen — sie ist keines der fuenf Erfolgskriterien, sondern eine Korrektheitsannahme UNTER SC-3/SC-4. Ein negatives Ergebnis waere ein Stopp-Grund fuer die D-05-Loeschsemantik und muss laut 16-03-SUMMARY vor produktivem Einsatz nachgeholt werden."
patterns-established: []
requirements-completed: [PERM-02]
coverage:
- id: D1
description: "Der Sync-Bericht zeigt neben der bestehenden Benutzerzeile zwei neue, immer sichtbare Zeilen (Gruppenmitgliedschaften, AD-Gruppen) sowie eine bedingte Amber-Zeile bei verschobener Standardmarkierung — kein vom Backend geliefertes Zaehlfeld bleibt unangezeigt"
requirement: "PERM-02"
verification:
- kind: other
ref: "awk '/interface SyncResult/,/^}/' page.tsx | grep -c 'groupMembershipsAdded|groupMembershipsRemoved|groupsAdopted|groupsRenamed|groupsDeleted|defaultMarkerMoved' == 6"
status: pass
- kind: other
ref: "grep -c 'defaultMarkerMoved > 0' page.tsx >= 1; grep -c 'text-amber-700' page.tsx >= 1"
status: pass
- kind: unit
ref: "cd apps/web && npx vitest run (192/192 gruen, keine Regression)"
status: pass
human_judgment: true
rationale: "Kein automatisierter Test rendert den erweiterten Sync-Bericht gegen einen echten API-Response — der manuelle Browser-Durchklick aus dem Plan-Verification-Block (drei Zahlenzeilen, Amber-Zeile bei defaultMarkerMoved>0) ist als WINDOWS.md #6 offen, kein Browser-Tool in dieser Session verfuegbar."
- id: D2
description: "Ein insgesamt fehlgeschlagener Sync-Request (Netzwerkfehler oder !res.ok) zeigt eine sichtbare text-sm text-destructive-Fehlerzeile statt eines Drei-Null-Berichts als stillen Erfolg"
requirement: "PERM-02"
verification:
- kind: other
ref: "awk '/const handleSync/,/^ };/' page.tsx | grep -c 'deactivated: 0' == 0; grep -c 'setSyncRequestError' im selben Bereich >= 3"
status: pass
- kind: unit
ref: "cd apps/web && npx tsc --noEmit (fehlerfrei)"
status: pass
human_judgment: false
- id: D3
description: "Vier neue i18n-Schluessel unter admin.ldap.sync (resultGroupMemberships, resultGroups, defaultMarkerMoved, requestError) in de.json UND en.json, Schluesselparitaet erhalten"
requirement: "PERM-02"
verification:
- kind: other
ref: "node-Schluesselcheck: for k of [...] de.admin.ldap.sync[k] && en.admin.ldap.sync[k] — ohne Wurf durchgelaufen"
status: pass
human_judgment: false
- id: D4
description: "Spaltenkoepfe der Freigabe-Matrix zeigen internalName ?? name als Text UND als title-Tooltip (D-04, dritte und letzte Anzeigestelle); keine Truthiness-Variante"
requirement: "PERM-02"
verification:
- kind: other
ref: "awk '/filteredGroups.map/,/<\\/th>/' grants/page.tsx | grep -c 'internalName ?? g.name' == 2; grep -c 'internalName ||' grants/page.tsx == 0"
status: pass
- kind: unit
ref: "cd apps/web && npx vitest run (192/192 gruen)"
status: pass
human_judgment: false
- id: D5
description: "Spaltensuche findet eine Gruppe sowohl ueber ihren internen als auch ueber ihren AD-Namen (Nullish-Fallback im Filter, kein leerer Spaltenkopf bei fehlendem internalName)"
requirement: "PERM-02"
verification:
- kind: other
ref: "awk '/const filteredGroups/,/\\);/' grants/page.tsx | grep -c 'internalName' >= 1"
status: pass
human_judgment: true
rationale: "Kein automatisierter Test deckt den Zwei-Werte-Suchfilter der Freigabe-Matrix ab — manueller Browser-Durchklick (Spaltensuche unter beiden Namen) ist Teil des offenen WINDOWS.md #6."
duration: 6min
completed: 2026-08-06
status: complete
---
# Phase 16 Plan 5: Sync-Bericht vollstaendig verdrahtet, sichtbarer Fehlerzustand, Freigabe-Matrix mit Anzeigename Summary
**Der Sync-Bericht auf `/admin/ldap` zeigt jetzt Benutzer-, Gruppenmitgliedschafts- und AD-Gruppen-Zahlen in einem einzigen Container (schliesst die seit D-21 bestehende Frontend-Luecke und die neue Sichtbarkeitsanforderung aus D-05/D-06), meldet eine verschobene Standardgruppen-Markierung in Amber statt in der Destruktiv-Farbe, und ein insgesamt fehlgeschlagener Sync-Request erscheint als sichtbarer Fehler statt eines Drei-Null-Erfolgsberichts. Die Freigabe-Matrix unter `/admin/modules/grants` zeigt in ihren Spaltenkoepfen den internen Namen mit AD-Namen-Fallback und Tooltip — die dritte und letzte D-04-Anzeigestelle. PERM-02 ist damit vollstaendig geliefert und in REQUIREMENTS.md geschlossen.**
## Performance
- **Duration:** 6 min (Commit-Spanne 16:36:xx bis 16:37:xx Uhr; Lesen von PLAN.md, 16-03-/16-04-SUMMARY.md, UI-SPEC.md, PATTERNS.md, STATE.md und der Zieldateien davor nicht mitgerechnet)
- **Started:** 2026-08-06 (erster Task-Commit f66546d)
- **Completed:** 2026-08-06 (zweiter Task-Commit fac152a)
- **Tasks:** 2
- **Files modified:** 4
## Accomplishments
- `SyncResult`-Interface (Frontend) additiv um sechs Zahlenfelder erweitert — die exakt gleichen Feldnamen wie auf `LdapSyncResult` (Backend, Plan 16-03): `groupMembershipsAdded`/`groupMembershipsRemoved` (D-21-Backend-Luecke, seit Phase 15 bestehend, nie verdrahtet) sowie `groupsAdopted`/`groupsRenamed`/`groupsDeleted`/`defaultMarkerMoved` (Plan 16-03)
- Neuer `syncRequestError`-State: `handleSync` setzt ihn zu Beginn jedes Laufs auf `null`, bei `!res.ok` UND im `catch`-Zweig auf `t('sync.requestError')` — der bisherige Drei-Null-Fallback (`{ created: 0, updated: 0, deactivated: 0, errors: ['Network error'] }`) ist vollstaendig entfernt, ein nie gelaufener Sync kann nicht mehr als erfolgreicher No-Op erscheinen
- Sync-Bericht-Container um drei neue Zeilen erweitert: Gruppenmitgliedschaften (`text-muted-foreground`, immer sichtbar), AD-Gruppen (`text-muted-foreground`, immer sichtbar auch bei allen Werten = 0), und bedingt (nur `defaultMarkerMoved > 0`) eine Amber-Zeile (`text-amber-700 dark:text-amber-400`) — bewusst nicht in der Destruktiv-Farbe, da eine verschobene Standardmarkierung ein bemerkenswerter, aber kein fehlerhafter Vorgang ist
- Vier neue i18n-Schluessel unter `admin.ldap.sync` in `de.json` und `en.json`: `resultGroupMemberships`, `resultGroups` (mit der in `<decisions_recorded>` dokumentierten `groupsAdopted`-Abweichung vom urspruenglichen Copywriting-Contract-Textentwurf), `defaultMarkerMoved`, `requestError`
- `Group`-Interface in `admin/modules/grants/page.tsx` um `internalName?: string | null` ergaenzt — das Feld kam bereits ohne Backend-Aenderung mit `GET /module-grants/matrix` mit (keine `select`-Klausel in `getMatrix()`, verifiziert)
- Spaltenkopf-Text und `title`-Tooltip nutzen jetzt `internalName ?? g.name` (Nullish, keine Truthiness-Variante) — dieselbe Zelle, derselbe Truncate-mit-Tooltip-Mechanismus, nur der Textwert aendert sich; das `matrixCheckboxLabel`-`aria-label` folgt automatisch
- Suchfilter der Matrix matcht jetzt beide Namen (`internalName ?? g.name` UND `g.name`) — die Suche nach dem internen wie nach dem urspruenglichen AD-Namen findet dieselbe Gruppe
- Vollstaendige Web-Testsuite gruen: 32 Testdateien, 192 Tests (keine Regression, `tsc --noEmit` fehlerfrei)
- PERM-02 in `REQUIREMENTS.md` auf `[x]` gesetzt und in der Traceability-Tabelle auf `Complete` — alle fuenf Erfolgskriterien der Phase sind durch die kombinierte Arbeit von 16-01 bis 16-05 geliefert
## Task Commits
Each task was committed atomically:
1. **Task 1: Sync-Bericht vollstaendig verdrahten und Fehlschlag sichtbar machen (D-06, RESEARCH.md Pitfall 3)** - `f66546d` (feat)
2. **Task 2: Anzeigename mit Fallback in den Spaltenkoepfen der Freigabe-Matrix (D-04)** - `fac152a` (feat)
**Plan metadata:** wird mit diesem Summary committet
## Files Created/Modified
- `apps/web/src/app/(portal)/admin/ldap/page.tsx` — `SyncResult`-Interface um sechs Felder erweitert; `syncRequestError`-State; `handleSync` ersetzt den Drei-Null-Fallback durch einen sichtbaren Fehlerzustand; Sync-Bericht-Container um drei neue `<p>`-Zeilen erweitert (zwei immer sichtbar, eine bedingt in Amber)
- `apps/web/src/app/(portal)/admin/modules/grants/page.tsx` — `Group.internalName?: string | null` im Interface; Spaltenkopf-Text/Tooltip auf `internalName ?? g.name`; `filteredGroups`-Suchfilter matcht beide Namen
- `apps/web/src/messages/de.json` / `en.json` — vier neue `admin.ldap.sync.*`-Schluessel (`resultGroupMemberships`, `resultGroups`, `defaultMarkerMoved`, `requestError`)
## Decisions Made
- PERM-02 wurde in `REQUIREMENTS.md` auf `[x]` gesetzt, weil alle fuenf im ROADMAP.md formulierten Erfolgskriterien der Phase (selektiver Import mit AD-Bindung, keine OU-weite Automatik, Rename-Nachzug, Loesch-Nachzug samt Mitgliedschaften/Freigaben, unberuehrte lokale Gruppen) bereits durch die Plaene 16-01/16-02/16-03 code-vollstaendig geliefert sind — dieser Plan liefert ausschliesslich die zuletzt fehlende Sichtbarkeitsschicht (Sync-Bericht, D-05/D-06) und die dritte D-04-Anzeigestelle, beides ohne Einfluss auf die fachliche Korrektheit der fuenf Kriterien selbst.
- Die A1/A2-Live-Pruefung gegen ein echtes Active Directory (WINDOWS.md #4, aus Plan 16-03) bleibt bewusst offen und wird NICHT als "durch PERM-02-Abschluss erledigt" behandelt — sie ist eine Korrektheitsannahme unter SC-3/SC-4 (Rename-/Loesch-Erkennung), kein eigenes Erfolgskriterium. Ein negatives Ergebnis waere weiterhin ein Stopp-Grund fuer die D-05-Loeschsemantik.
## Deviations from Plan
None — plan wurde exakt wie geschrieben ausgefuehrt. Beide Handler-/Zellenaenderungen folgten den in `16-PATTERNS.md` vorgezeichneten Analogien ohne Abweichung.
## Issues Encountered
None.
## User Setup Required
None — keine externe Service-Konfiguration erforderlich. Der laufende Docker-Stack (lokal) wurde von diesem Plan nicht angefasst; die Aenderungen liegen im Web-Quellcode und werden erst mit einem `--build`/`--force-recreate` durch den Nutzer wirksam. Kein Deploy auf den Testserver durch diesen Lauf (Projektregel).
## Known Stubs
Keine. Beide geaenderten Dateien rendern ausschliesslich echte, vom Backend gelieferte Werte — kein hartkodierter Platzhalter.
## Threat Flags
Keine neue Angriffsflaeche — beide Aenderungen zeigen bereits vom Backend gelieferte, fuer ADMIN/SUPER_ADMIN desselben Mandanten ohnehin sichtbare Werte als React-Textknoten (siehe Plan-`<threat_model>`, T-16-12/T-16-14 bereits mitigiert/akzeptiert).
## Next Phase Readiness
- Phase 16 (AD-Gruppen-Synchronisation) ist mit diesem Plan vollstaendig ausgefuehrt: 5/5 Plaene, PERM-02 geschlossen
- **Offener Punkt bleibt phasenweit bestehen (WINDOWS.md #4):** die A1/A2-Live-Pruefung gegen ein echtes Active Directory (objectGUID-Rename-Stabilitaet, byteweise Hex-Filter-Syntax) ist NICHT durchgefuehrt — kein erreichbares AD in dieser Sandbox. Vor produktivem Einsatz der D-05-Loeschsemantik gegen ViCoTest (`balios.ctl.local`) nachzuholen, siehe `16-03-SUMMARY.md`.
- **Zusaetzlich offen (WINDOWS.md #5, #6):** manuelle Browser-Durchklicks aus den Plan-Verification-Bloecken von 16-04 und 16-05 sind nicht ausgefuehrt (kein Browser-Tool in dieser Session) — vor `/gsd-ship` nachzuholen.
- Kein Folgeplan innerhalb dieser Phase (`affects: []`) — das Milestone kann mit Phase 16 als abgeschlossen betrachtet werden, vorbehaltlich der beiden oben genannten offenen Verifikationen.
---
*Phase: 16-ad-gruppen-synchronisation*
*Completed: 2026-08-06*