From 97465a6f2585a5da8fc0c3d5352f3a106ace6c59 Mon Sep 17 00:00:00 2001 From: Schalli Date: Wed, 29 Jul 2026 09:40:29 +0200 Subject: [PATCH] docs(260729-d3k): complete LDAP multi-base-DN quick task --- .planning/STATE.md | 10 +- .../260729-d3k-PLAN.md | 155 +++++++++++++++++ .../260729-d3k-SUMMARY.md | 159 ++++++++++++++++++ 3 files changed, 320 insertions(+), 4 deletions(-) create mode 100644 .planning/quick/260729-d3k-ldap-multi-base-dn-und-base-dn-als-scope/260729-d3k-PLAN.md create mode 100644 .planning/quick/260729-d3k-ldap-multi-base-dn-und-base-dn-als-scope/260729-d3k-SUMMARY.md diff --git a/.planning/STATE.md b/.planning/STATE.md index b922c3f..e824ba7 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -5,8 +5,8 @@ milestone_name: Ausschreibungs-Radar current_phase: 14 current_phase_name: rss-email-alert-ingestion-module-rollout status: executing -stopped_at: Completed 260728-lih quick task (LDAP sync selective + auto-sync default off) -last_updated: "2026-07-28T13:43:32.444Z" +stopped_at: Completed 260729-d3k quick task (LDAP multi-base-DN + base-DN-as-scope) +last_updated: "2026-07-29T07:39:42.771Z" last_activity: 2026-07-23 last_activity_desc: Completed 14-02-PLAN.md (RSS ingestion slice) progress: @@ -224,6 +224,7 @@ Recent decisions affecting current work: - [Phase ?]: CoverageBanner's denylist block is independent of the onlyDoe coverage-note condition — component renders when either block has content, not gated behind the DOE-only check - [Phase ?]: 14-05: tenderRadar i18n namespace added; Bundesland/CPV filter option values stay canonical German for backend compatibility, only labels translated; portal display slugs left untranslated as proper nouns - [Phase ?]: [260728-lih]: DELIBERATE back-compat break — empty groupFilterDns now means 'sync nothing' (was 'import everyone under baseDn'); early-return guard in syncUsersForTenant runs before search/deactivation so an empty selection never mass-deactivates existing LDAP users +- [Phase ?]: [260729-d3k]: syncUsersForTenant no-op guard re-keyed from empty groupFilterDns to empty parsed base-DN list — Base-DN(s) are now the sync scope, groupFilterDns is an optional extra restriction (ou= = extra bases, group DN = memberOf constraint) ### Pending Todos @@ -253,6 +254,7 @@ None yet. | 260714-lex | LDAP: Per-User Exclude/Denylist-Filter (Service-Accounts vom Sync ausschliessen) — live verifiziert: deaktiviert 4 Accounts, 2 echte User aktiv | 2026-07-14 | 9d1323f | (direct) | | 13 | Normalizer-Gap Phase 13 schliessen: NetServer/Cosinex-Bag-Dispatch (TenderNormalizerService) | 2026-07-23 | 9881005 | — | | 260728-lih | LDAP: Sync strikt selektiv (leere Auswahl = No-Op statt Voll-Import) + Auto-Sync-Default aus (syncIntervalMin 60→0) | 2026-07-28 | c54e424,57bc7f9,63a07ab | [260728-lih-ldap-sync-selektiv-und-auto-sync-default](.planning/quick/260728-lih-ldap-sync-selektiv-und-auto-sync-default/) | +| 260729-d3k | LDAP: Multi-Base-DN und Base-DN als Sync-Scope (statt leerer Gruppenfilter = No-Op) | 2026-07-29 | 5cbd530,96be7e1 | [260729-d3k-ldap-multi-base-dn-und-base-dn-als-scope](.planning/quick/260729-d3k-ldap-multi-base-dn-und-base-dn-als-scope/) | ## Deferred Items @@ -264,7 +266,7 @@ Items acknowledged and carried forward from previous milestone close: ## Session Continuity -Last session: 2026-07-28T13:43:32.416Z -Stopped at: Completed 260728-lih quick task (LDAP sync selective + auto-sync default off) +Last session: 2026-07-29T07:39:14.866Z +Stopped at: Completed 260729-d3k quick task (LDAP multi-base-DN + base-DN-as-scope) Resume file: None Last activity: 2026-07-14 - Built LDAP per-user exclude/denylist filter (9d1323f), migration applied on live DB, verified via Playwright: sync deactivated 4 excluded service accounts (administrator/krbtgt/guest/dns-ldap), 2 real LDAP users stay active, 0 wrongly created diff --git a/.planning/quick/260729-d3k-ldap-multi-base-dn-und-base-dn-als-scope/260729-d3k-PLAN.md b/.planning/quick/260729-d3k-ldap-multi-base-dn-und-base-dn-als-scope/260729-d3k-PLAN.md new file mode 100644 index 0000000..2485338 --- /dev/null +++ b/.planning/quick/260729-d3k-ldap-multi-base-dn-und-base-dn-als-scope/260729-d3k-PLAN.md @@ -0,0 +1,155 @@ +--- +phase: quick-260729-d3k +plan: 01 +type: execute +wave: 1 +depends_on: [] +files_modified: + - apps/api/src/ldap/ldap.service.ts + - apps/api/src/ldap/ldap.service.spec.ts + - apps/web/src/app/(portal)/admin/ldap/page.tsx + - apps/web/src/messages/de.json + - apps/web/src/messages/en.json +autonomous: true +requirements: + - 260729-d3k +must_haves: + truths: + - "The Base-DN admin field accepts multiple DNs (one per line) and persists them as a single `\\n`-separated String — no Prisma schema change, no migration." + - "LDAP sync searches EVERY configured base DN and merges/dedupes results by entry `dn` across all three search paths (collectSearchEntries, listGroups, searchUsers)." + - "An empty groupFilterDns no longer blocks sync: with >=1 base DN, all users under the base DN(s) are synced with `sanitizedFilter` (no memberOf restriction)." + - "groupFilterDns is now an OPTIONAL extra restriction: `ou=` entries are additional search bases (plain filter); non-`ou=` (group) DNs become a memberOf constraint applied to the base-DN search." + - "CRITICAL SAFETY: the syncUsersForTenant early-return No-Op keys ONLY on the parsed base-DN list being EMPTY. An empty base-DN list is the sole condition that skips search + the deactivation loop; an empty groupFilterDns never triggers the No-Op and therefore never mass-deactivates users." + - "i18n (de + en) describes the Base-DN(s) as the sync scope and the group filter as an optional additional restriction; the old '...nichts synchronisiert' / '...nothing is synced' wording is gone." + artifacts: + - "apps/api/src/ldap/ldap.service.ts — parseBaseDns() helper + multi-base collectSearchEntries/listGroups/searchUsers + base-DN-list-keyed deactivation guard." + - "apps/api/src/ldap/ldap.service.spec.ts — empty-base-DN No-Op test (replaces the empty-groupFilterDns No-Op), multi-base merge/dedup test, adjusted exclude-list/groupFilter specs." + - "apps/web/src/app/(portal)/admin/ldap/page.tsx — multi-line