Commit Graph

662 Commits

Author SHA1 Message Date
schalli 27a75ab990 docs(03-04): phase 03 verified — all 11 checks passed, 2 bugs fixed 2026-06-20 10:31:22 +02:00
schalli 576e311262 fix(03): strip TLD from domaincheck input before sending to API
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>
2026-06-20 09:37:39 +02:00
schalli 5708127dbb fix(03): module guard uses JWT tenantId fallback for deactivation enforcement
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>
2026-06-20 09:31:59 +02:00
schalli 46a6e277b8 fix(03): login redirect + API internal URL for Docker networking
- 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>
2026-06-20 09:28:05 +02:00
schalli f5a775c0df wip: phase-03 paused vor human verification (plan 04) 2026-06-19 14:51:31 +02:00
schalli 9b2b1eafcb fix(03): show actual error message in domaincheck page
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 14:43:27 +02:00
schalli b8ef870d1a fix(03): resolve tenant context for module activation
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>
2026-06-19 14:38:37 +02:00
schalli dad9a779df fix(03): add module settings page, dynamic sidebar categories
- 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>
2026-06-19 14:00:50 +02:00
schalli 2832d06ad7 docs(phase-03): update tracking after wave 2
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 13:41:54 +02:00
schalli fbd7d44e88 docs(03-03): complete module UI lazy loading plan summary
- Document module loader registry, category pages, and expanded module views
- Record threat mitigations T-03-09, T-03-10, T-03-11
- Self-check passed: all files and commits verified
2026-06-19 13:39:58 +02:00
schalli de63b10749 feat(03-03): expanded module view with dynamic routing and API client
- 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
2026-06-19 13:38:25 +02:00
schalli a191628fa5 feat(03-03): module loader utility with category page and lazy cards
- 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)
2026-06-19 13:36:09 +02:00
schalli 629ef81ea0 docs(03-02): complete Domaincheck module plan summary
- DNS-based domain availability checking across TLD variants
- Frontend page with input form and color-coded results
- Module self-seeds into registry on startup
2026-06-19 13:29:48 +02:00
schalli 1d9fd2280d feat(03-02): add domaincheck frontend - input form, results display, i18n
- 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
2026-06-19 13:27:55 +02:00
schalli 2e0a4ddc21 feat(03-02): add domaincheck backend - DNS service, API endpoint, module seed
- 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)
2026-06-19 13:24:26 +02:00
schalli 4867c30bcd docs(phase-03): update tracking after wave 1
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 12:40:02 +02:00
schalli 0007ef58d9 docs(03-01): complete Module SDK + Registry plan summary
- Module SDK package with versioned interface contract
- Database-driven module registry with per-tenant activation
- ModuleGuard for tenant-scoped module access control
2026-06-19 12:38:40 +02:00
schalli fa15d3527a feat(03-01): add ModuleRegistry NestJS module with CRUD and activation endpoints
- 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
2026-06-19 12:36:33 +02:00
schalli 8c24c1e267 feat(03-01): add Module SDK package and Prisma module registry schema
- Create @tessera/module-sdk with TesseraModule, ModuleRoute, ModuleManifest, ModuleCategory types
- Add Module and TenantModuleActivation Prisma models with tenant-scoped unique constraint
- Apply migration add-module-registry to PostgreSQL
- Framework-agnostic ComponentType for lazy-loaded module UIs
2026-06-19 12:33:55 +02:00
schalli 6e2f6e7c3e docs(03): create phase 3 plans - Module System & Domaincheck
4 plans in 3 waves:
- 03-01: Module SDK + Registry + Activation API
- 03-02: Domaincheck backend + frontend (vertical slice)
- 03-03: Lazy Loading + Category Pages
- 03-04: Visual Verification

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 12:14:54 +02:00
schalli 89f559ce62 docs(03): create phase plan for Module System & Domaincheck
4 plans across 3 waves: SDK + registry (W1), Domaincheck module +
lazy loading (W2), visual verification (W3). Covers MOD-01..04,
DCHK-01..03.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 12:13:20 +02:00
schalli 242553a532 docs(03): capture phase 3 context - Module System & Domaincheck
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 11:57:25 +02:00
schalli 11949da99a fix(02): fix prisma client in docker, resolve typescript errors 2026-06-19 08:49:23 +02:00
schalli 91758a0e44 docs(02-04): LDAP integration complete 2026-06-19 08:41:02 +02:00
schalli 6e19591168 feat(02-04): LDAP admin UI with config, mapping editor, and sync trigger 2026-06-19 08:40:29 +02:00
schalli f928cd7713 feat(02-04): LdapModule with sync service, config service, scheduler, and controller
- 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
2026-06-19 08:38:07 +02:00
schalli ac617f4fe5 feat(02-03): password reset flow, force-change interceptor, MailModule
- MailModule with SMTP transport configured from ENV variables
- MailService for password reset and welcome emails (plain text, i18n)
- Password reset flow: request-reset (public), reset-password (token-based)
- Change password for logged-in users with current password verification
- Admin reset password endpoint (ADMIN/SUPER_ADMIN only, D-03)
- ForcePasswordChangeInterceptor blocks all routes except change-password,
  logout, me when mustChangePassword=true (D-06, Pitfall 5)
- Frontend: reset-password request page, token reset page, change-password page
- Forgot password link added to login page
- MailHog service added to docker-compose.dev.yml for dev email testing
- SMTP env vars added to docker-compose.yml (defaults to MailHog)
- Complete DE/EN i18n coverage for reset and change password flows
- SUS packages installed: @nestjs-modules/mailer, nodemailer, ldapts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 13:48:23 +02:00
schalli eaaa9adfa5 docs(02-02): complete frontend auth and user/tenant CRUD plan 2026-06-18 13:42:00 +02:00
schalli bfb04eac66 feat(02-02): user CRUD API + admin page, tenant CRUD API + admin page
- Create UserController with GET/POST/PATCH/DELETE endpoints at /users
  - ADMIN sees own-tenant users only; SUPER_ADMIN sees all (T-02-10)
  - ADMIN cannot escalate to SUPER_ADMIN role (T-02-08)
  - ADMIN cannot delete self or cross-tenant users
- Create TenantController with GET/POST/PATCH/DELETE at /tenants
  - SUPER_ADMIN-only access (D-10)
  - Tenant deletion blocked if active users exist (T-02-09)
- Create CreateUserDto, UpdateUserDto, CreateTenantDto with class-validator
- Create admin/users page with user table, create/edit/delete modals
- Create admin/tenants page with tenant table, create/edit/deactivate (SUPER_ADMIN only)
- Add admin section to sidebar: Verwaltung > Benutzer + Mandanten
  - Verwaltung visible for ADMIN/SUPER_ADMIN; Tenants link SUPER_ADMIN only
- Install @nestjs/mapped-types for PartialType DTO pattern

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 13:38:54 +02:00
schalli e7b2a70fc9 feat(02-02): login page UI, header/sidebar auth wiring, i18n keys
- 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>
2026-06-18 13:34:43 +02:00
schalli cdf4d60038 feat(02-02): auth infrastructure -- route groups, middleware, session, auth-actions, auth store
- 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>
2026-06-18 13:32:53 +02:00
schalli 47f765ca99 docs(02-01): complete backend auth foundation 2026-06-18 13:29:59 +02:00
schalli 4b05627f3d feat(02-01): UserModule, TenantModule, admin seed, and app.module wiring
- 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
2026-06-18 13:28:04 +02:00
schalli 6190f3dd39 feat(02-01): AuthModule with Passport strategies, guards, and decorators
- 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
2026-06-18 13:24:59 +02:00
schalli d0b36c8f22 feat(02-01): Prisma schema expansion, RLS migration, and PrismaModule
- Add User, Role enum, PasswordResetToken, LdapConfig, LdapFieldMapping models
- Expand Tenant model with isActive, users relation, ldapConfig relation
- Create RLS migration with tenant isolation policies on all tenant-scoped tables
- Create PrismaModule (global), PrismaService, and forTenant extension
- Add JWT_SECRET, TESSERA_ADMIN_*, TESSERA_FORCE_CHANGE env vars to docker-compose
- Install @nestjs/jwt, @nestjs/passport, passport, argon2, class-validator deps
2026-06-18 13:22:38 +02:00
schalli dddc39f570 docs(02): create phase plan (5 plans, 4 waves) 2026-06-18 13:16:49 +02:00
schalli 8f58882db6 fix(02): revise plans based on checker feedback
Split oversized tasks per scope_sanity blockers:
- 02-01 Task 2 (18 files) -> Task 2 (AuthModule, 12 files) + Task 3 (UserModule+TenantModule+wiring, 8 files)
- 02-02 Task 1 (14 files) -> Task 1 (auth infrastructure, 9 files) + Task 2 (login UI+header/sidebar+i18n, 5 files)

Added runtime smoke test to 02-01 Task 3 verify (ts-node startup check).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 13:16:26 +02:00
schalli e8e89686f5 docs(02): create phase 2 authentication & multi-tenancy plans
5 plans across 4 waves covering all 9 requirements (AUTH-01..06, TNNT-01..03)
and 18 locked decisions (D-01..D-18):
- Plan 01 (W1): Backend auth foundation with Prisma schema, RLS, JWT, admin seed
- Plan 02 (W2): Frontend auth flow, login page, user/tenant CRUD admin pages
- Plan 03 (W2): SUS package verification, password reset, force-change interceptor
- Plan 04 (W3): LDAP sync service, per-tenant config, field mapping, admin UI
- Plan 05 (W4): Visual verification of complete auth and multi-tenancy system

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 13:10:13 +02:00
schalli 4da1c99807 docs(phase-2): research authentication and multi-tenancy domain 2026-06-18 13:00:15 +02:00
schalli 45286d58f9 docs(state): record phase 2 context session 2026-06-18 12:48:31 +02:00
schalli 1ba3433158 docs(02): capture phase context 2026-06-18 12:48:31 +02:00
schalli 8df059b5dd docs(state): phase 1 execution complete 2026-06-18 12:41:28 +02:00
schalli 366ccb8033 docs(01-03): visual verification complete 2026-06-18 12:41:22 +02:00
schalli a9018083b2 fix(01): remove traefik, lighten dark mode, fix sidebar accent color, move locale switcher to sidebar footer 2026-06-18 12:41:02 +02:00
schalli 224fd59196 docs(01-02): complete Portal Shell plan with SUMMARY, state updates
- SUMMARY.md documenting design tokens, i18n, layout components
- STATE.md advanced to plan 2/3, decisions recorded
- ROADMAP.md updated to 2/3 plans complete
- REQUIREMENTS.md: PRTAL-01, PRTAL-04, UI-01, UI-02, UI-03 marked complete
2026-06-18 10:31:16 +02:00
schalli 6039387857 feat(01-02): portal layout with header, sidebar, theme toggle, locale switcher
- Zustand sidebar store with persist middleware (collapse/expand, mobile open)
- Sticky header with logo, breadcrumb, theme toggle, locale switcher, user avatar
- Collapsible sidebar with Dashboard/Marketplace nav, accordion categories, footer
- Mobile responsive: hamburger menu with overlay sidebar on small screens
- Theme toggle cycling light/dark/system with mounted guard
- Locale switcher setting NEXT_LOCALE cookie with router.refresh
- Empty dashboard state with grid icon, "Keine Widgets aktiv" text, add button
- AppShell composing header + sidebar + responsive main content area
- All user-visible strings via useTranslations (UI-03 compliance)
2026-06-18 10:27:46 +02:00
schalli f3791c6cdd feat(01-02): design token system, i18n framework, and theme provider setup
- OKLCH design tokens with yellow #ffed00 primary and dark gray-blue dark mode
- next-intl cookie-based locale with DE/EN message files
- next-themes provider with system/light/dark support
- Sidebar and header layout dimension tokens
- Root layout with ThemeProvider and NextIntlClientProvider wrappers
2026-06-18 10:22:42 +02:00
schalli 0517e2b2b9 docs(01-01): complete walking skeleton plan
- Created 01-01-SUMMARY.md with execution results
- Updated STATE.md with plan completion and metrics
- Updated ROADMAP.md marking plan 01-01 complete
- Updated REQUIREMENTS.md marking INFRA-01, INFRA-02, INFRA-03 complete
2026-06-18 10:20:25 +02:00
schalli dbe2d505b8 chore(01-01): add tsbuildinfo to gitignore 2026-06-18 10:17:41 +02:00
schalli 2c12878cb1 feat(01-01): Next.js app + Docker Compose stack with network segmentation
- Next.js 15 app with Tailwind CSS v4, standalone output for Docker
- Root layout with de locale, page with Tessera placeholder
- Multi-stage Dockerfile for web with monorepo root context
- Docker Compose with 4 services: traefik, web, api, db
- Three segregated networks: frontend-net, backend-net, data-net (internal)
- Traefik v2.11 reverse proxy routing / to web, /api to api
- API strip prefix middleware for clean routing
- PostgreSQL 16-alpine with health checks and named volume
- Fixed API Dockerfile for pnpm monorepo node_modules structure
- Fixed Next.js standalone path for monorepo (apps/web/server.js)
- Fixed Traefik Docker API version compatibility
- Network segmentation: web NOT on data-net, api NOT on frontend-net
2026-06-18 10:17:21 +02:00