feat(laa-02): binde die fuenf Nutzer-CRUD-Dienste des Bereichs tenders an forTenant()
tender-saved-search.service.ts, tender-triage.service.ts, tender-notification-pref.service.ts und tender-email-config.service.ts laufen jetzt vollstaendig ueber forTenant() — vier neue Parameter (list, update, remove, listForUser, favoriteIds, getForUser, getConfigForApi, testConnection bekommen tenantId), die anwendungsseitige userId-Filterung bleibt unveraendert (Befund E: die Policies haben keine Benutzerdimension). tender-rss-feed.service.ts bindet nur createForUser (Zaehler + Anlage, beide ausschliesslich auf persoenlichen Zeilen); listForUser, createPlatform und remove bleiben mit Codekommentar bewusst ungebunden (WINDOWS #19 — eine gebundene plattformweite Zeile waere unter jedem Mandanten unsichtbar, ein gebundenes Einfuegen ohne Mandant wuerde abgewiesen). tender-notification-pref.service.ts und tender-email-config.service.ts uebersetzen eine P2002-Verletzung auf dem tenantlosen upsert-Schluessel (Befund F) in eine verstaendliche deutsche Meldung statt eines rohen Fehlers. tenders.controller.ts reicht tenantId an den acht betroffenen Aufrufstellen durch extractTriageContext() durch (kein neuer Aufloesungsweg); die drei RSS-Aufrufstellen bleiben unveraendert, da ihre Dienstmethoden nicht binden. Alle sieben angefassten Testdateien bekommen den Zwei-Client-Nachweis (__makeBoundClient ueber demselben Speicher) und Bindungstests je umgestellter Methode; tender-rss-feed.service.spec.ts zusaetzlich den Gegentest, dass die drei unveraendert bleibenden Pfade forTenant() NICHT aufrufen. Falsifiziert: ein probeweiser Rueckbau der list()-Bindung in tender-saved-search.service.ts machte genau den erwarteten Bindungstest rot, danach zurueckgenommen. docs/mandantentrennung-zugriffsklassifikation.md: Stand der fuenf Paare auf gebunden bzw. gemischt nachgezogen; tenderRssFeedSource von muss-mandantengebunden auf beides umklassifiziert (derselbe Praezedenzfall wie ldapConfig in 260909-ipc). 761 Tests gruen (743 + 18 neue Bindungsnachweise), Typpruefung sauber, Wegwerf-Werkzeug 32/32, kein Schema-/Migrations-/Compose-/ Umgebungsdatei-Diff. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AMASaSxv5QMY7RncqZriRR
This commit is contained in:
@@ -223,7 +223,7 @@ verwendet), Klasse, Stand (`gebunden`/`ungebunden`/`gemischt`, seit
|
||||
| apps/api/src/tenders/tender-digest.scheduler.ts | tenderMatch | beides | ungebunden | Ein einziger globaler Cron-Job liest über ALLE Mandanten (bewusst übergreifend, Pitfall-1-Kommentar im Dateikopf), der Versand je Treffer ist an dessen Mandanten gebunden. |
|
||||
| apps/api/src/tenders/tender-digest.scheduler.ts | tenderNotificationPref | beides | ungebunden | Dieselbe Begründung — Präferenzen werden über alle Mandanten gelesen, aber je Zeile mandantenbezogen ausgewertet. |
|
||||
| apps/api/src/tenders/tender-digest.scheduler.ts | user | beides | ungebunden | E-Mail-Adressen für den Versand werden über alle Mandanten gelesen, der eigentliche Versand ist je Treffer mandantengebunden. |
|
||||
| apps/api/src/tenders/tender-email-config.service.ts | tenderEmailConfig | muss-mandantengebunden | ungebunden | Nutzer-CRUD für die eigene Postfachanbindung (Phase 17, D-01) — anders als der Fan-out-Adapter oben, hier ist der Mandant aus der Anfrage bekannt. |
|
||||
| apps/api/src/tenders/tender-email-config.service.ts | tenderEmailConfig | muss-mandantengebunden | gebunden | Nutzer-CRUD für die eigene Postfachanbindung (Phase 17, D-01) — anders als der Fan-out-Adapter oben, hier ist der Mandant aus der Anfrage bekannt. Seit 260909-laa (Aufgabe 2) laufen `getConfigForApi` (beide Lesezugriffe), `saveConfig` und `testConnection` vollständig über `forTenant()`. |
|
||||
| apps/api/src/tenders/tender-fingerprint-backfill.service.ts | tender | keine-mandantengebundene-tabelle | ungebunden | Einmaliges Backfill-Skript über den plattformweiten `Tender`-Katalog (D-03). |
|
||||
| apps/api/src/tenders/tender-ingestion.service.ts | tender | keine-mandantengebundene-tabelle | ungebunden | Explizit im Dateikopf: "Multi-tenant safety (D-03, T-10-09): uses the plain, non-tenant-scoped ... queries ... these are platform-global". |
|
||||
| apps/api/src/tenders/tender-ingestion.service.ts | tenderSourcePollConfig | keine-mandantengebundene-tabelle | ungebunden | Plattformweiter Poll-Status, kein `tenantId` (Migration 20260909140000, Gruppe b). |
|
||||
@@ -231,11 +231,11 @@ verwendet), Klasse, Stand (`gebunden`/`ungebunden`/`gemischt`, seit
|
||||
| apps/api/src/tenders/tender-matching.service.ts | tenderMatch | beides | ungebunden | Sofortmeldung: Treffer über alle betroffenen Mandanten gelesen, Versand je Treffer mandantengebunden — siehe Abschnitt "Der Hintergrunddienst als Falle". |
|
||||
| apps/api/src/tenders/tender-matching.service.ts | tenderSavedSearch | beides | ungebunden | Dieselbe Begründung — gespeicherte Suchprofile aller Mandanten werden gegen neue Treffer geprüft, der Versand ist je Profil mandantengebunden. |
|
||||
| apps/api/src/tenders/tender-matching.service.ts | user | beides | ungebunden | Dieselbe Begründung — E-Mail-Adressen für die Sofortmeldung. |
|
||||
| apps/api/src/tenders/tender-notification-pref.service.ts | tenderNotificationPref | muss-mandantengebunden | ungebunden | Nutzer-CRUD für die eigenen Benachrichtigungseinstellungen — Mandant aus der Anfrage bekannt. |
|
||||
| apps/api/src/tenders/tender-rss-feed.service.ts | tenderRssFeedSource | muss-mandantengebunden | ungebunden | Nutzer-CRUD für die eigenen RSS-Quellen (anders als der Fan-out in `adapters/rss.adapter.ts`) — Mandant aus der Anfrage bekannt. WINDOWS #19 betrifft die nullbaren plattformweiten Zeilen, nicht diesen CRUD-Pfad. |
|
||||
| apps/api/src/tenders/tender-saved-search.service.ts | tenderSavedSearch | muss-mandantengebunden | ungebunden | Nutzer-CRUD für die eigenen gespeicherten Suchprofile — Mandant aus der Anfrage bekannt. |
|
||||
| apps/api/src/tenders/tender-notification-pref.service.ts | tenderNotificationPref | muss-mandantengebunden | gebunden | Nutzer-CRUD für die eigenen Benachrichtigungseinstellungen — Mandant aus der Anfrage bekannt. Seit 260909-laa (Aufgabe 2) laufen `getForUser`/`setForUser` vollständig über `forTenant()`; `setForUser` übersetzt eine P2002-Verletzung (Befund F) in eine verständliche deutsche Meldung. |
|
||||
| apps/api/src/tenders/tender-rss-feed.service.ts | tenderRssFeedSource | beides | gemischt | Nutzer-CRUD für die eigenen RSS-Quellen (anders als der Fan-out in `adapters/rss.adapter.ts`). Seit 260909-laa (Aufgabe 2) bindet `createForUser` (Zähler + Anlage, beide ausschließlich auf persönlichen Zeilen mit gesetztem Mandanten) über `forTenant()`; `listForUser`/`createPlatform`/`remove` bleiben bewusst ungebunden, weil sie (auch) die nullbare, plattformweite Zeile berühren (WINDOWS #19, Aufgabe 1 gemessen: eine gebundene Zeile wäre unter jedem Mandanten unsichtbar bzw. ein gebundenes Einfügen ohne Mandant würde abgewiesen). Korrektur der Klasse von `muss-mandantengebunden` auf `beides`, keine Verhaltensänderung — derselbe Präzedenzfall wie `ldapConfig` in 260909-ipc. |
|
||||
| apps/api/src/tenders/tender-saved-search.service.ts | tenderSavedSearch | muss-mandantengebunden | gebunden | Nutzer-CRUD für die eigenen gespeicherten Suchprofile — Mandant aus der Anfrage bekannt. Seit 260909-laa (Aufgabe 2) laufen `list`/`create`/`update`/`remove` vollständig über `forTenant()`. |
|
||||
| apps/api/src/tenders/tender-scheduler.service.ts | tenderSourcePollConfig | keine-mandantengebundene-tabelle | ungebunden | Plattformweiter DÖE-Poll-Status, kein `tenantId` — im Dateikopf explizit als "genuine platform-wide singleton" begründet. |
|
||||
| apps/api/src/tenders/tender-triage.service.ts | tenderTriage | muss-mandantengebunden | ungebunden | Favorisierungs-/Ablehnungsstatus eines Nutzers, `tenantId`-Spalte vorhanden. |
|
||||
| apps/api/src/tenders/tender-triage.service.ts | tenderTriage | muss-mandantengebunden | gebunden | Favorisierungs-/Ablehnungsstatus eines Nutzers, `tenantId`-Spalte vorhanden. Seit 260909-laa (Aufgabe 2) laufen `setTriage`/`listForUser`/`favoriteIds` vollständig über `forTenant()`. |
|
||||
| apps/api/src/tenders/tenders.controller.ts | tender | keine-mandantengebundene-tabelle | ungebunden | Lesezugriff auf den plattformweiten Katalog (D-03). |
|
||||
| apps/api/src/tenders/tenders.controller.ts | tenderSourcePollConfig | keine-mandantengebundene-tabelle | ungebunden | Plattformweiter Poll-Status, admin-verwaltet, kein `tenantId`. |
|
||||
| apps/api/src/tenders/tenders.module.ts | tenderSourcePollConfig | keine-mandantengebundene-tabelle | ungebunden | Singleton-Bestückung beim Boot — im Dateikopf explizit als "global, RLS-exempt (D-03)" begründet. |
|
||||
|
||||
Reference in New Issue
Block a user