feat(infra): add local-dev Docker Compose stack #57
+19
-11
@@ -97,19 +97,28 @@ cd apps/portal-bff && pnpm exec prisma generate && cd ../..
|
||||
pnpm nx run-many -t lint test build
|
||||
```
|
||||
|
||||
For the BFF to actually run end-to-end, you'll also need:
|
||||
For the BFF to actually run end-to-end, you'll also need the local infrastructure stack — Postgres, Redis, OpenTelemetry Collector — provisioned via Docker Compose:
|
||||
|
||||
```bash
|
||||
# .env from .env.example, then fill in DATABASE_URL with your local Postgres
|
||||
cp apps/portal-bff/.env.example apps/portal-bff/.env
|
||||
# 1. Configure infra secrets (copy template, edit, do not commit).
|
||||
cp infra/local/.env.example infra/local/.env
|
||||
$EDITOR infra/local/.env
|
||||
# Set strong dev values for POSTGRES_PASSWORD and REDIS_PASSWORD.
|
||||
|
||||
# Local Postgres via Docker (one-liner; will be replaced by a Docker Compose file in a later doc)
|
||||
docker run -d --name apf-postgres -p 5432:5432 \
|
||||
-e POSTGRES_USER=portal -e POSTGRES_PASSWORD=portal -e POSTGRES_DB=portal_dev \
|
||||
postgres:17-alpine
|
||||
# 2. Bring up the core stack (postgres + redis + otel-collector).
|
||||
docker compose -f infra/local/dev.compose.yml up -d
|
||||
|
||||
# 3. (Optional) Activate viewers when debugging:
|
||||
docker compose -f infra/local/dev.compose.yml --profile dbtools up -d # pgweb
|
||||
docker compose -f infra/local/dev.compose.yml --profile observability up -d # Jaeger UI
|
||||
|
||||
# 4. App-side env from .env.example, then fill in DATABASE_URL pointing
|
||||
# to the compose-managed Postgres (matches the values you set in
|
||||
# infra/local/.env).
|
||||
cp apps/portal-bff/.env.example apps/portal-bff/.env
|
||||
```
|
||||
|
||||
A proper local-dev infra spec (Postgres HA-like, Redis, OTel collector) will land with the on-prem infrastructure ADR; in the meantime the one-liner above is sufficient to run the BFF.
|
||||
Full reference for the local stack — service inventory, port table, persistence, bootstrap re-run procedure — lives in [`infra/README.md`](../infra/README.md) → "Local-dev stack".
|
||||
|
||||
---
|
||||
|
||||
@@ -351,12 +360,11 @@ This doc starts as a phase-1 + cross-cutting reference. As features for later ph
|
||||
When a section grows beyond a short subsection, it is extracted to its own file under `docs/development/`. Per the documentation convention (see [README.md](README.md)), we group into a folder once we have at least three related files; this doc is then re-organised into an index pointing at the extracted files. Until then, all sections live here.
|
||||
|
||||
| Future section | Phase | Triggered by |
|
||||
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Local infra recipe** — Docker Compose for Postgres, Redis, OTel Collector, and a Postgres-friendly viewer. | 2 / 3b | First feature that needs Redis (sessions, ADR-0010). Earlier if the BFF gains a meaningful amount of business code. |
|
||||
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Auth dev-loop** — Microsoft 365 Developer tenant configuration, MSAL Node connection, OIDC code-flow walkthrough, switching between dev and prod-like tenants. | 2 | Auth flow code lands ([ADR-0009](decisions/0009-auth-flow-oidc-pkce-msal-node.md)) once the dev tenant is provisioned by IT. |
|
||||
| **Session inspection** — reading the Redis session store in dev, decrypting the AES-GCM `tokens` blob with the dev key, force-logout patterns. | 2 | Sessions module lands ([ADR-0010](decisions/0010-session-management-redis.md)). |
|
||||
| **MFA step-up debugging** — triggering claims-challenge flows, verifying `mfaVerifiedAt` freshness, testing the SPA HTTP interceptor that handles 401 + claims challenge. | 2 | First `@RequireMfa()` route lands ([ADR-0011](decisions/0011-mfa-enforcement-entra-conditional-access.md)). |
|
||||
| **Observability dev-loop** — running an OTel collector container locally, viewing traces (Tempo / Jaeger UI), reading Pino logs with `pino-pretty`, correlating front spans to BFF spans via `traceparent`. | 2 | OTel SDK setup lands ([ADR-0012](decisions/0012-observability-pino-opentelemetry.md)); needs the local collector from "Local infra recipe". |
|
||||
| **Observability dev-loop** — viewing traces in the Jaeger UI provisioned by `infra/local/dev.compose.yml --profile observability`, reading Pino logs with `pino-pretty`, correlating front spans to BFF spans via `traceparent`. | 2 | OTel SDK setup lands ([ADR-0012](decisions/0012-observability-pino-opentelemetry.md)). |
|
||||
| **Audit-log inspection workflow** — querying `audit.events` as `audit_reader`, joining with app logs by `trace_id`, validating the append-only role grants in dev. | 2 | Audit module lands ([ADR-0013](decisions/0013-audit-trail-separated-postgres-append-only.md)). |
|
||||
| **Downstream API integration recipe** — adding a new `DownstreamApiConfig`, choosing the auth strategy (OBO vs service+assertion), wiring resilience policies, testing with a mocked downstream. | 2 | First downstream client lands ([ADR-0014](decisions/0014-downstream-api-access-obo-pattern.md)). |
|
||||
| **Component patterns library** — the in-house, spartan-style components (Angular CDK + Tailwind) as they ship, with a11y notes per component (keyboard model, ARIA, screen-reader expectations). | 5b suite | First non-placeholder component in `libs/shared/ui/`. |
|
||||
|
||||
+64
-5
@@ -3,15 +3,15 @@
|
||||
Infrastructure-as-code artefacts for the project. Separate from application code and from documentation: this folder contains the recipes and configs that the team and ops use to stand up running infrastructure (CI runners, future local-dev databases, future on-prem deploy assets).
|
||||
|
||||
| Subject | File / Folder | ADR / Reference |
|
||||
| -------------------------------------- | -------------------------------------------------- | ------------------------------------------------------------------- |
|
||||
| -------------------------------------- | -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Self-hosted CI runners (Gitea Actions) | [`ci-runners.compose.yml`](ci-runners.compose.yml) | [ADR-0015 §"Runners"](../docs/decisions/0015-cicd-gitea-actions.md) |
|
||||
| Shared `act_runner` configuration | [`runner-config.yaml`](runner-config.yaml) | [ADR-0015 §"Runners"](../docs/decisions/0015-cicd-gitea-actions.md) |
|
||||
| Runtime state of the runners | `data/` (git-ignored after `.gitignore`) | — |
|
||||
| Env-vars template for the runners | `.env.example` (`.env` is git-ignored) | — |
|
||||
| Local-dev runtime stack | [`local/`](local/) | [ADR-0006](../docs/decisions/0006-persistence-postgresql-prisma.md), [ADR-0010](../docs/decisions/0010-session-management-redis.md), [ADR-0012](../docs/decisions/0012-observability-pino-opentelemetry.md), [ADR-0013](../docs/decisions/0013-audit-trail-separated-postgres-append-only.md) |
|
||||
|
||||
Future folders / files that will land here as the corresponding ADRs ship:
|
||||
|
||||
- **`local/`** — Docker Compose for the developer's machine (Postgres + Redis + OTel collector). Triggered by the first feature that needs Redis (sessions, ADR-0010).
|
||||
- **`prod/`** — On-prem deploy manifests (HA Postgres, Redis Sentinel, OTel collector + backend, secret manager). Triggered by the on-prem infrastructure ADR (phase 3b).
|
||||
|
||||
---
|
||||
@@ -121,13 +121,72 @@ Old, no-longer-referenced images can be reaped during the periodic `docker syste
|
||||
|
||||
---
|
||||
|
||||
## Local-dev stack — `local/`
|
||||
|
||||
A Docker Compose recipe spinning up the runtime services the BFF and ADRs assume — Postgres, Redis, OpenTelemetry Collector — plus optional viewers (pgweb, Jaeger UI) gated behind Compose profiles. Designed to start in a single command on a contributor's WSL2 / Linux / macOS host.
|
||||
|
||||
| File | Role |
|
||||
| -------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
|
||||
| [`local/dev.compose.yml`](local/dev.compose.yml) | Service definitions: postgres, redis, otel-collector, plus pgweb and jaeger behind profiles |
|
||||
| [`local/.env.example`](local/.env.example) | Credentials + ports template (copy to `.env`, which is git-ignored) |
|
||||
| [`local/init/postgres/01-init.sql`](local/init/postgres/01-init.sql) | Bootstrap SQL for ADR-0013: audit roles + schema, applied on first boot only |
|
||||
| [`local/otel-collector.yaml`](local/otel-collector.yaml) | Collector pipeline: OTLP receivers → batch → debug exporter (always) + forward to Jaeger when active |
|
||||
|
||||
### First-time setup
|
||||
|
||||
```bash
|
||||
cd infra/local
|
||||
|
||||
# 1. Configure local secrets (copy template, edit, do not commit).
|
||||
cp .env.example .env
|
||||
$EDITOR .env
|
||||
# Set strong dev values for POSTGRES_PASSWORD and REDIS_PASSWORD
|
||||
# (defaults in the template are placeholders that the compose
|
||||
# rejects with `must be set in infra/local/.env` if left as-is).
|
||||
|
||||
# 2. Bring up the core stack (postgres + redis + otel-collector).
|
||||
docker compose -f dev.compose.yml up -d
|
||||
|
||||
# 3. (Optional) Activate viewers when needed:
|
||||
docker compose -f dev.compose.yml --profile dbtools up -d # pgweb
|
||||
docker compose -f dev.compose.yml --profile observability up -d # Jaeger UI
|
||||
docker compose -f dev.compose.yml --profile dbtools --profile observability up -d # both
|
||||
|
||||
# 4. Verify health.
|
||||
docker compose -f dev.compose.yml ps
|
||||
```
|
||||
|
||||
### Service endpoints (defaults)
|
||||
|
||||
| Service | Host port | Purpose |
|
||||
| ------------------- | --------- | ------------------------------------------------------------------- |
|
||||
| Postgres | 5432 | DB connection — `postgres://portal:<pwd>@localhost:5432/portal_dev` |
|
||||
| Redis | 6379 | Sessions, OBO cache (per ADR-0010 / ADR-0014) |
|
||||
| OTel Collector gRPC | 4317 | `OTEL_EXPORTER_OTLP_ENDPOINT` for the BFF and the SPA |
|
||||
| OTel Collector HTTP | 4318 | OTLP/HTTP variant |
|
||||
| pgweb (profile) | 8081 | http://localhost:8081 — Postgres GUI |
|
||||
| Jaeger UI (profile) | 16686 | http://localhost:16686 — trace explorer |
|
||||
|
||||
All ports are overridable via `.env` if the host machine has conflicts.
|
||||
|
||||
### Operational tips
|
||||
|
||||
- **Persistence** — state lives in named Docker volumes (`apf-portal-postgres-data`, `apf-portal-redis-data`). Survives `docker compose down`. Use `docker compose -f dev.compose.yml down -v` to wipe (also wipes the audit-roles bootstrap, which re-runs on the next fresh boot).
|
||||
- **Bootstrap re-run** — the SQL in `local/init/postgres/` only runs on a **fresh** Postgres data volume. To replay after editing the file, `down -v` (loses all dev data) or run the SQL manually with `docker compose exec postgres psql -U portal -d portal_dev -f /docker-entrypoint-initdb.d/01-init.sql`.
|
||||
- **Logs** — `docker compose -f dev.compose.yml logs -f <service>` to follow a single service. `otel-collector` is the loudest — its `debug` exporter prints every span / metric / log it receives.
|
||||
- **Image upgrades** — same policy as the runner image (deliberate, not via `:latest`). Renovate's docker-compose manager will surface bumps automatically once the dashboard rule allows them.
|
||||
|
||||
### Production parity
|
||||
|
||||
This stack is **dev-only**. The corresponding production layout (HA Postgres, Redis Sentinel cluster, OTel Collector with a real backend, secret manager) lives in the future on-prem-infrastructure ADR — see `prod/` placeholder below.
|
||||
|
||||
---
|
||||
|
||||
## Future infra concerns — placeholders
|
||||
|
||||
These are listed here so a contributor knows where to expect related files; they don't exist yet.
|
||||
|
||||
| File | Purpose | Triggered by |
|
||||
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- |
|
||||
| `local/dev.compose.yml` | Postgres 17 + Redis (Sentinel-flavoured single-node) + OTel collector for local dev | First feature that needs Redis or end-to-end OTel traces |
|
||||
| `local/init/postgres/*.sql` | Bootstrap SQL to create the Postgres roles `audit_owner` / `audit_writer` / `audit_reader` / `audit_archiver` (per ADR-0013) and provision the dev DB | Same as above |
|
||||
| --------------- | ----------------------------------------------------------------------------------------- | -------------------------------------------------- |
|
||||
| `prod/*` | On-prem deployment manifests (k8s, Compose, or whatever the on-prem infra ADR settles on) | The on-prem infrastructure ADR (phase 3b) |
|
||||
| `runbooks/*.md` | Operational runbooks (incident response, secret rotation, runner upgrade procedure, …) | First incident, or when ops cadence justifies them |
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# Local-dev secrets and ports for `infra/local/dev.compose.yml`.
|
||||
# Copy to `.env` (which is git-ignored) and adjust as needed.
|
||||
#
|
||||
# cp .env.example .env
|
||||
# $EDITOR .env
|
||||
|
||||
# ---------------------------------------------------------------- Postgres
|
||||
# `POSTGRES_PASSWORD` is mandatory — the compose refuses to boot without it.
|
||||
POSTGRES_USER=portal
|
||||
POSTGRES_PASSWORD=portal_dev_change_me
|
||||
POSTGRES_DB=portal_dev
|
||||
POSTGRES_PORT=5432
|
||||
|
||||
# ---------------------------------------------------------------- Redis
|
||||
# Same — mandatory.
|
||||
REDIS_PASSWORD=redis_dev_change_me
|
||||
REDIS_PORT=6379
|
||||
|
||||
# ---------------------------------------------------------------- OTel
|
||||
OTEL_GRPC_PORT=4317
|
||||
OTEL_HTTP_PORT=4318
|
||||
|
||||
# ---------------------------------------------------------------- Optional viewers
|
||||
# Only consumed when the matching Compose profile is activated:
|
||||
# --profile dbtools → pgweb
|
||||
# --profile observability → Jaeger UI
|
||||
PGWEB_PORT=8081
|
||||
JAEGER_UI_PORT=16686
|
||||
@@ -0,0 +1,145 @@
|
||||
# Local-dev infrastructure stack for `apf_portal`.
|
||||
#
|
||||
# Spins up the runtime dependencies the BFF and ADRs assume:
|
||||
# - PostgreSQL 17 (per ADR-0006)
|
||||
# - Redis 7 (per ADR-0010 — single node in dev,
|
||||
# Sentinel HA in prod)
|
||||
# - OpenTelemetry Collector (per ADR-0012 — receives OTLP from the
|
||||
# BFF and the SPA, debug-logs traces in
|
||||
# v1, forwards to Jaeger when activated)
|
||||
#
|
||||
# Optional viewers behind Compose profiles:
|
||||
# - --profile dbtools → pgweb (Postgres GUI)
|
||||
# - --profile observability → Jaeger UI (trace explorer)
|
||||
#
|
||||
# Usage from infra/local/:
|
||||
# cp .env.example .env
|
||||
# $EDITOR .env # set strong dev passwords
|
||||
# docker compose -f dev.compose.yml up -d
|
||||
#
|
||||
# To bring up viewers too:
|
||||
# docker compose -f dev.compose.yml --profile dbtools --profile observability up -d
|
||||
#
|
||||
# State persists in named volumes (`apf-portal-postgres-data`,
|
||||
# `apf-portal-redis-data`). To wipe and start fresh:
|
||||
# docker compose -f dev.compose.yml down -v
|
||||
#
|
||||
# Bootstrap SQL (audit roles + schema, per ADR-0013) is applied on
|
||||
# first boot from init/postgres/. To replay after editing it, wipe
|
||||
# the volume with `down -v` above.
|
||||
|
||||
name: apf-portal-dev
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:17.2-alpine
|
||||
container_name: apf-portal-postgres
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_USER: ${POSTGRES_USER:-portal}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set in infra/local/.env}
|
||||
POSTGRES_DB: ${POSTGRES_DB:-portal_dev}
|
||||
ports:
|
||||
- '${POSTGRES_PORT:-5432}:5432'
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
# Bootstrap SQL runs only on a fresh data volume.
|
||||
- ./init/postgres:/docker-entrypoint-initdb.d:ro
|
||||
networks:
|
||||
- apf-portal-dev
|
||||
healthcheck:
|
||||
test:
|
||||
['CMD-SHELL', 'pg_isready -U "${POSTGRES_USER:-portal}" -d "${POSTGRES_DB:-portal_dev}"']
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 5
|
||||
|
||||
redis:
|
||||
image: redis:7.4-alpine
|
||||
container_name: apf-portal-redis
|
||||
restart: unless-stopped
|
||||
# AOF (`--appendonly yes`) keeps sessions across container restarts —
|
||||
# the dev equivalent of the persistence we want from the prod
|
||||
# Sentinel cluster (per ADR-0010 §"Persistence").
|
||||
command:
|
||||
- redis-server
|
||||
- --requirepass
|
||||
- ${REDIS_PASSWORD:?REDIS_PASSWORD must be set in infra/local/.env}
|
||||
- --appendonly
|
||||
- 'yes'
|
||||
ports:
|
||||
- '${REDIS_PORT:-6379}:6379'
|
||||
volumes:
|
||||
- redis-data:/data
|
||||
networks:
|
||||
- apf-portal-dev
|
||||
healthcheck:
|
||||
test: ['CMD', 'redis-cli', '-a', '${REDIS_PASSWORD}', 'PING']
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 5
|
||||
|
||||
otel-collector:
|
||||
image: otel/opentelemetry-collector-contrib:0.115.0
|
||||
container_name: apf-portal-otel-collector
|
||||
restart: unless-stopped
|
||||
command: ['--config=/etc/otel-collector.yaml']
|
||||
volumes:
|
||||
- ./otel-collector.yaml:/etc/otel-collector.yaml:ro
|
||||
ports:
|
||||
# OTLP receivers — the BFF and the SPA send here.
|
||||
- '${OTEL_GRPC_PORT:-4317}:4317'
|
||||
- '${OTEL_HTTP_PORT:-4318}:4318'
|
||||
networks:
|
||||
- apf-portal-dev
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Optional: Postgres GUI (`--profile dbtools`).
|
||||
# pgweb is a lightweight, no-config alternative to pgAdmin.
|
||||
# ------------------------------------------------------------------
|
||||
pgweb:
|
||||
image: sosedoff/pgweb:0.16.2
|
||||
container_name: apf-portal-pgweb
|
||||
restart: unless-stopped
|
||||
profiles: [dbtools]
|
||||
environment:
|
||||
DATABASE_URL: postgres://${POSTGRES_USER:-portal}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-portal_dev}?sslmode=disable
|
||||
ports:
|
||||
- '${PGWEB_PORT:-8081}:8081'
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- apf-portal-dev
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Optional: Jaeger UI for trace exploration (`--profile observability`).
|
||||
# The collector pipeline above always tries to forward to `jaeger:4317`;
|
||||
# when this profile is off, those exports fail silently (logged at
|
||||
# warn level by the collector — no blocking effect on the debug
|
||||
# exporter that prints traces to stdout).
|
||||
# OTLP ports (4317/4318) are NOT published from this service to
|
||||
# avoid colliding with the collector — the collector talks to
|
||||
# Jaeger on the internal Compose network.
|
||||
# ------------------------------------------------------------------
|
||||
jaeger:
|
||||
image: jaegertracing/all-in-one:1.62
|
||||
container_name: apf-portal-jaeger
|
||||
restart: unless-stopped
|
||||
profiles: [observability]
|
||||
environment:
|
||||
COLLECTOR_OTLP_ENABLED: 'true'
|
||||
ports:
|
||||
- '${JAEGER_UI_PORT:-16686}:16686'
|
||||
networks:
|
||||
- apf-portal-dev
|
||||
|
||||
volumes:
|
||||
postgres-data:
|
||||
name: apf-portal-postgres-data
|
||||
redis-data:
|
||||
name: apf-portal-redis-data
|
||||
|
||||
networks:
|
||||
apf-portal-dev:
|
||||
name: apf-portal-dev
|
||||
@@ -0,0 +1,48 @@
|
||||
-- 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;
|
||||
@@ -0,0 +1,65 @@
|
||||
# OpenTelemetry Collector config for the local-dev stack.
|
||||
#
|
||||
# v1 scope (per ADR-0012):
|
||||
# - Accept OTLP from the BFF and the SPA on gRPC (4317) and HTTP
|
||||
# (4318). The default OTEL_EXPORTER_OTLP_ENDPOINT in dev points
|
||||
# here.
|
||||
# - Batch + log everything to stdout via the `debug` exporter — the
|
||||
# dev sees what their app emits without standing up a backend.
|
||||
# - When the `observability` Compose profile is active, additionally
|
||||
# forward to Jaeger (`jaeger:4317` on the internal Compose
|
||||
# network). When the profile is inactive, the OTLP→Jaeger export
|
||||
# fails at warn level but does not impact the debug pipeline.
|
||||
#
|
||||
# Production replaces the debug exporter with the proper backend
|
||||
# (chosen in the future on-prem infrastructure ADR — likely Tempo +
|
||||
# Loki + Mimir, or an OpenTelemetry-friendly all-in-one).
|
||||
|
||||
receivers:
|
||||
otlp:
|
||||
protocols:
|
||||
grpc:
|
||||
endpoint: 0.0.0.0:4317
|
||||
http:
|
||||
endpoint: 0.0.0.0:4318
|
||||
|
||||
processors:
|
||||
batch:
|
||||
# Small batches in dev so the developer sees output quickly.
|
||||
timeout: 5s
|
||||
send_batch_size: 100
|
||||
|
||||
exporters:
|
||||
debug:
|
||||
verbosity: detailed
|
||||
otlp/jaeger:
|
||||
endpoint: jaeger:4317
|
||||
tls:
|
||||
insecure: true
|
||||
sending_queue:
|
||||
enabled: true
|
||||
# When jaeger isn't running (profile off), retries fall back
|
||||
# to a small queue rather than blocking the pipeline.
|
||||
queue_size: 100
|
||||
retry_on_failure:
|
||||
enabled: true
|
||||
initial_interval: 5s
|
||||
max_interval: 30s
|
||||
|
||||
service:
|
||||
pipelines:
|
||||
traces:
|
||||
receivers: [otlp]
|
||||
processors: [batch]
|
||||
exporters: [debug, otlp/jaeger]
|
||||
logs:
|
||||
receivers: [otlp]
|
||||
processors: [batch]
|
||||
exporters: [debug]
|
||||
metrics:
|
||||
receivers: [otlp]
|
||||
processors: [batch]
|
||||
exporters: [debug]
|
||||
telemetry:
|
||||
logs:
|
||||
level: info
|
||||
Reference in New Issue
Block a user