Skip to main content
Last Updated: 2026-05-28 Authoritative sources: constitution.md §5 (Database), DATABASE_DEVELOPMENT_GUIDE, SUPABASE_CLI_LOCAL_WORKFLOW This page consolidates everything an engineer needs to ship a database change — from a spec gate to a deployed migration with RLS coverage. If you’ve never added a table before, follow this top-to-bottom once; afterwards use it as a checklist.

When to use which workflow

Encore OS supports two migration workflows. Use the right one: If you’re not sure, use declarative — it stays in sync with the live schema and avoids drift.

End-to-end workflow

1

Pre-flight

  • Confirm the spec is at pipeline_status: validated or later. New tables without a spec are forbidden — see SPEC_WORKFLOW.
  • Ensure npm run supabase:start is running locally (Docker daemon + Supabase stack).
  • Pull main: git fetch origin && git rebase origin/main.
2

Edit the declarative schema

Edit the relevant file under supabase/schemas/{core}/ (e.g. supabase/schemas/hr/employees.sql). Add the table, columns, indexes, and RLS policy in the same file — the final shape of the entity lives in one place.Follow the naming conventions:
  • Tables: {core}_{entity} snake_case (e.g. hr_credentials, pm_encounters).
  • Columns: snake_case; required audit columns id, created_at, updated_at, org_id (tenant); soft-delete deleted_at only when explicit policy requires.
3

Add the RLS policy in the same edit

Every business table MUST have RLS enabled and tested. Use the template (also in .cursor/rules/database-migrations.md):
For role-bounded reads (e.g. only HR managers see credentials), add a second policy. See RLS_PATTERNS for the canonical templates (tenant + role-bounded + read/write split).For PHI tables, add the standard audit trigger:
4

Generate the migration

This compares your edited schema against the current applied state and writes a timestamped migration to supabase/migrations/<ts>_add_hr_credentials.sql. Review the generated SQL — if it contains anything you didn’t intend, edit the declarative file and re-diff.For an imperative change instead: supabase migration new add_hr_credentials_backfill.
5

Validate before applying

Catches naming violations, missing RLS, missing tenant isolation, and security anti-patterns. Do not bypass. Common failures:
  • Missing enable row level security
  • Policy without org_id = auth_org_id() predicate
  • SECURITY DEFINER without search_path lockdown
  • Column-level grant without RLS
6

Apply locally

generate-types is required — TypeScript will fail later if you don’t.
7

Add RLS tests

Every new table needs an RLS test in tests/rls/{core}/{table}.rls.test.ts. Pattern:
Run: npm run test:rls -- hr/credentials. See rls-testing skill for failure-mode debugging.
8

Commit and push

Stage the declarative schema file, the generated migration, and the regenerated types together:
CI runs validate-migration, check-rls-coverage, test:rls, and architecture checks. Fix locally on failure — never --no-verify.
9

Deploy to dev / prod

Migrations apply automatically on merge through the Supabase branching pipeline. See SUPABASE_MULTI_ENV_SETUP for env wiring and SUPABASE_GO_LIVE_DASHBOARD_CHECKLIST for prod cuts.

Rollback

If a migration ships and breaks something:
  1. Do not delete the migration file. It’s already applied to dev/prod.
  2. Write a forward-fix migration that undoes the breaking change: supabase migration new revert_<original_name>.
  3. Apply locally, test, ship through the same pipeline.
  4. If the issue is PHI-data corruption, also create a compliance evidence entry under docs/compliance/evidence/.
See MIGRATION_ROLLBACK_STRATEGY for the full playbook.

Common mistakes (the ones reviewers will flag)


  • migration-authoring — pre-flight checklist + constitutional patterns; trigger when starting any migration.
  • rls-testing — debugging RLS test failures.
  • test-rls — running the RLS suite scoped to a table/core.
  • check-rls-coverage — gap report for tables missing tests.
Invoke from any AI session: just say “migration for hr credentials” and the skill triggers.