Authentication Flow
The authentication flow differs between mobile and web:Mobile (Current)
Web (Phase 2)
Authorization Layers
Recipe Room uses different authorization strategies per platform:Supabase RLS (Both Platforms)
Row Level Security is the primary authorization layer. Every table has RLS policies that enforce access control at the database level. This is the security backbone — even if application code has a bug, RLS prevents unauthorized data access.
Storage Policies (Both Platforms)
Supabase Storage policies restrict file uploads based on ownership. Users can only upload to their own folder path (matched against
auth.uid()).Mobile vs Web Security Model
The mobile app calls Supabase directly for all reads, writes, and authentication — via RPC functions, table queries, and
supabase.auth methods. There are no web API route dependencies. RLS policies are the primary security boundary./api/*) for an additional server-side validation layer. But for mobile, Supabase RLS + client-side Zod validation is the security model.
- Mobile:
supabaseclient fromsrc/lib/supabase.ts(anon key, user JWT via SecureStore) - Web:
lib/supabase/client.tsfor browser reads,lib/supabase/server.tsfor API routes (service role) - Never expose
SUPABASE_SERVICE_ROLE_KEYto any client
Input Validation
Inputs are validated client-side using Zod schemas from the shared package. On web (Phase 2), the same schemas validate server-side in API routes:Error Responses (Web API — Phase 2)
Standardized error format across all web API routes:| Function | Status Code |
|---|---|
validationError() | 400 |
unauthorizedError() | 401 |
forbiddenError() | 403 |
notFoundError() | 404 |
conflictError() | 409 |
internalError() | 500 |