0f00d6d93f
## Summary Bring up Postgres + Redis + OTel Collector in one command so contributors can run the BFF end-to-end without manually wiring each service. Replaces the throwaway `docker run postgres:17-alpine` one-liner that was in `docs/development.md` §3. ### 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: - `--profile dbtools` → `sosedoff/pgweb:0.16.2` (Postgres GUI on port 8081) - `--profile observability` → `jaegertracing/all-in-one:1.62` (Jaeger UI on 16686) - All ports overridable via `.env`. State in named volumes. Healthchecks on 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 + `audit` schema. Default privileges encode 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. - **`infra/local/otel-collector.yaml`** — pipeline: OTLP gRPC/HTTP → batch → debug exporter (always) + forward to `jaeger:4317`. When the observability profile is off, the Jaeger export logs warn-level retries but doesn't block the debug pipeline. ### Surrounding doc updates - **`infra/README.md`** — new "Local-dev stack" section: service inventory, port table, first-time setup walkthrough, persistence/bootstrap-replay tips. The previous `local/` placeholder line is removed. - **`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" line adjusted to point at the new Jaeger profile. ### Out of scope - **Production parity** — HA Postgres, Redis Sentinel, real OTel backend (Tempo / Loki / etc.) — defer to the on-prem infrastructure ADR (phase 3b). The dev-only nature of this stack is called out explicitly in `infra/README.md`. - **Wiring the BFF** to actually use these endpoints (NestJS config, Prisma datasource URL, OTel SDK init) — that's the **B — Observability foundations** chantier, next up. ## Test plan - [ ] `cd infra/local && cp .env.example .env && docker compose -f dev.compose.yml up -d` → all three core services come up healthy; verify with `docker compose ps`. - [ ] `psql postgres://portal:<pwd>@localhost:5432/portal_dev -c "\dn"` shows the `audit` schema; `\dg` shows the four audit roles. - [ ] `redis-cli -a <pwd> PING` → `PONG`. - [ ] Send a fake OTLP trace via grpcurl → see it printed by `docker compose logs otel-collector`. - [ ] `--profile dbtools up -d` → http://localhost:8081 shows pgweb UI, can navigate to the audit schema. - [ ] `--profile observability up -d` → http://localhost:16686 shows Jaeger UI; collector logs no longer report Jaeger export retries. - [ ] `docker compose down -v` cleanly removes everything; next `up -d` re-runs the bootstrap SQL. --------- Co-authored-by: Julien Gautier <julien.gautier@apf.asso.fr> Reviewed-on: #57
49 lines
2.3 KiB
SQL
49 lines
2.3 KiB
SQL
-- Bootstrap SQL for local-dev Postgres, applied on FIRST boot only
|
|
-- (Postgres image runs files in /docker-entrypoint-initdb.d once,
|
|
-- when the data volume is empty).
|
|
--
|
|
-- Implements the role + schema layout from ADR-0013 (Audit trail,
|
|
-- separated Postgres schema, append-only by Postgres role grants).
|
|
-- Production deployment manifests (future infrastructure ADR) will
|
|
-- replicate the same layout with real service accounts; in dev the
|
|
-- default `portal` user (created automatically from POSTGRES_USER)
|
|
-- is the schema owner, and the audit roles are granted to it for
|
|
-- testing role-based access patterns locally.
|
|
|
|
-- ---------------------------------------------------------------- Audit roles
|
|
-- NOLOGIN: these are permission containers, not login users. The BFF
|
|
-- connects as a login user that has been GRANTed the role.
|
|
CREATE ROLE audit_owner NOLOGIN;
|
|
CREATE ROLE audit_writer NOLOGIN;
|
|
CREATE ROLE audit_reader NOLOGIN;
|
|
CREATE ROLE audit_archiver NOLOGIN;
|
|
|
|
-- ---------------------------------------------------------------- Audit schema
|
|
-- Owned by audit_owner so DEFAULT PRIVILEGES below take effect for
|
|
-- every future table created under the schema (Prisma migration etc.).
|
|
CREATE SCHEMA audit AUTHORIZATION audit_owner;
|
|
|
|
GRANT USAGE ON SCHEMA audit TO audit_writer, audit_reader, audit_archiver;
|
|
|
|
-- ---------------------------------------------------------------- Append-only contract
|
|
-- ADR-0013 §"Append-only by role grants":
|
|
-- audit_writer → INSERT only
|
|
-- audit_reader → SELECT only
|
|
-- audit_archiver → DELETE only (used to prune past retention)
|
|
-- nobody → UPDATE, TRUNCATE
|
|
ALTER DEFAULT PRIVILEGES FOR ROLE audit_owner IN SCHEMA audit
|
|
GRANT INSERT ON TABLES TO audit_writer;
|
|
|
|
ALTER DEFAULT PRIVILEGES FOR ROLE audit_owner IN SCHEMA audit
|
|
GRANT SELECT ON TABLES TO audit_reader;
|
|
|
|
ALTER DEFAULT PRIVILEGES FOR ROLE audit_owner IN SCHEMA audit
|
|
GRANT DELETE ON TABLES TO audit_archiver;
|
|
|
|
-- ---------------------------------------------------------------- Dev convenience
|
|
-- The default `portal` superuser bypasses these grants anyway, but
|
|
-- granting the audit roles explicitly lets us test role-based access
|
|
-- with `SET ROLE audit_writer;` etc. from a psql session against the
|
|
-- dev DB. Production never grants all four to one user.
|
|
GRANT audit_owner, audit_writer, audit_reader, audit_archiver TO portal;
|