- Add vitest, @testing-library/react, @testing-library/jest-dom, jsdom, @vitejs/plugin-react as dev deps
- Create vitest.config.ts with jsdom environment and @ path alias
- Create test setup file importing jest-dom/vitest matchers
- Add test scripts to apps/web and root package.json
- Add test task to turbo.json pipeline
Users naturally type full domains (e.g. "google.de") but the API
validates DNS labels only. Extract the label part before the first
dot to prevent 400 validation errors.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ModuleGuard now reads tenantId from req.user?.tenantId as fallback
(same pattern as module-registry controller), and throws 403 instead
of silently allowing access when no tenant context exists.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Use window.location.href for full page reload after login (ensures auth state)
- Add API_INTERNAL_URL for server-side requests within Docker network
- Remove unnecessary credentials:'include' from SSR fetch calls
- Update planning state for Phase 03 progress
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Controller now falls back to user.tenantId from JWT when
req.tenantId is null (SUPER_ADMIN without x-tenant-id header).
Also added error display to admin modules page.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Admin modules page at /admin/modules with toggle switches
- Sidebar categories now fetch active modules from API dynamically
- Added "Module" link under admin section in sidebar
- Added i18n keys for module management (DE + EN)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Create [moduleSlug] page that loads module component via MODULE_REGISTRY whitelist
- Only registered slugs trigger dynamic imports; unknown slugs show not-found state (T-03-09)
- Create api.ts with getActiveModules and getModuleBySlug utility functions
- Back-link navigation from expanded view to category page
- Create module-loader.ts with MODULE_REGISTRY mapping slugs to dynamic imports (ssr:false)
- Create [category] page fetching active modules from API, filtering by category
- Create ModuleCard component with icon, name, description, and link to expanded view
- Add i18n keys for modules namespace (de + en)
- DNS-based domain availability checking across TLD variants
- Frontend page with input form and color-coded results
- Module self-seeds into registry on startup
- DomainInput component with text input and submit button
- ResultList component with green/red status badges (D-01)
- checkDomainAction fetches POST /modules/domaincheck/check with auth cookie
- Page renders within portal AppShell at /modules/domaincheck
- i18n keys added for both DE and EN locales
- CheckDomainDto with regex validation (T-03-05) and max 10 TLDs (T-03-06)
- DomaincheckService using node:dns/promises with 5s timeout per lookup
- POST /modules/domaincheck/check protected by UseModule guard (T-03-08)
- DomaincheckModule seeds itself into registry on startup via OnModuleInit
- Default TLDs: de, com, net, org (D-03)
- ModuleRegistryService with findAll, findBySlug, findActiveForTenant, activate/deactivate, seedModule
- ModuleRegistryController with GET /modules, GET /modules/active, POST activate/deactivate
- ModuleGuard + @UseModule() decorator for tenant-scoped module access control
- ActivateModuleDto with UUID validation
- Registered ModuleRegistryModule in AppModule imports
- LdapService uses ldapts for DIRECTORY SYNC ONLY (anti-pattern avoidance)
- LdapConfigService creates default field mappings per D-16 (displayName, mail, sAMAccountName)
- Custom field mappings can be added/removed per D-17
- Per-tenant LDAP config per D-18
- syncUsersForTenant deactivates users removed from LDAP per D-15
- LdapSyncScheduler sets tenant context explicitly per Pitfall 2
- Manual sync endpoint POST /ldap/sync per D-14
- Auto-sync cron checks syncIntervalMin per D-14
- Test connection endpoint for LDAP config validation
- OpenLDAP + phpLDAPadmin added to docker-compose.dev.yml
- LDAP search filter sanitization per T-02-16
- bindPassword never returned in API responses per T-02-17
- Create split-screen login page with branding left (#ffed00) and form right (D-01)
- Login form has username, password, and remember-me checkbox (D-02)
- Wire header user avatar with auth store: shows user initial, dropdown with role badge and logout
- Wire sidebar footer with auth store: shows user name, role, and initial
- Add auth, header role, and admin i18n keys to both de.json and en.json
- All new UI strings use t() function (no hardcoded text)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Create (auth) route group with standalone layout (no sidebar/header, D-04)
- Create (portal) route group wrapping children with AppShell
- Move dashboard page into (portal) route group
- Add Next.js middleware for JWT-based route protection using jose
- Create session.ts with verifySession/getSessionFromCookies helpers
- Create auth-actions.ts server actions: login, logout, fetchCurrentUser
- Create Zustand auth-store for client-side user state
- Install jose and zod dependencies
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
- Create LocalStrategy (username/password via argon2) and JwtStrategy (cookie extractor)
- Create JwtAuthGuard with @Public() decorator support for route opt-out
- Create RolesGuard checking SUPER_ADMIN/ADMIN/USER roles per D-12
- Create AuthService with validateUser, login (30-day httpOnly cookie), logout
- Create AuthController with POST /auth/login, POST /auth/logout, GET /auth/me
- Create LoginDto with class-validator decorators
- Create @Public, @Roles, @CurrentUser decorators
- Update main.ts with ValidationPipe, CORS credentials, cookie-parser
- Install cookie-parser for httpOnly JWT cookie support