- Remove 'Configure insecure registry' step from both backend and frontend jobs
- systemctl not available in Gitea Actions container environment
- Runner host must be pre-configured with insecure registry support
- Fixes: System has not been booted with systemd error
- Remove 'Configure insecure registry' step from both jobs
- systemctl is not available in Gitea Actions container environment
- Runner host must be pre-configured with insecure registry in daemon.json
- This is a one-time setup by administrator on the runner host
- Resolves: System has not been booted with systemd as init system error
- Add Docker daemon configuration step to both backend and frontend jobs
- Configure insecure-registries to allow HTTP connections to registry
- Restart Docker daemon and verify configuration
- Resolves HTTP error when pushing to HTTP-only registry at 192.168.241.13:8080
- Add Docker daemon configuration step to both backend and frontend jobs
- Configure insecure-registries to allow HTTP connections to registry
- Restart Docker daemon and verify configuration
- Resolves HTTP error when pushing to HTTP-only registry at 192.168.241.13:8080
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.
Create fresh NpgsqlConnection per tenant iteration instead of reusing
EF Core's managed connection. This prevents connection disposal issues
when iterating over multiple tenant IDs from the JWT clubs claim.
The fix ensures each iteration has its own connection lifecycle with
proper SET LOCAL app.current_tenant_id for RLS compliance.
- Add path exemption in TenantValidationMiddleware for /api/clubs/me
- Change authorization policy from RequireMember to RequireViewer
- Fix KEYCLOAK_CLIENT_ID in docker-compose.yml (workclub-app not workclub-api)
- Endpoint now works without X-Tenant-Id header as intended
- Other endpoints still protected by tenant validation
This fixes the chicken-and-egg problem where frontend needs to call
/api/clubs/me to discover available clubs before selecting a tenant.
- Add path exemption in TenantValidationMiddleware for /api/clubs/me
- Change authorization policy from RequireMember to RequireViewer
- Fix KEYCLOAK_CLIENT_ID in docker-compose.yml (workclub-app)
- Resolves frontend chicken-and-egg problem for club discovery
Verified:
- /api/clubs/me returns 200 OK without X-Tenant-Id header
- /api/tasks still requires X-Tenant-Id (400 Bad Request)
- Other endpoints unaffected
Simplify root page to redirect to /login on server side, eliminating
unnecessary client-side logic.
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Update realm-export.json with fixed UUID endianness, correct passwords,
mappers, and SSL configuration. Add ALTER DEFAULT PRIVILEGES for app_admin
in PostgreSQL init.sh to ensure proper role permissions.
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Reorganize SeedDataService to establish RLS policies before granting
app_admin role to prevent permission issues. Remove --no-restore flag
from Dockerfile.dev to ensure proper build.
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Set tenant context before querying DB in ClubRoleClaimsTransformation.TransformAsync
to avoid chicken-and-egg problem where tenant context is needed but not yet available.
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
PostgreSQL SET LOCAL only persists within a transaction scope. Added explicit transaction creation if none exists, ensuring tenant context is properly set before queries execute. Fixes tenant isolation for multi-tenant RLS filtering.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Allow SET LOCAL execution for all database commands by removing the transaction check.
EF Core creates implicit transactions for queries, so SET LOCAL works regardless.
This fixes the issue where read operations without explicit transactions were not getting
tenant context set properly, leading to incorrect RLS filtering and data visibility.
- Replaced placeholder UUIDs (club-1-uuid, club-2-uuid) with real database UUIDs
- Updated all 5 test users via Keycloak database
- Restarted Keycloak to clear caches and apply changes
Impact:
- JWT tokens now contain real UUIDs in clubs claim
- API endpoints accept X-Tenant-Id with real UUIDs (returns 200 OK)
- Unblocks 46 remaining QA scenarios
Documentation:
- Created update-keycloak-club-uuids.py script for automation
- Added KEYCLOAK_UPDATE_GUIDE.md with step-by-step instructions
- Recorded learnings in notepad
Ref: .sisyphus/evidence/final-f3-manual-qa.md lines 465-512
- Added Keycloak audience protocol mapper to workclub-app client
- Maps 'workclub-api' to aud claim in access tokens
- Disabled issuer validation in API for local dev
- External clients use localhost:8080, internal use keycloak:8080
- Prevents validation mismatch in Docker network environment
This resolves 401 Unauthorized errors on all authenticated endpoints.
Ref: .sisyphus/evidence/final-f3-manual-qa.md lines 418-444
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.
- Changed KEYCLOAK_ID → KEYCLOAK_CLIENT_ID
- Changed KEYCLOAK_SECRET → KEYCLOAK_CLIENT_SECRET
- Fixes 'ClientFetchError: The string did not match the expected pattern'
- Frontend now loads successfully at http://localhost:3000
- Updated project summary to document fix (Blocker #5 resolved)
- Removed invalid init.sql with syntax error (ALTER DEFAULT PRIVILEGES IN DATABASE unsupported)
- Added init.sh with corrected SQL using IN SCHEMA public
- Fixes PostgreSQL initialization for RLS and permissions setup
Ultraworked with Sisyphus <https://github.com/code-yeongyu/oh-my-opencode>
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Verified and marked as complete:
- ✅ All frontend tests pass (45/45 passing after test infrastructure fix)
- ✅ Kustomize manifests build without errors (verified in Task 25)
- ✅ All Must NOT Have items absent (verified via grep - no MediatR, Swashbuckle, generic repo, CQRS, event sourcing)
Confirmed correct patterns in use:
- ✅ Finbuckle MultiTenant
- ✅ Built-in OpenAPI (not Swashbuckle)
- ✅ Direct DbContext usage (no repository pattern)
- ✅ RLS with SET LOCAL (17 occurrences)
Progress: 28/53 checkboxes complete (53%)