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>
This commit is contained in:
@@ -10,8 +10,6 @@ files_modified:
|
||||
- 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/app/(portal)/admin/users/page.tsx
|
||||
- apps/web/src/app/(portal)/admin/tenants/page.tsx
|
||||
- apps/web/src/app/layout.tsx
|
||||
- apps/web/src/middleware.ts
|
||||
- apps/web/src/lib/session.ts
|
||||
@@ -30,6 +28,8 @@ files_modified:
|
||||
- apps/api/src/tenant/tenant.controller.ts
|
||||
- apps/api/src/tenant/tenant.module.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
|
||||
autonomous: true
|
||||
requirements:
|
||||
- AUTH-02
|
||||
@@ -122,33 +122,23 @@ See Plan 02-01 for the full artifacts table.
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Login page, auth layout, Next.js middleware, auth store, and auth-wired portal components</name>
|
||||
<name>Task 1: Auth infrastructure -- route groups, middleware, session, auth-actions, and auth store</name>
|
||||
<read_first>
|
||||
- apps/web/src/app/layout.tsx (root layout to understand provider structure)
|
||||
- apps/web/src/components/layout/header.tsx (user avatar placeholder to wire)
|
||||
- apps/web/src/components/layout/sidebar-footer.tsx (user info placeholder to wire)
|
||||
- apps/web/src/components/layout/app-shell.tsx (AppShell wrapper for portal routes)
|
||||
- apps/web/src/lib/stores/sidebar-store.ts (existing Zustand store pattern to follow)
|
||||
- apps/web/src/messages/de.json (existing i18n keys to extend)
|
||||
- apps/web/src/messages/en.json (existing i18n keys to extend)
|
||||
- apps/web/src/app/globals.css (design tokens for styling login page)
|
||||
- .planning/phases/02-authentication-multi-tenancy/02-RESEARCH.md (Pattern 4: Next.js middleware, session.ts pattern, DAL pattern)
|
||||
</read_first>
|
||||
<files>
|
||||
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/app/layout.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/web/src/components/layout/header.tsx
|
||||
apps/web/src/components/layout/sidebar-footer.tsx
|
||||
apps/web/src/messages/de.json
|
||||
apps/web/src/messages/en.json
|
||||
apps/web/package.json
|
||||
apps/web/src/app/layout.tsx
|
||||
</files>
|
||||
<action>
|
||||
Install frontend auth dependencies: cd apps/web and pnpm add jose zod
|
||||
@@ -184,14 +174,50 @@ See Plan 02-01 for the full artifacts table.
|
||||
- Zustand store with user state (id, username, displayName, role, tenantId) or null
|
||||
- Actions: setUser, clearUser
|
||||
- No persist middleware (user state comes from API, not localStorage)
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /home/vicolab/projects/tessera-ctl && pnpm turbo type-check --filter=@tessera/web</automated>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- (auth) route group has standalone layout without AppShell per D-04
|
||||
- (portal) route group wraps children with AppShell (header + sidebar)
|
||||
- Next.js middleware validates JWT cookie and redirects unauthenticated to /login
|
||||
- middleware.ts allows /login and /reset-password without auth
|
||||
- session.ts exports verifySession using jose
|
||||
- auth-actions.ts exports login, logout, fetchCurrentUser
|
||||
- auth-store.ts exports useAuthStore Zustand hook
|
||||
- Type-check passes for @tessera/web
|
||||
</acceptance_criteria>
|
||||
<done>Route groups created (auth standalone, portal with AppShell); Next.js middleware protects routes via JWT verification; auth-actions provide login/logout/fetchCurrentUser; Zustand auth store created.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Login page UI, header/sidebar auth wiring, and i18n keys</name>
|
||||
<read_first>
|
||||
- apps/web/src/app/(auth)/layout.tsx (from Task 1 -- standalone layout)
|
||||
- apps/web/src/lib/auth-actions.ts (from Task 1 -- login action to call)
|
||||
- apps/web/src/lib/stores/auth-store.ts (from Task 1 -- store to populate)
|
||||
- apps/web/src/components/layout/header.tsx (user avatar placeholder to wire)
|
||||
- apps/web/src/components/layout/sidebar-footer.tsx (user info placeholder to wire)
|
||||
- apps/web/src/messages/de.json (existing i18n keys to extend)
|
||||
- apps/web/src/messages/en.json (existing i18n keys to extend)
|
||||
- apps/web/src/app/globals.css (design tokens for styling login page)
|
||||
</read_first>
|
||||
<files>
|
||||
apps/web/src/app/(auth)/login/page.tsx
|
||||
apps/web/src/components/layout/header.tsx
|
||||
apps/web/src/components/layout/sidebar-footer.tsx
|
||||
apps/web/src/messages/de.json
|
||||
apps/web/src/messages/en.json
|
||||
</files>
|
||||
<action>
|
||||
Create apps/web/src/app/(auth)/login/page.tsx per D-01 split-screen design:
|
||||
- 'use client' component
|
||||
- Full-screen split layout: LEFT side (hidden on mobile, flex-1 on md+) shows Tessera branding with primary yellow (#ffed00 / var(--primary)) background, large "Tessera" text, and tagline. RIGHT side (full width mobile, flex-1 desktop) shows login form on white/dark background.
|
||||
- Form fields: username input, password input, "Angemeldet bleiben" (Remember me) checkbox per D-02
|
||||
- Submit button with primary color
|
||||
- Error message display area
|
||||
- Form submission calls the login action, which POSTs to /auth/login on the API. On success, redirect to '/' (dashboard). On error, show error message.
|
||||
- Form submission calls the login action from auth-actions.ts, which POSTs to /auth/login on the API. On success, redirect to '/' (dashboard). On error, show error message.
|
||||
- All strings through useTranslations('auth') hook per UI-03 pattern
|
||||
- Include i18n keys for: auth.login, auth.username, auth.password, auth.rememberMe, auth.submit, auth.error.invalidCredentials, auth.branding.tagline
|
||||
|
||||
@@ -200,7 +226,7 @@ See Plan 02-01 for the full artifacts table.
|
||||
- Import useAuthStore to get current user
|
||||
- Show user initial (first letter of displayName or username) in the avatar circle
|
||||
- On click, show a dropdown with: user display name, role badge, "Abmelden" (Logout) button
|
||||
- Logout button calls the logout action
|
||||
- Logout button calls the logout action from auth-actions.ts
|
||||
- Keep the existing hamburger, logo, breadcrumb, and ThemeToggle structure intact
|
||||
|
||||
Update apps/web/src/components/layout/sidebar-footer.tsx:
|
||||
@@ -217,23 +243,19 @@ See Plan 02-01 for the full artifacts table.
|
||||
<automated>cd /home/vicolab/projects/tessera-ctl && pnpm turbo type-check --filter=@tessera/web</automated>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- (auth) route group has standalone layout without AppShell per D-04
|
||||
- (portal) route group wraps children with AppShell (header + sidebar)
|
||||
- Login page is split-screen with branding left and form right per D-01
|
||||
- Login form has username, password, and remember-me checkbox per D-02
|
||||
- Next.js middleware validates JWT cookie and redirects unauthenticated to /login
|
||||
- middleware.ts allows /login and /reset-password without auth
|
||||
- Header shows real user initial and dropdown with logout per auth store
|
||||
- Sidebar footer shows real user name and role per auth store
|
||||
- All new UI strings use i18n t() function (no hardcoded text)
|
||||
- Both de.json and en.json have all new auth/admin translation keys
|
||||
- Both de.json and en.json have all new auth/header/admin translation keys
|
||||
- Type-check passes for @tessera/web
|
||||
</acceptance_criteria>
|
||||
<done>Login page renders split-screen layout; unauthenticated users are redirected to /login; authenticated users see their name in header and sidebar; all strings are internationalized.</done>
|
||||
<done>Login page renders split-screen layout per D-01; header shows user dropdown with logout; sidebar footer shows user info; all strings internationalized in DE/EN.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: User CRUD API + admin page and Tenant CRUD API + admin page</name>
|
||||
<name>Task 3: User CRUD API + admin page and Tenant CRUD API + admin page</name>
|
||||
<read_first>
|
||||
- apps/api/src/user/user.service.ts (from Plan 02-01, user operations)
|
||||
- apps/api/src/user/user.module.ts (from Plan 02-01)
|
||||
@@ -349,7 +371,7 @@ See Plan 02-01 for the full artifacts table.
|
||||
</threat_model>
|
||||
|
||||
<verification>
|
||||
After both tasks complete:
|
||||
After all three tasks complete:
|
||||
1. Navigate to http://localhost:3000 -- should redirect to /login
|
||||
2. Login with admin/admin123 -- should redirect to dashboard, header shows "admin" user
|
||||
3. Navigate to /admin/users -- should show user table with the admin account
|
||||
|
||||
Reference in New Issue
Block a user