| 16-ad-gruppen-synchronisation |
02 |
auth |
| nestjs |
| prisma |
| groups |
| module-grants |
| vitest |
|
| phase |
provides |
| 16-ad-gruppen-synchronisation (Plan 16-01) |
Group.internalName + Group.ldapObjectGuid Spalten (Migration angewendet), LdapService.importGroupsByDn() |
|
|
| GroupsService.reassignDefaultBeforeDelete(tenantId, groupId): deterministischer, nicht-werfender Standardgruppen-Handoff-Baustein (D-06) fuer Plan 16-03 |
| GroupsService.update(): serverseitige Namenssperre fuer importierte Gruppen (BadRequestException bei gesetztem ldapObjectGuid), unabhaengiges internalName-Feld mit Leerstring-Normalisierung auf null (D-03/D-04) |
| GroupsService.listForTenant(): liefert internalName zusaetzlich zu name |
| UpdateGroupDto ohne ldapDn (D-07 — keine nachtraegliche AD-Bindung ueber diesen Weg mehr moeglich) |
| ModuleGrantsService.getUserAccess(): Anzeigename mit Fallback (internalName ?? name) an beiden Projektionsstellen, ohne Frontend-Diff (UI-SPEC Surface Contract 6) |
|
| 16-03-rekonziliation |
| 16-04-dialog-umbau |
| 16-05-anzeige-fallback-frontend |
|
| tokens |
tasks |
commits |
| 7155 |
3 |
3 |
|
| added |
patterns |
|
|
| Batch-taugliche Variante eines Ownership-Checks: reassignDefaultBeforeDelete() nutzt bewusst nicht findOwned() (dessen NotFoundException ist HTTP-gebaut), sondern ein eigenes findFirst-Muster, das bei fehlendem/fremdem Datensatz still false liefert statt zu werfen — fuer Batch-Sync-Laeufe (Plan 16-03) |
| Serverseitige Feldsperre als Backend-Invariante statt UI-Disable: die Namenssperre auf importierten Gruppen sitzt in GroupsService.update(), nicht nur im Formular |
|
|
| created |
modified |
|
|
| apps/api/src/groups/groups.service.ts |
| apps/api/src/groups/groups.service.spec.ts |
| apps/api/src/groups/dto/update-group.dto.ts |
| apps/api/src/groups/module-grants.service.ts |
| apps/api/src/groups/module-grants.service.spec.ts |
|
|
| Alle drei Tasks in einer Datei (groups.service.ts) editiert, aber fuer atomare Task-Commits per Write/Edit-Sequenz in Task-Reihenfolge auseinandergezogen (kein git add -p auf einer Live-Bearbeitung) — Task 1 zuerst vollstaendig geschrieben, getestet und committet, danach erst Task-2-Aenderungen an derselben Datei vorgenommen |
| Bestehender Test 'update() mit ldapDn bindet an eine AD-Gruppe' ersatzlos entfernt statt angepasst — die Funktionalitaet ist nach D-07 absichtlich abgeschafft, kein Aequivalent noetig |
| PERM-02 bleibt in REQUIREMENTS.md unangetastet auf [ ] (Pending) — der Plan deckt nur einen Teil der Anforderung ab, das Requirement schliesst laut Plan-Vorgabe erst mit Plan 16-05 |
|
| Namenssperre vor Leerstring-Pruefung: die Reihenfolge in update() (erst ldapObjectGuid-Check, dann trim/empty-Check) verhindert, dass eine gesperrte Gruppe mit der falschen Fehlermeldung antwortet |
|
|
| id |
description |
requirement |
verification |
human_judgment |
| D1 |
reassignDefaultBeforeDelete(tenantId, groupId) verschiebt die Standardmarkierung deterministisch (DEFAULT_GROUP_NAME zuerst, sonst aelteste andere Gruppe per createdAt asc), loescht nichts, wirft in keinem der sechs Faelle (D-06) |
PERM-02 |
| kind |
ref |
status |
| unit |
apps/api/src/groups/groups.service.spec.ts#GroupsService.reassignDefaultBeforeDelete (D-06) (6 Faelle) |
pass |
|
|
false |
|
| id |
description |
requirement |
verification |
human_judgment |
| D2 |
Ein PATCH mit name auf eine Gruppe mit gesetztem ldapObjectGuid wird serverseitig mit BadRequestException/HTTP 400 abgelehnt — echte Backend-Invariante, nicht nur UI-Konvention (D-03) |
PERM-02 |
| kind |
ref |
status |
| unit |
apps/api/src/groups/groups.service.spec.ts#GroupsService.update — Namenssperre und interner Name (D-03/D-04) (9 Faelle) |
pass |
|
|
false |
|
| id |
description |
requirement |
verification |
human_judgment |
| D3 |
internalName ist fuer jede Gruppe setz-/loeschbar; leere/nur-Leerzeichen-Werte normalisieren auf null statt eines leeren Anzeigenamens; listForTenant() liefert internalName zusaetzlich zu name (D-04) |
PERM-02 |
| kind |
ref |
status |
| unit |
apps/api/src/groups/groups.service.spec.ts#GroupsService.update — Namenssperre und interner Name (D-03/D-04) |
pass |
|
|
false |
|
| id |
description |
requirement |
verification |
human_judgment |
| D4 |
UpdateGroupDto verliert ldapDn (D-07) und erhaelt internalName?: string | null — kein Codepfad kann eine lokale Gruppe mehr nachtraeglich an AD binden |
PERM-02 |
| kind |
ref |
status |
| unit |
cd apps/api && npx tsc --noEmit (typkorrekt, Controller kompiliert weiterhin) + acceptance-criteria grep auf update-group.dto.ts (0 ldapDn, internalName vorhanden) |
pass |
|
|
false |
|
| id |
description |
requirement |
verification |
human_judgment |
| D5 |
ModuleGrantsService.getUserAccess() liefert an beiden Projektionsstellen (viaGroups, groups[].name) internalName ?? name; kein Frontend-Diff (UI-SPEC Surface Contract 6) |
PERM-02 |
| kind |
ref |
status |
| unit |
apps/api/src/groups/module-grants.service.spec.ts#ModuleGrantsService.getUserAccess — Anzeigename mit Fallback (D-04) (3 Faelle) |
pass |
|
| kind |
ref |
status |
| other |
git diff --name-only HEAD -- apps/web | wc -l == 0 |
pass |
|
|
false |
|
|
5min (Commit-Spanne 2ef9b86 bis f71e614; Kontext-Lesen davor nicht mitgerechnet) |
2026-08-06 |
complete |