Design: Auth & Admin Roles
Authentication
- Provider: Supabase Auth.
- Method: JWT (JSON Web Token) passed in the
Authorization: Bearer <token>header. - Verification: The backend calls
supabase.auth.get_user(token)to verify the token is valid and not expired.
Admin Authorization (Updated 2026-02-16)
We are moving toward JWT + role as the primary source of truth for admin authorization. The static X-Admin-Key is now a secondary bootstrap mechanism and will be phased out.
Primary: Supabase JWT Role
- Implementation:
get_current_admindependency. - Check: Validates Supabase JWT and ensures
user_metadata.role == 'admin'. - Status: Production default.
Secondary: X-Admin-Key
- Purpose: Internal scripts or bootstrap if Supabase Auth is unavailable.
- Header:
x-admin-key. - Status: Deprecated (Transition Phase).
Roles Model
Roles are stored in the user's app_metadata or user_metadata in Supabase.
- student: Default role. Can chat and view their own wallet.
- teacher: (Future) Can view analytics for their classes.
- admin: Can trigger scrapers, upload curriculum, manage the vector index, and manage users.
Admin Dashboard API
The following endpoints support the Admin Dashboard:
- GET /admin/users: List all users with pagination.
- PATCH /admin/users/{user_id}/role: Update a user's role (admin, student, teacher).
- GET /admin/references: List all curriculum references found by scrapers.
- GET /admin/scrape-runs: Monitor scraping history.
- POST /admin/vector-embedding: Trigger ingestion for a specific reference.
- POST /admin/upload-curriculum: Manual PDF upload and ingestion.
Future: Custom Claims
Plan to migrate roles into JWT Custom Claims via Supabase Postgres Hooks for faster authorization checks without a DB lookup.