Can one user reach another user's rows?
Row Level Security that checks ownership, not just login.
- Policies, views and SECURITY DEFINER functions
- Columns users must not edit: plan, role, credits
- Storage buckets and per-user folders
Apps built with Lovable and other AI tools look finished in the preview. RowProof checks what happens in production: who can read and change each row, whether payments grant and remove access correctly, and whether a stranger can spend your AI budget. In writing. Standard and Advanced prove each finding with live tests.
No passwords, secret keys or production data needed.
A scanner reads your configuration. A Standard or Advanced review also tests it: two real accounts, your own app client, and a written note of what each one could read or change.
Row Level Security that checks ownership, not just login.
Stripe events decide who has access, not the success page.
Paid model calls stay behind login and per-user limits.
Paste one query into the Supabase SQL editor (on Lovable Cloud: Cloud, then SQL editor) and run it. It reads only the database catalog and returns a list of findings sorted by severity. It never reads your rows and changes nothing.
C01RLS off on a table the API can reachC02RLS off, no grants yet (latent)C03Policy that lets every row throughC04Policy that also applies to anonC05"Signed in" treated as ownershipC06RLS on with no policy at allC07View that bypasses RLSC08Materialized view readable by the APIC09SECURITY DEFINER function callable via /rpcC10SECURITY DEFINER without a fixed search_pathC11Public storage bucketC12Storage policy without an owner checkC13Rows writable in someone else's nameC14Personal or secret columns the API can readC15Access decided by user-editable metadataC16Users can edit their own plan or roleThe script points to the policy. The two-account test proves what it allows. The report gives the fix and the retest.
-- script output C05 HIGH public.orders :: "logged in reads" SELECT policy only checks that the caller is signed in (auth.uid() IS NOT NULL). Any account can reach every row it covers. -- two-account test, through the app's own client user B, signed in, selected orders created by user A -> 3 rows returned -- fix and retest USING ((select auth.uid()) = user_id) user B, same request -> 0 rows
Example from a test database, not from a client.
Async and in writing. Scope and a fixed price are agreed before any work starts.
No. Starter needs only the script output. Standard and Advanced need read access to the repository and a staging URL where I sign up my own test accounts. Never send passwords, service role keys or Stripe secret keys.
No. It is a written review of the areas listed above. It does not cover your infrastructure, third-party services or load, and it is not a guarantee that no other issue exists.
Supabase and Lovable Cloud (Postgres with Row Level Security), Stripe billing, and serverless functions that call AI APIs.
Yes. Your code only goes into AI tools where training on my data is turned off: Claude, ChatGPT and Codex. AI helps me read code faster. In Standard and Advanced every finding is confirmed by a live test; Starter findings are labeled as catalog observations or heuristic warnings.
Yes. Every finding in the report says how. The fix sprint is optional.
No. RowProof is independent.
Buy a fixed-price review on Upwork, from US$ 30, with payment protection for both sides. Send the script output with your first message.
See what you get before you buy: a sample report run on the public test database.