614de2815a
- LdapService.syncGroupMembershipsForTenant (neu, privat): pro AD-gebundener Group (ldapDn gesetzt) ein memberOf-Reverse-Query je Base-DN, nie ein Attribut-Lesen (Range-Retrieval-Pitfall). GroupMembership(source: LDAP) wird per createMany/skipDuplicates angelegt (lässt bestehende MANUAL-Zeilen unangetastet, D-19/D-20) und per deleteMany(source: 'LDAP', notIn: [...]) bereinigt. Jede Gruppe läuft in eigenem try/catch, ein Fehler landet als "Gruppe <name>: <message>" in result.errors, die Schleife läuft weiter. - Aufruf in syncUsersForTenant nach der Deaktivierungsschleife (Schritt 5) und vor lastSyncAt (Schritt 6) — hinter dem bestehenden Base-DN-No-Op-Wächter, kein separater Job, kein zweiter Button (D-21). - LdapSyncResult um groupMembershipsAdded/groupMembershipsRemoved erweitert. - ldap.service.spec.ts: neuer describe-Block mit 13 Tests (adjacency, empty, encoding, ordering, idempotency, concurrency/backstop) plus Anpassung der drei bestehenden Prisma-Fixtures und einer Ergebnis-Assertion an die erweiterte LdapSyncResult-Form. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>