RLS on every new table
rls-guardAn event trigger that enables row level security on every table created outside the Supabase-managed schemas, so a new table is never readable through the Data API before it has policies. Install it as postgres: supautils lets that role create event triggers.
Database primitivesmanaged
Install
It needs no other module.
npx better-supabase add rls-guardConfigure
The blocks entries in your config, with the default mode.
import { defineConfig } from "better-supabase/config";
export default defineConfig({
blocks: {
// Modes: "managed". The default is "managed".
"rls-guard": { mode: "managed" },
},
});Migrations
The files
npx better-supabase add rls-guard writes into your declarative schema with the default layout.Client
This block is SQL only: call its functions from your policies, RPCs and the other modules.
Events
With the outbox installed, the module writes these in the same transaction as the change.
This module writes no outbox events.
Dependencies
No dependencies
It installs on its own and integrates with no optional module.
Recipes
No UI recipe uses it yet. See all recipes.
More in Database primitives
- Update timestampsupdated-atKeeps an updated_at column current on every update.
- Realtime table changesrealtime-tablesBroadcasts a change signal (no row data) once per statement on bsb:t:<schema>.<table>[:<tenant>], or bsb:t:<schema>.<table>:u:<user> for realtime.users tables, for live queries.
- JSON Schema checks for jsonbjsonb-schemaspg_jsonschema check constraints for jsonb columns with a `schema` in the `json` config, so the database enforces the same shape as the types. A trigger reports what failed through jsonschema_validation_errors, which the client maps to a validation error.
- pgTAP helperspgtaptests.create_user, tests.authenticate_as and catalog checks (every_table_has_rls, policies_use, no_anon_policies, every_table_audited, partitions_have_rls) for `supabase test db`. Written to supabase/tests, never to your schema.
- Read setsread-setsOne `stable` function per `defineReadSet` in `readSets`, so `db.$many(readSet, params)` is a single GET.
- Number sequencesnumberingGapless numbers per tenant, entity and period. next_number locks the row in the caller's transaction, and a trigger fills the document column so a separate round trip cannot open a gap.