65 lines
2.5 KiB
Markdown
65 lines
2.5 KiB
Markdown
# DESIGN — F-002 Database foundation with module-owned schemas
|
|
|
|
## Affected modules
|
|
- `src/infrastructure/db` (new): pool factory + migration runner entry.
|
|
|
|
## Modules touched
|
|
- `src/infrastructure/db`
|
|
- `project/migrations/` (new folder, SQL files)
|
|
- `project/docker-compose.yml` (new)
|
|
|
|
## Modules NOT touched
|
|
- All business modules. No HTTP API change. No shared/ change.
|
|
|
|
## New interfaces
|
|
- `src/infrastructure/db/pool.ts`: `createPoolFromEnv(): Pool` (fail fast if `DATABASE_URL` missing), `query(text, params)` helper typed over pg.
|
|
- npm scripts: `db:up`, `db:down`, `db:status`, `docker:up`, `docker:down`, `test:integration`.
|
|
|
|
## API changes
|
|
- None.
|
|
|
|
## Database changes
|
|
- Baseline migration `001_baseline.js` (node-pg-migrate, pgm.sql):
|
|
- `CREATE EXTENSION IF NOT EXISTS citext;`
|
|
- `CREATE EXTENSION IF NOT EXISTS pgcrypto;`
|
|
- `CREATE TABLE app_meta (key text PRIMARY KEY, value text NOT NULL, updated_at timestamptz NOT NULL DEFAULT now());`
|
|
- Down: drop table, drop extensions.
|
|
- Migration version tracking table owned by the migration tool.
|
|
|
|
## Naming convention (documented rule)
|
|
```text
|
|
<module>_<table> e.g. catalog_products, inventory_stock, orders_orders
|
|
<module>_<table>_id_seq sequences owned by their table
|
|
```
|
|
- A module never queries tables without its own prefix.
|
|
- Migrations are immutable once merged; fixes ship as new migrations.
|
|
|
|
## Events
|
|
- None.
|
|
|
|
## External integrations
|
|
- Docker Compose: postgres:16-alpine (port 5432), redis:7-alpine (port 6379), named volumes.
|
|
|
|
## Cache changes
|
|
- None (Redis present but unused until cache ticket).
|
|
|
|
## Security considerations
|
|
- Compose credentials are dev-only and public by design; documented as such.
|
|
- `.env.example` committed, real `.env` gitignored.
|
|
- No secrets in migration files.
|
|
|
|
## Toolchain decisions
|
|
- Migration tool: **node-pg-migrate** (pure npm dependency, battle-tested, SQL-first via `pgm.sql`, supports up/down and dry-run). Rejected: hand-rolled runner (reinvention), Flyway/golang-migrate (foreign toolchains for a Node monolith).
|
|
- Driver: **pg** (standard).
|
|
- Env loading: Node 22 `--env-file` flag; no dotenv dependency.
|
|
|
|
## Test strategy
|
|
- Integration tests (`*.itest.ts`) run only when `TEST_DATABASE_URL` is set: `describe.skipIf` — explicit, no magic.
|
|
- They verify: fresh up creates schema; second up is no-op; down reverts cleanly; `app_meta` usable via pool helper.
|
|
|
|
## Migration strategy
|
|
- Greenfield; compose starts empty volume, migrations run from zero.
|
|
|
|
## Rollback strategy
|
|
- `db:down` reverts last migration; compose volumes can be removed with `docker compose down -v`.
|