feat(16-03): add syncBoundGroupsForTenant reconciliation method

- New private LdapService.syncBoundGroupsForTenant(): rename detection
  (SC-3), disappearance deletion with default-marker handoff before delete
  (SC-4/D-05/D-06), legacy ldapDn-only binding GUID backfill (D-07), and a
  32-hex-char guard before any objectGUID filter interpolation (T-16-01)
- LdapSyncResult grows additively: groupsAdopted, groupsRenamed,
  groupsDeleted, defaultMarkerMoved
- LdapService constructor takes GroupsService; LdapModule imports
  GroupsModule (no cycle)
- 14 new test cases covering the full behavior matrix plus idempotency
This commit is contained in:
2026-08-06 16:15:09 +02:00
parent da0361df5f
commit 522293417a
3 changed files with 751 additions and 9 deletions
+7 -1
View File
@@ -1,5 +1,6 @@
import { Module } from '@nestjs/common';
import { ScheduleModule } from '@nestjs/schedule';
import { GroupsModule } from '../groups/groups.module';
import { UserModule } from '../user/user.module';
import { LdapConfigService } from './ldap-config.service';
import { LdapSyncScheduler } from './ldap-sync.scheduler';
@@ -11,9 +12,14 @@ import { LdapService } from './ldap.service';
*
* Provides per-tenant LDAP configuration (D-18), manual sync (D-14),
* auto-sync scheduler (D-14), and configurable field mapping (D-16/D-17).
*
* GroupsModule is imported so LdapService can call
* GroupsService.reassignDefaultBeforeDelete()/ensureDefaultGroup() from
* syncBoundGroupsForTenant() (Plan 16-03, D-06) — no cycle: GroupsModule
* imports neither LdapModule nor UserModule.
*/
@Module({
imports: [ScheduleModule.forRoot(), UserModule],
imports: [ScheduleModule.forRoot(), UserModule, GroupsModule],
controllers: [LdapController],
providers: [LdapService, LdapConfigService, LdapSyncScheduler],
exports: [LdapService, LdapConfigService],