17 KiB
phase, plan, subsystem, tags, requires, provides, affects, actuals, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, coverage, duration, completed, status
| phase | plan | subsystem | tags | requires | provides | affects | actuals | tech-stack | key-files | key-decisions | patterns-established | requirements-completed | coverage | duration | completed | status | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 16-ad-gruppen-synchronisation | 01 | auth |
|
|
|
|
|
|
|
|
|
|
|
34min | 2026-08-06 | complete |
Phase 16 Plan 1: AD-Gruppen-Import (Tracer + Schema) Summary
Selektiver AD-Gruppen-Import über alle Schichten (Prisma bis Next.js), rename-stabile Identität via objectGUID, Migration lokal angewendet und per SQL-Test festgenagelt
Performance
- Duration: 34 min (Tracer-Commit 15:09 Uhr bis Migrations-Commit 15:43 Uhr; Checkpoint-Wartezeiten nicht mitgerechnet)
- Started: 2026-08-06T13:09:35Z (Tracer-Commit)
- Completed: 2026-08-06T13:43:19Z (Migrations-Commit)
- Tasks: 3 (Checkpoint:decision, Tracer, Migration)
- Files modified: 10
Accomplishments
Group.internalName(sync-immuner Anzeigename) undGroup.ldapObjectGuid(rename-stabiler Identitätsschlüssel) als versionierte, one-way-Migration angelegt, lokal angewendet und per SQL-Textest festgenageltLdapService.listGroups()erweitert umalreadyImported-Kennzeichnung und stabile Sortierung;LdapService.importGroupsByDn()neu, mit Duplikat-Erkennung (skip), Namenskollisions-Meldung (reject-with-report) und Fehlerzeilen statt Batch-AbbruchobjectGUIDwird korrekt alsBuffergelesen (explicitBufferAttributes) und als 32-stelliger Hex-String gespeichert — der zuvor als offene Annahme geführte Punkt (RESEARCH.md A2) ist für den Schreibpfad bewiesenPOST /ldap/groups/import(RBAC ADMIN/SUPER_ADMIN) und neue Sektion "AD-Gruppen importieren" in/admin/ldapmit sichtbaren Discovery-/Import-Fehlerzuständen (bewusste Abweichung vom sonst stillen Fehler-Verschlucken der Seite)- Vollständige API-Testsuite grün: 40 Testdateien, 526 Tests
Task Commits
Each task was committed atomically:
- Task 1: Freigabe der one-way Schema-Erweiterung (D-04) —
checkpoint:decision, kein eigener Commit; Freigabeapprove-both - Task 2: Tracer — AD-Gruppe auswählen und importieren, durch alle Schichten -
3523e43(feat, tdd) - Task 3: Migration erzeugen, gegen die lokale Datenbank anwenden, per SQL-Test festnageln -
626e296(feat)
Plan metadata: wird nach diesem Summary committet
Files Created/Modified
apps/api/prisma/schema.prisma-Group.internalName,Group.ldapObjectGuid,@@unique([tenantId, ldapObjectGuid])apps/api/prisma/migrations/20260806133916_add_group_internal_name_and_object_guid/migration.sql- neue, versionierte Migration (zweiADD COLUMN, einCREATE UNIQUE INDEX, keine RLS-Anweisung)apps/api/src/ldap/ldap.service.ts-listGroups(config, tenantId)mitalreadyImported,importGroupsByDn(),escapeLdapFilterBuffer(),LdapGroupImportResultapps/api/src/ldap/ldap.controller.ts-GET groupsreichttenantIddurch, neue RoutePOST groups/importapps/api/src/ldap/dto/ldap-config.dto.ts-ImportGroupsDtoapps/api/src/ldap/ldap.service.spec.ts- neuer describe-Block "LdapService — AD group import (SC-1/SC-2, D-01/D-02)" (8 Fälle + Sortierung + alreadyImported)apps/api/src/groups/migration-sql.spec.ts- neuer describe-Block für die neue Migration (4 Fälle)apps/web/src/app/(portal)/admin/ldap/page.tsx- Sektion "AD-Gruppen importieren", sieben neue State-Variablen, zwei Handler mit sichtbarem Fehlerzustandapps/web/src/messages/de.json/en.json-admin.ldap.groupImport.*
Decisions Made
- Checkpoint 1 (Task 1):
approve-both— beide Spalten plus Unique-Index in einer Migration. Freigegeben 2026-08-06 vom Projektinhaber. - Post-Tracer-Checkpoint:
verified— Tracer-Scheibe per Code-Review akzeptiert, bevor Task 3 (Migration) begonnen wurde. - Drei zurückgestellte kosmetische Beobachtungen aus dem Review (bewusst nicht umgesetzt in diesem Plan):
listGroups()undexistingByGuidinimportGroupsByDn()nutzenthis.prismastatttenantPrisma— beide Lesepfade filtern aber explizit auftenantId, kein Cross-Tenant-Leck. Belassen wie ist.escapeLdapFilterBuffer()ist aktuell ungenutzt — Plan 16-03 ist der erste Aufrufer. Belassen im Code.- Legacy-Gruppen mit
ldapDn, aber ohneldapObjectGuid, meldenalreadyImported: false. Wird durch das GUID-Backfill in Plan 16-03 aufgelöst. Belassen wie ist.
Deviations from Plan
Auto-fixed Issues
1. [Rule 3 - Blocking] prisma migrate dev verweigert nicht-interaktive Shell — Migrationsablauf über migrate diff + Handdatei + migrate deploy ersetzt
- Found during: Task 3
- Issue: Der geplante Befehl
prisma migrate dev --name add_group_internal_name_and_object_guidbricht in dieser Shell sofort mit "Prisma Migrate has detected that the environment is non-interactive" ab — auch mitCI=true, gepipetemy-stdin und--create-only. Ein Versuch, überscripteine Pseudo-TTY zu erzwingen, hing unbegrenzt an einem echten interaktiven Prompt und musste per SIGKILL beendet werden. - Fix: Äquivalenter, vollständig nicht-interaktiver Weg:
prisma migrate diff --from-migrations ... --to-schema-datamodel ... --scripterzeugt exakt dieselbe SQL, die dann von Hand in ein neues Migrationsverzeichnis (20260806133916_add_group_internal_name_and_object_guid/migration.sql) geschrieben wurde — im Stil der bereits im Repo vorhandenen hand-editierten Migrationen.prisma migrate deploy(nicht-interaktiv per Design) hat sie anschließend angewendet. - Files modified: apps/api/prisma/migrations/20260806133916_add_group_internal_name_and_object_guid/migration.sql
- Verification:
prisma migrate statuszeigt "Database schema is up to date!";\d "Group"zeigt beide Spalten und den Unique-Index - Committed in:
626e296
2. [Rule 3 - Blocking] _prisma_migrations-Tabelle fehlte in der lokalen Datenbank — Baseline nachgezogen
- Found during: Task 3
- Issue: Nach dem SIGKILL des hängenden
script-Prozesses (siehe Punkt 1) meldeteprisma migrate status, dass ALLE 25 Migrationen unangewendet seien, und\dtzeigte, dass die Tabelle_prisma_migrationsin der Datenbank gar nicht existierte — obwohl alle 28 Anwendungstabellen inklusive der bereits angewendeten Group-RLS-Policy vorhanden undGroupmit 0 Zeilen leer war. Kein Datenverlust, aber die Migrationshistorie war nicht (mehr) nachverfolgbar. - Fix: Vor dem Anwenden der neuen Migration wurden die 24 bereits im Schema sichtbaren Altmigrationen einzeln per
prisma migrate resolve --applied <name>als bereits angewendet markiert (reine Metadaten-Operation, keine DDL). Erst danach liefertemigrate statuskorrekt genau eine ausstehende Migration (die neue), die permigrate deployangewendet wurde. - Files modified: keine Codedateien — nur Datenbank-Metadaten (
_prisma_migrations-Tabelle) auf dem lokalen Dev-Container - Verification:
SELECT migration_name, finished_at FROM "_prisma_migrations"zeigt alle 25 Migrationen mitfinished_atgesetzt; volle Testsuite (526 Tests) grün - Committed in:
626e296(kein DB-Zustand wird versioniert; die Baseline-Aktion selbst ist nicht committbar)
3. [Rule 1 - Bug] Eigene Migrations-Kommentarzeile enthielt versehentlich das Suchmuster "row level security"
- Found during: Task 3
- Issue: Der erklärende Kommentar in der neuen
migration.sqlbegründete den fehlenden RLS-Schritt mit dem wörtlichen Ausdruck "FORCE ROW LEVEL SECURITY" — dadurch schlug sowohl das Acceptance-Criterion (grep -ci 'row level security'soll 0 ergeben) als auch der eigene neue Spec-Test fehl. - Fix: Kommentar umformuliert, ohne die Begründung zu verlieren ("die entsprechende Absicherung" statt der wörtlichen SQL-Phrase); Spec-Test auf ein Regex-Muster für tatsächliche
ALTER TABLE ... ENABLE/FORCE ROW LEVEL SECURITY-Anweisungen umgestellt statt auf reinen Substring-Match. - Files modified: apps/api/prisma/migrations/20260806133916_add_group_internal_name_and_object_guid/migration.sql, apps/api/src/groups/migration-sql.spec.ts
- Verification:
grep -ci 'row level security' migration.sql= 0;npx vitest run src/groups/migration-sql.spec.tsgrün (14 Tests) - Committed in:
626e296
4. [Rule 1 - Bug] requirements mark-complete PERM-02 hätte den Requirement-Status verfälscht — Checkbox zurückgesetzt
- Found during: State-Update-Schritt nach Task 3
- Issue: Die Plan-Frontmatter listet
requirements: [PERM-02], und der Standard-State-Update-Schritt hakt daraufhin PERM-02 in REQUIREMENTS.md als erledigt ab. PERM-02 beschreibt aber die vollständige AD-Sync-Kette (Umbenennung folgt nach, Verschwinden löscht kaskadierend,memberOfpflegt Mitgliedschaften) — dieser Plan liefert nur den selektiven Import (den Anfang der Kette). Die verbleibenden vier Pläne der Phase 16 liefern Rekonziliation, Anzeige-Fallback und Dialog-Umbau erst noch. Ein Abhaken jetzt hätte Requirements-Tracking und spätere Audit-/Ship-Gates fälschlich glauben lassen, PERM-02 sei vollständig erfüllt. - Fix: Checkbox in REQUIREMENTS.md Zeile 67 manuell auf
[ ]zurückgesetzt, nachdem der Standard-Befehl sie automatisch gesetzt hatte.requirements-completedim Frontmatter dieses Summarys bleibt trotzdem[PERM-02](Plan-Frontmatter-Vertrag), aber die eigentliche Traceability-Tabelle bleibt korrekt „Pending", bis der letzte Plan der Phase liefert. - Files modified: .planning/REQUIREMENTS.md
- Verification:
grep -n 'PERM-02' .planning/REQUIREMENTS.mdzeigt weiterhin[ ]und Traceability-Zeile „Pending" - Committed in: wird mit dem abschließenden Metadaten-Commit dieses Plans committet
Total deviations: 4 auto-fixed (2 blocking / Migrationsverfahren, 1 Bug in eigenem Kommentartext, 1 Bug in Requirements-Tracking) Impact on plan: Alle drei Anpassungen waren notwendig, um Task 3 überhaupt abzuschließen bzw. um die eigenen Acceptance-Kriterien zu erfüllen. Kein Scope Creep — die Migration selbst entspricht exakt dem im Plan vorgesehenen Inhalt (zwei nullable Spalten, ein Unique-Index, keine RLS-Anweisung).
Issues Encountered
- Siehe Deviations oben — alle drei Punkte betrafen ausschließlich das Migrationsverfahren in dieser nicht-interaktiven Shell, nicht die fachliche Logik des Plans.
User Setup Required
None - keine externe Service-Konfiguration erforderlich. Der Testserver wurde von diesem Plan nicht angefasst; prisma migrate deploy läuft dort ohnehin automatisch beim Container-Start (apps/api/Dockerfile:38).
Next Phase Readiness
- Beide Identitätsspalten (
internalName,ldapObjectGuid) existieren jetzt in Schema, Migration und laufender lokaler Datenbank — Plan 16-03 (Rekonziliation/Rename-Erkennung) kann darauf aufsetzen escapeLdapFilterBuffer()liegt bereit, aber ungenutzt, für den binären Existenz-Sweep in Plan 16-03- Die drei zurückgestellten kosmetischen Beobachtungen (siehe Decisions) sind dokumentiert und sollten bei der Planung von 16-02/16-03 im Blick behalten werden
- Flagged assumption weiterhin offen: RESEARCH.md A1 (objectGUID bleibt über AD-Umbenennung stabil) und A2 (Binärfilter-Syntax) sind gegen kein echtes Verzeichnis geprüft — dieser Plan schreibt die GUID nur, liest sie nicht filternd zurück. Live-Prüfung ist Bestandteil von Plan 16-03 gegen ViCoTest.
Phase: 16-ad-gruppen-synchronisation Completed: 2026-08-06