Files
mercadodevida/work/artifacts/F-002/implementer.md
rikrdo 425fedd13e feat(F-002): database foundation with migrations and dev compose
- node-pg-migrate + pg: baseline migration (extensions, app_meta) with working down
- src/infrastructure/db fail-fast pool and typed query helper
- docker-compose: postgres:16-alpine + redis:7-alpine with one-command up
- table naming convention <module>_<table> documented in README
- integration tests (6) against real PostgreSQL; strict identifier validation
  for test DDL after security-gate hardening round
- deps justified in spec/tech.md; all gates approved; verify.sh green
2026-08-14 22:00:16 +02:00

64 lines
3.6 KiB
Markdown

# Implementer — F-002 Database foundation with module-owned schemas
done -> work/artifacts/F-002/implementer.md
## Files created (all under project/ unless noted)
- docker-compose.yml (postgres:16-alpine + redis:7-alpine, named volumes, healthchecks, dev-only creds)
- .env.example
- migrations/001_baseline.js (node-pg-migrate; citext + pgcrypto extensions, app_meta table, with down)
- src/infrastructure/db/pool.ts (createPoolFromEnv fail-fast, typed query helper)
- src/infrastructure/db/tests/db-test-support.ts (recreateDatabase, runMigrations, tableExists helpers; strict identifier validation for DDL-interpolated db name)
- src/infrastructure/db/tests/db-test-support.test.ts (pure helper tests incl. identifier rejection)
- src/infrastructure/db/tests/migrations.itest.ts
- src/infrastructure/db/tests/pool.itest.ts
- scripts/db-status.mjs
## Files modified
- package.json: deps (pg, node-pg-migrate; @types/pg dev) + scripts (test:integration, docker:up/down, db:up/down/status)
- vitest.config.ts: include *.itest.ts; fileParallelism false (integration files share one test DB)
- .gitignore: .env
- README.md: Database section + table naming convention
- spec/tech.md: dependency justification rows for pg / node-pg-migrate / @types/pg
- specs/F-002-database-foundation/DESIGN.md + TASKS.md: migration filename corrected to .js (node-pg-migrate native format)
## Database migrations
- 001_baseline: extensions citext + pgcrypto, table app_meta(key, value, updated_at). Down fully reverts.
- Tracking table: pgmigrations (owned by node-pg-migrate).
## API changes
- None.
## Tests added
- migrations.itest.ts: fresh up creates schema / second up is no-op / down rolls back cleanly
- pool.itest.ts: SELECT 1 roundtrip / app_meta insert-read-delete via query helper / fail fast without DATABASE_URL
## Tests passed (evidence)
```
npm run docker:up -> mdv-dev-postgres Healthy, mdv-dev-redis Healthy
npm run db:up (1st) -> MIGRATION 001_baseline (UP), Migrations complete!
npm run db:up (2nd) -> No migrations to run! (no-op)
npm run db:status -> 001_baseline listed as applied
npm run db:down -> MIGRATION 001_baseline (DOWN); psql to_regclass('public.app_meta') -> empty
npm run db:up (again) -> re-applies cleanly
npm run lint -> OK
npm run lint:boundaries -> Boundary check OK: 11 file(s) checked
npm run typecheck -> exit 0
npm run build -> exit 0
npm test -> 4 files passed, 2 integration files skipped explicitly without TEST_DATABASE_URL (11 passed | 6 skipped)
npm run test:integration -> Test Files 2 passed (2), Tests 6 passed (6) against real PostgreSQL 16
docker exec mdv-dev-redis redis-cli ping -> PONG
```
## Known limitations
- node-pg-migrate programmatic runner requires explicit migrationsTable (passed 'pgmigrations' in the test helper to match CLI default).
- Integration tests drop/create the shared test database; vitest fileParallelism disabled to avoid the race (documented in vitest.config.ts).
- No connection retry/backoff yet; not needed while only dev scripts connect.
## Follow-up work
- F-004 will centralize env/config (current fail-fast reader stays until then).
- First real module tables arrive with F-005+ following <module>_<table> convention.
## Security hardening round (requested by security gate)
- db-test-support.ts now validates the database name from TEST_DATABASE_URL against /^[a-zA-Z_][a-zA-Z0-9_]*$/ before interpolating it into DROP/CREATE DATABASE DDL; rejection covered by db-test-support.test.ts.
- Re-verified: lint, typecheck, npm test (11 passed), test:integration (6 passed).