The jwt callback was only checking isAdmin during initial login when
account was present, but not on subsequent session refreshes. This caused
the admin status to be lost after the initial login.
- Moved admin status check outside of the 'if (account)' block
- Now checks isAdmin on every JWT callback when accessToken is available
- Removed localhost:3000/* from redirectUris in realm-export.json
- Removed localhost:3000 from webOrigins in realm-export.json
- Removed localhost:3000/* from post.logout.redirect.uris
- Removed localhost:3000 from keycloak-realm-import-configmap.yaml
- Updated running Keycloak instance via kcadm.sh
Only port 30080 is now configured for OAuth redirects.
The deployment was unreachable because the Next.js server was binding
to localhost:3000 (127.0.0.1) instead of 0.0.0.0, making it only
accessible inside the Docker container.
- Added HOSTNAME=0.0.0.0 to Dockerfile build and runtime stages
- Added HOSTNAME=0.0.0.0 to docker-compose.yml for nextjs service
This allows the server to accept connections from external hosts.
The build was failing because KEYCLOAK_ISSUER and KEYCLOAK_CLIENT_ID
were undefined during the static generation phase. Added default values
that match the development configuration.
- Added fallback for KEYCLOAK_ISSUER
- Added fallback for KEYCLOAK_CLIENT_ID
Trust external host for Auth.js, provide missing frontend auth env/secrets, and submit a proper CSRF-backed sign-in POST so browser login reaches Keycloak reliably.
- Backend `/signup` endpoint returns 200 OK with an empty body (`TypedResults.Ok()`), causing `res.json()` to throw 'Unexpected end of JSON input'. Removed the `res.json()` return.
- Added Suspense boundary in login page to fix `useSearchParams` build error.
- Bypass NextAuth OIDC discovery with explicit token/userinfo endpoints using internal Docker DNS, avoiding 'issuer string did not match' errors.
- Fix next.config.ts API route interception that incorrectly forwarded NextAuth routes to backend by using 'fallback' rewrites.
- Add 'Use different credentials' button to login page and AuthGuard for clearing stale sessions.
Make auth/tasks/shifts end-to-end tests deterministic with robust role-aware
fallbacks, single-worker execution, and non-brittle selectors aligned to the
current UI contracts.
Mark verified plan/evidence checklists complete after re-validating backend,
frontend, E2E, security isolation, and infrastructure commands.
Stabilize test harness across full stack:
Backend integration tests:
- Fix Auth/Club/Migration/RLS/Member/Tenant/RLS Isolation/Shift/Task test suites
- Add AssemblyInfo.cs for test configuration
- Enhance CustomWebApplicationFactory + TestAuthHandler for stable test environment
- Expand RlsIsolationTests with comprehensive multi-tenant RLS verification
Frontend test harness:
- Align vitest.config.ts with backend API changes
- Add bunfig.toml for bun test environment stability
- Enhance api.test.ts with proper test setup integration
- Expand test/setup.ts with fixture initialization
All tests now passing: backend 12/12 unit + 63/63 integration, frontend 45/45
Resolve post-login routing and tenant context issues by proxying frontend API
calls, redirecting authenticated users away from /login, and hardening club
loading with retries/loading guards.
Align tenant identity end-to-end by returning tenantId in /api/clubs/me and
sending X-Tenant-Id from cookie-backed tenantId instead of local clubId,
restoring authorized tasks/shifts data access after club selection.
Simplify root page to redirect to /login on server side, eliminating
unnecessary client-side logic.
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
NextAuth.js v5 requires an explicit API route to expose authentication endpoints.
Added missing route handler at frontend/src/app/api/auth/[...nextauth]/route.ts that imports and exports handlers from the auth configuration.
This fixes:
- /api/auth/signin endpoint (was 404)
- /api/auth/callback endpoint
- /api/auth/session endpoint
- Frontend authentication flow initialization
Verification: Endpoint now returns HTTP 200 and frontend loads without ClientFetchError.
Implements Tasks 23 & 24: Backend and Frontend Dockerfiles
Backend Dockerfiles:
- Dockerfile.dev: Development with dotnet watch hot reload
- Base: sdk:10.0, installs dotnet-ef tool
- Layer caching: csproj files copied before source
- Entry: dotnet watch run with --no-restore
- Dockerfile: Production multi-stage build
- Build stage: sdk:10.0, restore + build + publish
- Runtime stage: aspnet:10.0-alpine (~110MB)
- Health check: /health/live endpoint
- Non-root: USER app (built-in)
Frontend Dockerfiles:
- Dockerfile.dev: Development with Bun hot reload
- Base: node:22-alpine, installs Bun globally
- Layer caching: package.json + bun.lock before source
- Command: bun run dev
- Dockerfile: Production standalone 3-stage build
- Deps stage: Install with --frozen-lockfile
- Build stage: bun run build → standalone output
- Runner stage: node:22-alpine with non-root nextjs user
- Copies: .next/standalone, .next/static, public
- Health check: Node.js HTTP GET to port 3000
- Entry: node server.js (~240MB)
All Dockerfiles use layer caching optimization and security best practices.
Note: Docker build verification skipped (Docker daemon not running).
Implements Task 19: Task List + Task Detail + Status Transitions UI
New components:
- useTasks hook: TanStack Query hooks (useTasks, useTask, useCreateTask, useUpdateTask)
- Task list page: shadcn Table with status filter, pagination, status badges
- Task detail page: Full task info with valid status transition buttons
- New task form: Create task with title, description, assigneeId, dueDate
Key features:
- Status transitions match backend logic: Open→Assigned→InProgress→Review→Done
- Review status allows back-transition to InProgress (only bidirectional)
- Only valid next states shown as buttons (VALID_TRANSITIONS map)
- Status badge colors: Open=gray, Assigned=blue, InProgress=yellow, Review=red, Done=green
- TanStack Query with automatic cache invalidation on mutations
- Next.js 15+ async params pattern (use() hook)
TDD:
- 3 task list tests (renders rows, status badges, new task button)
- 3 task detail tests (Open→Assigned, InProgress→Review, Review→Done+InProgress)
All tests pass (31/31). Build succeeds.
- Add middleware.ts for route protection (redirects unauthenticated users to /login)
- Add useActiveClub() hook for managing active club context (localStorage + session)
- Add apiClient() fetch wrapper with automatic Authorization + X-Tenant-Id headers
- Configure vitest with jsdom environment and global test setup
- Add comprehensive test coverage: 16/16 tests passing (hooks + API utility)
- Install test dependencies: vitest, @testing-library/react, @vitejs/plugin-react, happy-dom
Task 10 COMPLETE - all acceptance criteria met
- Install next-auth@5.0.0-beta.30 and @auth/core@0.34.3
- Configure Keycloak OIDC provider with JWT and session callbacks
- Add module augmentation for JWT and Session types (clubs claim support)
- Export auth handlers and configuration
INCOMPLETE: Missing middleware.ts, useActiveClub() hook, API utility, and tests
Will complete in follow-up session resumption