Record consumer span failures; context + redaction hardening [Bug-1157]

Story 1157Epic None7 files · +233/−32

PR #37 · pramaan-io/pramaan-agents · merged 2026-06-10

Why this matters

Your traces lie. Your logs leak. Your correlation bleeds.

Three quiet failures inside the consumer

Record two inherits record one's ID. Timeline merges. Root cause lost.

The fix — One record, one span, one case file — and never let secrets leak.

How it flows

sequenceDiagram
  autonumber
  participant Q as Queue
  participant H as Handler / Clerk
  participant S as Span / Hearing
  participant L as Logger / Transcript
  Q->>H: deliver record
  H->>H: open case file: set corr_id (token)
  H->>S: open hearing
  S->>L: log corr-id + redact secrets
  S->>S: on failure: status=ERROR + exception
  H->>H: close: reset token
  Q-->>H: next record (fresh case)

observability/correlation.py · handler.py

Methodin → outwhat it does
set_correlation_id(value) → Token[str | None]writes corr id into ContextVar and returns a token for later reset
reset_correlation_id(token) → Nonerestores the previous corr id via the token so records never bleed
_envelope_correlation_id(raw_body) → str | Nonepulls the corr id out of the raw envelope so logs stay inside record scope

What changed, file by file

Extracts correlation id from the raw envelope via _envelope_correlation_id, so handler logs no longer mint correlation outside record scope (claims 3, 4).

new methodsignature
_envelope_correlation_id(raw_body) → str | None

Adds token-based set and reset helpers for the correlation ContextVar, preventing cross-record bleed between consumer invocations (claim 3).

new methodsignature
set_correlation_id(value) → Token[str | None]
reset_correlation_id(token) → None

Files changed (7)

File±
src/pramaan_agents/handler.py ★+48 −19
src/pramaan_agents/observability/correlation.py ★+7 −3
src/pramaan_agents/observability/logger.py ★+11 −3
src/pramaan_agents/runtime/sqs_consume.py+3 −3
tests/observability/test_handler_trace.py+95 −2
tests/observability/test_logger.py+47 −1
tests/observability/test_sqs_consume.py+22 −1