DR-091 — Anon table grants are retracted and every policy names its roles; there is no event trigger for this
The squash baseline set ALTER DEFAULT PRIVILEGES … GRANT ALL ON TABLES TO anon, so 70
public tables were born anon-readable over the public Data API.
20260724233500_id347_anon_lockdown.sql retracts it on public and api.
Unlike the function case (DR-035), there is NO event trigger and no CI gate here. This
is authoring discipline: a migration that re-adds a default GRANT re-opens the surface
silently. Every new SELECT policy MUST name its roles explicitly
(TO authenticated, service_role) — the actual id-347 exposure was six policies written
with no TO clause, which therefore targeted PUBLIC with USING (true).
check-api-view-coverage.ts INV-10 does not cover this: it asserts only that anon has no
write on api views, and anon SELECT is explicitly permitted by that invariant. That is
why nothing caught id-347.
Detail: canonical:supabase/CLAUDE.md.