Supabase one-shot schema replaced with six node-pg-migrate files

Commit `b9f5f60a` is the portability change that makes this fork runnable on plain Postgres 16. The upstream one-shot schema - with its `auth.users` FK, RLS policies, and `handle_new_user` trigger - is broken into six sequential migration files runnable against any Postgres instance, plus a migration runner with Managed Identity support for Azure.

infrastructurecompliance

Maintained by Allen Morgan · verified on MikeWatch

The six migrations are: 0000_initial (upstream schema with all Supabase-specific items stripped and annotated with TODO(entraid) comments explaining each removal), 0001_tenant_policy (tenants and tenant_group_policies tables for Entra multi-tenant mode), 0002_user_profile_email (adds an email column so user lookups don't need the Supabase Auth admin API), 0003_user_profile_provider_keys (OpenAI and Azure OpenAI key columns), 0004_user_profile_fast_model, and 0005_postgres_roles (recreates the web_anon / authenticated / service_role PostgREST role topology).

The runner in scripts/runMigrations.ts uses node-pg-migrate. For supabase and local modes it picks DATABASE_URL directly. For entra mode it mints a Postgres Flexible Server Managed Identity token via @azure/identity and injects it as the password. After all migrations complete the runner emits NOTIFY pgrst, 'reload schema' so PostgREST picks up schema changes without a container restart.

The Supabase-specific pieces that were removed: the user_id FK to auth.users (now a plain unique constraint, with the Entra OID stored directly), all RLS policies (authorization moved to backend/src/lib/access.ts), and the handle_new_user trigger (profile creation is now an application-level upsert in the auth middleware).

The MI token-minting branch in the runner is Entra-specific. If you adopt this migration set for a non-Azure deployment, that branch needs to be stripped or made conditional.

So what This is the most consequential change in the fork for anyone wanting to run outside Supabase. If Supabase dependency removal is on your roadmap, study this migration set before writing your own. Even on a Supabase deployment, splitting the one-shot schema into per-feature files is a cleaner pattern. The Managed Identity token-minting in the runner is specific to Azure Postgres Flexible Server and needs adjustment for other targets.

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

1 commit from Altien/mikeOssAzure, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
b9f5f60a feat(db): node-pg-migrate runner and provider-neutral migrations Allen Morgan 2026-05-08 ↗ GitHub
commit body
Replaces the upstream Supabase one-shot schema (RLS policies, auth.users
FK, handle_new_user trigger) with six sequential node-pg-migrate
migrations that run against any Postgres 16+ server:

  0000_initial            - full upstream schema, supabase deps removed
  0001_tenant_policy      - tenants + tenant_group_policies tables for
                            Entra-mode tenant lifecycle
  0002_user_profile_email - email column on user_profiles
  0003_user_profile_provider_keys - OpenAI/AOAI per-user key columns
  0004_user_profile_fast_model    - fast_model column
  0005_postgres_roles     - recreates the PostgREST role topology
                            (web_anon / authenticated / service_role)
                            for deployments where Supabase's bootstrap
                            doesn't run

scripts/runMigrations.ts is the runner used by Container App Jobs (and
locally via npm run migrate:dev). It picks DATABASE_URL when
AUTH_PROVIDER!=entra, or mints a Postgres-flexserver Managed Identity
token when entra mode is active. After migration completes it issues
NOTIFY pgrst, 'reload schema' so PostgREST picks up the new shape
without a restart.

Adds node-pg-migrate, pg, and @types/pg.

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-193.md from inside the repo you want the changes in.

⬇ Download capture-thread-193.md