RowShield
Guides

Supabase security across client projects: an agency baseline

An agency’s Supabase footprint is a portfolio: dozens of live projects, each one somebody’s production system, each configured by whoever happened to ship it. Standards drift between teams, clients inherit contractors, and the project you scaffolded two years ago now runs a shop whose orders table nobody has thought about since. Security work has to be designed for that turnover rather than against it.

The failure mode is rarely dramatic. One client project skips the policy pair on a new orders table during a rushed release; nothing fails; the storefront keeps working. Months later the table still answers anonymous requests, and the exposure belongs to your client, your contract and your reputation simultaneously. Per-project baselines exist precisely so that one rushed release cannot quietly opt a project out.

What follows is a working baseline for agencies: what every project must satisfy before handover, how to make the check cheap enough to run everywhere, and how to set thresholds that reflect differing stakes — a brochure site holding no personal data and a clinic booking system do not deserve the same scrutiny.

RowShield does not detect this yet. This guide gives you the catalog queries to check it yourself. The nine rules that do ship are listed on the rules index.

Treat every project as someone else’s production

The mindset shift is small and profitable: you are not securing your own systems, you are acting as custodian for systems whose owners cannot audit you. That reframes shortcuts. A skipped policy is not technical debt owed to yourself; it is risk transferred to a client who has no way to see it, priced into a fixed-fee contract nobody renegotiated.

Custodianship also survives team churn when it is written down. Document each project’s access model — which roles read and write which tables — in the repository itself, next to the migrations that create them. When a different developer picks the project up in a year, the intent travels with the schema instead of leaving with a group chat.

A baseline every project passes

Keep the baseline boring enough to apply everywhere: RLS enabled and forced on every public table; policies scoped to an owner or membership column on every table; no public buckets unless the design genuinely publishes those files; service keys confined to server environments. One catalogue query, run in each project’s SQL editor, verifies the first item in seconds:

SELECT n.nspname AS schema_name,
       c.relname AS table_name,
       c.relrowsecurity AS rls_enabled
FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname = 'public'
  AND c.relkind IN ('r', 'p')
ORDER BY n.nspname, c.relname;

Thresholds that match stakes

Anything the query flags gets fixed before the invoice goes out, not filed as follow-up. Follow-up items in agency work have a half-life measured in weeks, and exposure does not wait politely. Where a client declines the fix — it happens — record the decision in writing, because custodianship includes ensuring the refusal was informed rather than unnoticed.

Not every project warrants equal depth, and pretending otherwise spreads attention thin. Set two tiers: projects holding personal data — orders with addresses, bookings with phone numbers, anything about children — receive the full pass plus scheduled monitoring; content-only brochure projects receive the structural pass. Write the tier into the engagement letter so scope disputes end before they start.

Re-run the tiered check at natural moments: before handover, before handing maintenance to another contractor, and after any project revives from dormancy. Revivals matter more than people expect — the code is remembered, the database configuration is not, and a year of dormant migrations is exactly when a missing policy pair goes unnoticed.

Monitoring a portfolio without a platform team

RowShield does not automate this checklist — a person still walks each project — but it removes the part agencies realistically cannot sustain: remembering to re-check thirty projects every month. Add each client project as a monitored target, choose scan frequency per plan, and let transitions drive attention: resolved findings close, regressions reopen, silence means nothing changed.

Alert routing matters at portfolio scale. Send findings to a channel the delivery team already reads rather than a mailbox named after this initiative, because initiatives get renamed and channels get muted. RowShield reads catalogue and bucket metadata only, never client rows, and is an independent product unaffiliated with Supabase — a sentence worth repeating to clients during procurement.

Frequently asked

Who owns the fix when a client project turns out to be exposed?
Contractually the client owns the risk, but practically you own the relationship and the clock. Fix first where you hold credentials, inform promptly, and put the recurring check in place before the conversation about how it happened begins. Agencies recover from incidents; they struggle with incidents discovered by clients first.
How do we stop new projects drifting from the baseline?
Make the baseline a template: starter migrations that enable and force RLS, a seed policy pair per table, and the catalogue query wired into the README as a pre-handover step. Templates convert intention into default, and defaults survive deadline weeks far better than memory does.
Does monitoring replace the manual review?
No. RowShield watches configuration states — disabled RLS, world-readable tables, exposed buckets — and reports change. The judgment about which role may see cancelled orders, or whether a shared read is intentional, remains a human decision informed by each client’s own access model.

Check your project in about ten seconds

Paste a URL. No signup, no writes, nothing stored.

Run the free audit
agency supabase securitymanage supabase client projectssupabase multi project baselineclient handover supabase audit