docs: add ADR-0012 for observability (Pino + OpenTelemetry, W3C Trace Context, stdout + collector)
Pin the observability foundation. Two signals are in scope: structured logs and distributed traces. Logs: pino + nestjs-pino, JSON line-delimited on stdout, with a fixed envelope (level, time, service, version, env, trace_id, span_id, session_id, user_id_hash, audience, msg, ...). Pino redact strips a reviewable allowlist of sensitive paths (Authorization/Cookie headers, *.password, *.access_token, *.refresh_token, ...). user_id_hash uses a per-environment salt (LOG_USER_ID_SALT) so the same userId is not correlatable across environments. Tracing: OpenTelemetry SDK for Node + auto-instrumentations (HTTP, Express, NestJS, pg, ioredis, Prisma). The SPA also runs OTel-Web with an HTTP interceptor propagating traceparent on outbound calls; the same trace_id is the correlation identifier from the user click to the DB query. No separate X-Correlation-ID. Request-scoped context lives in nestjs-cls; the Pino formatter and the future audit-log writer pull from CLS - no per-call threading. Sampling is 100% at the application; tail sampling is performed at the local OpenTelemetry Collector (deferred to the phase-3 infrastructure ADR, where the on-prem backend - Grafana stack, ELK, or other - will be chosen). Output: stdout for logs, OTLP/HTTP for traces, both consumed by the local collector. The application stays vendor-neutral. Audit logs are explicitly out of scope of this ADR - they share the trace_id but use a separate writer and a separate sink (next ADR). decisions/README.md index updated. CLAUDE.md gains an explicit 'Observability' summary pointing to ADR-0012.
This commit is contained in:
@@ -40,7 +40,7 @@ The structural choices are recorded as ADRs and summarized below. Any change to
|
||||
- **MFA:** enforced by Entra ID Conditional Access (org-side policy, P1 licensing required); BFF sanity-checks the `amr` claim at session creation; `@RequireMfa()` decorator and freshness-based step-up are designed-in for future sensitive routes (no v1 consumer) — see [ADR-0011](decisions/0011-mfa-enforcement-entra-conditional-access.md).
|
||||
- **Identity:** multi-tenant Microsoft Entra ID with B2B invitation for workforce in v1, dual-audience design ready for future External ID activation — see [ADR-0008](decisions/0008-identity-model-entra-workforce-dual-audience.md).
|
||||
- **Authentication flow:** OIDC Authorization Code + PKCE via `@azure/msal-node`, executed entirely on the BFF; SPA never holds tokens; `__Host-` prefixed cookies, double-submit CSRF, RP-initiated logout — see [ADR-0009](decisions/0009-auth-flow-oidc-pkce-msal-node.md).
|
||||
- **Observability:** Pino structured logs + OpenTelemetry traces with W3C Trace Context propagation — to be locked-in in phase 2.
|
||||
- **Observability:** Pino + `nestjs-pino` for structured JSON logs, OpenTelemetry SDK + auto-instrumentations for traces, W3C Trace Context propagation across SPA → BFF → DB → Redis, `nestjs-cls` for request-scoped context (`trace_id`, `session_id`, `user_id_hash`, `audience`), 100 % sampling at the app with tail sampling deferred to the OTel Collector, stdout + OTLP shipping — see [ADR-0012](decisions/0012-observability-pino-opentelemetry.md).
|
||||
- **Local quality gates:** Husky + lint-staged + commitlint with Conventional Commits — see [ADR-0007](decisions/0007-pre-commit-hooks-and-conventional-commits.md).
|
||||
- **Runtime:** Node.js latest LTS major.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user