Skip to main content
The browser runtime writes to Supabase with the public anon key, so the only thing standing between an end user and the firstflow_* tables is Row Level Security (RLS). This page explains the model the migrations ship with, the two access paths, and how to tighten policies for production.
The anon key is in your client bundle and visible to anyone. RLS not the key is what keeps one user from reading or writing another user’s rows. Review your policies before going to production.

Two access paths

The service_role key bypasses RLS by design it is trusted backend code. Keep it server-only (never NEXT_PUBLIC_*, never committed). All untrusted, browser-originated writes go through the anon key and are subject to your policies.

What the migrations ship

0001_initial.sql creates the tables and 0002_strict_rls.sql enables RLS on them. The shipped policies are a baseline; because FirstFlow trusts whatever user.id your app provides (it has no auth of its own), the SDK cannot know how your users map to rows. Treat the shipped policies as a starting point and adapt them to your auth model.
Read 0002_strict_rls.sql in the repo before relying on the defaults, and confirm the policies match how your app authenticates to Supabase (a Supabase Auth session, a signed JWT, or anon-only).

Tightening policies

The right policy depends on how your browser client authenticates to Supabase:
  • You use Supabase Auth in your app. The signed-in user’s JWT carries auth.uid(). Scope rows to it so users only touch their own:
  • You do not use Supabase Auth (the browser holds only the anon key). The database cannot verify the user_id a client sends, so anon writes are effectively trust-on-write. For stronger guarantees, proxy persistence through your own backend with the service_role key, or mint a short-lived signed token (see signUserToken in the Server SDK) and verify it in a policy.

Verifying RLS

After applying the migrations, confirm RLS is on:
Then test from the browser: a logged-in user should be able to read and write their own flow runs and nothing else.

Next

Review what you own operationally, then run the production checklist before going live.