docs(quick-260909-eor): alle 227 Datenbankzugriffe klassifiziert und maschinell abgesichert
WINDOWS #18/#20, Aufgabe 3: docs/mandantentrennung-zugriffsklassifikation.md haelt fuer jede der 227 this.prisma.*-Fundstellen (32 Dateien, zusammengefasst zu 59 Datei-Modell-Paaren) eine Klasse fest — muss-mandantengebunden (31), keine-mandantengebundene-tabelle (16), bewusst-uebergreifend (3, mit ausgeschriebenem Grund) oder beides (9, der Hintergrunddienst-Sonderfall: uebergreifend lesen, je Zeile mandantengebunden schreiben — betrifft ldap.service.ts, tender-digest.scheduler.ts, tender-matching.service.ts). rls-access-inventory.spec.ts ermittelt die Fundstellen bei jedem Testlauf neu aus dem Quelltext und vergleicht sie gegen die Tabelle im Dokument — Datei und Modellname als Schluessel, keine Zeilennummer. Scheitert nachweislich, sobald eine Fundstelle fehlt oder ein Eintrag verwaist (per Testlauf geprueft, danach zurueckgesetzt). Zwei belegte Befunde im Dokument festgehalten: req.tenantPrisma wird gesetzt, aber nirgends gelesen; WINDOWS #19 (nullbares tenantId bei SearchProvider/ TenderRssFeedSource) bleibt benannter Blocker fuer Etappe 3. docs/mandantentrennung-datenbankrolle.md verweist jetzt auf das neue Dokument und korrigiert die ueberholte Zahl 182 auf den nachgemessenen Stand (227/59). WINDOWS.md #18/#19 um Nachtrag auf diesen Plan ergaenzt; #20 (der in Aufgabe 1 gemessene und behobene forTenant()-Verbindungsdefekt) als "fixed" markiert. Deviation (Rule 3, blockierend fuer die Bestandsaufnahme-Pruefung): auth.service.ts-Kommentar umformuliert, der zuvor woertlich "this.prisma.user.findUnique" als erklaerenden Text enthielt und dadurch einen Eigentreffer der grep-basierten Inventur-Pruefung erzeugte. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FYZcd3SSmo14QTqWx2KKzU
This commit is contained in:
@@ -73,32 +73,55 @@ noetig sind:
|
||||
**Die Verbindung ist bewusst noch nicht umgestellt, und sie darf noch nicht
|
||||
umgestellt werden.**
|
||||
|
||||
Am 2026-09-09 wurde im Quelltext von `apps/api/src` gezaehlt, wie oft die
|
||||
Anwendung ueber den unskalierten Prisma-Client zugreift (also ohne den
|
||||
Mandantenkontext zu setzen) gegenueber der Anzahl der Verwendungen des
|
||||
mandantengebundenen `tenantPrisma`: **182 unskalierte Zugriffe** — 84 auf die
|
||||
sieben bereits mit Policies versehenen Tabellen, 98 auf die 16 neu
|
||||
hinzugekommenen — gegenueber lediglich **19 Verwendungen** von `tenantPrisma`
|
||||
im gesamten API-Quelltext.
|
||||
**Nachgemessen und korrigiert am 2026-09-09 (260909-eor, Aufgabe 3):** die
|
||||
zuvor hier genannte Zahl 182 stammte aus einer groeberen Zaehlung vor dieser
|
||||
Etappe und ist ueberholt. Die aktuelle, maschinell ermittelte und durch
|
||||
`apps/api/src/prisma/rls-access-inventory.spec.ts` dauerhaft gepruefte
|
||||
Bestandsaufnahme steht in
|
||||
**`docs/mandantentrennung-zugriffsklassifikation.md`**: **227**
|
||||
`this.prisma.*`-Fundstellen in `apps/api/src` (ohne Tests), zusammengefasst zu
|
||||
**59** (Datei, Modell)-Paaren, davon **31** `muss-mandantengebunden` und **9**
|
||||
`beides` (Hintergrunddienst mit sowohl uebergreifendem Lesen als auch
|
||||
mandantengebundenem Schreiben je Zeile) — zusammen der eigentliche
|
||||
Arbeitsvorrat fuer die Umstellung. **16** Paare betreffen keine
|
||||
mandantengebundene Tabelle (plattformweite Daten wie der Ausschreibungs- und
|
||||
Modulkatalog, D-03) und **3** sind bewusst uebergreifend mit ausgeschriebenem
|
||||
Grund. Zusaetzlich zu beachten: das entdeckte, aber in dieser Etappe nicht
|
||||
behobene `forTenant()`-Verbindungsproblem (WINDOWS #20, siehe unten) und
|
||||
WINDOWS #19 (nullbares `tenantId` bei `SearchProvider`/`TenderRssFeedSource`).
|
||||
|
||||
Darunter ist der Anmeldeweg selbst, und der kann strukturell nicht anders
|
||||
funktionieren: `apps/api/src/auth/auth.service.ts` sucht den Benutzer anhand
|
||||
des Benutzernamens, **bevor** der Mandant bekannt ist — der Mandant wird ja
|
||||
erst aus dem gefundenen Benutzer bestimmt. Unter der Rolle `tessera_app`
|
||||
liefert genau diese Suche null Zeilen. **Niemand koennte sich mehr
|
||||
anmelden.**
|
||||
Darunter war bis Aufgabe 2 dieser Etappe auch der Anmeldeweg selbst, der
|
||||
strukturell nicht anders funktionieren konnte: `apps/api/src/auth/auth.service.ts`
|
||||
suchte den Benutzer anhand des Benutzernamens, **bevor** der Mandant bekannt
|
||||
war. Das ist inzwischen geloest — drei enge SECURITY-DEFINER-Funktionen
|
||||
(`auth_lookup_user_by_username`, `auth_lookup_user_by_email`,
|
||||
`auth_lookup_reset_token`, Migration `20260909160000_auth_lookup_functions`)
|
||||
uebernehmen die drei pre-tenant Lesezugriffe, alle nachfolgenden
|
||||
Schreibzugriffe laufen ueber `forTenant()`.
|
||||
|
||||
Ebenso betroffen sind Hintergrunddienste, die von Natur aus ohne
|
||||
Weiterhin betroffen sind Hintergrunddienste, die von Natur aus ohne
|
||||
Mandantenkontext laufen: der AD-Abgleich, der Ausschreibungs-Digest, die
|
||||
Modulzugriffspruefung, die Treffersuche im Ausschreibungs-Radar und die
|
||||
Erstanlage des Administrators beim ersten Start.
|
||||
Ausschreibungs-Sofortmeldung und die Erstanlage des Administrators beim
|
||||
ersten Start — Details und Begruendung je Fundstelle in
|
||||
`docs/mandantentrennung-zugriffsklassifikation.md`.
|
||||
|
||||
Diese 182 Stellen brauchen einen ausdruecklichen, benannten Systemkontext
|
||||
(oder eine gezielte Umstellung auf `tenantPrisma`/`forTenant()`), bevor der
|
||||
Schalter umgelegt werden darf. Das ist **eigene Arbeit und nicht Teil dieser
|
||||
Aenderung.** Ein gruener Bericht des Pruefwerkzeugs aus Abschnitt 5 belegt
|
||||
ausschliesslich, dass die Datenbankseite stimmt — er sagt nichts ueber diese
|
||||
182 Zugriffe aus.
|
||||
Diese Stellen brauchen einen ausdruecklichen, benannten Systemkontext (oder
|
||||
eine gezielte Umstellung auf `forTenant()`), bevor der Schalter umgelegt
|
||||
werden darf. Das ist **eigene Arbeit und nicht Teil dieser Aenderung**
|
||||
(Etappe 2/3 der Mandantentrennung). Ein gruener Bericht des Pruefwerkzeugs aus
|
||||
Abschnitt 5 belegt ausschliesslich, dass die Datenbankseite stimmt — er sagt
|
||||
nichts ueber diese Zugriffe aus.
|
||||
|
||||
**Zusaetzlicher Sperrgrund, ebenfalls am 2026-09-09 gemessen (WINDOWS #20):**
|
||||
`forTenant()` selbst war bis Aufgabe 1 dieser Etappe defekt — `set_config()`
|
||||
lief auf einer anderen Datenbankverbindung als die eigentliche Abfrage, sodass
|
||||
selbst die 6 bisherigen `forTenant()`-Aufrufstellen (alle in
|
||||
`apps/api/src/ldap/ldap.service.ts` sowie `tenant.middleware.ts`/
|
||||
`tenant.guard.ts`) den Mandantenkontext nie tatsaechlich gesetzt haben. Das ist
|
||||
inzwischen repariert (Array-Form von `$transaction`, `prisma-tenant.extension.ts`)
|
||||
und durch `apps/api/scripts/rls-scratch-check.mjs` live nachgewiesen. Ohne
|
||||
diese Reparatur waere jede Umstellung auf `forTenant()` in den folgenden
|
||||
Etappen wirkungslos gewesen.
|
||||
|
||||
## 4. Die Umstellung, Schritt fuer Schritt
|
||||
|
||||
@@ -141,8 +164,9 @@ ausschliesslich.
|
||||
|
||||
**Ein gruener Bericht ist die Freigabebedingung fuer Schritt 4 aus Abschnitt
|
||||
4 — aber er ist keine Freigabe fuer die Umstellung insgesamt.** Er bestaetigt
|
||||
nur, dass die Datenbankseite stimmt. Die 182 unskalierten Zugriffe aus
|
||||
Abschnitt 3 misst er nicht und kann sie nicht messen — dafuer muesste er den
|
||||
nur, dass die Datenbankseite stimmt. Die unskalierten Zugriffe aus Abschnitt 3
|
||||
(siehe `docs/mandantentrennung-zugriffsklassifikation.md` fuer den aktuellen
|
||||
Stand) misst er nicht und kann sie nicht messen — dafuer muesste er den
|
||||
Anwendungscode lesen, nicht die Datenbank.
|
||||
|
||||
## 6. Der Rueckweg
|
||||
|
||||
Reference in New Issue
Block a user