Skip to content

Add correlation IDs and structured telemetry to apps/api #21

Description

@patoperpetua

Parent: #6
Depends on: #17
Blocks: #16 (send endpoint should use this from the start)

Goal

Add request correlation ID generation and structured logging to apps/api so every inbound request can be traced from receipt to provider outcome. This must be in place before the template-send endpoint (#16) is wired, so telemetry is consistent across both contact and send flows.

Scope

Correlation ID middleware / helper

  • Generate a correlationId (UUID v4 or CUID2 — match what is already used in apps/api or poc-plattform-kit if available) for every inbound request.
  • Accept an X-Correlation-Id header from trusted callers and propagate it (validate format; reject obviously malformed values to prevent log injection).
  • Attach the correlationId to structured log entries for the duration of the request.
  • Include correlationId in all PostKitErrorResponse bodies (type from @singleton-sd/post-kit-types).

Structured log fields

Every log entry for a send request should include:

correlationId   string
tenantId        string        (once resolved — omit before auth)
environment     string        (once resolved)
templateKey     string        (once known)
outcome         'sent' | 'failed' | 'validation_error' | 'auth_error'
durationMs      number
providerMessageId  string | undefined
errorCode       PostKitErrorCode | undefined

Never log:

  • Full email bodies
  • Recipient email addresses (log a boolean hasRecipient or a domain-only hash if needed for debugging)
  • API keys or bearer tokens
  • Template variable values

Logger abstraction

  • Wrap Azure Functions' built-in context.log / InvocationContext logger in a thin structured logger that serialises the fields above as JSON.
  • The logger must be injectable so unit tests can capture output.
  • Follow the logging conventions already present in apps/api — read the existing function handlers before introducing a new pattern.

Contact endpoint integration

Backfill correlation ID propagation into the existing /contact function handler (non-breaking — add the header and logs, do not change the response shape).

Constraints

  • Do not log PII: no email addresses, names, message content, or bearer tokens in structured logs.
  • Log injection: validate and truncate any caller-supplied X-Correlation-Id value before using it in log output.
  • The logger must not be a global singleton — it must be instantiated per request.
  • Keep the implementation inside apps/api; do not create a separate package for this.

Acceptance criteria

  • Every request to apps/api produces a correlationId (generated or propagated).
  • correlationId appears in the response body on errors (PostKitErrorResponse).
  • Structured log fields listed above are emitted for each request.
  • PII fields are not present in any log entry.
  • A malformed or injected X-Correlation-Id value is sanitised before logging.
  • The /contact endpoint emits correlation IDs without changing its response contract.
  • Unit tests confirm: correlation ID generated when header absent, propagated when valid header present, sanitised when header is malformed.
  • pnpm -r --if-present run test passes.

Agent implementation notes

Read the existing function handlers in apps/api/src/functions/ before adding the logger so the new code follows existing patterns. Check whether a correlation/request-ID utility already exists in the monorepo before adding a new dependency. Branch: feat/N-correlation-telemetry (use actual issue number).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent-readyMeets every criterion in docs/github-source-of-truth.md, section 4 — safe for an agent to claimenhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions