26 Commits

Author SHA1 Message Date
WorkClub Automation
9cb80e4517 fix(auth): restore keycloak sign-in for NodePort access
All checks were successful
CI Pipeline / Backend Build & Test (push) Successful in 58s
CI Pipeline / Frontend Lint, Test & Build (push) Successful in 28s
CI Pipeline / Infrastructure Validation (push) Successful in 4s
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.
2026-03-13 06:52:18 +01:00
WorkClub Automation
e0790e9132 Fix TaskListItemDto missing title/status properties
All checks were successful
CI Pipeline / Backend Build & Test (pull_request) Successful in 49s
CI Pipeline / Frontend Lint, Test & Build (pull_request) Successful in 30s
CI Pipeline / Infrastructure Validation (pull_request) Successful in 3s
2026-03-09 15:53:38 +01:00
WorkClub Automation
672dec5f21 Fix task and shift self-assignment features
Some checks failed
CI Pipeline / Backend Build & Test (pull_request) Successful in 48s
CI Pipeline / Frontend Lint, Test & Build (pull_request) Failing after 28s
CI Pipeline / Infrastructure Validation (pull_request) Successful in 4s
2026-03-09 15:47:57 +01:00
WorkClub Automation
867dc717cc fix(shifts): expose ExternalUserId in ShiftSignupDto to fix frontend signup state
Some checks failed
CI Pipeline / Backend Build & Test (pull_request) Failing after 49s
CI Pipeline / Frontend Lint, Test & Build (pull_request) Successful in 29s
CI Pipeline / Infrastructure Validation (pull_request) Successful in 3s
2026-03-09 14:46:35 +01:00
WorkClub Automation
6119506bd3 fix(frontend): remove invalid json parsing on shift signup
All checks were successful
CI Pipeline / Backend Build & Test (pull_request) Successful in 53s
CI Pipeline / Frontend Lint, Test & Build (pull_request) Successful in 27s
CI Pipeline / Infrastructure Validation (pull_request) Successful in 3s
- 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.
2026-03-09 14:25:12 +01:00
WorkClub Automation
1322def2ea fix(auth): resolve Keycloak OIDC issuer mismatch and API proxy routing
Some checks failed
CI Pipeline / Backend Build & Test (pull_request) Successful in 49s
CI Pipeline / Frontend Lint, Test & Build (pull_request) Failing after 26s
CI Pipeline / Infrastructure Validation (pull_request) Successful in 4s
- 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.
2026-03-09 14:21:03 +01:00
WorkClub Automation
add4c4c627 fix(frontend): restore member self-assignment for shifts and tasks
All checks were successful
CI Pipeline / Backend Build & Test (push) Successful in 1m12s
CI Pipeline / Frontend Lint, Test & Build (push) Successful in 35s
CI Pipeline / Infrastructure Validation (push) Successful in 4s
CI Pipeline / Backend Build & Test (pull_request) Successful in 52s
CI Pipeline / Frontend Lint, Test & Build (pull_request) Successful in 33s
CI Pipeline / Infrastructure Validation (pull_request) Successful in 4s
Root Cause:
- Shift: Next.js 16.1.6 incompatible rewrite pattern caused runtime SyntaxError
- Task: Missing self-assignment UI for member role

Fix:
- Updated next.config.ts rewrite pattern from regex to wildcard syntax
- Added "Assign to Me" button to task detail page with useSession integration
- Added test coverage for self-assignment behavior with session mocks

Testing:
- Lint:  PASS (ESLint v9)
- Tests:  47/47 PASS (Vitest v4.0.18)
- Build:  PASS (Next.js 16.1.6, 12 routes)

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-03-08 19:07:19 +01:00
WorkClub Automation
5cf43976f6 fix(frontend): resolve lint blockers for gitea frontend-ci 2026-03-06 22:26:55 +01:00
WorkClub Automation
4788b5fc50 test(e2e): stabilize Playwright suite and close plan verification
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.
2026-03-06 16:03:03 +01:00
WorkClub Automation
f8f3e0f01e test(harness): stabilize backend+frontend QA test suite (12/12+63/63 unit+integration, 45/45 frontend)
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
2026-03-06 09:19:32 +01:00
WorkClub Automation
9950185213 fix: stabilize auth-to-tenant flow and correct tenant header mapping
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.
2026-03-06 08:01:09 +01:00
WorkClub Automation
5fb148a9eb chore(evidence): add QA evidence and notepads from debugging sessions
Add comprehensive QA evidence including manual testing reports, RLS isolation
tests, API CRUD verification, JWT decoded claims, and auth evidence files.
Include updated notepads with decisions, issues, and learnings from full-stack
debugging sessions.

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-03-05 19:22:55 +01:00
WorkClub Automation
3d14ace20a fix(frontend): add server-side redirect to login
Simplify root page to redirect to /login on server side, eliminating
unnecessary client-side logic.

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-03-05 19:22:45 +01:00
WorkClub Automation
8643c3dfa7 fix(frontend): create NextAuth.js API route handler
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.
2026-03-05 13:59:16 +01:00
WorkClub Automation
b6f4c905d4 test(e2e): add Playwright E2E tests for auth, tasks, and shifts
Tasks 26-28: Comprehensive E2E test suite covering:
- Auth flow with Keycloak OIDC (6 tests)
- Task management lifecycle (10 tests)
- Shift sign-up and capacity enforcement (4 tests)

Total: 20 E2E tests (auth + tasks + shifts + smoke)

Tests require Docker Compose stack to run, but all compile successfully.
2026-03-05 10:34:03 +01:00
WorkClub Automation
364c155f9d fix(test): replace vi.mocked with type casting for Bun compatibility
Fixes technical debt from Tasks 10, 18-20.

Problem:
- 38/46 frontend tests failing due to vi.mocked() not supported in Bun
- happy-dom environment causing document errors in some tests

Solution:
1. Replaced all vi.mocked(fn) calls with (fn as any) type casting
   - useActiveClub.test.ts: 3 occurrences (localStorage mocks)
   - auth-guard.test.tsx: 13 occurrences (useSession, useTenant, useRouter)
   - club-switcher.test.tsx: 3 occurrences (useRouter)
   - task-detail.test.tsx: 4 occurrences (useRouter, useTasks)
   - task-list.test.tsx: 1 occurrence (useTasks)

2. Updated vitest.config.ts:
   - Changed environment from happy-dom to jsdom (better DOM support)
   - Added exclude pattern to prevent e2e tests interference

Test Results:
- Before: 8/46 passing (38 failures)
- After: 45/45 passing (0 failures) 

No source code changes - only test infrastructure fixes.
2026-03-03 21:18:05 +01:00
WorkClub Automation
326a4f30e8 infra(k8s): add dev overlay with resource limits and health checks
Implements Task 25: Kustomize Dev Overlay + Resource Limits + Health Checks

Files Created:
- infra/k8s/overlays/dev/kustomization.yaml - Dev overlay config
  - References base manifests
  - Namespace: workclub-dev
  - Replicas: 1 for all deployments
  - Image tags: dev for workclub-api and workclub-frontend
  - Environment label: development

- infra/k8s/overlays/dev/patches/backend-resources.yaml
  - Backend resources: cpu=50m-200m, memory=128Mi-256Mi
  - Strategic merge patch targeting workclub-api deployment

- infra/k8s/overlays/dev/patches/frontend-resources.yaml
  - Frontend resources: cpu=50m-200m, memory=128Mi-256Mi
  - Strategic merge patch targeting workclub-frontend deployment

- frontend/src/app/api/health/route.ts
  - Missing health endpoint (declared in base manifest but not implemented)
  - Simple Next.js route handler returning {status: 'ok'}

Resource Limits (Dev vs Base):
- Dev: 50m-200m CPU, 128Mi-256Mi memory (50% of base)
- Base: 100m-500m CPU, 256Mi-512Mi memory

Verification:
- kustomize build succeeds (exit 0)
- All deployments replicas=1
- Lower resource limits applied correctly
- Image tags set to dev
- Frontend /api/health route registered
- Evidence saved to .sisyphus/evidence/task-25-kustomize-dev.yaml (495 lines)

Note: commonLabels deprecated warning (non-blocking), consider using labels in future.
2026-03-03 21:11:18 +01:00
WorkClub Automation
6124557f11 infra(docker): add Dockerfiles for backend and frontend
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).
2026-03-03 20:59:20 +01:00
WorkClub Automation
c29cff3cd8 feat(ui): add login page, club picker, and dashboard
Implements Task 21: Login Page + First-Login Club Picker + Dashboard

New pages:
- Login page: Sign in with Keycloak button, clean centered layout
- Select club page: Club selection cards for multi-club users
- Dashboard: Summary with task/shift counts and quick links

Key features:
- Login delegates to Keycloak via NextAuth signIn('keycloak')
- Club picker shows cards with name + sport type
- Clicking club → setActiveClub() → redirects to /dashboard
- Dashboard shows active club name, open tasks count, upcoming shifts count
- Quick action links to /tasks and /shifts pages
- TanStack Query hooks with proper filters (status: 'Open', future shifts only)

TDD:
- 2 login tests (component export, signIn exists)
- 2 select-club tests (component export, useTenant exists)
- 4 dashboard tests (component export, hooks exist)

Task 21 tests: 8/8 pass. Build succeeds (9 routes registered).

Note: 38 pre-existing tests from Tasks 10,18-20 fail due to Bun+vitest
test infrastructure issues (vi.mocked() not supported, localStorage mock).
This is technical debt to be addressed separately.
2026-03-03 20:44:07 +01:00
WorkClub Automation
817c9ba537 feat(ui): add shift management UI with list, detail, and sign-up
Implements Task 20: Shift Sign-Up UI - List + Detail + Create Pages

New components:
- useShifts hook: TanStack Query hooks (useShifts, useShift, useCreateShift, useSignUpShift, useCancelSignUp)
- Shift list page: Card-based UI (NOT table) with capacity bars and Past badges
- Shift detail page: Full info with sign-up/cancel buttons, member list
- New shift form: Create shifts with title, description, location, times, capacity
- ShiftCard component: Reusable card with capacity Progress bar

Key features:
- Card-based UI pattern (shadcn Card, NOT Table - more visual for schedules)
- Capacity calculation: (currentSignups / capacity) * 100 for Progress bar
- Past shift detection: new Date(startTime) < new Date() → shows 'Past' badge
- Sign-up button visibility: !isPast && !isFull && !isSignedUp
- Cancel button visibility: !isPast && isSignedUp
- Role-based 'New Shift' button: Manager/Admin only
- TanStack Query with automatic cache invalidation on mutations
- Navigation includes Shifts link in sidebar

New shadcn components:
- Progress: Radix UI progress bar with transform-based fill
- Textarea: Styled textarea for shift descriptions

TDD:
- 3 shift card tests (capacity display, full capacity, past shifts)
- 3 shift detail tests (sign-up button, cancel button, mutation calls)

All tests pass (37/37: 31 existing + 6 new). Build succeeds.
2026-03-03 20:22:52 +01:00
WorkClub Automation
c8ae47c0bc feat(ui): add task management UI with list, detail, and create pages
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.
2026-03-03 20:12:31 +01:00
WorkClub Automation
46bbac355b feat(ui): add layout, club-switcher, and auth guard
Implements Task 18: App Layout + Club-Switcher + Auth Guard

New components:
- TenantContext: Manages activeClubId state with TanStack Query
- QueryProvider: TanStack Query client wrapper (60s stale time)
- AuthGuard: Auth + tenant redirect logic (unauthenticated → /login)
- ClubSwitcher: shadcn DropdownMenu for switching clubs
- SignOutButton: Simple sign out button
- Protected layout: Sidebar navigation + top bar with ClubSwitcher

Key features:
- Fetches clubs from /api/clubs/me
- Auto-loads activeClubId from localStorage
- Sets X-Tenant-Id cookie on club switch
- Invalidates all queries on club switch
- Redirect logic: unauthenticated → /login, 0 clubs → message, 1 club → auto-select, >1 clubs + no active → /select-club

TDD:
- 6 AuthGuard tests (loading, unauthenticated, 0 clubs, 1 club, multiple clubs, authenticated)
- 3 ClubSwitcher tests (renders current club, lists all clubs, calls setActiveClub on selection)

Dependencies:
- Added @tanstack/react-query

All tests pass (25/25). Build succeeds.
2026-03-03 19:59:14 +01:00
WorkClub Automation
54b893e34e test(frontend): add Playwright E2E test setup
Implement Task 17: Frontend Test Infrastructure - Playwright

Configuration:
- playwright.config.ts: baseURL localhost:3000, Chromium only
- Screenshot on failure, trace on first retry
- Auto-start webServer (bun dev) if not running
- Test directory: ./e2e/

Smoke Test:
- e2e/smoke.spec.ts: Navigate to / and assert page title
- Verifies Next.js app loads successfully

Package Updates:
- Added @playwright/test@^1.58.2
- Added test:e2e script to run Playwright tests
- Chromium browser (v1208) installed

Note: Vitest setup was completed in Task 10
Build: TypeScript checks pass, 1 test discovered
Pattern: Standard Playwright configuration for Next.js
2026-03-03 19:45:06 +01:00
WorkClub Automation
d3f8e329c3 feat(frontend-auth): complete NextAuth.js Keycloak integration with middleware, hooks, and API utility
- 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
2026-03-03 19:01:13 +01:00
WorkClub Automation
6a9f4d52b2 feat(frontend-auth): add NextAuth.js v5 Keycloak integration (partial - Task 10)
- 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
2026-03-03 18:52:44 +01:00
WorkClub Automation
ba024c45be feat(domain): add core entities — Club, Member, WorkItem, Shift with state machine
- Create domain entities in WorkClub.Domain/Entities: Club, Member, WorkItem, Shift, ShiftSignup
- Implement enums: SportType, ClubRole, WorkItemStatus
- Add ITenantEntity interface for multi-tenancy support
- Implement state machine validation on WorkItem with C# 14 switch expressions
- Valid transitions: Open→Assigned→InProgress→Review→Done, Review→InProgress (rework)
- All invalid transitions throw InvalidOperationException
- TDD approach: Write tests first, 12/12 passing
- Use required properties with explicit Guid/Guid? for foreign keys
- DateTimeOffset for timestamps (timezone-aware, multi-tenant friendly)
- RowVersion byte[] for optimistic concurrency control
- No navigation properties yet (deferred to EF Core task)
- No domain events or validation attributes (YAGNI for MVP)
2026-03-03 14:09:25 +01:00