Files
tessera-ctl/.planning/phases/02-authentication-multi-tenancy/02-02-SUMMARY.md
T

10 KiB

phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, duration, completed
phase plan subsystem tags requires provides affects tech-stack key-files key-decisions patterns-established requirements-completed duration completed
02-authentication-multi-tenancy 02 auth, ui
jwt
jose
zustand
next-middleware
login
rbac
user-crud
tenant-crud
i18n
phase provides
02-authentication-multi-tenancy/01 Backend auth (AuthModule, UserService, TenantService, JWT guards, admin seed)
phase provides
01-foundation-portal-shell/02 Portal shell (AppShell, Header, Sidebar, i18n, theming)
Split-screen login page with form submission to API
Next.js middleware for JWT-based route protection
Auth-wired header with user dropdown and logout
Auth-wired sidebar footer with user info
Zustand auth store for client-side user state
User CRUD API endpoints with role-based tenant isolation
Tenant CRUD API endpoints (SUPER_ADMIN only)
Admin users management page
Admin tenants management page
Sidebar admin section with role-based visibility
Complete DE/EN i18n keys for auth, admin, header
03-marketplace
04-module-system
ldap-sync
added patterns
jose
zod
@nestjs/mapped-types
Route groups: (auth) for standalone pages, (portal) for AppShell-wrapped pages
Next.js middleware JWT verification with jose for Edge runtime
Server Actions for auth operations (login/logout/fetchCurrentUser)
Zustand store without persist for API-driven client state
NestJS controller-level tenant isolation for ADMIN role
created modified
apps/web/src/app/(auth)/layout.tsx
apps/web/src/app/(auth)/login/page.tsx
apps/web/src/app/(portal)/layout.tsx
apps/web/src/app/(portal)/page.tsx
apps/web/src/middleware.ts
apps/web/src/lib/session.ts
apps/web/src/lib/auth-actions.ts
apps/web/src/lib/stores/auth-store.ts
apps/api/src/user/user.controller.ts
apps/api/src/user/dto/create-user.dto.ts
apps/api/src/user/dto/update-user.dto.ts
apps/api/src/tenant/tenant.controller.ts
apps/api/src/tenant/dto/create-tenant.dto.ts
apps/web/src/app/(portal)/admin/users/page.tsx
apps/web/src/app/(portal)/admin/tenants/page.tsx
apps/web/src/app/layout.tsx
apps/web/src/components/layout/header.tsx
apps/web/src/components/layout/sidebar-footer.tsx
apps/web/src/components/layout/sidebar.tsx
apps/web/src/messages/de.json
apps/web/src/messages/en.json
apps/api/src/user/user.module.ts
apps/api/src/tenant/tenant.module.ts
apps/web/package.json
apps/api/package.json
Used route groups (auth)/(portal) for layout separation instead of conditional rendering
Server Actions for login/logout with manual cookie forwarding for cross-port dev setup
Zustand auth store without persist: user data comes from API on each portal load
Controller-level tenant filtering for ADMIN role rather than relying solely on RLS
Remember-me controls cookie maxAge (30d vs session-only), not separate token type
Route groups: (auth) for unauthenticated, (portal) for authenticated pages
Next.js middleware: JWT verification with jose, public route allowlist
Auth store: fetchCurrentUser() in header useEffect populates Zustand
Admin pages: role-checked at component level with access-denied fallback
API controllers: class-validator DTOs with ! assertions for strict TS
AUTH-02
AUTH-03
AUTH-04
TNNT-02
8min 2026-06-18

Phase 2 Plan 02: Frontend Auth & User/Tenant CRUD Summary

Split-screen login with JWT middleware route protection, auth-wired portal chrome, and admin CRUD pages for users (ADMIN+) and tenants (SUPER_ADMIN)

Performance

  • Duration: 8 min
  • Started: 2026-06-18T11:30:35Z
  • Completed: 2026-06-18T11:39:05Z
  • Tasks: 3
  • Files modified: 26

Accomplishments

  • Split-screen login page with Tessera branding (yellow #ffed00 left panel) and form (right panel), including remember-me checkbox for session duration control
  • Next.js middleware validates JWT on every route, redirects unauthenticated users to /login, and handles mustChangePassword redirect
  • Header displays logged-in user initial with dropdown (display name, role badge, logout); sidebar footer shows user name and role from Zustand auth store
  • User CRUD API with ADMIN/SUPER_ADMIN access: ADMIN scoped to own tenant, cannot escalate to SUPER_ADMIN role
  • Tenant CRUD API with SUPER_ADMIN-only access: includes user count, blocks deletion of tenants with active users
  • Admin users page with table, create/edit/delete modals; admin tenants page with table, create/edit/deactivate
  • Sidebar "Verwaltung" section visible to ADMIN+, with "Mandanten" link only for SUPER_ADMIN
  • Complete DE/EN i18n coverage for all new auth, admin, and header strings

Task Commits

Each task was committed atomically:

  1. Task 1: Auth infrastructure - cdf4d60 (feat: route groups, middleware, session, auth-actions, auth store)
  2. Task 2: Login page UI and header/sidebar wiring - e7b2a70 (feat: split-screen login, user dropdown, i18n)
  3. Task 3: User/Tenant CRUD API + admin pages - bfb04ea (feat: controllers, DTOs, admin UI, sidebar admin nav)

Files Created/Modified

Created

  • apps/web/src/app/(auth)/layout.tsx - Standalone auth layout (no sidebar/header)
  • apps/web/src/app/(auth)/login/page.tsx - Split-screen login page with form
  • apps/web/src/app/(portal)/layout.tsx - Portal layout wrapping with AppShell
  • apps/web/src/app/(portal)/page.tsx - Dashboard page (moved from root)
  • apps/web/src/middleware.ts - JWT-based route protection middleware
  • apps/web/src/lib/session.ts - Edge-compatible JWT verification with jose
  • apps/web/src/lib/auth-actions.ts - Server actions: login, logout, fetchCurrentUser
  • apps/web/src/lib/stores/auth-store.ts - Zustand store for client-side user state
  • apps/api/src/user/user.controller.ts - User CRUD endpoints with role/tenant guards
  • apps/api/src/user/dto/create-user.dto.ts - CreateUserDto with class-validator
  • apps/api/src/user/dto/update-user.dto.ts - UpdateUserDto extending CreateUserDto
  • apps/api/src/tenant/tenant.controller.ts - Tenant CRUD endpoints (SUPER_ADMIN only)
  • apps/api/src/tenant/dto/create-tenant.dto.ts - CreateTenantDto with slug validation
  • apps/web/src/app/(portal)/admin/users/page.tsx - User management admin page
  • apps/web/src/app/(portal)/admin/tenants/page.tsx - Tenant management admin page

Modified

  • apps/web/src/components/layout/header.tsx - Auth-wired user avatar dropdown with logout
  • apps/web/src/components/layout/sidebar-footer.tsx - Auth-wired user info display
  • apps/web/src/components/layout/sidebar.tsx - Added Verwaltung admin section
  • apps/web/src/messages/de.json - Added auth, header.role, admin i18n keys
  • apps/web/src/messages/en.json - Added auth, header.role, admin i18n keys
  • apps/api/src/user/user.module.ts - Added UserController
  • apps/api/src/tenant/tenant.module.ts - Added TenantController
  • apps/web/package.json - Added jose, zod
  • apps/api/package.json - Added @nestjs/mapped-types

Decisions Made

  • Route groups over conditional rendering: Used Next.js route groups (auth) and (portal) to separate layouts cleanly. The (auth) group has a minimal layout (no sidebar/header per D-04), while (portal) wraps everything in AppShell.
  • Server Action cookie forwarding: In development (separate ports 3000/3001), the login server action manually reads Set-Cookie from the API response and sets it via Next.js cookies() API to bridge the cross-origin gap.
  • Remember-me via cookie duration: The remember-me checkbox controls whether the session cookie has a 30-day maxAge (checked) or is a session cookie (unchecked, expires on browser close). Both use the same JWT.
  • Controller-level tenant isolation: ADMIN user requests filter by tenantId at the controller level as defense-in-depth alongside RLS, ensuring ADMIN users never see cross-tenant data even if RLS is misconfigured.
  • Installed @nestjs/mapped-types: Required for PartialType DTO pattern (UpdateUserDto extends CreateUserDto with all fields optional).

Deviations from Plan

Auto-fixed Issues

1. [Rule 1 - Bug] Added definite assignment assertions to DTO properties

  • Found during: Task 3 (User/Tenant CRUD)
  • Issue: TypeScript strict mode required definite assignment for DTO class properties, causing type-check failures
  • Fix: Added ! definite assignment assertions to required DTO properties (standard NestJS DTO pattern with class-validator)
  • Files modified: create-user.dto.ts, create-tenant.dto.ts
  • Verification: pnpm turbo type-check passes
  • Committed in: bfb04ea (Task 3 commit)

2. [Rule 3 - Blocking] Installed @nestjs/mapped-types

  • Found during: Task 3 (User/Tenant CRUD)
  • Issue: PartialType import from @nestjs/mapped-types was not available; package not listed in plan dependencies
  • Fix: Ran pnpm add @nestjs/mapped-types in apps/api
  • Files modified: apps/api/package.json, pnpm-lock.yaml
  • Verification: UpdateUserDto compiles correctly, type-check passes
  • Committed in: bfb04ea (Task 3 commit)

Total deviations: 2 auto-fixed (1 bug, 1 blocking) Impact on plan: Both auto-fixes necessary for compilation. No scope creep.

Issues Encountered

  • Stale .next cache: After moving page.tsx from root to (portal)/ route group, the .next/types directory still referenced the old location. Fixed by clearing .next cache before type-check.

User Setup Required

None - no external service configuration required. JWT_SECRET env var must be set for production (development uses a fallback).

Next Phase Readiness

  • Login flow is fully wired: user can authenticate via split-screen login page and reach the portal
  • Auth state flows through the entire portal: header dropdown, sidebar footer, admin page access checks
  • User and tenant CRUD is complete for admin workflows
  • Ready for LDAP sync (Phase 2, Plan 03 if planned) or marketplace features (Phase 3)
  • Password reset flow (D-03) requires SMTP setup -- deferred to separate plan

Self-Check: PASSED

All 16 created/expected files verified on disk. All 3 task commits (cdf4d60, e7b2a70, bfb04ea) verified in git log. Type-check passes for all packages.


Phase: 02-authentication-multi-tenancy Completed: 2026-06-18