Skip to content

Latest commit

 

History

History
24 lines (13 loc) · 2.7 KB

database.md

File metadata and controls

24 lines (13 loc) · 2.7 KB

Database and migrations

Part of the coding standards. supabase/README.md owns migration order, table grants, and the database gate. docs/operations.md owns applying migrations to staging and production.

Constraints

  • A CHECK passes when its expression is NULL. Test nullable columns explicitly with IS NOT NULL inside the branch that requires them (#19).
  • Grant the privileges a client read path needs, and let RLS limit the rows. Revoking SELECT broke the daily usage count (#70). When a migration narrows grants, check every client write path that touches the table (#44).

Locks on tables with production rows

npm run lint runs squawk on new migrations. Check every -- squawk-ignore against the table's production size: an ignore is fine on a small table and wrong on a large one. Index builds on populated tables use CREATE INDEX CONCURRENTLY in their own file (#13), and long locks run at low traffic (#11).

Compare times on one clock

Do not compare a timestamp produced by an Edge Function with one produced by Postgres. Clock skew made the erase fence either accept writes after "Delete all data" or reject fresh requests. Take both times from the database, or compare counters (#13).

Destructive data changes

A migration that anyone can apply must not delete user data as a side effect. Put the deletion in a function, leave the call out of the migration, and run it as a separate step that needs explicit authorization for that environment. Write down the preservation and restore path before that step (#72, #71). 20260926090100_legacy_debate_cleanup.sql now follows this.

Privileged clients

Use the generated Database type with createClient<Database>(...) rather than casting the client through unknown (#13). A service-role client filters by the user ID it validated from the bearer token, never by an ID from the request body (#90 security review).