f5551e33c7
Co-Authored-By: claude-flow <ruv@ruv.net>
4.7 KiB
4.7 KiB
Review-Report — 2026-03-15
Ergebnis: ✅ Bestanden
Alle Quality Gates bestanden. Keine kritischen Probleme gefunden. Zwei Minor-Issues behoben waehrend des Reviews.
Quality Gates
| Gate | Status | Details |
|---|---|---|
| Engine Tests | ✅ | 254/254 bestanden (17 Dateien) |
| Staffing Tests | ✅ | 37/37 bestanden (3 Dateien) |
| API Tests | ✅ | 209/209 bestanden (21 Dateien) |
| Application Tests | ✅ | 67/67 bestanden (15 Dateien) |
| Gesamt | ✅ | 567/567 Tests bestanden |
| TypeScript (web) | ✅ | 0 Fehler |
| TypeScript (api) | ✅ | 0 Fehler |
| Paketabhaengigkeiten | ✅ | Keine Zyklen |
Architektur-Checkliste
- Keine zirkulaeren Abhaengigkeiten — engine, staffing, ui sind sauber isoliert
engineundstaffinghaben keine DB-Imports- Alle 24 tRPC-Router in
packages/api/src/router/index.tsregistriert - SSE-Events: 10 Emitter fuer Allocation, Project, Budget, Vacation, Role, Notification
- SSE-Debouncing (50ms) aktiv in event-bus.ts
TypeScript & Typsicherheit
- Keine unkommentierten
any-Types — alle Vorkommnisse haben// eslint-disable-next-lineoder sind intentionale Casts - Prisma-Enums an Client-Grenzen mit
as unknown as SharedTypegecastet - JSONB-Felder korrekt gecastet
- Nullable FKs mit optional chaining behandelt
exactOptionalPropertyTypesPattern eingehalten (Spread statt{ key: undefined })
Datenbank & Prisma
- Geldbetraege als Integer-Cents
- Kein unsicheres Raw-SQL in App-Routern — einziges
$executeRawin resource.ts nutzt tagged template literals (parameterisiert) - Composite Indexes fuer Assignment, DemandRequirement, Vacation vorhanden
Sicherheit
protectedProcedureerfordert jetztsession.userUNDdbUser(gehaertet)- Vacation create/cancel: Ownership-Check fuer USER-Rolle
user.listaufadminProcedureeingeschraenktentitlement.getBalance: Ownership-Check fuer USER-Rolle- Allocation listView/list/listDemands/listAssignments: Anonymisierung angewendet
- Security Headers in next.config.ts (X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy)
- Keine Passwoerter/Secrets in tRPC-Responses —
settings.tsgibt nurhasApiKey/hasSmtpPasswordBooleans zurueck - Alle Mutations hinter
managerProcedureoderadminProcedure - Kein
publicProcedurein Routern
UI & Komponenten
- AppShell: Kollabierbare Navigationsgruppen (Estimating, ACN-Orga)
- Tailwind-Opacity nur in 5er-Schritten (CSS-Fix fuer
/92,/88,/94) trpc.role.listkorrekt als Array behandelt
Waehrend des Reviews behoben
Minor: assignment-bookings Test-Sync
- Datei:
packages/application/src/__tests__/assignment-bookings.test.ts - Problem:
clientId: truewurde zumprojectSelect inlist-assignment-bookings.tshinzugefuegt, aber 3 Test-Assertions nicht aktualisiert (pre-existing) - Fix:
clientId: truein alle 3 Test-Select-Assertions eingefuegt → 67/67 Tests bestanden
Offene Items (nicht-blockierend)
Diese stammen aus dem Security-Audit und sind im Backlog (docs/security-audit-2026-03-15.md):
- SSE Event-Filterung — Events werden global an alle authentifizierten User gebroadcastet, ohne Rollen-/Projekt-Scoping
- Rate Limiting — Kein Rate Limiter auf Auth, Admin-Tests, oder API-Endpunkten
- Passwort-Policy — Nur
min(8)ohne Komplexitaetsanforderungen - xlsx Parser — Bekannte Advisories (Prototype Pollution, ReDoS) in
xlsx@0.18.5 - JWT maxAge — Auth.js Default 30 Tage ohne explizite Konfiguration
- Next.js Middleware — Kein
middleware.tsfuer serverseitige Route-Protection
Empfehlungen
- SSE-Event-Filterung priorisieren — groesstes verbleibendes Datenschutz-Risiko
- Rate Limiting mit
rate-limiter-flexible+ Redis einbauen (Auth zuerst) xlsxdurchexceljsoderSheetJS Proersetzen fuer untrusted Parsingmiddleware.tsfuer/(app)/Routen einfuegen
Learnings-Vorschlag fuer LEARNINGS.md
### Security: protectedProcedure muss dbUser pruefen (2026-03-15)
`protectedProcedure` pruefte nur `session.user`, nicht ob der DB-User noch existiert.
Geloest: `dbUser`-Check in die Middleware eingefuegt. Stale Sessions werden jetzt abgelehnt.
Konsequenz: Alle Test-Caller muessen ein gueltiges `dbUser`-Objekt mitgeben.
### Security: IDOR-Checks bei Self-Service-Endpunkten (2026-03-15)
Vacation create/cancel und Entitlement getBalance hatten keine Ownership-Checks.
USER-Rolle konnte Aktionen fuer beliebige Ressourcen ausfuehren.
Pattern: Bei `protectedProcedure`-Endpunkten die eine `resourceId` akzeptieren,
immer `resource.userId === ctx.dbUser.id` pruefen fuer nicht-privilegierte Rollen.