RLS policies alone don't grant table-level access in Postgres — missing GRANTs caused "permission denied for table profiles" in production even though the RLS policies were correct. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017DUU6CnxECCDeqDNYJgr5x
32 lines
1.8 KiB
SQL
32 lines
1.8 KiB
SQL
-- Fixes a production-only bug: every table in this schema was created with
|
|
-- RLS policies but no Postgres-level GRANTs, which local self-hosted
|
|
-- Supabase's Docker bootstrap happens to pre-grant broadly on the `public`
|
|
-- schema — masking the gap in every local dev/test session so far — but a
|
|
-- fresh Supabase Cloud project does not. Confirmed against Supabase's own
|
|
-- docs (supabase.com/docs/guides/auth/managing-user-data): RLS policies
|
|
-- only ever narrow access an underlying GRANT already allows; with no
|
|
-- GRANT, every request from the `anon`/`authenticated` roles fails at the
|
|
-- Postgres level before RLS is even evaluated ("permission denied for
|
|
-- table ..."), regardless of how permissive the policy is. First surfaced
|
|
-- as CompleteProfileScreen's username-save failing after Google sign-in on
|
|
-- app.diagrav.com.
|
|
--
|
|
-- `authenticated`/`service_role` get full CRUD per table — RLS (already
|
|
-- written and unchanged by this migration) is what actually narrows each
|
|
-- operation to the right rows. `anon` gets SELECT only, matching Supabase's
|
|
-- own least-privilege example; nothing in this app reads `public` schema
|
|
-- tables before sign-in today, but it's a harmless, RLS-gated default to
|
|
-- have in place rather than an under-grant that surfaces as another opaque
|
|
-- "permission denied" later.
|
|
--
|
|
-- The `alter default privileges` statements make this automatic for tables
|
|
-- any future migration creates, so this class of bug can't recur.
|
|
|
|
grant usage on schema public to anon, authenticated, service_role;
|
|
|
|
grant select on all tables in schema public to anon;
|
|
grant select, insert, update, delete on all tables in schema public to authenticated, service_role;
|
|
|
|
alter default privileges in schema public grant select on tables to anon;
|
|
alter default privileges in schema public grant select, insert, update, delete on tables to authenticated, service_role;
|