Skip to content
TALA
Esc
navigateopen⌘Jpreview
On this page

Environments

Three environments mapped onto three branches, the TLS rules for each, and the Supabase connection traps and RLS lockdown that are not optional.

dev staging prod
Branch dev staging main
Database local Postgres tala_dev Supabase (shared) Supabase — not created as of 2026-09-09
DB_SYNCHRONIZE may be true locally must be set to false forced false by NODE_ENV
migrationsRun false false false

Migrations are run explicitly in every environment. Nothing runs them at boot.

Environment validation

The backend validates its environment at startup via validateEnv and refuses to boot on a bad one. It checks exactly two variables:

Variable Rule
SECRET_KEY at least 32 characters, and must not match /change-?me/i
BUFFER_KEY exactly 64 hex characters

DATABASE_URL is not validated — a missing or malformed connection string fails later, at the first query, not at boot.

.env.example is the authoritative reference for everything else — read it before debugging a connection.

TLS to the database

if (this._configService.get<string>("DB_SSL") === "false") return false;

DB_SSL=false is a local-Postgres-only escape hatch, for a Homebrew build compiled without SSL.

Outside production the connection also uses ssl.rejectUnauthorized: false. That is a permissive TLS path intended for local development, but it applies to any non-production connection — including a staging connection to a hosted database. On staging that means the traffic is encrypted but the database’s certificate is never verified, so a substituted certificate would be accepted. Narrowing the flag to local Postgres is unowned.

In production, DB_SSL_CA may pin a CA as either an inline PEM or a path to one. If DB_SSL_CA is unset, the certificate is still validated against Node’s bundled CAs and a warning is logged.

Supabase

Use the session pooler, never the direct host:

postgresql://postgres.<ref>:<password>@aws-1-<region>.pooler.supabase.com:5432/postgres
Trap Detail
Direct host is IPv6-only db.<ref>.supabase.co has AAAA and no A record — unroutable from most laptops without the paid IPv4 add-on
Port 5432 is session mode. 6543 is transaction mode and breaks TypeORM’s prepared statements
Username postgres.<project-ref>, not postgres
Region prefix newer projects use aws-1-, not aws-0-
DB_SSL=false Never against Supabase — it disables transport encryption outright

Row-level security

Supabase publishes the public schema through PostgREST and grants anon and authenticated full DML on everything created there. The anon key is public by design. TypeORM knows nothing about RLS, so tables created by a migration land wide open.

LockDownPublicSchema enables RLS on all public tables and revokes those roles’ grants and their default privileges. The default privileges are the part people skip: leave them in place and the next table a migration creates re-opens the hole.

Was this page helpful?