← ClaudeAtlas

supabaselisted

Build on Supabase correctly — Row Level Security, auth, realtime, storage, edge functions, and the Postgres underneath. Use when wiring a Supabase client, writing or reviewing RLS policies, debugging "anyone can read everyone's rows", setting up auth, adding realtime subscriptions, handling file storage, or deciding what belongs in an edge function vs the database. The
kouroshez/coding-os · ★ 4 · API & Backend · score 76
Install: claude install-skill kouroshez/coding-os
# Supabase Supabase is Postgres with a public API in front of it. That inversion is the whole risk model: the `anon` key ships to the browser, so **the database — not the application — is the security boundary**. Row Level Security is not optional hardening; it is the only thing standing between a user and everyone else's rows. > Scan a migration for tables left without RLS: > `python3 scripts/check_rls.py supabase/migrations/*.sql` ## RLS is the security boundary (enable it on every table) ```sql -- Wrong — table is reachable via the anon key with NO policy = fully public create table notes (id uuid primary key, user_id uuid, body text); -- Correct — enable RLS, then policies grant the minimum create table notes (id uuid primary key, user_id uuid references auth.users, body text); alter table notes enable row level security; create policy "owner reads own notes" on notes for select using (auth.uid() = user_id); create policy "owner writes own notes" on notes for insert with check (auth.uid() = user_id); ``` A table created without `enable row level security` is readable and writable by anyone holding the `anon` key — which is every visitor. Enable RLS on **every** table in a public schema, then add policies. `using` filters which rows are visible/updatable; `with check` validates rows being inserted/updated. Detail → [references/rls-and-auth.md](references/rls-and-auth.md). ## The two keys — never confuse them ``` anon key → ships to the browser. RLS appl