WorkClub Automation
0ef1d0bbd4
feat(shifts): add Shift CRUD API with sign-up/cancel and capacity management
...
- ShiftService with 7 methods: list, detail, create, update, delete, signup, cancel
- 5 DTOs: ShiftListDto, ShiftDetailDto, CreateShiftRequest, UpdateShiftRequest, ShiftSignupDto
- Minimal API endpoints: GET /api/shifts, GET /api/shifts/{id}, POST, PUT, DELETE, POST /signup, DELETE /signup
- Capacity validation: sign-up rejected when full → 409 Conflict
- Past shift blocking: cannot sign up for past shifts → 422 Unprocessable
- Duplicate signup prevention: check existing before create → 409 Conflict
- Concurrency: 2-attempt retry loop for last-slot race conditions
- Authorization: POST/PUT (Manager+), DELETE (Admin), signup/cancel (Member+)
- Test infrastructure: Added X-Test-UserId header support for member ID injection
- 13 TDD integration tests: CRUD, sign-up, capacity, past shift, concurrency
- Build: 0 errors (6 BouncyCastle warnings expected)
Task 15 complete. Wave 3: 3/5 tasks done.
2026-03-03 19:30:23 +01:00
WorkClub Automation
8dfe32dc95
docs(plan): mark Task 14 complete
2026-03-03 19:19:27 +01:00
WorkClub Automation
8550dd213a
feat(tasks): add Task CRUD API with 5-state workflow
...
- TaskService with CRUD operations + state machine enforcement
- 5 DTOs: TaskListDto, TaskDetailDto, CreateTaskRequest, UpdateTaskRequest
- Minimal API endpoints: GET /api/tasks, GET /api/tasks/{id}, POST, PATCH, DELETE
- State machine: Open→Assigned→InProgress→Review→Done (invalid transitions → 422)
- Concurrency: DbUpdateConcurrencyException → 409 Conflict
- Authorization: POST (Manager+), DELETE (Admin), GET/PATCH (Member+)
- RLS: Automatic tenant filtering via TenantDbConnectionInterceptor
- 10 TDD integration tests: CRUD, state transitions, concurrency, role enforcement
- Build: 0 errors (6 BouncyCastle warnings expected)
Task 14 complete. Wave 3: 2/5 tasks done.
2026-03-03 19:19:21 +01:00
WorkClub Automation
cff101168c
test(rls): add multi-tenant isolation integration tests
...
- 6 comprehensive RLS tests: complete isolation, no context, insert protection, concurrent requests, cross-tenant spoof, interceptor verification
- Uses Testcontainers PostgreSQL + Dapper for raw SQL validation
- Parallel safety test: 50 concurrent requests with ConcurrentBag
- Build passes: 0 errors (6 expected BouncyCastle warnings)
- Evidence: task-13-rls-isolation.txt (21KB), task-13-concurrent-safety.txt
- Learnings: RLS testing patterns, SET LOCAL vs SET, concurrent testing with Task.WhenAll
Task 13 complete. Wave 3: 1/5 tasks done.
2026-03-03 19:11:01 +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
4322ec925d
docs(plan): mark Tasks 1-9, 11-12 as complete
...
Wave 1 (Tasks 1-6): COMPLETE
Wave 2 (Tasks 7-12): Tasks 7-9, 11-12 COMPLETE; Task 10 partial (auth config only)
2026-03-03 18:53:12 +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
3a82933fd5
fix(backend): simplify Finbuckle namespace imports and register DB interceptors
...
- Use consolidated Finbuckle.MultiTenant namespace instead of separate imports
- Switch TenantProvider to use untyped IMultiTenantContextAccessor (Finbuckle 9.x pattern)
- Register TenantDbConnectionInterceptor and SaveChangesTenantInterceptor as singletons
- Add interceptors to DbContext configuration for RLS tenant context support
- Update evidence files for Task 7 and Task 8 verification
2026-03-03 18:52:35 +01:00
WorkClub Automation
c9cb629ddb
fix(backend): use explicit Finbuckle.MultiTenant namespace imports
2026-03-03 14:32:55 +01:00
WorkClub Automation
eff6fded72
chore(backend): clean up redundant Finbuckle package and add ITenantProvider interface
2026-03-03 14:32:43 +01:00
WorkClub Automation
28964c6767
feat(backend): add PostgreSQL schema, RLS policies, and multi-tenant middleware
...
- Add EF Core migrations for initial schema (clubs, members, work_items, shifts, shift_signups)
- Implement RLS policies with SET LOCAL for tenant isolation
- Add Finbuckle multi-tenant middleware with ClaimStrategy + HeaderStrategy fallback
- Create TenantValidationMiddleware to enforce JWT claims match X-Tenant-Id header
- Add tenant-aware DB interceptors (SaveChangesTenantInterceptor, TenantDbConnectionInterceptor)
- Configure AppDbContext with tenant scoping and RLS support
- Add test infrastructure: CustomWebApplicationFactory, TestAuthHandler, DatabaseFixture
- Write TDD integration tests for multi-tenant isolation and RLS enforcement
- Add health check null safety for connection string
Tasks: 7 (PostgreSQL schema + migrations + RLS), 8 (Finbuckle multi-tenancy + validation), 12 (test infrastructure)
2026-03-03 14:32:21 +01:00
WorkClub Automation
b9edbb8a65
feat(auth): add Keycloak JWT authentication and role-based authorization
...
- Configure JWT Bearer authentication with Keycloak realm integration
- Create ClubRoleClaimsTransformation to parse 'clubs' claim and add ASP.NET roles
- Add authorization policies: RequireAdmin, RequireManager, RequireMember, RequireViewer
- Add health check endpoints (/health/live, /health/ready, /health/startup)
- Add integration tests for authorization (TDD approach - tests written first)
- Configure middleware order: Authentication → MultiTenant → Authorization
- Add Keycloak configuration to appsettings.Development.json
- Add AspNetCore.HealthChecks.NpgSql v9.0.0 package
TDD Verification:
- Tests initially FAILED (expected before implementation) ✓
- Implementation complete but blocked by Task 8 Infrastructure errors
- Cannot verify tests PASS until Finbuckle.MultiTenant types resolve
Security Notes:
- RequireHttpsMetadata=false for dev only (MUST be true in production)
- Claims transformation maps Keycloak roles (lowercase) to ASP.NET roles (PascalCase)
- Health endpoints are public by default (no authentication required)
Blockers:
- Infrastructure project has Finbuckle.MultiTenant type resolution errors from Task 8
- Tests cannot execute until TenantProvider compilation errors are fixed
2026-03-03 14:27:30 +01:00
Sisyphus CI
b7854e9571
feat(seed): add development seed data script
...
- Create SeedDataService in Infrastructure/Seed with idempotent seeding
- Seed 2 clubs: Sunrise Tennis Club, Valley Cycling Club
- Seed 7 member records (5 unique Keycloak test users)
- Seed 8 work items covering all status states
- Seed 5 shifts with date variety (past, today, future)
- Seed shift signups for realistic partial capacity
- Register SeedDataService in Program.cs with development-only guard
- Use deterministic GUID generation from club names
- Ensure all tenant IDs match for RLS compliance
- Track in learnings.md and evidence files for Task 22 QA
2026-03-03 14:23:50 +01:00
WorkClub Automation
c44cb1c801
docs(frontend): add Task 5 Next.js setup learnings and evidence
2026-03-03 14:11:15 +01:00
WorkClub Automation
a1032484bd
docs(k8s): add Task 6 Kustomize base manifests learnings
...
- Kustomize vs Helm trade-offs and base+overlay pattern
- K8s resource naming conventions with workclub- prefix
- .NET health probe semantics (startup/liveness/readiness)
- StatefulSet + headless service pattern for Postgres
- PostgreSQL 16-alpine with pg_isready health check
- Keycloak 26.x production mode configuration
- Ingress path-based routing (/ → frontend, /api → backend)
- ConfigMap strategy for non-sensitive configuration
- Resource requests/limits placeholders for overlays
- Image tag strategy with :latest placeholder
- Gotchas: serviceName, headless service publishNotReadyAddresses, probe timeouts
2026-03-03 14:10:04 +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
OpenCode Assistant
cf7b47cb69
infra(docker): add Docker Compose with PostgreSQL and Keycloak
...
- Add docker-compose.yml (v3.9) with postgres:16-alpine and keycloak:26.1 services
- Configure PostgreSQL with separate workclub and keycloak databases
- Setup Keycloak with database backend, admin user, and realm import capability
- Create PostgreSQL init script to provision development databases and users
- Add placeholder realm-export.json for Keycloak realm configuration
- Configure healthchecks and app-network bridge for service discovery
- Document configuration and patterns in learnings.md
2026-03-03 14:07:29 +01:00
Sisyphus Executor
c7dd3299d7
chore(scaffold): initialize git repo and monorepo with .NET solution
2026-03-03 14:02:37 +01:00