findAll/findOne/remove zaehlen Benutzer je Mandant jetzt ueber drei
gebundene Aufrufstellen (tenantPrisma.user.count mit where: { tenantId
}, in remove zusaetzlich isActive: true) statt ueber den
Relationszaehler, der nach dem Scharfschalten unbemerkt unter der
Regel von User gelaufen waere (260911-e2s, Aufgabe 1, Pruefungen 5-7).
Fan-out-Muster aus UserService.findAllForPlatformAdmin uebernommen; die
vier tenant-Zugriffe bleiben ungebunden (Tenant ohne Regel). Antwortform,
Meldungen und Statuscodes unveraendert.
tenant.controller.spec.ts legt die Testlage aus dem Nichts an (20
Faelle): Zwei-Klienten-Nachweis ueber __makeBoundClient, Rollen-
Metadaten-Test (Klasse SUPER_ADMIN, kein Handler ueberschreibt), Wachhund
gegen mehrfache Klientenerzeugung. Falsifizierungsnachweis durchgefuehrt:
der probeweise ungebundene Zaehler in findOne macht 2 Faelle rot mit
"Cannot read properties of undefined (reading 'count')" — die dkv-Form
der Falsifizierung, nicht nur eine falsche Zahl —, danach zurueckgenommen.
Klassifikation und Entwicklungsanleitung nachgezogen: 64 Paare (ein
neues, tenant.controller.ts/user), Uebersichtszeile 8/3, Klassen-
Verteilung 32 muss-mandantengebunden, Erkennungsluecke fuer
Relationseinbindungen im Kopf der Bestandsaufnahme benannt, "Zwei
belegte Befunde" und "Was diese Etappe NICHT entscheidet" (erster
Punkt aufgeloest). Beide Dokument-Falsifizierungsnachweise durchgefuehrt
(falsche Klasse macht rls-access-inventory.spec.ts rot, falsche
Uebersichtszahl macht das herleitende Gate rot), zurueckgenommen.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AMASaSxv5QMY7RncqZriRR
Die vorige Aufgabe-2-Teilcommit (11f5731) hatte nur die Loeschung von
tenant.middleware.ts und die neue tenant.guard.spec.ts erfasst — ein
`git add` mit mehreren Pfaden schlug wegen eines bereits entfernten
Pfads fataler fehl und liess die restlichen fuenf Dateien unstaged,
ohne dass das beim Commit auffiel (Rule 1 — Prozessfehler, hier
korrigiert). Dieser Commit traegt den eigentlichen Umbau nach:
tenant.guard.ts ohne Prisma-Abhaengigkeit, die geleerte
FORTENANT_ASSIGNMENT_EXCEPTIONS samt Wachhund-Test in
rls-access-inventory.spec.ts, und die drei berichtigten
Kommentarzeilen (app.module.ts, module.guard.ts, dkv.controller.ts).
Inhaltlich identisch mit dem, was bereits verifiziert wurde (891 Tests
gruen, Typpruefung sauber) — nur die Staging-Reihenfolge war fehlerhaft.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AMASaSxv5QMY7RncqZriRR
Die seit Etappe 1 offene Architekturfrage zum gebundenen Klienten auf
dem Anfrageobjekt ist entschieden: neun umgestellte Bereiche binden
ausnahmslos dienst-intern (ein Klient je Methode), ein Klient auf
req.tenantPrisma ohne Leser war tote Verdrahtung, die wie ein
Sicherheitsmechanismus aussah. tenant.guard.ts verliert die
Prisma-Abhaengigkeit und setzt nur noch req.tenantId; die nie
verdrahtete tenant.middleware.ts (identische Logik, in keinem Modul
registriert) ist geloescht.
tenant.guard.spec.ts legt die Testlage aus dem Nichts an — alle fuenf
Zweige (kein Nutzer, USER, ADMIN mit ignorierter x-tenant-id-Kopfzeile
T-04-03, SUPER_ADMIN mit/ohne Wechsel, mandantenloser Nicht-SUPER_ADMIN)
sowie die Abwesenheit der alten Eigenschaft in jedem Durchlass-Fall.
Falsifizierungsnachweis durchgefuehrt: das probeweise Wiedereinfuehren
der alten Zuweisung macht 4 der 7 Faelle rot (u. a. "expected true to
be false" auf 'tenantPrisma' in req), danach zurueckgenommen.
rls-access-inventory.spec.ts: FORTENANT_ASSIGNMENT_EXCEPTIONS ist leer
und selbstpruefend (neuer Wachhund gegen veraltete Eintraege). Drei
Fremdkommentare (app.module.ts, module.guard.ts, dkv.controller.ts)
korrigiert, die noch auf die nie verdrahtete Middleware verwiesen.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AMASaSxv5QMY7RncqZriRR
- TenantService.create ruft nach prisma.tenant.create ensureDefaultGroup
auf; Fehler werden protokolliert, nicht propagiert (Muster aus
UserService.create)
- tenant.module.ts importiert GroupsModule (keine Zirkularitaet, wie
UserModule bereits vormacht)
- AdminSeedService.onApplicationBootstrap besteht jetzt aus zwei
sequenziellen await-Schritten: seedAdmin() (bisheriger Rumpf, plus
ensureDefaultGroup nach dem Tenant-Upsert und VOR user.create), dann
ensureDefaultGroupsForAllTenants() als abschliessende Reparatur ueber
ALLE Mandanten — laeuft unabhaengig von seedAdmin()s fruehen
Rueckkehrpfaden (fehlende ENV / Admin existiert bereits) und ist je
Mandant sowie insgesamt try/catch-gekapselt, blockiert den API-Start nie
- Reparatur sitzt bewusst NICHT als eigener onApplicationBootstrap-Hook
in GroupsModule (Ordering-Falle aus tender-scheduler.service.ts)
- tenant.service.spec.ts, admin-seed.service.spec.ts (neu): Reihenfolge,
beide fruehen Rueckkehrpfade, Fehlerisolation je Mandant, Idempotenz
ueber zwei Bootstrap-Laeufe
Middleware runs before guards in NestJS — req.user was always undefined
when TenantMiddleware executed, so req.tenantId was never set.
Convert to TenantGuard (APP_GUARD, registered after JwtAuthGuard) so it
runs after JWT validation and can read req.user.tenantId correctly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Create UserService with findByUsername (unscoped), create, update, deactivate, delete
- Create AdminSeedService that seeds Super-Admin from Docker ENV on bootstrap (D-05/D-07/D-13)
- Create TenantService with findAll, findById, create, update
- Create TenantMiddleware extracting tenantId from JWT with Super-Admin tenant switching (D-08/D-10)
- Wire PrismaModule, AuthModule, UserModule, TenantModule into AppModule
- Register JwtAuthGuard and RolesGuard as global APP_GUARD providers
- Apply TenantMiddleware to all routes via NestModule.configure
- Add @Public() decorator to HealthController for unauthenticated access