Haven't tried nuvix yet. Defaults-on RLS is the right call for sure, that's the failure mode that catches most people. the trickier bit is that even once RLS is on by default, the policy logic itself still has the auth.uid() = null silent-fail issue, which is a SQL semantics thing more than a tooling default. Curious if nuvix handles that differently or just enforces "never write a policy without an IS NOT NULL guard"? Worth checking either way for anyone starting fresh. for folks already on Supabase, the three checks I posted are the cheap remediation path without migrating.
Quick bonus pitfall #4 since it came up a few times after I posted: RPC functions defined as SECURITY DEFINER bypass RLS entirely. They run as the function owner (usually postgres), not the calling user. Useful for admin operations, dangerous if used for normal user queries. If you've got an RPC function that returns user data, double-check whether it's SECURITY DEFINER (bypasses RLS, runs with full privileges) or SECURITY INVOKER (respects the calling user's policies). Default is INVOKER, but a lot of AI codegen tools default to DEFINER without flagging it. Easiest live test for all four: open SQL editor as a second user's JWT and run a SELECT on the table. If you get rows you shouldn't see, you have one of them.
The `mailer_autoconfirm` config flag is legacy and gets overridden by the dashboard toggle in current Supabase versions. Even with the toggle off in the UI, a few things can still auto-confirm: a third-party provider (Google/GitHub) attached to the same email, a phone provider with auto-confirm on, or a custom trigger on `auth.users` that sets `email_confirmed_at`. Quickest check is querying directly: `select email, email_confirmed_at, confirmed_at, raw_app_meta_data from auth.users where email = 'test@x.com'` right after signup. If `email_confirmed_at` is populated immediately, something server-side is doing it. Then `select * from pg_trigger where tgrelid = 'auth.users'::regclass` to rule out a stray trigger from a migration or template. If the column is null but the session works anyway, that's a different bug, the session is being issued without confirmation, which usually means `enable_confirmations` got flipped in a recent dashboard save and didn't persist. Toggle it off, save, refresh, toggle back on, save again. The dashboard occasionally drops writes silently.