docs(quick-260911-mkj): Abschnitte abgeleitet, WINDOWS #27 geschlossen, Restmenge als eigener Eintrag

- Klassifikationsdokument: Klassen-Verteilung (35/21/14/2, 72 Paare),
  Uebersichtsabsatz (zweite methodische Luecke, geschlossen) und
  Hintergrunddienst-Nachtrag (ldap/getAllActiveConfigs reicht auch in
  LdapFieldMapping hinein) aus Tabelle/Greps abgeleitet, nicht abgeschrieben
- Kritikschrift: Nachtrag (260911-mkj) unter (n4) im Bereich tenant, Vermerk
  im Etappe-2-Abschluss dass #27 geschlossen ist
- WINDOWS.md: #27 fixed (Nachweis: vierte Erkennungsform, Proben,
  Zwischenmessung 7/3/1); neuer Eintrag #33 fuer die Empfaenger ausserhalb
  der vier Erkennungsformen (tenders.seed.ts, backfill-tender-source.ts)
- Spec: WINDOWS #TBD-MKJ-Platzhalter durch #33 ersetzt

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AMASaSxv5QMY7RncqZriRR
This commit is contained in:
2026-09-11 16:49:58 +02:00
parent 5ad23d0537
commit 388690fdf0
4 changed files with 104 additions and 14 deletions
@@ -2471,6 +2471,28 @@ Mandantenzahl belanglos, dieselbe Form wie
Wartungsrolle gegen die gebundene Fan-out-Zaehlung ist dieselbe Pruefung wie
im Bereich `user` — kein eigener Eintrag noetig.
**Nachtrag (260911-mkj):** WINDOWS #27 — die in (b) beschriebene
Erkennungsluecke der Bestandsaufnahme — ist geschlossen. Eine vierte
Erkennungsform in `rls-access-inventory.spec.ts` (`analyzeSource`,
`SCHEMA_RELATIONS`) loest Relationsfelder ueber `schema.prisma` auf ihr
Zielmodell auf und traegt das Zielmodell als eigene Fundstelle ein — der
Nachweis steht gegen KONTROLLIERTE Proben im Spec, nicht gegen die drei
realen Stellen aus (b): die einzige gefaehrliche Auspraegung
(`tenant.controller.ts`, ungebundener aeusserer Aufruf auf ungeschuetzter
Tabelle mit Einbindung in eine geschuetzte Tabelle) traegt die Form seit
(n3)/Aufgabe 3 (dem Fan-out-Ersatz) nicht mehr — deshalb Probestrings, die
dieselbe Form nachbilden (ungebunden und gebunden). Gemessen: SIEBEN neue
(Datei, Modell)-Paare, DREI fortgeschriebene Staende, davon
`ldap-config.service.ts`/`ldapFieldMapping` als einziger Klassenwechsel
(`muss-mandantengebunden` -> `beides`, siehe (b) oben: `getAllActiveConfigs`
reicht auch in `LdapFieldMapping` hinein, nicht nur in `Tenant`). Verbleibende
Grenze, LAUT gehalten statt still: ein Empfaenger ausserhalb aller vier
Erkennungsformen bleibt fuer JEDE Form unsichtbar — gemessen
`tenders/tenders.seed.ts` (Funktionsparameter `prisma: PrismaService`) und
`tenders/backfill-tender-source.ts` (eigenstaendiges Skript, eigener `new
PrismaClient()`), beide als eigener Ledger-Eintrag gefuehrt (nicht
stillschweigend mit #27 mitgeschlossen).
### (n5) Was dieser Durchlauf bewusst nicht anfasst
- Der direkte Prisma-Zugriff im Controller (Muster wie `user.controller.ts`)
@@ -3072,7 +3094,8 @@ Bedingung gebunden wie #18), #21 (dkv-Planer-Startpfad), #22
(module-registry, unterscheidbares Signal fehlt), #24 (plattformweite
RSS-Verwaltung unter der Anwendungsrolle), #25 (dashboard, beweisvernichtende
Fehlerrichtung), #26 (calendar, verschluckte Leere), #27
(Relationszugriffe für die Bestandsaufnahme unsichtbar), #28 (auth,
(Relationszugriffe für die Bestandsaufnahme unsichtbar, seit 260911-mkj
geschlossen), #28 (auth,
verschluckte Leere), plus die drei neuen Einträge dieses Laufs (Startpfad
des Mailmoduls, verschluckte Leere `favorites`, verschluckte Leere
`settings` — Nummern siehe Aufgabe 3 dieses Plans).
@@ -131,6 +131,25 @@ Bodensatz, nicht die vollständige Zahl gebundener Zugriffe in `groups`; die
Bestandsaufnahme unten (Spalte "Stand", je (Datei, Modell)-Paar) ist die
autoritative Quelle.
**Zweite methodische Lücke, seit 260911-mkj geschlossen — aber nur in der
Bestandsaufnahme:** die beiden Rohtreffer-Greps dieser Tabelle
(`this\.prisma\.[a-zA-Z]*` bzw. `tenantPrisma\.[a-zA-Z]*\.`) zählen
Relationsziele (`include:`, `select:`, `_count:`, Relationsfilter in
`where:`/`orderBy:`) strukturell NICHT — ein `include: { module: true }`
auf `tenantPrisma.tenantModuleActivation` erzeugt keinen Rohtreffer auf
`module`, weil `module` in der Datei nie als `tenantPrisma.module` steht.
Die Spalten und die Summenzeile behalten deshalb ihre bisherige Bedeutung
und ihre bisherigen Werte (weiterhin 68 ungebunden / 178 gebunden, NACH-
GERECHNET, nicht abgeschrieben) — sie zählen weiterhin nur direkte
Modellaufrufe. Autoritativ für Relationszugriffe ist allein die
Bestandsaufnahme unten, deren vierte Erkennungsform
(`rls-access-inventory.spec.ts`, `analyzeSource`) die Ziele als eigene
Paare führt: sieben der 72 Paare dort tauchen in KEINER Rohtrefferzahl
dieser Übersicht auf, zum Beispiel
`module-registry/module-access.service.ts`/`group` (nur über den
Relationsfilter `group: { memberships: { some: { userId } } }` sichtbar,
niemals als `tenantPrisma.group` im Quelltext).
| Bereich | Ungebunden | Gebunden | Hinweis |
|---|---|---|---|
| tenders | 35 | 27 | **war 62/0**, dann 36/26 nach 260909-laa — 260910-jab (Aufgabe 2) hat `tender-rss-feed.service.ts`/`listForUser` zusätzlich auf `forTenant()` umgestellt (WINDOWS #19 geschlossen, Befund F: ungebunden hätte die Reparatur den Pfad sonst still auf nur die plattformweiten Zeilen reduziert): ein Rohtreffer wandert von ungebunden nach gebunden (36→35, 26→27). Die 35 verbleibenden ungebundenen Treffer sind die zwölf bewusst nicht angefassten Paare (D-03-Katalog, zwei Fan-out-Adapter) plus die zwei bewusst ungebundenen RSS-Pfade (`createPlatform`/`remove`, WINDOWS #24) plus die übergreifenden Hälften der beiden Hintergrunddienste (Etappe-3-Übergabe) |
@@ -147,7 +166,7 @@ autoritative Quelle.
| settings | 1 | 3 | **war 4/0** — 260911-gwh (Aufgabe 2) hat `getSmtpConfig`, `saveSmtpConfig`, `getDecryptedSmtpConfig` auf `forTenant()` umgestellt (3 gebundene `smtpConfig`-Rohtreffer). Der eine verbleibende ungebundene Rohtreffer ist der umbenannte Planer-Startpfad `loadAnySmtpConfigForStartupTransport()` (Befund D, WINDOWS #30) — bewusst, mit dreifacher Markierung; Befund K (`tenders`/`dkv` hängen an `getDecryptedSmtpConfig`) ist damit erfüllt |
| **Summe** | **68** | **178** | Ungebunden: war 118 nach 260910-das, dann 108 nach 260910-exd (module-registry 17→7), dann 107 nach 260910-jab (`tenders` 36→35, `listForUser` gebunden), dann 95 nach 260910-krx (`dashboard` 13→1), dann 83 nach 260911-cwh (`calendar` 12→0), unverändert nach 260911-e2s (`tenant` bleibt bei 8 ungebundenen Rohtreffern), dann 78 nach 260911-fh9 (`auth` 8→3), jetzt 68 nach 260911-gwh (`favorites` 7→0, `settings` 4→1). Gebunden: war 124, dann 134 nach 260910-exd (zusätzlich 10 in `module-registry`), dann 135 nach 260910-jab (zusätzlich 1 in `tenders`), dann 147 nach 260910-krx (zusätzlich 12 in `dashboard`), dann 159 nach 260911-cwh (zusätzlich 12 in `calendar`), dann 162 nach 260911-e2s (zusätzlich 3 in `tenant`), dann 167 nach 260911-fh9 (zusätzlich 5 in `auth`), jetzt 178 nach 260911-gwh (zusätzlich 8 in `favorites`, 3 in `settings`). Dies ist der ENDSTAND der Etappe 2: jeder verbleibende ungebundene Rohtreffer ist einer der in diesem Dokument benannten, bewusst ungebundenen Fälle. Diese Übersicht ist eine Buchführungshilfe; **autoritativ ist die Fundstellentabelle unten**, die `rls-access-inventory.spec.ts` bei jedem Lauf gegen den Quelltext prüft |
## Klassen-Verteilung (nach (Datei, Modell)-Fundstellen, 65 Paare)
## Klassen-Verteilung (nach (Datei, Modell)-Fundstellen, 72 Paare)
Stand 260909-jts (Aufgabe 3): 61 Paare aus dem vorherigen Durchlauf
(260909-ipc) plus ein bisher vollstaendig unsichtbares Paar
@@ -236,13 +255,36 @@ bestaetigt). Zwei Paare aendern nur ihre `Stand`-Spalte, keine ihrer Klasse:
der ENDSTAND der Etappe 2 — die Zahl ist der Ausgabe von
`rls-access-inventory.spec.ts` entnommen, nicht geschaetzt.
**Stand 260911-mkj (Aufgabe 1/2):** 72 Paare — 65 aus dem Endstand der
Etappe 2 plus SIEBEN neue Paare der vierten Erkennungsform (WINDOWS #27):
`groups/module-grants.service.ts`/`module` (`keine-mandantengebundene-tabelle`,
`gebunden`), `ldap/ldap-config.service.ts`/`tenant`
(`keine-mandantengebundene-tabelle`, `ungebunden`),
`module-registry/module-access.service.ts`/`group` UND `/groupMembership`
(beide `muss-mandantengebunden`, `gebunden`),
`tenders/tender-digest.scheduler.ts`/`tender`
(`keine-mandantengebundene-tabelle`, `gebunden`) UND `/tenderSavedSearch`
(`muss-mandantengebunden`, `gebunden`),
`tenders/tenders.controller.ts`/`tenderSource`
(`keine-mandantengebundene-tabelle`, `ungebunden`). Drei Paare aendern ihren
Stand, eines davon zusaetzlich die Klasse:
`ldap-config.service.ts`/`ldapFieldMapping` wechselt von
`muss-mandantengebunden`/`gebunden` auf `beides`/`gemischt` — der
uebergreifende Planer-Lesepfad `getAllActiveConfigs()` reicht ueber
`include: { fieldMappings: true }` in `LdapFieldMapping` hinein, dieselbe
Unterabfrage-Form, die WINDOWS #27 aufgedeckt hat.
`module-registry.service.ts`/`module` und `tender-matching.service.ts`/
`tender` wechseln je von `ungebunden` auf `gemischt`, ihre Klasse bleibt.
Die Zahl 72 ist der Ausgabe von `rls-access-inventory.spec.ts` entnommen,
nicht geschaetzt.
| Klasse | Anzahl Paare |
|---|---|
| muss-mandantengebunden | 33 |
| keine-mandantengebundene-tabelle | 17 |
| beides | 13 |
| muss-mandantengebunden | 35 |
| keine-mandantengebundene-tabelle | 21 |
| beides | 14 |
| bewusst-uebergreifend | 2 |
| **Summe** | **65** |
| **Summe** | **72** |
## Der Hintergrunddienst als Falle — sechs Fälle
@@ -278,6 +320,19 @@ beim Start — mit einer zusätzlichen Verdeckungsschicht, siehe unten:
Zustand zum Zeitpunkt der ldap-Umstellung korrekt beschreibt und für
spätere Etappen als Beleg dient, siehe auch
`docs/mandantentrennung-etappe2-fehlerrichtung.md`, Abschnitt (e), Befund D.
**Nachtrag (260911-mkj):** WINDOWS #27 geschlossen — derselbe Bereich
`ldap` traegt
einen zweiten, bislang unsichtbaren Planer-Lesezugriff:
`LdapConfigService.getAllActiveConfigs()` (`ldap-config.service.ts`)
reicht ueber `include: { tenant: true, fieldMappings: true }` sowohl in
`Tenant` (schutzlos, harmlos) als auch in `LdapFieldMapping` (geschuetzt
ueber Join auf `LdapConfig`) hinein. Nach dem Scharfschalten verstummt
die Feldzuordnung mit der Elternzeile, nicht getrennt von ihr — der
Etappe-3-Systemkontext muss BEIDE Tabellen sehen. Die Bestandsaufnahme
fuehrt `ldapFieldMapping` deshalb seither als `beides`/`gemischt` statt
`muss-mandantengebunden`/`gebunden` (siehe Bestandsaufnahme unten,
`ldap-config.service.ts`/`ldapFieldMapping`).
- **`tender-digest.scheduler.ts`** (Ausschreibungs-Digest) — **Stand
260909-laa, Aufgabe 3: Je-Treffer-Hälfte geschlossen, übergreifende
Hälfte an Etappe 3 übergeben.** Liest `tenderMatch` (Kandidatenabfrage,