feat: wire Supabase browser client to WorkOS access token#33
feat: wire Supabase browser client to WorkOS access token#33bryanfawcett wants to merge 1 commit intomainfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
mukoko-nhimbe-api | 9d394e1 | Commit Preview URL Branch Preview URL |
May 08 2026, 06:37 AM |
|
Claude finished @bryanfawcett's task —— View job PR Security & Quality Review
|
The browser Supabase client had no path for the signed-in person's access token, so every direct supabase.* call (Kraal feed, entity host lookups, createEventOnSupabase, getEventHostInfo) was running anon against RLS that reads auth.jwt()->>sub. - src/lib/supabase/client.ts: adds setSupabaseAccessToken(token) and a global.fetch override that injects Authorization: Bearer <token> + apikey on every Supabase request. Module-level token holder so the cached client doesn't need to be torn down on token refresh. - src/components/auth/auth-context.tsx: useEffect keyed on accessToken forwards it into the Supabase client every time WorkOS rotates it. - vitest.config.ts: resolve.alias maps @/ → ./src/ so the new @/lib/supabase/client import in auth-context.tsx resolves under jsdom (Next.js + tsc already understood the alias via tsconfig). Verified: 160 / 160 frontend tests, 283 / 283 worker tests, npm run build clean, npm run lint clean. The stytch_user_id → external_user_id rename was stripped from this PR: a wider D1 → Supabase migration is being scoped separately, so the column rename will be moot once D1 is removed. https://claude.ai/code/session_01Dp6YFZCHz1HjL9svPWmso2
3e4c329 to
9d394e1
Compare
|
Claude finished @bryanfawcett's task —— View job Claude finished @bryanfawcett's task PR Security & Quality Review
|


Why
The browser Supabase client had no path for the signed-in person's access token, so every direct
supabase.*call (Kraal feed,getEntitiesForPerson,createEventOnSupabase,getEventHostInfo) was running anonymously against RLS policies that readauth.jwt()->>sub. This PR wires WorkOS' access token into Supabase so those calls authenticate asidentity.person.id.This PR is now intentionally narrow — the previously-bundled D1 column rename was stripped because D1 itself is being removed in a follow-up migration PR (per direction: "if we have Supabase we don't need D1"). The Supabase ↔ WorkOS token wiring is the foundational unlock for that migration.
What's in this PR
Supabase ↔ WorkOS wiring
src/lib/supabase/client.ts: addssetSupabaseAccessToken(token)and aglobal.fetchoverride that injectsAuthorization: Bearer <token>+apikey: <anon>on every Supabase request. Token holder is module-level, so the cached client doesn't need to be torn down on rotation.src/components/auth/auth-context.tsx:useEffectkeyed onaccessTokencallssetSupabaseAccessToken()whenever WorkOS surfaces a new token.Test infra
vitest.config.ts: addsresolve.aliasmapping@/→./src/. The new@/lib/supabase/clientimport inauth-context.tsxis the first@/import that the auth-context test transitively pulls in; without the alias, vitest's import-analysis can't resolve it. (Next.js +tscalready understood the alias viatsconfig.json— vitest just needed the same map.)What's deferred
A full D1 → Supabase migration (mega-PR, agreed) covers:
auth/sync//me//profilereadingidentity.personinstead of D1usersevents.event/events.organiserevents.rsvp_action+events.ticket+events.waitlist_entryengagement.review+engagement.interaction_counteraudit_logs,kiosk_pairings,payments,event_series) into new Supabase schemasDBbinding fromwrangler.tomltogglePostReactioncolumn-name bug (column isreaction_type, notreaction) — found via Supabase MCP audit while validating this PRVerified clean
Test plan
accessTokenis forwarded into Supabase (devtools network tab: anysupabase.co/rest/v1/*request showsAuthorization: Bearer <jwt>)/kraalwhile signed in → confirm circles list loads (RLS resolvesauth.jwt()->>subto person_id)https://claude.ai/code/session_01Dp6YFZCHz1HjL9svPWmso2