From 9553e5304d459e7466441e440319514287877fce Mon Sep 17 00:00:00 2001 From: Schalli Date: Tue, 14 Jul 2026 13:48:26 +0200 Subject: [PATCH] chore(planning): mark LDAP exclude filter done, catch up STATE.md Record the per-user exclude/denylist filter (9d1323f) and its live verification as complete, close out the two other carried-over items (full-sync verify, quick-tasks bookkeeping), and backfill the STATE.md Quick Tasks table with the direct-fix commits that never got /gsd-quick entries. Co-Authored-By: Claude Opus 4.8 (1M context) --- .planning/.continue-here.md | 19 ++++++++++++------- .planning/HANDOFF.json | 27 ++++++++++++--------------- .planning/STATE.md | 21 ++++++++++++++------- 3 files changed, 38 insertions(+), 29 deletions(-) diff --git a/.planning/.continue-here.md b/.planning/.continue-here.md index 368fac8..3b89586 100644 --- a/.planning/.continue-here.md +++ b/.planning/.continue-here.md @@ -3,8 +3,8 @@ context: default phase: null task: null total_tasks: null -status: in_progress -last_updated: 2026-07-09T14:36:45.919Z +status: idle +last_updated: 2026-07-14T08:16:00.000Z --- # BLOCKING CONSTRAINTS — Read Before Anything Else @@ -30,7 +30,9 @@ No active GSD phase — the v1.0 milestone was already at 100% before this sessi - Test/staging deploy: https://alpha.tessera.ctl.de, server 192.168.13.12 ("ViCoTest"), SSH root access, app deployed via `docker compose` pulling `git.vicolab.de/schalli/tessera-ctl/{web,api}:latest` from Gitea CI. - Zentyal/Samba AD test directory: 192.168.13.13 (LDAP), domain `intern.vicolab.de`, base DN `dc=intern,dc=vicolab,dc=de`, bind as `Administrator@intern.vicolab.de`. -Last confirmed-working state (verified live via Playwright against alpha.tessera.ctl.de): LDAP connection test succeeds, group/OU discovery returns 36 real groups/OUs from Zentyal AD, and the new search box correctly filters that list (typed "Personal" → only "Personalabteilung" remained). +Last confirmed-working state (verified live via Playwright against alpha.tessera.ctl.de): full LDAP sync now works end-to-end. The per-user exclude/denylist filter (commit 9d1323f) was built, migration applied on the live DB, and verified live: with administrator/krbtgt/guest/dns-ldap/ldap$ on the denylist, "Jetzt synchronisieren" returned Erstellt:0/aktualisiert:2/deaktiviert:4, and a psql check confirmed the 4 excluded service accounts are isActive=false while 2 real LDAP users stay active and 0 were wrongly created. Connection test + group/OU discovery (36 entries) + search box all still working. + +All three items that were open at the last pause are now DONE: (1) per-user exclude filter built+verified, (2) live full-sync verified, (3) STATE.md quick-tasks table caught up. No open LDAP work remains. @@ -50,9 +52,12 @@ All of the above were verified live either on the local dev stack or directly on -- **Per-user LDAP exclude/denylist filter** — user explicitly asked for a way to exclude *specific individual users* (not just group/OU-based inclusion) from LDAP sync, giving `administrator`, `krbtgt`, `guest`, `dns-ldap`, `ldap$` as examples of service accounts they don't want imported. The existing `groupFilterDns` include-filter (+ new search box) does NOT cover this — it only restricts which OUs/groups are searched, not individual usernames within an included scope. This request got sidetracked (user pivoted to praising the existing feature + asking for the search box) and was never revisited. **This is the most likely next thing the user wants.** -- **Live full-sync verification** — only "Verbindung testen" and "Gruppen/OUs suchen" (discovery) were exercised live against the real Zentyal AD. An actual "Jetzt synchronisieren" run with a `groupFilterDns` selection saved and applied has not been observed/verified end-to-end yet. -- **STATE.md bookkeeping** — the "Quick Tasks Completed" table only lists through `260708-cuc`. Commits `010aceb`, `39aa4bf`, `8e8305c`, `baff7ce`, `246dc89`, `aaa2922` were done as direct fixes (fully diagnosed, small, urgent-to-unblock-live-testing) without spinning up the formal `/gsd-quick` planner+executor pipeline each time, so they have no `.planning/quick/` entries or STATE.md rows. Purely cosmetic/audit-trail catch-up, not urgent. +None open. The three items carried from the previous pause are all resolved: +- ✅ **Per-user LDAP exclude/denylist filter** — built (commit 9d1323f) and live-verified. Excludes individual usernames (service accounts) from sync, independent of the group/OU include-filter. Skips matches case-insensitively BEFORE recording the DN, so an already-imported user added to the denylist gets deactivated on the next sync. +- ✅ **Live full-sync verification** — ran a real "Jetzt synchronisieren" against Zentyal with the denylist saved; Erstellt:0/aktualisiert:2/deaktiviert:4, DB-confirmed. +- ✅ **STATE.md bookkeeping** — Quick Tasks table caught up with the direct-fix commits (8e8305c, 39aa4bf, 010aceb, baff7ce, 246dc89, aaa2922, 9d1323f). + +No GSD phase active; v1.0 milestone was already 100%. Next work is likely new module development — ask the user. @@ -87,5 +92,5 @@ The user is clearly hands-on and technical, corrects scope/boundary violations i -Start with: ask the user which of the three remaining_work items to pick up next (per-user LDAP exclude/denylist, live full-sync verification run, or STATE.md catch-up) — do not assume; they were mid-conversation about LDAP filtering when this pause was triggered by a context-budget warning, not by reaching a natural stopping point. +No open LDAP work. Ask the user what to pick up next — most likely new module development now that v1.0 plus the LDAP hardening pass are complete. If they resume LDAP, the natural next candidates would be surfacing deactivated LDAP users in the admin UI (currently only visible via the isActive flag) or a sync-preview before applying, but neither has been requested. diff --git a/.planning/HANDOFF.json b/.planning/HANDOFF.json index 01276df..ca9435e 100644 --- a/.planning/HANDOFF.json +++ b/.planning/HANDOFF.json @@ -1,13 +1,13 @@ { "version": "1.0", - "timestamp": "2026-07-09T14:36:45.919Z", + "timestamp": "2026-07-14T08:16:00.000Z", "phase": null, "phase_name": null, "phase_dir": null, "plan": null, "task": null, "total_tasks": null, - "status": "paused", + "status": "idle", "completed_tasks": [ {"id": 1, "name": "LDAP: fix FavoriteLink 500 (missing migration, prod)", "status": "done", "commit": "afef9b2"}, {"id": 2, "name": "LDAP: revert CTL-specific AD prefill per user feedback", "status": "done", "commit": "8e8305c"}, @@ -16,25 +16,22 @@ {"id": 5, "name": "Auth: case-insensitive usernames (login, seed, LDAP sync, migration)", "status": "done", "commit": "baff7ce"}, {"id": 6, "name": "LDAP: fix ldapts empty-array-attribute bug causing email collision on sync", "status": "done", "commit": "246dc89"}, {"id": 7, "name": "LDAP: search box for discovered groups/OUs list", "status": "done", "commit": "aaa2922"}, - {"id": 8, "name": "Favorites: icon proxy for CORP-restricted sites (claude.ai) + realistic UA fix", "status": "done", "commit": "f06a2ff (and related)"} - ], - "remaining_tasks": [ - {"id": 9, "name": "LDAP: per-user exclude/denylist filter (user asked, not yet built -- only group/OU include-filter + search box were done; individual-username exclusion is a separate, still-open ask)", "status": "not_started"}, - {"id": 10, "name": "Live-verify a full LDAP sync run (created/updated counts) against real Zentyal AD -- only connection test + group discovery were verified live, not an actual 'Jetzt synchronisieren' run with the new groupFilterDns applied", "status": "not_started"}, - {"id": 11, "name": "STATE.md quick-tasks table is behind -- several of today's commits (010aceb, 39aa4bf, 8e8305c, baff7ce, 246dc89, aaa2922) were direct fixes/features done without formal /gsd-quick entries; STATE.md only lists up to 260708-cuc", "status": "not_started"} + {"id": 8, "name": "Favorites: icon proxy for CORP-restricted sites (claude.ai) + realistic UA fix", "status": "done", "commit": "f06a2ff (and related)"}, + {"id": 9, "name": "LDAP: per-user exclude/denylist filter -- exclude individual usernames (service accounts like administrator/krbtgt/guest/dns-ldap/ldap$) from sync, independent of the group/OU include-filter. Backend (schema+migration, DTO, service skip-before-syncedDns so excluded users get deactivated, controller+scheduler threading), frontend admin section (add/remove/save), de/en i18n, 3 unit tests. Live-verified on alpha.tessera.ctl.de.", "status": "done", "commit": "9d1323f"}, + {"id": 10, "name": "Live full-sync verification against real Zentyal AD -- ran 'Jetzt synchronisieren' with exclude list saved; result Erstellt:0/aktualisiert:2/deaktiviert:4; DB confirmed the 4 excluded service accounts isActive=false, 2 real LDAP users active, 0 wrongly created", "status": "done", "commit": "9d1323f (verification)"}, + {"id": 11, "name": "STATE.md quick-tasks table catch-up -- added rows for the direct-fix commits (8e8305c, 39aa4bf, 010aceb, baff7ce, 246dc89, aaa2922, 9d1323f) that had no /gsd-quick dirs", "status": "done", "commit": "(STATE.md edit)"} ], + "remaining_tasks": [], "blockers": [], "async_jobs": [], - "human_actions_pending": [ - {"action": "Continue live-testing LDAP sync against Zentyal/Samba AD test server (192.168.13.13 LDAP, test box 192.168.13.12) -- confirm a real sync run imports the right users with the groupFilterDns restriction applied", "context": "Only 'Verbindung testen' and 'Gruppen/OUs suchen' were verified live; an actual sync execution with a group filter selected+saved was not yet run/observed", "blocking": false}, - {"action": "Decide whether the per-user exclude/denylist feature (service accounts like administrator/krbtgt/guest/dns-ldap/ldap$ showing up as importable users) is still wanted, and if so scope it (manual denylist vs. checkbox-deselect in a preview)", "context": "User asked for this explicitly, got sidetracked into praising the existing group filter + requesting the search box instead -- never circled back", "blocking": false} - ], + "human_actions_pending": [], "decisions": [ {"decision": "Reverted CTL-specific AD server/domain hardcoded as form defaults", "rationale": "User: 'das war nie das Ziel' -- Tessera is a generic multi-tenant product, must not bake one customer's infra into shared admin UI", "phase": null}, {"decision": "LDAP bindDn/bindPassword made fully optional (anonymous bind support)", "rationale": "User explicitly requested removing the requirement to enter a bind user/password", "phase": null}, - {"decision": "Usernames normalized to lowercase everywhere (storage + lookup), not just at login", "rationale": "User: login was case-sensitive and shouldn't be; centralized in UserService rather than per-callsite", "phase": null} + {"decision": "Usernames normalized to lowercase everywhere (storage + lookup), not just at login", "rationale": "User: login was case-sensitive and shouldn't be; centralized in UserService rather than per-callsite", "phase": null}, + {"decision": "Per-user exclude list skips matches BEFORE recording the DN in syncedDns", "rationale": "So a user added to the denylist after already being imported gets deactivated on the next sync (rather than lingering active); exclude match is case-insensitive to align with lowercase username handling", "phase": null} ], - "uncommitted_files": [], - "next_action": "Ask user whether to (a) build the per-user LDAP exclude/denylist feature they originally asked for, (b) do a live full-sync verification run against Zentyal, or (c) catch up STATE.md's quick-tasks table for today's commits -- context is at ~71%, so start whichever they pick as a single focused quick task, not all three.", + "uncommitted_files": ["(unstaged) .planning/STATE.md, .planning/HANDOFF.json, .planning/.continue-here.md -- planning bookkeeping, not yet committed"], + "next_action": "No open LDAP work. All three previously-remaining items (per-user exclude filter, live full-sync verify, STATE.md catch-up) are done. Next session: ask the user what to pick up next -- likely new module work now that v1.0 + LDAP hardening are complete. No GSD phase active.", "context_notes": "This whole session was reactive, ad-hoc fixing driven by live-testing on a real production-style deployment (alpha.tessera.ctl.de, test box 192.168.13.12) plus a freshly stood-up Zentyal/Samba AD test directory (192.168.13.13, domain intern.vicolab.de) that the user built specifically so LDAP could be tested against something real. No GSD phase is active -- the v1.0 milestone was already at 100% before this session; everything today was quick-task-style bugfixing/feature work, several done directly without spinning up the full /gsd-quick planner+executor pipeline (justified each time by being small, fully-diagnosed, and urgent to unblock live testing). CRITICAL boundary: user explicitly does NOT want me running docker compose pull/up/down/restart/rebuild on the test server myself -- only docker logs / psql for read-only debugging. They pull/rebuild themselves and tell me when done, then I test via Playwright in the browser." } diff --git a/.planning/STATE.md b/.planning/STATE.md index 0d88286..6aa6d18 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -6,9 +6,9 @@ current_phase: 9 current_phase_name: cert-manager-module status: complete stopped_at: UAT 8/8 passed — Phase 9 complete (2026-07-02) -last_updated: "2026-07-02T06:46:00.000Z" -last_activity: 2026-07-02 -last_activity_desc: Phase 9 UAT complete — all 9 phases done +last_updated: "2026-07-14T08:16:00.000Z" +last_activity: 2026-07-14 +last_activity_desc: LDAP per-user exclude/denylist filter built + live-verified on alpha.tessera.ctl.de (9d1323f) progress: total_phases: 9 completed_phases: 9 @@ -150,6 +150,13 @@ None yet. | 260707-csw | LDAP AD Anbindung: Zugangsdaten aus XWiki vorbefuellen und Import-Filter fuer Benutzer/Gruppen | 2026-07-07 | a5c500d | [260707-csw-ldap-ad-anbindung-zugangsdaten-aus-xwiki](.planning/quick/260707-csw-ldap-ad-anbindung-zugangsdaten-aus-xwiki/) | | 260707-lgh | Favoriten-Widget: Icon-Proxy fuer Cross-Origin-Resource-Policy-Seiten (claude.ai) | 2026-07-07 | f06a2ff | [260707-lgh-favoriten-widget-icon-proxy-fuer-cross-o](.planning/quick/260707-lgh-favoriten-widget-icon-proxy-fuer-cross-o/) | | 260708-cuc | Fix: FavoriteLink-Tabelle fehlt in Prod-DB, nie als Migration committed (500 auf GET /favorites) | 2026-07-08 | afef9b2 | [260708-cuc-fix-favoritelink-tabelle-fehlt-in-prod-d](.planning/quick/260708-cuc-fix-favoritelink-tabelle-fehlt-in-prod-d/) | +| 260708-rev | LDAP: CTL-spezifisches AD-Prefill entfernt (Multi-Tenant, "das war nie das Ziel") | 2026-07-08 | 8e8305c | (direct) | +| 260708-tst | LDAP: Verbindung testen vor dem Speichern einer Config moeglich | 2026-07-08 | 39aa4bf | (direct) | +| 260709-abd | LDAP: anonymous bind (bindDn/bindPassword optional, Schema nullable + Migration) | 2026-07-09 | 010aceb | (direct) | +| 260709-ciu | Auth: Benutzernamen ueberall case-insensitive (Login, Seed, LDAP-Sync + Daten-Migration) | 2026-07-09 | baff7ce | (direct) | +| 260709-lda | LDAP: ldapts empty-array-Attribut-Bug (E-Mail-Kollision auf Unique-Constraint) | 2026-07-09 | 246dc89 | (direct) | +| 260709-sbx | LDAP: Suchbox fuer die entdeckten Gruppen/OUs-Liste | 2026-07-09 | aaa2922 | (direct) | +| 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) | ## Deferred Items @@ -161,7 +168,7 @@ Items acknowledged and carried forward from previous milestone close: ## Session Continuity -Last session: 2026-07-08T07:22:00.000Z -Stopped at: context exhaustion at 77% (2026-07-02) -Resume file: .planning/phases/08-dashboard-widgets-vollimplementierung/08-CONTEXT.md -Last activity: 2026-07-08 - Completed quick task 260708-cuc: Fix FavoriteLink-Tabelle fehlt in Prod-DB; deployed and verified live on alpha.tessera.ctl.de +Last session: 2026-07-14T08:16:00.000Z +Stopped at: LDAP per-user exclude/denylist feature complete + live-verified +Resume file: .planning/.continue-here.md +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