Full enterprise web operating system including: - Next.js 14 frontend with App Router, i18n (DE/EN), shadcn/ui - NestJS 10 backend with Prisma, JWT auth, Swagger docs - Keycloak 24 SSO with role-based access control - HR module (employees, time tracking, absences, org chart) - LEAN module (3S planning, morning meeting SQCDM, skill matrix) - Integrations module (PlentyONE, Zulip, Todoist, FreeScout, Nextcloud, ecoDMS, GembaDocs) - Dashboard with customizable drag & drop widget grid - Docker Compose infrastructure (PostgreSQL 16, Redis 7, Keycloak 24) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
6.0 KiB
6.0 KiB
tOS Project Code Review Memory
Project Overview
- Type: Enterprise Web Operating System with HR, LEAN modules
- Stack: Next.js 14 + NestJS 10 + Prisma + PostgreSQL + Keycloak
- Structure: pnpm monorepo with turbo (apps/web, apps/api, packages/shared)
Code Standards (from PLAN.md)
| Area | Language | Convention |
|---|---|---|
| Code & Comments | English | Required |
| UI Text | German (via i18n) | next-intl |
| Variables | camelCase | employeeId |
| Components | PascalCase | DashboardWidget |
| Files | kebab-case | user-service.ts |
| Constants | UPPER_SNAKE_CASE | MAX_VACATION_DAYS |
Critical Patterns Found
Authentication
- Global
JwtAuthGuardwith@Public()opt-out decorator - Global
RolesGuardwith@Roles()decorator - Keycloak integration via NextAuth (frontend) and passport-jwt (backend)
- IMPORTANT: Always verify JWT signatures, never just decode
- Guards registered in correct order: JWT -> Roles -> Permissions (app.module.ts L74-88)
- JWT strategy validates user exists and is active on every request
Frontend Architecture
- Server/Client split: Server page.tsx -> Client *-content.tsx
- State: Zustand (sidebar, dashboard), TanStack Query (server state)
- i18n: next-intl with de.json/en.json, default locale = "de"
- Dashboard: dnd-kit widget grid, widget registry pattern
- Styling: Tailwind + shadcn/ui, HSL CSS vars, dark mode via class
Integration Architecture (Phase 3 - Disabled)
- Location:
apps/api/integrations.backup/ - Only PlentyONE/Zulip/Todoist extend BaseConnector
- FreeScout/Nextcloud/ecoDMS/GembaDocs have independent implementations
Keycloak Client ID Mismatch (CRITICAL - RECURRING)
- Realm:
tos-frontend/tos-backend - apps/api/.env:
tos-api| apps/web/.env:tos-nextauth(MISMATCH)
Key Issues to Watch
- params API: Mixed sync/async patterns across pages
- Hardcoded German: dashboard-content.tsx, widget-grid.tsx bypass i18n
- Mock Data: HR hooks (employees, time-tracking, absences) use mock data
- Type Conflicts: types/index.ts vs types/hr.ts have conflicting exports
- Auth Layout:
(auth)/layout.tsxis'use client'-- blocks SSR - Error pages: Link to
/dashboardwithout locale prefix - ENCRYPTION_KEY:
optional()in validation -- must be required
Backend-Specific Issues (from Phase 7 Review)
- Morning Meeting Permissions: ALL endpoints use DASHBOARD_VIEW -- any user can CRUD meetings
- Private method access: time-tracking.controller.ts L237-239 uses bracket notation
this.service['privateMethod'] - Prisma cleanDatabase(): Uses Promise.all ignoring FK constraints (prisma.service.ts L48-61)
- Roles guard leaks info: Error messages reveal required role names (roles.guard.ts L31-33)
- enableImplicitConversion: In ValidationPipe (main.ts L44) -- can cause type coercion bugs
- Break tracking via string parsing: time-tracking uses note field for break detection (L216-219, L257-258)
- Audit interceptor: oldData always undefined (audit.interceptor.ts L60), salary not sanitized (L131)
- Unregistered interceptors: LoggingInterceptor and TimeoutInterceptor defined but never registered
- N+1 queries: skill-entries.service.ts analyzeGaps (L515-523), s3-planning findAll (L173-178)
- bulkUpsert not transactional: skill-entries.service.ts L429-476 -- partial failures possible
- No backdating limit: Manual time entries have no restriction on how far back entries can be created
- Holiday calculation missing: absences calculateWorkingDays does not account for public holidays
- Vacation carry-over TODO: BUrlG compliance gap (absences.service.ts L979)
File Locations
| Purpose | Path |
|---|---|
| Prisma Schema | apps/api/prisma/schema.prisma |
| Frontend Types | apps/web/src/types/ |
| HR Hooks | apps/web/src/hooks/hr/ |
| LEAN Hooks | apps/web/src/hooks/lean/ |
| Dashboard | apps/web/src/components/dashboard/ |
| i18n Messages | apps/web/messages/ |
| Integration Backup | apps/api/integrations.backup/ |
| Auth Guards | apps/api/src/auth/guards/ |
| Auth Permissions | apps/api/src/auth/permissions/ |
| Encryption Service | apps/api/src/common/services/encryption.service.ts |
| HR Employees | apps/api/src/modules/hr/employees/ |
| HR Time Tracking | apps/api/src/modules/hr/time-tracking/ |
| HR Absences | apps/api/src/modules/hr/absences/ |
| LEAN Skill Matrix | apps/api/src/modules/lean/skill-matrix/ |
| LEAN Morning Meeting | apps/api/src/modules/lean/morning-meeting/ |
| LEAN S3 Planning | apps/api/src/modules/lean/s3-planning/ |
| Audit Module | apps/api/src/modules/audit/ |
| Config Validation | apps/api/src/config/config.validation.ts |
Review History
Phase 7 Full Backend Review (2026-02-06)
- Overall: 7.8/10 | 3 Critical, 14 Important issues
- Scores: Auth 8 | Prisma 7 | HR/Emp 8 | HR/Time 7 | HR/Abs 8
- LEAN/Skill 8 | LEAN/Morning 7 | LEAN/S3 8 | Dashboard 8
- Common 8 | Users 8 | Audit 7 | app.module 9
- See:
phase7-backend-review.md
Phase 6 Frontend Review (2026-02-06)
- 5 Critical, 9 Important, detailed 10-area review
- See:
phase6-frontend-review.md
Infrastructure + Integration Review (2026-02-06)
- Docker 7/10 | Keycloak 7/10 | Env 4/10 | Integration 6/10
- See:
infra-integration-review.md
Phase 5 Review (2026-02-05)
- HR modules: Employees, Time Tracking, Absences
Phase 3 Review (2026-02-05)
- Integration connectors reviewed; module now disabled
Phase 1 Review (2024)
- JWT validation, type sync, CORS, Keycloak fixes applied
Backend Architecture Notes
- Global guards chain: JwtAuthGuard -> RolesGuard -> PermissionsGuard
- Response envelope via TransformInterceptor:
{success, data, timestamp} - Global HttpExceptionFilter catches all exceptions, no internal leaks
- AES-256-GCM encryption for salary + bank accounts (fixed salt issue noted)
- Audit via decorator
@AuditLog()+ global AuditInterceptor - Permissions enum uses entity:action format (e.g.,
employees:read) - DEFAULT_ROLE_PERMISSIONS maps roles to permission arrays