docs(quick-260911-cwh): complete Bereich calendar plan
This commit is contained in:
+7
-5
@@ -4,11 +4,11 @@ milestone: v1.2
|
|||||||
current_phase: 17
|
current_phase: 17
|
||||||
current_phase_name: eigene-ausschreibungs-quellen-je-nutzer
|
current_phase_name: eigene-ausschreibungs-quellen-je-nutzer
|
||||||
status: verified
|
status: verified
|
||||||
stopped_at: "Quick 260910-krx abgeschlossen: Bereich dashboard der Etappe 2 (Mandantentrennung) umgestellt, 12/13 Zugriffe gebunden, WINDOWS #25 neu offen"
|
stopped_at: "Quick 260911-cwh abgeschlossen: Bereich calendar der Etappe 2 (Mandantentrennung) umgestellt, 12/12 Zugriffe gebunden, WINDOWS #26 neu offen"
|
||||||
last_updated: "2026-09-11T07:05:45.197Z"
|
last_updated: "2026-09-11T08:01:13.625Z"
|
||||||
last_activity: 2026-09-10
|
last_activity: 2026-09-10
|
||||||
last_activity_desc: Quick 260910-jab — drei zu kurz greifende RLS-Regeln geschlossen (GroupMembership beide Seiten, ModuleGrant beide Ziele, TenderRssFeedSource Lese-/Schreibsplit), listForUser gebunden, Aktenstand kohaerent
|
last_activity_desc: Quick 260910-jab — drei zu kurz greifende RLS-Regeln geschlossen (GroupMembership beide Seiten, ModuleGrant beide Ziele, TenderRssFeedSource Lese-/Schreibsplit), listForUser gebunden, Aktenstand kohaerent
|
||||||
state_head: 67b50240d6a3f0dca2c2bfbd0a129269f9a7ab53
|
state_head: e0e163ec636cb48d15cc06ba9ee246a86b5d50a0
|
||||||
progress:
|
progress:
|
||||||
total_phases: 17
|
total_phases: 17
|
||||||
completed_phases: 3
|
completed_phases: 3
|
||||||
@@ -119,6 +119,7 @@ Progress: [██████████] 100%
|
|||||||
| Phase quick-260909-ipc P01 | 55min | 3 tasks | 8 files |
|
| Phase quick-260909-ipc P01 | 55min | 3 tasks | 8 files |
|
||||||
| Phase quick-260910-jab P01 | 70min | 3 tasks | 16 files |
|
| Phase quick-260910-jab P01 | 70min | 3 tasks | 16 files |
|
||||||
| Phase quick-260910-krx P01 | 26min | 3 tasks | 7 files |
|
| Phase quick-260910-krx P01 | 26min | 3 tasks | 7 files |
|
||||||
|
| Phase quick-260911-cwh P01 | 21min | 3 tasks | 7 files |
|
||||||
|
|
||||||
## Accumulated Context
|
## Accumulated Context
|
||||||
|
|
||||||
@@ -297,6 +298,7 @@ Recent decisions affecting current work:
|
|||||||
- [Phase 17]: [260909-ipc]: getAllActiveConfigs()/onApplicationBootstrap() bleiben dauerhaft ungebunden (Befund B) — Klasse von (ldap-config.service.ts, ldapConfig) korrigiert auf beides
|
- [Phase 17]: [260909-ipc]: getAllActiveConfigs()/onApplicationBootstrap() bleiben dauerhaft ungebunden (Befund B) — Klasse von (ldap-config.service.ts, ldapConfig) korrigiert auf beides
|
||||||
- [Phase 17]: [260909-ipc]: Standardgruppen-Uebergabe (groups.service.ts) bewusst nicht angefasst — Reihenfolgebedingung fuer Etappe 4
|
- [Phase 17]: [260909-ipc]: Standardgruppen-Uebergabe (groups.service.ts) bewusst nicht angefasst — Reihenfolgebedingung fuer Etappe 4
|
||||||
- [Phase 17]: 260910-krx: Bereich dashboard vollstaendig umgestellt — 12 gebunden, 1 begruendet ungebunden (Modulkatalog); getLayout/saveLayout gemeinsam gebunden; saveLayout uebersetzt PrismaClientUnknownRequestError (nicht P2002) in deutsche Konfliktmeldung; WINDOWS #25 fuer die beweisvernichtende Schleife offen angelegt
|
- [Phase 17]: 260910-krx: Bereich dashboard vollstaendig umgestellt — 12 gebunden, 1 begruendet ungebunden (Modulkatalog); getLayout/saveLayout gemeinsam gebunden; saveLayout uebersetzt PrismaClientUnknownRequestError (nicht P2002) in deutsche Konfliktmeldung; WINDOWS #25 fuer die beweisvernichtende Schleife offen angelegt
|
||||||
|
- [Phase 17]: [quick-260911-cwh]: Bereich calendar Etappe 2 gebunden — Cache-Schluessel bleibt ohne Mandantenanteil (User.id ist plattformweit eindeutige UUID, Etappe-3-Entscheidung (1) betrifft nur username/email); keine neue Fehleruebersetzung fuer Besitzpruefungen noetig (Wettlauf-Fall wirft P2025, strukturell unerreichbar); refreshCacheInBackground zaehlt nicht als sechster Hintergrunddienst-Fall
|
||||||
|
|
||||||
### Pitfalls & Anti-Patterns
|
### Pitfalls & Anti-Patterns
|
||||||
|
|
||||||
@@ -425,8 +427,8 @@ sind. Kein Anlass, sie vorher erneut vorzulegen.
|
|||||||
|
|
||||||
## Session Continuity
|
## Session Continuity
|
||||||
|
|
||||||
Last session: 2026-09-11T07:05:44.595Z
|
Last session: 2026-09-11T08:01:13.009Z
|
||||||
Resumed: 2026-09-09 — Sitzung ueber /gsd-resume-work fortgesetzt; Einstiegspunkt Etappe 2 (Bereich ldap), Auswahl des Nutzers steht aus.
|
Resumed: 2026-09-09 — Sitzung ueber /gsd-resume-work fortgesetzt; Einstiegspunkt Etappe 2 (Bereich ldap), Auswahl des Nutzers steht aus.
|
||||||
Stopped at: Quick 260910-krx abgeschlossen: Bereich dashboard der Etappe 2 (Mandantentrennung) umgestellt, 12/13 Zugriffe gebunden, WINDOWS #25 neu offen
|
Stopped at: Quick 260911-cwh abgeschlossen: Bereich calendar der Etappe 2 (Mandantentrennung) umgestellt, 12/12 Zugriffe gebunden, WINDOWS #26 neu offen
|
||||||
Resume file: None
|
Resume file: None
|
||||||
Last activity: 2026-09-10 - Completed quick task 260910-jab: Die drei zu kurz greifenden Datenbankregeln (T-JTS-02, T-JTS-03, WINDOWS #19) geschlossen
|
Last activity: 2026-09-10 - Completed quick task 260910-jab: Die drei zu kurz greifenden Datenbankregeln (T-JTS-02, T-JTS-03, WINDOWS #19) geschlossen
|
||||||
|
|||||||
+168
@@ -0,0 +1,168 @@
|
|||||||
|
---
|
||||||
|
phase: quick-260911-cwh
|
||||||
|
plan: 01
|
||||||
|
subsystem: database
|
||||||
|
tags: [prisma, postgresql, row-level-security, multi-tenancy, nestjs, vitest, calendar]
|
||||||
|
|
||||||
|
requires:
|
||||||
|
- phase: quick-260910-krx
|
||||||
|
provides: Bereich dashboard vollstaendig gebunden, Muster fuer generierten-Client-Messung (Pruefung 5b)
|
||||||
|
provides:
|
||||||
|
- "Bereich calendar (calendar.service.ts, Modell calendarSource) vollstaendig an forTenant() gebunden, alle zwoelf Datenbankzugriffe"
|
||||||
|
- "Elfter Abschnitt runCalendarAreaChecks in rls-scratch-check.mjs mit 13 neuen Pruefungen (davon vier ueber den generierten Client)"
|
||||||
|
- "calendar.service.spec.ts NEU angelegt — erste Testlage dieses Bereichs, 23 Testfaelle mit Zwei-Klienten-Nachweis"
|
||||||
|
- "Kritikschrift Abschnitt '## Bereich calendar' mit gemessenem Cache-Schluessel-Urteil und Zugangsdaten-Erhaltungsbefund"
|
||||||
|
- "WINDOWS #26: offener Ledger-Eintrag zur lautlosen Fehlerrichtung im Bereich calendar"
|
||||||
|
affects: [etappe-2-mandantentrennung, calendar-modul, rls-scratch-check-tooling]
|
||||||
|
|
||||||
|
actuals:
|
||||||
|
tokens: 25378
|
||||||
|
tasks: 3
|
||||||
|
commits: 3
|
||||||
|
plan_head_before: 508d9e43015df192f5b86c39ac1e81c983f100b8
|
||||||
|
|
||||||
|
tech-stack:
|
||||||
|
added: []
|
||||||
|
patterns:
|
||||||
|
- "forTenant(this.prisma, tenantId) als lokale tenantPrisma-Konstante je Methode mit Datenbankzugriff (dienst-interner Weg, wie alle acht Bereiche vor calendar)"
|
||||||
|
- "Zwei-Klienten-Testnachweis via __makeBoundClient(tenantId) — ungebundener Fake protokolliert nicht, gebundener schon"
|
||||||
|
- "Generierter-Client-Messung an einer schemagleichen Wegwerf-Tabelle (Spaltenmenge zur Laufzeit gegen schema.prisma geprueft) statt Roh-SQL, fuer Fehlerklassen die die Anwendung tatsaechlich sieht"
|
||||||
|
|
||||||
|
key-files:
|
||||||
|
created:
|
||||||
|
- apps/api/src/calendar/calendar.service.spec.ts
|
||||||
|
modified:
|
||||||
|
- apps/api/scripts/rls-scratch-check.mjs
|
||||||
|
- docs/mandantentrennung-etappe2-fehlerrichtung.md
|
||||||
|
- apps/api/src/calendar/calendar.service.ts
|
||||||
|
- apps/api/src/calendar/calendar.controller.ts
|
||||||
|
- docs/mandantentrennung-zugriffsklassifikation.md
|
||||||
|
- .planning/WINDOWS.md
|
||||||
|
|
||||||
|
key-decisions:
|
||||||
|
- "Cache-Schluessel (userId:from:to) bleibt OHNE Mandantenanteil — die vierteilige Kette (schema.prisma User.id @default(uuid()) -> JwtStrategy.validate -> auth.service.ts sub:user.id -> extractContext) zeigt eine plattformweit eindeutige UUID, die Etappe-3-Entscheidung (1) betrifft User.username/User.email, nicht User.id"
|
||||||
|
- "Keine neue Fehleruebersetzung fuer die drei Besitzpruefungen noetig: der gemessene Wettlauf-Fall wirft PrismaClientKnownRequestError/P2025 (nicht PrismaClientUnknownRequestError wie im Bereich dashboard), und dieser Pfad ist durch die vorgeschaltete findUnique-Besitzpruefung strukturell unerreichbar"
|
||||||
|
- "refreshCacheInBackground wird NICHT als sechster Hintergrunddienst-Fall gefuehrt — sie iteriert nicht ueber Mandanten, sondern traegt den Mandanten der Anfrage, die sie angestossen hat (Befund B)"
|
||||||
|
- "Antwortsemantik 403 (Forbidden bei fremdem Besitz) vs. 404 (NotFound bei unbekannter Kennung) bleibt unveraendert — waere eine API-Aenderung ausserhalb des Auftrags"
|
||||||
|
|
||||||
|
requirements-completed: [WINDOWS-18, ETAPPE-2-CALENDAR]
|
||||||
|
|
||||||
|
coverage:
|
||||||
|
- id: D1
|
||||||
|
description: "Alle zwoelf Datenbankzugriffe von calendar.service.ts laufen gebunden ueber forTenant(), ein tenantPrisma-Klient je Methode mit Datenbankzugriff"
|
||||||
|
requirement: ETAPPE-2-CALENDAR
|
||||||
|
verification:
|
||||||
|
- kind: unit
|
||||||
|
ref: "apps/api/src/calendar/calendar.service.spec.ts — 23 Testfaelle"
|
||||||
|
status: pass
|
||||||
|
- kind: unit
|
||||||
|
ref: "apps/api/src/prisma/rls-access-inventory.spec.ts — Bestandsaufnahme stimmt mit Quelltext ueberein"
|
||||||
|
status: pass
|
||||||
|
- kind: other
|
||||||
|
ref: "node apps/api/scripts/rls-scratch-check.mjs — runCalendarAreaChecks, 13 neue Pruefungen"
|
||||||
|
status: pass
|
||||||
|
human_judgment: false
|
||||||
|
- id: D2
|
||||||
|
description: "Kritikschrift misst die umgekehrte Fehlerrichtung an der ausgelieferten Regel (Migration 20260909140000, bestaetigt unveraendert durch 20260910120000) inklusive vier Pruefungen ueber den generierten Prisma-Client an einer schemagleichen Wegwerf-Tabelle"
|
||||||
|
requirement: WINDOWS-18
|
||||||
|
verification:
|
||||||
|
- kind: other
|
||||||
|
ref: "node apps/api/scripts/rls-scratch-check.mjs — Pruefungen calendarsource-wegwerftabelle-deckt-alle-spalten-des-generierten-clients, calendarsource-generierter-client-*"
|
||||||
|
status: pass
|
||||||
|
human_judgment: false
|
||||||
|
- id: D3
|
||||||
|
description: "Fuenf handgepflegte Dokumentstellen der Klassifikation nachgezogen und maschinell gegen den Quelltext gegatet; WINDOWS-Ledger-Eintrag #26 in Tabelle, JSON-Block und Kopfzaehlern konsistent"
|
||||||
|
verification:
|
||||||
|
- kind: unit
|
||||||
|
ref: "apps/api/src/prisma/rls-access-inventory.spec.ts"
|
||||||
|
status: pass
|
||||||
|
- kind: other
|
||||||
|
ref: "Plan-Verify-Gates Aufgabe 3 (Uebersichtszeile, Summenzeile, Klassen-Verteilung, Hintergrunddienst-Abschnitt, WINDOWS.md-Konsistenz) — manuell in der Ausfuehrung nachvollzogen"
|
||||||
|
status: pass
|
||||||
|
human_judgment: false
|
||||||
|
|
||||||
|
duration: 21min
|
||||||
|
completed: 2026-09-11
|
||||||
|
status: complete
|
||||||
|
---
|
||||||
|
|
||||||
|
# Quick Task 260911-cwh: Etappe 2 Mandantentrennung, Bereich calendar — Summary
|
||||||
|
|
||||||
|
**Alle zwoelf `calendarSource`-Datenbankzugriffe in `calendar.service.ts` auf `forTenant()` umgestellt (ein `tenantPrisma`-Klient je Methode), mit einer aus dem Nichts angelegten Testlage (23 Faelle), 13 neuen Wegwerf-Pruefungen — vier davon ueber den generierten Prisma-Client — und einem gemessenen, schriftlich festgehaltenen Urteil zum Cache-Schluessel sowie zur Zugangsdaten-Erhaltung.**
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
- **Duration:** 21 min
|
||||||
|
- **Started:** 2026-09-11T07:39:07Z
|
||||||
|
- **Completed:** 2026-09-11T08:00:00Z (ca.)
|
||||||
|
- **Tasks:** 3
|
||||||
|
- **Files modified:** 7 (6 modified, 1 neu angelegt)
|
||||||
|
|
||||||
|
## Accomplishments
|
||||||
|
|
||||||
|
- Neunter Bereich der Etappe 2 (Mandantentrennung) abgeschlossen: `calendar` — der einzige bisher umgestellte Bereich, der verschluesselte Zugangsdaten zu FREMDEN Servern (Exchange/CalDAV/ICS) haelt
|
||||||
|
- `apps/api/scripts/rls-scratch-check.mjs`: elfter Abschnitt `runCalendarAreaChecks` mit 13 namentlich benannten Pruefungen, davon vier ueber den generierten Client an einer Wegwerf-Tabelle, deren 17-Spalten-Deckung zur Laufzeit gegen `schema.prisma` geprueft wird — alle 101 Pruefungen des Werkzeugs bestehen
|
||||||
|
- `calendar.service.spec.ts`: NEU angelegt (dieser Bereich hatte zuvor KEINE Testdatei), 23 Testfaelle mit Zwei-Klienten-Nachweis, decken jeden Datenbankpfad, alle drei Besitzpruefungen je Ausnahmeart, die drei Zugangsdaten-Erhaltungsfaelle, beide Rueckschreibungen der Aggregationsschleife und den Wachhund fuer "genau ein Klient je Aufruf" ab
|
||||||
|
- Kritikschrift (`docs/mandantentrennung-etappe2-fehlerrichtung.md`, Abschnitt `## Bereich calendar`) mit (k1)-(k5): die tatsaechlich gemessene Fehlerklasse des Wettlauf-Falls (`PrismaClientKnownRequestError`/P2025, ANDERS als im Bereich `dashboard`), das vierteilige Cache-Schluessel-Urteil, die Backend- UND Frontend-Leere-als-Abwesenheit-Kette samt Fehlerverschluckung
|
||||||
|
- Fuenf handgepflegte Stellen der Klassifikation nachgezogen (Bestandsaufnahme-Zeile, Uebersichtszeile 0/12, Summenzeile 83/159, Klassen-Verteilung mit Stand-Vermerk, Hintergrunddienst-Abschnitt mit dem Sonderfall `refreshCacheInBackground`), WINDOWS-Ledger-Eintrag #26 angelegt
|
||||||
|
|
||||||
|
## Task Commits
|
||||||
|
|
||||||
|
Each task was committed atomically:
|
||||||
|
|
||||||
|
1. **Aufgabe 1: Fehlerrichtung messen** - `bf5fc4d` (feat)
|
||||||
|
2. **Aufgabe 2: Testlage anlegen, alle zwoelf Zugriffe binden** - `77cb124` (feat)
|
||||||
|
3. **Aufgabe 3: Restliche Dokumentstellen, WINDOWS-Ledger, Falsifizierungsnachweise** - `e0e163e` (docs)
|
||||||
|
|
||||||
|
_Kein TDD-Modus fuer diesen Plan — die Testlage wurde in Aufgabe 2 als Voraussetzung neu angelegt, nicht als RED/GREEN-Zyklus einzeln entwickelt._
|
||||||
|
|
||||||
|
## Files Created/Modified
|
||||||
|
|
||||||
|
- `apps/api/scripts/rls-scratch-check.mjs` - elfter Abschnitt `runCalendarAreaChecks` (13 neue Pruefungen), Helfer `readSchemaModelFieldNames()`
|
||||||
|
- `docs/mandantentrennung-etappe2-fehlerrichtung.md` - Abschnitt `## Bereich calendar` mit (k1)-(k5)
|
||||||
|
- `apps/api/src/calendar/calendar.service.spec.ts` - NEU, 23 Testfaelle, Zwei-Klienten-Nachweis
|
||||||
|
- `apps/api/src/calendar/calendar.service.ts` - alle zwoelf Zugriffe gebunden, Klassenkommentar praezisiert, Cache-Schluessel-Urteil und Hintergrunddienst-Begruendung als Kommentare
|
||||||
|
- `apps/api/src/calendar/calendar.controller.ts` - sechs kontextnutzende Handler reichen Benutzer- UND Mandantenkennung durch
|
||||||
|
- `docs/mandantentrennung-zugriffsklassifikation.md` - fuenf handgepflegte Stellen nachgezogen
|
||||||
|
- `.planning/WINDOWS.md` - neuer offener Eintrag #26
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
|
||||||
|
- Cache-Schluessel bleibt ohne Mandantenanteil — vierteilige Kette gemessen, Urteil in Code UND Kritikschrift verankert (siehe `key-decisions` oben)
|
||||||
|
- Keine neue Fehleruebersetzung fuer die Besitzpruefungen: gemessener Wettlauf-Fall (P2025) ist ueber die vorgeschaltete Pruefung strukturell unerreichbar
|
||||||
|
- `refreshCacheInBackground` bleibt ausserhalb des Hintergrunddienst-Abschnitts (kein sechster Fall) — sie traegt den Mandanten der Anfrage, iteriert nicht ueber mehrere Mandanten
|
||||||
|
- Antwortsemantik 403/404 bewusst unveraendert gelassen
|
||||||
|
|
||||||
|
## Deviations from Plan
|
||||||
|
|
||||||
|
None - plan executed exactly as written. Alle Planungsbefunde (A-L) wurden zur Ausfuehrungszeit nachgeprueft und bestaetigt; keine Abweichung von den Planungsbefunden trat auf.
|
||||||
|
|
||||||
|
## Falsifizierungsnachweise (drei, alle durchgefuehrt und zurueckgenommen)
|
||||||
|
|
||||||
|
1. **Aufgabe 2 — halb gebundene Aggregationsschleife:** Die Bindung der Synchronstatus-Rueckschreibung im Erfolgspfad von `fetchAndCacheEvents` wurde probeweise zurueckgenommen (`tenantPrisma.calendarSource.update` → `this.prisma.calendarSource.update`). Ergebnis: der benannte Test `aggregateEvents, Erfolgspfad: das Laden der Quellen UND die Synchronstatus-Rueckschreibung bei Erfolg stehen gebunden unter derselben Mandantenkennung im Protokoll` ging rot mit der Meldung `erwarteter gebundener Aufruf calendarSource.update(tenant=t1) fehlt im Protokoll: [{"tenantId":"t1","model":"calendarSource","method":"findMany"}]: expected false to be true`. Bindung wiederhergestellt, Testlage danach wieder gruen (23/23).
|
||||||
|
2. **Aufgabe 3a — falscher Stand in der Bestandsaufnahme:** Die Zeile `calendar.service.ts`/`calendarSource` wurde probeweise auf `Stand: ungebunden` zurueckgesetzt. Ergebnis: `rls-access-inventory.spec.ts` ging rot mit `Abweichender Stand (Dokument vs. Quelltext): apps/api/src/calendar/calendar.service.ts::calendarSource — dokumentiert=ungebunden, gemessen=gebunden`. Zurueckgesetzt, Test danach wieder gruen (10/10).
|
||||||
|
3. **Aufgabe 3b — falsche Uebersichtszahl:** Die Uebersichtszeile `calendar` wurde probeweise auf `5 | 12` (statt der gemessenen `0 | 12`) gesetzt. Ergebnis: das herleitende Gate (`grep -qE "^\| calendar \| ${DU} \| ${DB} \| \*\*war 12/0\*\*"`) meldete `UEBERSICHTSZEILE calendar nennt nicht die neu gemessenen Zahlen 0/12 im etablierten Stil`. Zurueckgesetzt, Gate danach wieder erfuellt.
|
||||||
|
|
||||||
|
## Issues Encountered
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
## User Setup Required
|
||||||
|
|
||||||
|
None - keine externe Diensteinrichtung erforderlich.
|
||||||
|
|
||||||
|
## Next Phase Readiness
|
||||||
|
|
||||||
|
- Neunter von zwoelf Bereichen der Etappe 2 abgeschlossen — Klassen-Verteilung (63 Paare) unveraendert, nur die `Stand`-Spalte des `calendar`-Paares gewechselt
|
||||||
|
- Der Schalter (`DATABASE_URL` → Rolle `tessera`, `BYPASSRLS`) bleibt AUS — keine Compose-/Umgebungsdatei angefasst, keine Schema-/Migrationsaenderung, nichts in Active Directory
|
||||||
|
- Baseline am Ende gehalten: 883 Tests gruen (57 Dateien, davon 23 neu), Typpruefung sauber, `rls-scratch-check.mjs` meldet 101/101 Pruefungen bestanden
|
||||||
|
- WINDOWS #26 bleibt bis nach dem Scharfschalten (Etappe 4) offen — an dieselbe Bedingung gebunden wie #18, Familie mit #23/#25
|
||||||
|
- Naechster Bereich der Etappe 2 (zehnter von zwoelf) ist aus der Klassen-Verteilung in `docs/mandantentrennung-zugriffsklassifikation.md` zu waehlen
|
||||||
|
|
||||||
|
## Self-Check: PASSED
|
||||||
|
|
||||||
|
All created/modified files verified present on disk; all three task commit hashes (`bf5fc4d`, `77cb124`, `e0e163e`) verified present in git history.
|
||||||
|
|
||||||
|
---
|
||||||
|
*Phase: quick-260911-cwh*
|
||||||
|
*Completed: 2026-09-11*
|
||||||
Reference in New Issue
Block a user