Skip to content

feat: migrate from Clerk+NeoDB to Supabase Auth+DB - #105

Merged
crewcricle merged 4 commits into
mainfrom
vorflux/clerk-to-supabase-migration
Jul 25, 2026
Merged

feat: migrate from Clerk+NeoDB to Supabase Auth+DB#105
crewcricle merged 4 commits into
mainfrom
vorflux/clerk-to-supabase-migration

Conversation

@crewcricle

@crewcricle crewcricle commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Migrates crewRoster web from Clerk + NeoDB to Supabase Auth + Supabase DB, unifying web and mobile on the same auth/database stack. Fixes 11 security and functional issues found during audit, plus 3 additional API routes that still accepted client-supplied tenantId.

Changes

  • Auth + DB migration: Replaced Clerk + NeoDB with Supabase Auth (@supabase/ssr) + Supabase JS client across all API routes, middleware, auth hooks, and UI components (login, signup, demo)
  • P0-2 Server-side tenant enforcement: All 6 API routes (roster, timesheets, timesheets/approve, profiles, user/profile, checkout) now derive tenantId server-side via requireAuth() → profile lookup. No route accepts tenantId from query params or request body. All client-side callers updated to stop sending it.
  • Soft-delete enforcement: save-shifts and push notification edge function now use soft-delete (deleted_at) instead of hard DELETE; push token unregister on mobile also uses soft-delete
  • Realtime roster: Enabled Supabase Realtime subscription + 30s polling fallback so roster changes appear without page refresh
  • tenant_members table: Added with RLS policies, REPLICA IDENTITY FULL, and signup triggers (handle_new_user, handle_invited_user)
  • Migration cleanup: Deleted duplicate 20240001_core_schema.sql, moved .superseded to docs/archive/, removed channels/messages from RLS policies
  • Fixup migration (20260725_fixup_tenants_columns.sql): Added missing tenants.slug and tenants.owner_id columns (referenced by handle_new_user trigger but missing from core schema); fixed tenant_members.role DEFAULT from invalid 'member' to valid 'employee'
  • Component split: RosterGrid.tsx (774→220 lines) extracted into ShiftCreationModal.tsx, ShiftItem.tsx, RosterHeader.tsx
  • Database types: Generated full typed Database interface from migrations in packages/validators/src/database.types.ts (9 tables, functions, enums, relationships)
  • Test consolidation: Deleted stale tests/web/ (4 spec files, all scenarios covered by apps/web/e2e/); deleted root playwright.config.ts
  • CodeQL fixes: Removed 3 unused variables/imports flagged by CodeQL
  • Dependencies: Removed @clerk/nextjs, @neondatabase/serverless, postgres; added @supabase/ssr, @supabase/supabase-js

Testing

  • pnpm tsc --noEmit in packages/validators/passes
  • pnpm tsc --noEmit in apps/web/passes
  • pnpm --filter @packages/validators test51/51 passing (4 test files: conflicts, conflict edge cases, shift, auth)
  • pnpm installpasses
  • E2E tests (apps/web/e2e/) and RLS pgTap verification pending live Supabase project access

Session Details

  • Session: View Session
  • Requested by: Unknown
  • Address comments on this PR. Add (aside) to your comment to have me ignore it.

- Replace Clerk auth with Supabase Auth (@supabase/ssr) middleware
- Migrate all API routes from NeoDB sql() to Supabase client
- Add server-side tenant verification (tenantId from auth session, not request)
- Fix hard deletes: save-shifts and push tokens now use soft-delete
- Fix /api/user/profile data leak (remove arbitrary userId param)
- Fix /api/checkout auth (requireAuth + role check)
- Add tenant_members table migration with RLS policies
- Add signup trigger: handle_new_user creates tenant + profile + membership
- Deduplicate conflict detection: import from @packages/validators
- Fix mobile availability INSERT to include tenant_id
- Delete duplicate 20240001_core_schema.sql migration
- Update env.example for Supabase credentials
@strix-security

Copy link
Copy Markdown

Strix is installed on this repository, but we couldn't run this PR security review because this workspace's trial has ended. Add a card to resume code reviews here.

@vercel

vercel Bot commented Jul 23, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
crew-roster Ready Ready Preview, Comment Jul 25, 2026 3:40am

- Implement realtime roster refresh via Supabase Realtime + 30s polling fallback
- Update demo mode to use Supabase Auth signInWithPassword (replace Clerk tokens)
- Fix mobile push token insert to include tenant_id
- Fix mobile push token unregister to use soft-delete instead of DELETE
- Add REPLICA IDENTITY FULL for shifts, rosters, clock_events
- Remove empty ui-shared package
- P2-3: Generate Database types from migrations into
  packages/validators/src/database.types.ts with full Table/Row/Insert/Update
  types for all 9 tables plus Functions and Enums. Added database export
  path to package.json.
- P2-4: Delete stale tests/web/ directory and root playwright.config.ts
  (all test cases already covered by apps/web/e2e/).
- Fix migration landmine: create 20260725_fixup_tenants_columns.sql adding
  missing tenants.slug and tenants.owner_id columns (referenced by
  handle_new_user trigger), and fix tenant_members.role DEFAULT from
  invalid 'member' to valid 'employee'.
Comment thread apps/web/src/features/roster/RosterGrid.tsx Fixed
Comment thread apps/web/src/features/roster/RosterGrid.tsx Fixed
Comment thread apps/web/src/features/roster/RosterHeader.tsx Fixed
…les routes

Three API routes still accepted tenantId from request params (GET + POST),
enabling cross-tenant data access. This completes the P0-2 security fix:

- /api/roster: GET and POST now derive tenantId via getTenantId() instead
  of searchParams.get('tenantId') and body.tenantId
- /api/timesheets: Derives tenantId server-side, removes from query params
- /api/profiles: Derives tenantId server-side, removes from query params

All client-side API callers updated to stop sending tenantId:
- rosterApi.fetchCurrentRoster(weekStart) — removed tenantId param
- rosterApi.copyForwardRoster(weekStart, rosterId) — removed tenantId param
- useTimesheets — removed tenantId from query string
- RosterGrid — removed tenantId from /api/profiles fetch and create-shift POST
- rosterStore — removed tenantId from fetchCurrentRoster and copyForwardRoster
- useRosterRealtime — removed tenantId from fetchCurrentRoster calls

CodeQL fixes:
- Removed unused format import from RosterHeader.tsx
- Removed unused modalEmployeeId/modalDayIndex state from RosterGrid.tsx
@crewcricle
crewcricle merged commit 83880e7 into main Jul 25, 2026
8 checks passed
@crewcricle
crewcricle deleted the vorflux/clerk-to-supabase-migration branch July 25, 2026 04:10
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.

2 participants