Version: 1.0.0Documentation Index
Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt
Use this file to discover all available pages before exploring further.
Last Updated: 2026-04-24
Audience: Developers and AI agents working on Postgres schema for Encore Health OS. This document is the canonical reference for maintaining DDL under
supabase/schemas/ and generating versioned migrations under supabase/migrations/ with the Supabase CLI.
Goals
- Single source of truth for DDL:
supabase/schemas/**/*.sqldescribes the desired database shape (tables, types, routines, policies where appropriate). - Reproducible promotion:
supabase/migrations/*.sqlremains whatsupabase db reset, CI, and remotes apply. For normal DDL, those files are produced bysupabase db diff, not by hand. - Tooling:
@supabase/pg-deltaand@supabase/pg-topofrom pg-toolbelt assist with export, optional apply-to-empty-DB experiments, and ordering diagnostics. They are not a substitute forsupabase db diffin this repo.
Directory layout
After a successfulnpm run db:schemas:export, pg-delta typically emits a tree similar to:
pg-delta already groups by object type. If you split DDL manually, name files so dependencies are satisfied (e.g. base tables before foreign keys that reference them). @supabase/pg-topo validates statement-level ordering when you run npm run db:schemas:lint.
Column ordering: When altering existing tables in exported files, append new columns at the end of the table definition where possible to reduce noisy diffs on re-export.
Environment variables
| Variable | Purpose | Default |
|---|---|---|
SUPABASE_LOCAL_DB_URL | Postgres URL for pgdelta targets/sources | postgresql://postgres:postgres@127.0.0.1:54322/postgres |
SUPABASE_SCHEMAS_DIR | Declarative schema root | <repo>/supabase/schemas |
SUPABASE_CATALOG_EXPORT_PATH | Output for npm run db:catalog:export | <repo>/reports/db/catalog-snapshot.json |
npm scripts (root package.json)
| Script | What it runs |
|---|---|
npm run db:schemas:export | pgdelta declarative export --integration supabase → refresh supabase/schemas/ from a running local DB |
npm run db:schemas:apply | pgdelta declarative apply — applies declarative tree to a target DB (use for disposable / empty DBs only) |
npm run db:schemas:plan | pgdelta plan … — forward args (see tsx scripts/database/pgdelta-run.ts plan --help via npx pgdelta plan --help) |
npm run db:catalog:export | pgdelta catalog-export — JSON catalog snapshot for offline diffs |
npm run db:catalog:remote:dev / npm run db:catalog:remote:prod | Export read-only hosted dev/prod catalog snapshots from Postgres system catalogs |
npm run db:schemas:validate / npm run db:schemas:lint | @supabase/pg-topo static analysis over supabase/schemas/ (skips if no .sql files yet) |
npm run db:schemas:diff | supabase stop then forwards to supabase db diff — pass -- -f <name> [flags] |
npm run db:docs:generate | Generate schema markdown docs from catalog snapshot or migration inventory fallback |
npm run db:docs:generate:dev / npm run db:docs:generate:prod | Generate environment-specific schema docs from hosted catalog snapshots |
npm run db:docs:check | Verify generated schema docs are up-to-date |
npm run db:docs:refresh | Export catalog then regenerate schema docs |
npm run db:docs:refresh:all | Export hosted dev and prod catalogs, then regenerate both environment-specific doc sets |
Alpha warning:@supabase/pg-deltais pre-1.0. Pin versions inpackage.json; use export/lint locally/CI, avoiddeclarative-applyagainst production.
First-time bootstrap (populate supabase/schemas/)
When Docker and the local Supabase DB port (54322 per supabase/config.toml) are available:
.sql tree. Until then, only supabase/schemas/README.md may be present — db:schemas:lint intentionally no-ops when there are zero .sql files.
Day-to-day DDL workflow
- Change DDL in
supabase/schemas/(not insupabase/migrations/). - Optional:
npm run db:schemas:lint— catches parse errors / unresolved dependencies / cycles viapg-topo. - Stop local Supabase:
npx supabase stop(required beforedb diffin this workflow). - Generate migration:
npx supabase db diff -f <snake_case_description>
Shortcut:npm run db:schemas:diff -- -f <snake_case_description> - Review the generated SQL under
supabase/migrations/— watch for unintendedDROPs. - Start + reset:
npx supabase start && npx supabase db reset - Validate:
npm run validate-migration -- --latest - Test RLS:
npm run test:rls(and other suites per change risk).
schema lane) unless explicitly marked / named for system-defaults DML.
Lovable-originated schema changes
Lovable can apply DDL directly to hosted DEV, which bypasses local migration authoring. Treat this as a drift-capture workflow:- Run
npm run db:pull-from-dev -- --name <descriptive_slug>to generate a migration from hosted DEV changes. - Review the generated migration under
supabase/migrations/for safety, lane correctness, and constitution requirements. - If local Supabase is available, replay locally (
npx supabase start && npx supabase db reset) and runnpm run db:schemas:exportsosupabase/schemas/stays aligned. - Run
npm run validate-migration -- --latestandnpm run test:rlsbefore merging.
supabase/migrations/*.sql remains the promotion source of truth; declarative files are an audit/authoring surface, not a production deployment shortcut.
When not to rely on declarative + db diff alone
Keep explicit migrations (hand-authored or carefully reviewed) for cases that diff tools handle poorly (aligns with Supabase / migra limitations):
| Topic | Guidance |
|---|---|
| DML | Use idempotent migrations in the system-defaults lane (-- @lane: system-defaults or filename convention). Never tenant/test data. |
| View ownership / grants | Capture in a dedicated migration; verify security behavior (views bypass RLS by default in Postgres unless security_invoker). |
| Materialized views | Prefer explicit migration; refresh schedules may need pg_cron + vault patterns. |
RLS ALTER POLICY | Often safer to DROP POLICY + CREATE POLICY in a migration; ensure init-plan pattern (select auth.uid()) per db:check:rls-initplan. |
| Comments | COMMENT ON statements in migrations if you need them versioned. |
| Partitions | For active tables, use ADR-020 two-phase pattern (phase-1 shadow + sync, phase-2 cutover); treat as migration-authored unless proven stable in your diff workflow. |
| Publication | Logical replication / CDC workflow changes; treat as migration-authored unless proven stable in your diff workflow. |
| Domain | Custom data type definitions; treat as migration-authored unless proven stable in your diff workflow. |
Rollbacks
- Revert or edit the declarative
.sqlto the prior desired state. npx supabase stopnpx supabase db diff -f <describe_rollback>- Review carefully for data loss (
DROP COLUMN, narrowing types, etc.). - Apply locally (
db reset) and run tests before opening a PR.
Relationship to constitution / platform rules
- §5 Migrations only — still true: production schema changes ship as
supabase/migrations/*.sql. - RLS + tenant isolation — declarative SQL must follow the same patterns as migrations (
SECURITY DEFINERhelpers, no recursive policies,organization_idon business tables). See DATABASE_DEVELOPMENT_GUIDE.md and.cursor/rules/database-patterns.mdc. - PF-96 / multi-tenant literals — unchanged; declarative workflow does not relax jurisdiction or tenant-configurability rules.
See also
- SUPABASE_CLI_LOCAL_WORKFLOW.md — CLI-first operations + declarative section
- MIGRATION_LANES.md — CI migration lane policy
- supabase/schemas/README.md — short operator checklist