Local dev and the test suite previously defaulted to the live production Neon database, and running the tests mutated prod data. Add guardrails plus a proper local Postgres + migrations workflow so production can't be hit by mistake: - docker-compose: local Postgres 17 (matches prod) + auto-created teqo_test - dev guard refuses a non-local DATABASE_URL; tests refuse non-_test databases - .env.test isolates the suite; vitest/playwright load it and fail closed - Payload migrations set up (push disabled); build runs `payload migrate`, so deploys apply pending migrations to prod automatically - baseline `initial` migration + idempotent consent.text varchar->jsonb fix - `pnpm db:pull` copies prod content locally, excluding supporter PII - docs (README, AGENTS.md) + agent skills for the local-db/migration workflow
3 KiB
3 KiB
| name | description |
|---|---|
| local-database | Set up, refresh, and safely use the Teqo local Postgres database, and copy production content locally with `pnpm db:pull`. Use when starting local development, when the local database is empty or stale, when preparing the test database, or when the user mentions the local DB, docker-compose, db:pull, or seeding local data. Enforces that local development and tests never touch the production Neon database. |
Teqo Local Database
Production is a live Neon Postgres with real citizens' PII. Local development and tests run against a local Docker Postgres and must never connect to production.
Guardrails already in place (do not weaken them)
pnpm devrunsscripts/guard-dev-db.mjsand refuses to start ifDATABASE_URLis a non-local host. Escape hatch:ALLOW_REMOTE_DB=true(use only with a very good reason).- Tests load
.env.test(databaseteqo_test) and callassertTestDatabase()(tests/helpers/assertTestDatabase.ts), which throws unless the database name ends in_test. - Never repoint
DATABASE_URLin.env,.env.local, or.env.testat Neon..env.testis committed and local-only on purpose.
Local connection values
- Dev database:
postgresql://teqo:teqo@localhost:5432/teqo - Test database:
postgresql://teqo:teqo@localhost:5432/teqo_test - Local Postgres major version is pinned to 17 in
docker-compose.ymlto match production Neon.
First-time setup
- Ensure Docker is running (
open -a Dockeron macOS if the daemon is down). pnpm db:start— boots local Postgres and auto-createsteqo_test.- Set
DATABASE_URL=postgresql://teqo:teqo@localhost:5432/teqoin.env.local. - Load schema + data (pick one):
- Mirror prod content (recommended): see "Refresh local content from prod" below.
- Empty schema from migrations:
pnpm migrate.
pnpm dev.
Stop the database with pnpm db:stop.
Refresh local content from prod (pnpm db:pull)
PROD_DATABASE_URL="<unpooled Neon URL>" pnpm db:pull
- The unpooled URL is
DATABASE_URL_UNPOOLEDin.env.local. scripts/db-pull.mjsonly reads prod (viapg_dump) and only writes local; it refuses any non-local target.- It excludes PII: row data of
contact,signature,subscription(and their_rels) is not copied; the table structure is kept. - It resets and rebuilds the local
publicschema, so it overwrites local data.
Prepare / reset the test database
The test DB needs the schema applied via migrations:
DATABASE_URL=postgresql://teqo:teqo@localhost:5432/teqo_test pnpm migrate
Then run pnpm test (or pnpm test:int / pnpm test:e2e). Playwright injects the test DB into its own dev server and never reuses a running one.
Never do
- Point any
DATABASE_URLat Neon for dev or tests. - Run the test suite against a database not ending in
_test. - Try to use
db:pullto push local → prod (it cannot; it is read-only on the source).
Related
- Schema changes and migrations: use the
payload-migrationsskill.