Accrue.Webhook.WebhookEvent (accrue v0.3.0)

Copy Markdown View Source

Ecto schema for the accrue_webhook_events table.

This is the single-table ledger for all inbound webhook events from any processor. The status column projects Oban's job lifecycle onto a queryable field for admin UI and retention management (D2-33).

Status lifecycle

:received -> :processing -> :succeeded
                         -> :failed -> :dead
:dead -> :replayed -> :received (replay cycle)

Raw body storage

raw_body is stored as :binary (PostgreSQL bytea) for byte-exact forensic replay of signature verification (research Q1). The Inspect protocol is implemented to EXCLUDE raw_body from inspect output to prevent accidental PII logging (T-2-04a).

Idempotency

The unique index on (processor, processor_event_id) ensures each event is persisted at most once (D2-25). Duplicate POSTs return the existing row without re-enqueuing.

Summary

Functions

Builds a changeset for the hot-path webhook insert.

Builds a changeset for status transitions.

Returns the list of valid webhook event statuses.

Types

t()

@type t() :: %Accrue.Webhook.WebhookEvent{
  __meta__: term(),
  data: term(),
  endpoint: term(),
  id: term(),
  inserted_at: term(),
  livemode: term(),
  processed_at: term(),
  processor: term(),
  processor_event_id: term(),
  raw_body: term(),
  received_at: term(),
  status: term(),
  type: term(),
  updated_at: term()
}

Functions

ingest_changeset(attrs)

@spec ingest_changeset(map()) :: Ecto.Changeset.t()

Builds a changeset for the hot-path webhook insert.

Only casts the fields needed at ingestion time. Status defaults to :received via the schema default.

status_changeset(event, new_status)

@spec status_changeset(
  %Accrue.Webhook.WebhookEvent{
    __meta__: term(),
    data: term(),
    endpoint: term(),
    id: term(),
    inserted_at: term(),
    livemode: term(),
    processed_at: term(),
    processor: term(),
    processor_event_id: term(),
    raw_body: term(),
    received_at: term(),
    status: term(),
    type: term(),
    updated_at: term()
  },
  atom()
) :: Ecto.Changeset.t()

Builds a changeset for status transitions.

Used by the Oban dispatch worker to move events through :processing -> :succeeded / :failed / :dead and by the replay path to reset to :received.

statuses()

@spec statuses() :: [atom()]

Returns the list of valid webhook event statuses.