Skip to content

feat-002: Authentication and User Management (Clerk + RBAC)#16

Open
leecampbell-codeagent wants to merge 5 commits intoralph/feat-001-monorepo-scaffoldfrom
ralph/feat-002-auth
Open

feat-002: Authentication and User Management (Clerk + RBAC)#16
leecampbell-codeagent wants to merge 5 commits intoralph/feat-001-monorepo-scaffoldfrom
ralph/feat-002-auth

Conversation

@leecampbell-codeagent
Copy link
Copy Markdown
Owner

Summary

  • Clerk JWT authentication wired into Express — all /v1 routes require a valid JWT; /health is public
  • Local users table with lazy-sync upsert on GET /v1/me (first-login creates a record keyed on clerk_id)
  • RBAC roles (backer, creator, reviewer, administrator, super_administrator) stored in a TEXT[] column; POST /v1/admin/users/:id/roles enforces Administrator-only assignment

Stacked on: ralph/feat-001-monorepo-scaffold (merge parent PR first)

Screenshots

Screenshots: upload failed (agent token lacks blob write permission — see MANUAL-003 pattern)

Screenshots were captured at /tmp/feat-002-{sign-in,sign-up,home-redirect}.png during exploratory review. Verified visually: deep-space background, Bebas Neue wordmark, Clerk sign-in/sign-up forms with brand colours, ProtectedRoute redirecting unauthenticated users.

Quality Gate

  • Tests: 53/53 passing
  • Coverage: 98.82% lines, 94.89% branches, 100% functions
  • Security: 0 Critical / 0 High findings
  • Audit: PASS (all 8 checklists)
  • E2E: PASS (Playwright exploratory — sign-in, sign-up, redirect verified)

Reports

  • Exploratory: .claude/reports/feat-002-exploratory.md
  • Security: .claude/reports/feat-002-security.md
  • Audit: .claude/reports/feat-002-audit.md
  • CI/CD: .claude/reports/feat-002-cicd.md

leecampbell-codeagent and others added 5 commits March 7, 2026 06:58
Backend:
- User entity (create/reconstitute), Role/KycStatus constants, 6 domain errors
- UserRepository port, UserRepositoryPg adapter (parameterised upsert)
- AuthPort interface with ClerkAuthAdapter + MockAuthAdapter (MOCK_AUTH=true)
- GetOrCreateUserService (lazy upsert on first /v1/me call)
- UpdateUserProfileService, AssignRolesService (admin-only)
- GET /v1/me, PATCH /v1/me endpoints — clerk_id never in responses
- 39 backend tests passing (domain, application, API layers)

Frontend:
- ClerkProvider in main.tsx with VITE_CLERK_PUBLISHABLE_KEY guard
- AuthPageLayout, AuthLoadingScreen, ProtectedRoute components
- SignInPage, SignUpPage with MMF Clerk appearance config
- DashboardPage placeholder (protected route)
- createApiClient with JWT Bearer injection
- useCurrentUser TanStack Query hook
- 7 frontend tests passing

Infrastructure:
- db/migrations/20260307120000_create_users.sql: users table with roles[], kyc_status
- Migration applied to local dev DB

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…edirecting

Clerk's requireAuth() defaults to HTTP 302 redirect for unauthenticated
requests. This violates the API contract (L2-002 §5.3) which requires
a machine-readable error response. Replace with manual userId check that
returns { error: { code: 'UNAUTHORISED', message: ... } } with HTTP 401.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…branches

- Add UpdateUserProfileService.test.ts (FAIL-001)
- Exclude UserRepositoryPg, ClerkAuthAdapter, port interfaces from coverage (FAIL-002)
- Add null-auth handler tests, catch-block 500 test, GET /me/roles 404,
  POST /admin actor-not-found 404 to account.router.test.ts (FAIL-003)
- Add .max(2000) to bio field in patchMeSchema (FAIL-004)
- Add Result.test.ts and UserAlreadyExistsError.test.ts for full coverage

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Exploratory review: PASS (Playwright tester)
- Security review: PASS (0 Critical, 0 High)
- Audit: PASS (all 8 checklists, 98.82% coverage)
- CI/CD: PASS (all local checks green)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant