Bring up Postgres + Redis + OTel Collector in one command so
contributors can run the BFF end-to-end without each setting up
the runtime services manually. Replaces the throwaway
`docker run postgres:17-alpine` one-liner that was in §3 of
docs/development.md.
What lands:
- `infra/local/dev.compose.yml` — three core services
(postgres 17.2-alpine, redis 7.4-alpine,
otel/opentelemetry-collector-contrib 0.115.0) plus two
viewers gated behind Compose profiles (pgweb under
`--profile dbtools`, Jaeger 1.62 under
`--profile observability`). All ports overridable via .env;
state in named volumes; healthchecks on the data services.
- `infra/local/.env.example` — credentials + ports template.
POSTGRES_PASSWORD and REDIS_PASSWORD are mandatory (compose
refuses to boot without them); other keys default sensibly.
- `infra/local/init/postgres/01-init.sql` — bootstrap SQL per
ADR-0013: `audit_owner` / `audit_writer` / `audit_reader` /
`audit_archiver` roles plus `audit` schema, with default
privileges encoding the append-only contract (INSERT to
writer, SELECT to reader, DELETE to archiver, no UPDATE /
TRUNCATE to anyone). Applied on first Postgres boot only;
documented re-run procedure in infra/README.md.
- `infra/local/otel-collector.yaml` — pipeline: OTLP gRPC/HTTP
→ batch → debug exporter (always) + forward to `jaeger:4317`
(no-op when the observability profile is off; logs warn-level
retry but doesn't block other exporters).
Surrounding docs updated:
- `infra/README.md` — new "Local-dev stack" section with
service inventory, port table, first-time setup, operational
tips. The `local/` row replaces the previous placeholder.
- `docs/development.md` §3 — rewritten to walk through the
compose-based setup; cross-links to `infra/README.md` for
the full reference. Roadmap entry for "Local infra recipe"
removed from §8 (now implemented); "Observability dev-loop"
entry adjusted to point at the new Jaeger profile.
Production parity is intentionally left for the on-prem
infrastructure ADR (phase 3b) — this is the dev-only stack.