Chimeway.Traces.Explanation (chimeway v1.0.0)

Copy Markdown View Source

Structured explanation of a single delivery — the primary operator debugging artifact.

Returned by Chimeway.Traces.explain_delivery/1. Contains the full context needed to answer "why was this delivery suppressed/failed/succeeded?" without requiring additional queries.

Fields

  • delivery_id — UUID of the delivery row
  • event_id — UUID of the parent event
  • correlation_id — host-app correlation string (request_id, trace_id), or nil
  • notification_key — stable notification type identifier
  • recipient_id — recipient identity string
  • channel — delivery channel string (for example "in_app", "email", "webhook_partner")
  • render_key — stable per-channel render identity persisted on the delivery row, or nil
  • render_version — stable per-channel render version persisted on the delivery row, or nil
  • status — final delivery status: :succeeded | :failed | :suppressed | :pending | :cancelled

  • planning_reason — orchestration/planning reason when the delivery is intentionally held, else nil
  • planning_context — sanitized persisted planning facts for explainability, else nil
  • next_eligible_at — UTC timestamp for the next dispatchable moment when deferred, else nil
  • resume_source — sanitized scheduler/source label when a deferred row later resumes, else nil
  • resume_scheduled_at — original UTC time the deferred row was scheduled to resume, else nil
  • resumed_at — UTC timestamp when the canonical delivery row left deferred state, else nil
  • suppression_reason — reason atom string when status is :suppressed OR :cancelled, else nil. The four documented reason strings are:
    • "channel_disabled" — set when status is :suppressed (policy preference blocked the channel)
    • "retries_exhausted" — set when status is :cancelled (Oban exhausted max_attempts on transient failures, REL-03 D-10/D-11)
    • "permanent_failure" — set when status is :cancelled (adapter returned a permanent error)
    • "bounced" — set when status is :cancelled (adapter returned a bounce)
  • last_attempt — map with :outcome, :inserted_at, :attempt_number, :error_class, :adapter_module for the most recent attempt, or nil. :adapter_module is nil for pre-Phase-29 attempts.
  • digest — digest-specific reasoning for source or emitted digest rows, else nil
  • timeline — chronological list of lifecycle events, each a map with :at, :event, :detail

Summary

Types

t()

@type t() :: %Chimeway.Traces.Explanation{
  channel: String.t(),
  correlation_id: String.t() | nil,
  delivery_id: String.t(),
  digest: map() | nil,
  event_id: String.t(),
  last_attempt:
    %{
      outcome: atom(),
      inserted_at: DateTime.t(),
      attempt_number: pos_integer() | nil,
      error_class: String.t() | nil,
      adapter_module: String.t() | nil
    }
    | nil,
  next_eligible_at: DateTime.t() | nil,
  notification_key: String.t(),
  planning_context: map() | nil,
  planning_reason: String.t() | nil,
  recipient_id: String.t(),
  render_key: String.t() | nil,
  render_version: pos_integer() | nil,
  resume_scheduled_at: DateTime.t() | nil,
  resume_source: String.t() | nil,
  resumed_at: DateTime.t() | nil,
  status:
    :succeeded | :failed | :suppressed | :pending | :cancelled | :dispatched,
  suppression_reason: String.t() | nil,
  timeline: [timeline_entry()]
}

timeline_entry()

@type timeline_entry() :: %{at: DateTime.t(), event: atom(), detail: map()}