Files
tessera-ctl/.planning/quick/260911-mkj-windows-27-schliessen-relations-blindste/260911-mkj-SUMMARY.md
T
schalli 8829999e70
Tessera CI/CD / Lint & Type Check (push) Successful in 45s
Tessera CI/CD / Tests (push) Successful in 53s
Tessera CI/CD / Build & Publish Images (push) Successful in 28s
docs(quick-260911-mkj): WINDOWS #27 geschlossen und verifiziert
2026-09-11 16:57:57 +02:00

145 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
phase: quick-260911-mkj
plan: 01
subsystem: testing
tags: [prisma, rls, multi-tenancy, static-analysis, vitest]
requires:
- phase: quick-260911-e2s
provides: "Bestandsaufnahme-Grundgeruest (rls-access-inventory.spec.ts, drei Erkennungsformen), WINDOWS #27 aufgedeckt"
provides:
- "Vierte Erkennungsform in rls-access-inventory.spec.ts: Relationszugriffe (include:/select:/_count:/Relationsfilter) werden ueber schema.prisma auf ihr Zielmodell aufgeloest und als eigene Fundstelle gefuehrt"
- "72 (Datei, Modell)-Paare in der Bestandsaufnahme (65 -> 72, sieben neue, drei fortgeschriebene Staende)"
- "WINDOWS #27 fixed mit Nachweis; neuer Ledger-Eintrag #33 fuer die von allen vier Formen unerreichbare Restmenge (tenders.seed.ts, backfill-tender-source.ts)"
affects: [etappe-4-scharfschalten, rls-preflight]
actuals:
tokens: 19657
tasks: 2
commits: 2
plan_head_before: 926359b067596b8d627660d926831b885e74d8d9
tech-stack:
added: []
patterns:
- "Kontextstapel-Parser (scanRelationKeys) fuer verschachtelte Prisma-Query-Objekte, aufgeloest gegen ein zur Testzeit geparstes schema.prisma"
- "String-Blanking (blankStringLiterals) fuer klammertiefen-sichere Argumentbereichs-Erkennung, getrennt von der unveraenderten Kommentarfrei-Quelle der Formen 1-3"
key-files:
created: []
modified:
- apps/api/src/prisma/rls-access-inventory.spec.ts
- docs/mandantentrennung-zugriffsklassifikation.md
- docs/mandantentrennung-etappe2-fehlerrichtung.md
- .planning/WINDOWS.md
key-decisions:
- "Vierte Erkennung schreibt Relationsziele direkt in unboundModels/boundModels (Klientenname = Modellname mit kleinem Anfangsbuchstaben) statt eines eigenen Fundstellentyps, damit findAccessSites/computeStandByKey und die bestehenden Vergleichstests unveraendert bleiben"
- "ldap-config.service.ts/ldapFieldMapping wechselt von muss-mandantengebunden auf beides — der Elternpfad getAllActiveConfigs() ist bereits als Hintergrunddienst-Fall an Etappe 3 uebergeben, kein neuer Befund"
- "RELATION_SPEC_EXCEPTIONS bleibt schmal (eine Datei, backfill-tender-source.ts); die zweite unerreichbare Datei (tenders.seed.ts, kein Relationszugriff) wird stattdessen als eigener Ledger-Eintrag #33 gefuehrt, nicht stillschweigend mit #27 mitgeschlossen"
requirements-completed: [WINDOWS-27, ETAPPE-4-VORAUSSETZUNG]
duration: ~45min
completed: 2026-09-11
status: complete
---
# Phase quick-260911-mkj: WINDOWS #27 schliessen — Relations-Blindstelle Summary
**Vierte Erkennungsform in `rls-access-inventory.spec.ts` macht Relationszugriffe (`include:`/`select:`/`_count:`/Relationsfilter) sichtbar, die Prisma als Unterabfrage auf eine zweite Tabelle unter DEREN Regel rendert — Bestandsaufnahme waechst von 65 auf 72 Paare, WINDOWS #27 ist geschlossen.**
## Performance
- **Duration:** ~45 min
- **Completed:** 2026-09-11
## Nachweis WINDOWS #27
**Zwischenmessung (Aufgabe 1, VOR dem Nachziehen der Bestandsaufnahme) — woertlich, wie im Plan verlangt:**
```
× jede im Quelltext gefundene (Datei, Modell)-Fundstelle ist im Dokument eingetragen
Fehlende Eintraege im Dokument:
apps/api/src/groups/module-grants.service.ts::module
apps/api/src/ldap/ldap-config.service.ts::tenant
apps/api/src/module-registry/module-access.service.ts::group
apps/api/src/module-registry/module-access.service.ts::groupMembership
apps/api/src/tenders/tender-digest.scheduler.ts::tender
apps/api/src/tenders/tender-digest.scheduler.ts::tenderSavedSearch
apps/api/src/tenders/tenders.controller.ts::tenderSource
× der eingetragene Stand stimmt mit dem im Quelltext gemessenen ueberein
Abweichender Stand (Dokument vs. Quelltext):
apps/api/src/ldap/ldap-config.service.ts::ldapFieldMapping — dokumentiert=gebunden, gemessen=gemischt
apps/api/src/module-registry/module-registry.service.ts::module — dokumentiert=ungebunden, gemessen=gemischt
apps/api/src/tenders/tender-matching.service.ts::tender — dokumentiert=ungebunden, gemessen=gemischt
Test Files 1 failed (1)
Tests 2 failed | 22 passed (24)
```
Das ist EXAKT die zur Planungszeit gemessene Untergrenze: 7 fehlende Paare,
3 Stand-Abweichungen. Der Detektor SIEHT die Relationszugriffe, bevor das
Dokument nachgezogen ist — der geforderte Beweis der Wirkung.
**Zahlen (Aufgabe 1/2, aus der Ausgabe von `rls-access-inventory.spec.ts` und den Gates entnommen, nicht geschaetzt):**
- 7 neue Paare, 3 fortgeschriebene Staende, davon 1 Klassenwechsel (`ldap-config.service.ts`/`ldapFieldMapping`: `muss-mandantengebunden` → `beides`)
- 1 Waechter-(a)-Ausnahme (`RELATION_SPEC_EXCEPTIONS`: `apps/api/src/tenders/backfill-tender-source.ts`), 0 Waechter-(b)-Verstoesse
- Bestandsaufnahme: 65 → **72 Paare** (35 muss-mandantengebunden, 21 keine-mandantengebundene-tabelle, 14 beides, 2 bewusst-uebergreifend — exakt die zur Planungszeit projizierte Verteilung)
- Acht gepinnte Proben, darunter A (WINDOWS #27 ungebunden) und B (WINDOWS #27 gebunden, derselbe Aufruf auf einem `forTenant(`-Klienten) — beide bestanden
- Gesamtsuite: **1007/1007 Tests, 62/62 Dateien gruen** (Baseline 994/62); Typpruefung sauber; `rls-scratch-check.mjs` **137/137** bestanden
- WINDOWS-Ledger: #27 `fixed`; neuer Eintrag **#33** fuer die von allen vier Erkennungsformen unerreichbare Restmenge (`tenders/tenders.seed.ts`, `tenders/backfill-tender-source.ts`). Kopf nach diesem Lauf: `open_count: 14`, `total_count: 33`.
## Accomplishments
- **Task 1** (`test(quick-260911-mkj): vierte Erkennungsform fuer Relationszugriffe, WINDOWS #27`, Commit `5ad23d0`):
- `analyzeFile` in `analyzeSource(source, relPath)` herausgeloest (testbar gegen Probestrings)
- `parseSchemaRelations()` liest `schema.prisma` zur Testzeit, `SCHEMA_RELATIONS` (Map Modell -> Map Feld -> Zielmodell), `CLIENT_NAME_TO_MODEL` fuer den Anker; Lookahead `(?=\s|$)` bewusst gesetzt (ohne ihn verliert die Feldzeilen-Regex jede Listenrelation am Zeilenende — der im Plan benannte erste Prototyp-Fehler, hier vermieden)
- Vierte Erkennung: Ankerregex nur ueber bekannte Empfaenger (`this.prisma`, `boundNames`, Transaktionsparameter beider Formen), Argumentbereich per Klammertiefe auf einer string-geblankten Kopie (`blank`), Wertform-Aufloesung gegen gleichnamige Konstanten derselben Datei, Kontextstapel-Scan (`scanRelationKeys`) fuer verschachtelte Relationsfelder inkl. `_count: true`
- Drei neue Waechter (Rohzahl vs. erkannte Modellaufrufe, Stale-Check `RELATION_SPEC_EXCEPTIONS`, `unresolvedRelationSpecValues` leer), zwei Schema-Tests, acht gepinnte Proben — alle 24 Tests der Spec-Datei gruen
- Bestandsaufnahme fortgeschrieben: sieben neue Zeilen, drei geaenderte Staende, Kopfabsatz "Erkennungsluecke GESCHLOSSEN" ersetzt den alten "seit 260911-e2s vermessen"-Absatz
- **Task 2** (`docs(quick-260911-mkj): Abschnitte abgeleitet, WINDOWS #27 geschlossen, Restmenge als eigener Eintrag`, Commit `388690f`):
- Klassifikationsdokument: Uebersichtsabsatz ("Zweite methodische Luecke ... geschlossen"), Klassen-Verteilung (Ueberschrift + Summenzeile + Tabelle, aus der Bestandsaufnahme GEZAEHLT: 35/21/14/2/72), Hintergrunddienst-Nachtrag zum ersten Fall (`getAllActiveConfigs()` reicht auch in `LdapFieldMapping` hinein — kein neuer Fall, Ueberschrift bleibt "sechs Faelle")
- Kritikschrift: `Nachtrag (260911-mkj)` unter `(n4)` im `## Bereich tenant` (verweist auf Befund G/(b) und die Restmenge), Vermerk im `## Etappe 2 — Abschluss`, dass #27 geschlossen ist
- Ledger: neuer Eintrag `#33` angelegt (Ledger fuer die Restmenge), dann `#27` auf `fixed` gesetzt, dann der `WINDOWS #TBD-MKJ`-Platzhalter im Spec-Kommentar durch `WINDOWS #33` ersetzt
## Deviations from Plan
### Auto-fixed Issues
None — plan executed exactly as specified for the actual detector/document logic.
### Documented Drift (nicht auto-fixed, nicht Teil dieses Plans)
**1. [Vorbestehende Abweichung, nicht dieser Plan] `docs/mandantentrennung-etappe3-auftrag.md` und Teile von `.planning/HANDOFF.json` weichen bereits VOR Beginn dieser Ausfuehrung von der Basis `cc26197` ab.**
- **Gefunden bei:** dem Allowlist-Diff-Gate in Aufgabe 1 (`git diff --name-only cc26197`)
- **Ursache:** Commit `926359b` ("docs: Auftrag fuer Etappe 3 der Mandantentrennung, gemessen statt erinnert", Autor Schalli) landete auf `main`, BEVOR diese Ausfuehrung begann — die im Auftrag genannte Basis-HEAD `261e736` war zu diesem Zeitpunkt bereits um einen fremden Commit veraltet.
- **Pruefung:** `git show --stat 926359b` zeigt ausschliesslich `docs/mandantentrennung-etappe3-auftrag.md` (neu) und `.planning/HANDOFF.json` — nichts unter `apps/api/src`, kein Schema, keine Migration, keine Compose-/Umgebungsdatei. Ausserhalb des Geltungsbereichs dieses Plans, nicht angefasst.
- **Auswirkung auf die Verify-Gates:** das im Plan definierte Allowlist-Gate (`git diff --name-only cc26197` gegen eine feste Dateiliste) meldet `docs/mandantentrennung-etappe3-auftrag.md` als "unerwartete Aenderung", weil es diesen fremden, bereits gemergten Commit mitzaehlt. Die tatsaechlich von dieser Ausfuehrung veraenderten Dateien sind ausschliesslich die vier oben genannten (bestaetigt durch `git status --short` vor jedem Commit und durch die beiden Commits `5ad23d0`/`388690f` selbst — je genau die im Plan als Deliverables genannten Dateien, keine mehr).
- **Nicht behoben, weil:** ausserhalb der Erlaubnisliste dieses Plans (nur die Spec-Datei, `apps/api/prisma/**`, zwei benannte Dokumente, `.planning/`) — ein fremder, bereits abgeschlossener Commit gehoert nicht in diesen Auftrag.
## Known Stubs
None — dieser Plan aendert ausschliesslich Testcode und Dokumentation, keine UI/keine Laufzeitpfade.
## Threat Flags
None — die Aenderungen liegen vollstaendig innerhalb des im Plan definierten `threat_model` (T-MKJ-01 bis T-MKJ-05), keine neue Angriffsflaeche ausserhalb dessen.
## BEFUND — nicht behoben
Keiner. Die Zwischenmessung lieferte exakt 7 fehlende Paare / 3 Stand-Abweichungen (die geplante Untergrenze, keine zusaetzlichen ungenannten Funde); jedes der sieben neuen Paare wurde einzeln am Quelltext geprueft (siehe Zeilenverweise in der Bestandsaufnahme-Tabelle) und ist entweder `keine-mandantengebundene-tabelle` (Elternbindung wirkungslos, nicht schaedlich) oder `muss-mandantengebunden`/`gebunden` (Relationsfilter auf einem bereits gebundenen Klienten in eine Tabelle desselben Mandanten). Keine ungebundene Einbindung in eine geschuetzte Tabelle auf ungeschuetztem Elternpfad, die nicht bereits als Hintergrunddienst-Fall benannt waere.
## Self-Check: PASSED
- `apps/api/src/prisma/rls-access-inventory.spec.ts`: FOUND, enthaelt `analyzeSource`, `parseSchemaRelations`, `SCHEMA_RELATIONS`, `RELATION_SPEC_EXCEPTIONS`, 24 `it(`-Bloecke, alle gruen
- `docs/mandantentrennung-zugriffsklassifikation.md`: FOUND, 72 (Datei, Modell)-Paare, Klassen-Verteilung 35/21/14/2
- `docs/mandantentrennung-etappe2-fehlerrichtung.md`: FOUND, `Nachtrag (260911-mkj)` unter `(n4)` und im Abschluss-Abschnitt
- `.planning/WINDOWS.md`: FOUND, `#27` Status `fixed`, `#33` neu mit Status `open`, Kopfzaehler (`open_count: 14`, `total_count: 33`) konsistent mit den Tabellenzeilen
- Commit `5ad23d0`: FOUND in `git log --oneline --all`
- Commit `388690f`: FOUND in `git log --oneline --all`
- Baseline: 1007/1007 Tests, 62/62 Dateien gruen; `npm --prefix apps/api run type-check` sauber; `rls-scratch-check.mjs` 137/137 bestanden
- Schalter aus, kein Dienstcode, kein Schema/Migration, keine Compose-/Umgebungsdatei veraendert (bestaetigt per `git status --short` vor jedem Commit)