docs(quick-260911-mkj): WINDOWS #27 geschlossen und verifiziert
This commit is contained in:
+2
-1
@@ -390,6 +390,7 @@ None yet.
|
||||
| 260911-e2s | Mandantentrennung Etappe 2, Bereich tenant — von anderer Art: alle 8 Zugriffe gehen auf die Mandantentabelle SELBST, die per Definition keinen Mandanten hat. **'Nichts zu binden' war trotzdem falsch, und der Grund ist der wichtigste Fund seit dem kaputten Helfer in Etappe 1:** drei der acht Zugriffe (`findAll`, `findOne`, `remove` im Controller) zaehlen ueber `include: { _count: { select: { users } } }` in die GESCHUETZTE Tabelle `User` hinein — Prisma 6.19 rendert das als `LEFT JOIN (SELECT tenantId, COUNT(*) FROM User ...)`, das unter DEREN Regel laeuft. Nach dem Scharfschalten haette die Mandantenliste des Plattform-Admins fuer jeden Mandanten 0 Benutzer gezeigt, und der Loeschriegel T-02-09 waere vakuum geworden (der Fremdschluessel faengt es noch, aber als 500 statt 400). Behoben per Fan-out je Mandant ueber gebundenen Client, Muster aus `UserService.findAllForPlatformAdmin`. **Die Bestandsaufnahme ist fuer Relationszugriffe strukturell blind** — sie sieht nur `this.prisma.<Modell>`, nicht was ein `include:` in eine zweite Tabelle hineinrechnet. Alle 19 `include:`-Stellen und alle `_count`-Stellen einzeln beurteilt, vom Orchestrator UND vom Verifizierer unabhaengig gegengeprueft (der Plan-Pruefer hatte diesen Punkt als 'plausibel' durchgewinkt statt ihn zu pruefen): nur diese drei waren gefaehrlich. Der MECHANISMUS bleibt offen und ist als WINDOWS #27 festgehalten — der Planer wollte keinen Eintrag, weil die Instanz behoben ist; Orchestrator und Verifizierer sahen das anders, weil eine Luecke im Messwerkzeug, die nachweislich einen echten Defekt verborgen hat, genau dafuer ins Ledger gehoert. **Die seit Etappe 1 offene Architekturfrage ist entschieden:** `req.tenantPrisma` wurde bei jeder Anfrage gebaut und NIRGENDS gelesen; neun Bereiche haben die Konvention auf dienst-internes `forTenant()` festgelegt. Middleware geloescht (sie war nirgends registriert — der Auftrag irrte bei `app.module.ts:57`, dort ist der Guard verdrahtet), Guard ohne Prisma-Abhaengigkeit, setzt nur noch `req.tenantId` (22 Leser in 9 Dateien) und den `x-tenant-id`-Wechsel fuer SUPER_ADMIN (4 Frontend-Stellen) — beides erstmals getestet; Guard und Middleware hatten NIE Tests, 'ihre Tests' in Etappe 1 war eine Annahme. Totes Kabel, das wie eine Sicherung aussieht, ist schlimmer als keins. Ausnahmeliste in `rls-access-inventory.spec.ts` geleert und mit Wachhund versehen. Drei Kommentare berichtigt, die `TenantMiddleware`/`req.tenantPrisma` als lebendig beschrieben. Executor fing einen still fehlgeschlagenen `git add` (2 von 7 Dateien) selbst an `git status` und lieferte nach. **Verifiziert 10/10 mit vier eigenhaendigen Falsifizierungen** (Header-Wechsel zweimal gebrochen, Fan-out gebrochen, Wachhund ausgeloest — je exakt die benannten Tests rot; 911/911 Tests, 59 Dateien, Typpruefung sauber, 110/110 Live-Pruefungen; 64 Paare und Klassenverteilung 32/17/13/2 nachgerechnet) | 2026-09-11 | 652e762,11f5731,17dca0d,c8de72e | [260911-e2s-mandantentrennung-etappe-2-bereich-tenan](./quick/260911-e2s-mandantentrennung-etappe-2-bereich-tenan/) |
|
||||
| 260911-fh9 | Mandantentrennung Etappe 2, Bereich auth — die drei in Etappe 1 bewusst ausgelassenen Wege (`getMe`, `changePassword`, `adminResetPassword`) gebunden, alle drei brauchten neue Signaturen (nahmen nur `userId`). Der Anmeldeweg ueber die drei SECURITY-DEFINER-Funktionen NICHT angefasst, per `pg_proc` belegt (weiterhin genau 9 Spalten, auch nachdem die Wegwerf-Tabelle `User` 5 fehlende Spalten bekam). Verbleibende 3 'ungebundene' Stellen sind die `$queryRaw`-Anmeldesuchen, keine Modellzugriffe. **Falle, die der Auftrag selbst gestellt hatte:** Selbstbedienung darf NICHT an `req.tenantId` binden — der Guard laesst SUPER_ADMIN diese Kennung per `x-tenant-id` umschalten (Marktplatz), 'mein Profil' haette ihn sich selbst gegenueber unsichtbar gemacht; gebunden wird an den Mandanten aus dem Sitzungsnachweis (`@CurrentUser().tenantId`), der Controller enthaelt null Verweise auf `req.tenantId`/`x-tenant-id`. **Zwei Loecher in `adminResetPassword` geschlossen, keines davon ein Mandantenproblem:** der Weg pruefte weder den Mandanten des Ziels noch dessen Rolle — ein ADMIN konnte das Passwort eines SUPER_ADMIN ueberschreiben. Beides jetzt dicht, SUPER_ADMIN-Pfad ueber `UserService.findByIdForPlatformAdmin`; `AuthModule` importiert `UserModule`, zyklusfrei. Der Schwesterweg `PATCH /users/:id` hat dieselbe Rollenluecke (T-02-08 prueft nur das ZUWEISEN der Rolle, nicht die bestehende Rolle des Ziels) — ausserhalb der Erlaubnisliste, als WINDOWS #29 festgehalten. **Umgekehrte Fehlerrichtung ist hier leise, nicht laut:** `getMe`-Leere wird zu 200 mit leerem Rumpf, `header.tsx` tut bei `if (u)` nichts — 'nicht angemeldet' und 'Zeile unsichtbar' sind derselbe Wert (WINDOWS #28); `changePassword`-Leere liest sich als `networkError`. Identitaets-Attrappe (ldap-Form) durch asymmetrischen Doppel ersetzt: ungebundener Nachbau ohne Modelle, gebundener ohne `$queryRaw` — beide Grenzen einzeln falsifizierbar. **Verifiziert 8/8** (951/951 Tests, 60 Dateien, Typpruefung sauber, 120/120 Live-Pruefungen; zwei Falsifizierungen vom Pruefer eigenhaendig reproduziert — genau 4 bzw. 2 benannte Tests rot) | 2026-09-11 | 9782bea,92aa8c4,f68beb3 | [260911-fh9-mandantentrennung-etappe-2-bereich-auth-](./quick/260911-fh9-mandantentrennung-etappe-2-bereich-auth-/) |
|
||||
| 260911-gwh | **Mandantentrennung Etappe 2, Bereiche favorites + settings — LETZTER Durchlauf, Etappe 2 abgeschlossen.** 7 `favoriteLink`-Zugriffe und 3 `smtpConfig`-Anfragepfade gebunden; genau ein `smtpConfig`-Zugriff bleibt bewusst offen: der Startpfad, umbenannt in `loadAnySmtpConfigForStartupTransport()` — SECHSTER Fall der Hintergrunddienst-Falle (`findFirst()` ohne Mandanten beim Hochfahren in `mail.module.ts`; heute bedient er einen willkuerlichen Mandanten, nach dem Scharfschalten null), beide Zustaende am Ort, WINDOWS #30. **Befund K geschlossen:** `getDecryptedSmtpConfig(tenantId)` bindet — die Reihenfolgebedingung fuer Etappe 4 aus dem tenders-Lauf ist erfuellt und in Kritikschrift (t4)/(d4) und Klassifikation als erfuellt vermerkt. **Widget-Besitzriegel in `favorites.create()` eingebaut, weil GEMESSEN noetig:** Pruefung 7 zeigt, dass ein gebundenes Anlegen mit fremder `widgetId` GELINGT — die Fremdschluessel-Pruefung umgeht den Zeilenschutz; vom Verifizierer live reproduziert und der Riegel durch Rueckbau falsifiziert (genau 4 Tests rot). Beide Bereiche hatten keine Testdatei fuer ihren Dienst; `favorites.service.spec.ts` (23) und `settings.service.spec.ts` (20) neu, `nodemailer` gemockt. Ledger #31/#32 fuer die stille Leere (leere Favoritenleiste = 'nie etwas gespeichert'; fehlende SMTP-Konfiguration = 'nicht eingerichtet', obwohl die Zugangsdaten da sind). Der Planer scheiterte am Sitzungslimit NACH dem Schreiben des Plans, VOR der Rueckmeldung — Plan lag vollstaendig auf der Platte (1226 Zeilen, Struktur gueltig), vom Orchestrator committet, vom Pruefer als Erstleser gegen den Baum gehalten. **Verifiziert 9/9** (994/994 Tests, 62 Dateien, Typpruefung sauber, 137/137 Live-Pruefungen; Uebersicht 68/178, Klassenverteilung 33+17+13+2=65 und Migrations-Zaehlung 4+3+16=23 vom Pruefer nachgerechnet) | 2026-09-11 | 88896d3,8f2c13a,b5f22e2,1240932 | [260911-gwh-mandantentrennung-etappe-2-bereiche-favo](./quick/260911-gwh-mandantentrennung-etappe-2-bereiche-favo/) |
|
||||
| 260911-mkj | **WINDOWS #27 geschlossen — die Bestandsaufnahme sieht jetzt Relationszugriffe.** Vierte Erkennungsform in `rls-access-inventory.spec.ts`: `include:`/`select:`/`_count:` werden ueber `schema.prisma` (zur Testzeit gelesen) auf das Zielmodell aufgeloest und als (Datei, Modell)-Fundstelle gefuehrt, gebunden oder ungebunden je nach umschliessendem Klienten. Zwei Wachhunde, die LAUT werden statt still: Empfaenger ausserhalb der vier Formen (raw vs. matched) und nicht aufloesbare Konstanten — beide vom Verifizierer live gebrochen und rot gesehen. Gemessen mit Prototyp, Vorhersage exakt getroffen: 7 neue Paare, 3 Stand-Aenderungen, eine Klassenaenderung (`ldap-config.service.ts`/`ldapFieldMapping` -> `beides`/`gemischt`, weil `getAllActiveConfigs()` ueber `include: { fieldMappings }` in die geschuetzte Tabelle reicht — genau die #27-Form, bisher unsichtbar, kein neuer Gefahrenfall). Klassifikation 65 -> 72 Paare (35/21/14/2). Acht gepinnte Proben, darunter die beiden #27-Formen (`_count.select.users` auf `this.prisma.tenant` -> `user` ungebunden; auf gebundenem Klienten -> gebunden). **Zwei Dateien standen in KEINER Erkennungsform** (`tenders.seed.ts` mit Client als Funktionsparameter, `backfill-tender-source.ts` mit eigenem `new PrismaClient()`) — heute harmlos, als WINDOWS #33 eigenstaendig festgehalten statt still in #27 mitgeschlossen. Planer fing einen Fehler im eigenen Prototyp (Lookahead beim Schema-Parsen, ohne den alle Listenrelationen am Zeilenende verloren gingen). **Verifiziert 6/6** (1007/1007 Tests, Typpruefung sauber, nur die Spec unter `apps/api/src` angefasst). Info vom Pruefer: der Lookahead ist nicht durch einen eigenen Regressionstest gedeckt — der raw/matched-Wachhund ist der eigentliche Schutz | 2026-09-11 | 5ad23d0,388690f | [260911-mkj-windows-27-schliessen-relations-blindste](./quick/260911-mkj-windows-27-schliessen-relations-blindste/) |
|
||||
| 260909-eor | Etappe 1 der Mandantentrennung: Anmeldeweg mandantenfaehig gemacht und alle Zugriffe klassifiziert. **Kernfund (#20):** `forTenant()` setzte den Mandantenkontext per set_config auf der Transaktionsverbindung, dispatchte die Abfrage aber ueber den aeusseren Client — empirisch reproduziert (set_config auf Backend-PID 254999, Abfrage auf 255000, Kontext dort NULL). Die Trennung hat damit nie funktioniert, auch nicht an den Stellen, die sie scheinbar nutzten; nach dem Scharfschalten haetten diese Abfragen NULL Zeilen geliefert, was der LDAP-Loeschzweig als 'Gruppe im Verzeichnis verschwunden' gedeutet und geloescht haette. Behoben und live nachgewiesen. Der Anmeldeweg bekam drei SECURITY-DEFINER-Funktionen als schmale Ausnahme (feste Spaltenliste, Gleichheitsbedingung, LIMIT 1) — eine Policy haette nicht gereicht, weil sie zwangslaeufig die ganze Tabelle freigibt. Browser-Gegenprobe lokal bestanden: Anmeldung laedt das Portal, falsches Kennwort verraet weiterhin nicht welches Feld, Kennwort-vergessen laeuft durch (der einzige Protokollfehler war ein lokal fehlender Mailserver, also NACH dem Datenbankzugriff). Klassifikation aller 227 Zugriffe in 59 Einheiten, maschinell gegen Abdriften abgesichert: 31 muessen mandantengebunden werden, 9 teilweise, 16 betreffen keine mandantengebundene Tabelle, 3 bleiben bewusst uebergreifend. 701 Tests gruen | 2026-09-09 | da0ac04 | [260909-eor-anmeldeweg-mandantenfaehig-machen-und-al](./quick/260909-eor-anmeldeweg-mandantenfaehig-machen-und-al/) |
|
||||
| 260910-jab | Die drei zu kurz greifenden Datenbankregeln geschlossen — T-JTS-02, T-JTS-03, WINDOWS #19 (bewusste Reihenfolge-Abweichung, vorgezogen auf Nutzerwunsch, statt wie geplant nach Etappe 2). Neue, handgeschriebene, lokal angewandte Migration `20260910120000_rls_widen_membership_grant_and_platform_read`: `GroupMembership` prueft jetzt beide Seiten der Beziehung (Gruppe UND Benutzer), `ModuleGrant` prueft zusaetzlich beide moeglichen Ziele mit Leer-Zulassung (D-04), `TenderRssFeedSource` bekommt vier nach Befehl getrennte Regeln (Lesen schliesst plattformweite Zeilen ein, Schreiben verlangt weiterhin einen Mandanten — die Trennung ist noetig, weil ein einzelner USING-Ausdruck sonst auch UPDATE/DELETE mitregelt). `SearchProvider` bewusst NICHT angefasst: die WINDOWS-#19-Praemisse ist fuer dieses Modell widerlegt (kein Codeweg erzeugt eine mandantenlose Zeile). Drei loch-behauptende Pruefungen im Wegwerf-Werkzeug UMGEKEHRT statt geloescht (66→74 Pruefungen), mit Verweis auf die alten Pruefungsnamen und Befundkennungen im Meldetext. Genau EIN Anwendungspfad musste mitgebunden werden (`TenderRssFeedSourceService.listForUser`) — sonst haette die Reparatur ihn still von 'liefert nach dem Scharfschalten nichts' auf 'liefert nur die plattformweiten Zeilen, taeuscht Vollstaendigkeit vor' verschlechtert; Falsifizierungsnachweis gefuehrt (Bindung zurueckgenommen, genau ein Test rot, zurueckgesetzt). WINDOWS #19 geschlossen mit Beleg, WINDOWS #24 neu angelegt (Verwaltungsweg fuer plattformweite Zeilen unter der Anwendungsrolle fehlt weiterhin — verschwindet nicht mit #19). Aktenstand kohaerent: Klassifikation, Kritikschrift (neuer Abschnitt "Regelschluss T-JTS-02, T-JTS-03 und WINDOWS #19" mit Signaltabelle beider Fehlerrichtungen je Regel), Betriebsanleitung, WINDOWS.md — fuenf ueberholte Bestandsstellen mit Nachtraegen versehen, alte Messprotokolle bleiben woertlich stehen. Selbst gemessen statt uebernommen: Baseline 833/56 Tests, 66/66 Live-Pruefungen; Endstand 839/56, 74/74; keine zweite Sitzungsvariable fuer den Benutzer gefunden (nur `app.current_tenant`). Rule-1-Fix: implizites `any` in `tenders.controller.ts` nach der Bindung behoben. `npx prisma` versuchte ungefragt Prisma 8 herunterzuladen — abgebrochen, lokale gepinnte 6.19.3 verwendet | 2026-09-10 | f4f3115,6b23735,03fb3bf | [260910-jab-mandantentrennung-die-drei-zu-kurz-greif](./quick/260910-jab-mandantentrennung-die-drei-zu-kurz-greif/) |
|
||||
|
||||
@@ -433,6 +434,6 @@ sind. Kein Anlass, sie vorher erneut vorzulegen.
|
||||
|
||||
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.
|
||||
Stopped at: **ETAPPE 2 DER MANDANTENTRENNUNG ABGESCHLOSSEN (2026-09-11).** Alle zwoelf Bereiche umgestellt und einzeln verifiziert: ldap 7/7, groups 9/9, tenders 8/9+Fix, dkv 9/9, user 10/10, module-registry 9/9, dashboard 10/11+Fix, calendar 12/12, tenant 10/10, auth 8/8, favorites+settings 9/9; dazu die drei Datenbankregeln (260910-jab, 11/11). Endstand: 994 Tests in 62 Dateien (Ausgang 701/53), 137 Live-Pruefungen gegen die Wegwerf-Datenbank (Ausgang 8), Klassifikation 65 Paare / 68 ungebunden / 178 gebunden — jeder ungebundene Zugriff liegt auf einer plattformglobalen Tabelle oder einem benannten Startpfad, keiner aus Versehen. Alles gepusht. DER SCHALTER IST WEITER AUS. NAECHSTE SCHRITTE: (A) ETAPPE 3 — die zwei Produktentscheidungen des Users vom 2026-09-10: Anmeldenamen pro Mandant (Schema `@@unique([tenantId, username/email])`, Anmeldeweg muss den Mandanten VOR der Suche kennen, SECURITY-DEFINER-Funktionen mit zwei Gleichheitsbedingungen) und Benutzerdimension in den Regeln (zweite Sitzungsvariable `app.current_user`/`current_user_id()`, forTenant() um userId erweitern, Regeln der zehn nutzerbezogenen Tabellen). Dazu Systemkontext fuer die sechs Hintergrunddienst-Faelle (#21, #30 und die vier `beides`-Uebergaben aus tenders/ldap). (B) VOR ETAPPE 4 ZWINGEND: WINDOWS #27 (Relations-Blindstelle der Bestandsaufnahme) schliessen — sonst stuetzt sich die Vorabpruefung auf ein Werkzeug, das `include:`/`_count:` in fremde Tabellen nicht sieht. (C) ETAPPE 4 — Scharfschalten mit rls-preflight.mjs; die Vorabpruefung muss die stillen Leere-Faelle #23/#25/#26/#28/#31/#32 abdecken. DER USER HAT AUSDRUECKLICH GESAGT: beim Scharfschalten anhalten und fragen. Ledger: 14 offen von 32.
|
||||
Stopped at: **ETAPPE 2 DER MANDANTENTRENNUNG ABGESCHLOSSEN (2026-09-11).** Alle zwoelf Bereiche umgestellt und einzeln verifiziert: ldap 7/7, groups 9/9, tenders 8/9+Fix, dkv 9/9, user 10/10, module-registry 9/9, dashboard 10/11+Fix, calendar 12/12, tenant 10/10, auth 8/8, favorites+settings 9/9; dazu die drei Datenbankregeln (260910-jab, 11/11). Endstand: 994 Tests in 62 Dateien (Ausgang 701/53), 137 Live-Pruefungen gegen die Wegwerf-Datenbank (Ausgang 8), Klassifikation 65 Paare / 68 ungebunden / 178 gebunden — jeder ungebundene Zugriff liegt auf einer plattformglobalen Tabelle oder einem benannten Startpfad, keiner aus Versehen. Alles gepusht. DER SCHALTER IST WEITER AUS. NAECHSTE SCHRITTE: (A) ETAPPE 3 — die zwei Produktentscheidungen des Users vom 2026-09-10: Anmeldenamen pro Mandant (Schema `@@unique([tenantId, username/email])`, Anmeldeweg muss den Mandanten VOR der Suche kennen, SECURITY-DEFINER-Funktionen mit zwei Gleichheitsbedingungen) und Benutzerdimension in den Regeln (zweite Sitzungsvariable `app.current_user`/`current_user_id()`, forTenant() um userId erweitern, Regeln der zehn nutzerbezogenen Tabellen). Dazu Systemkontext fuer die sechs Hintergrunddienst-Faelle (#21, #30 und die vier `beides`-Uebergaben aus tenders/ldap). (B) WINDOWS #27 ist GESCHLOSSEN (260911-mkj) — die Bestandsaufnahme sieht Relationszugriffe, 72 Paare. (C) ETAPPE 4 — Scharfschalten mit rls-preflight.mjs; die Vorabpruefung muss die stillen Leere-Faelle #23/#25/#26/#28/#31/#32 abdecken. DER USER HAT AUSDRUECKLICH GESAGT: beim Scharfschalten anhalten und fragen. Ledger: 14 offen von 33. VOLLSTAENDIGER ETAPPE-3-AUFTRAG: docs/mandantentrennung-etappe3-auftrag.md (Reihenfolge 3b Benutzerdimension -> 3a Anmeldenamen -> 3c Systemkontext; 3a enthaelt die eine offene Produktfrage; nichts davon blockiert das Live-Gehen am Dienstag 2026-09-15).
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user