Backend Clerk token verification and Supabase data layer, in one commit
`a7ea67d0` completes the Clerk migration on the backend side and consolidates document storage on Supabase, dropping the Cloudflare R2 requirement. It rewrites auth middleware, schema constraints, account deletion, user-lookup endpoints, and object storage configuration in 492 additions across 19 files.
The auth change is the core of the commit. backend/src/middleware/auth.ts previously validated Supabase tokens; it now calls @clerk/backend to verify Clerk session JWTs. A new backend/src/lib/clerk.ts holds the Clerk client initialized with CLERK_SECRET_KEY. The resolved Clerk user id lands in res.locals.userId. Downstream code that does row.user_id === user.id works without changes because the frontend and backend now share the same Clerk id.
Clerk session tokens don't carry email, so email resolution became a separate step. The backend now calls the Clerk API with a short-lived cache. A lookup failure is non-fatal: it yields an empty result for shared-item queries rather than a 500. Sharing endpoints that previously hit Supabase's auth admin API to look up other users were repointed to Clerk's user APIs.
The schema change is a consequence of Clerk ids not being UUIDs. Columns that previously referenced auth.users (which enforces UUID format) were relaxed to plain text. The Supabase Auth signup trigger that auto-created user profiles was dropped; the backend's existing lazy profile creation handles first-login setup instead. Account deletion was rewritten to call Clerk to remove the user in addition to cleaning up database rows. The now-dead Supabase JWT helper was removed.
Storage moved from Cloudflare R2-specific env vars (R2_ENDPOINT_URL, R2_ACCESS_KEY_ID, etc.) to generic S3 vars (S3_ENDPOINT_URL, S3_REGION, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, S3_BUCKET_NAME). The AWS SDK client code needed no changes - Supabase Storage's S3-compatible endpoint at https://<project-ref>.supabase.co/storage/v1/s3 works against the existing client unchanged.
zgbrenner was explicit about what validation exists: TypeScript build and existing frontend tests. The backend has no automated test runner. End-to-end verification requires a live Supabase project and a deployed backend. No multi-tenant isolation was added; Gary stays single-user with per-table user_id filtering.
Spotted something wrong? Or know the PR text has fresher detail than the writeup above?