Chimeway.Webhooks.ProcessFeedbackWorker (chimeway v1.0.0)

Copy Markdown View Source

Oban worker that processes inbound webhook feedback from a durable ingress row.

Job args contain only ingress_id per Phase 33 D-01 (durable-spine-over-queue-archaeology). All correlation data — adapter identity, delivery_id, provider_message_id, normalized_status — is read from the persisted Chimeway.Webhooks.Ingress row rather than carried through Oban job args.

Safe-noop semantics:

  • Hard-deleted ingress rows → :ok (Pitfall 2: race against operator/test cleanup).
  • Already-ignored rows → :ok (idempotent dedup convergence).
  • Already-processed rows → :ok (idempotent re-run on Oban retry).
  • Stale delivery_id → write ingress_state: :ignored, ignored_reason: :delivery_not_found, return :ok.
  • Stale provider_message_id → write ingress_state: :ignored, ignored_reason: :provider_message_id_not_found, return :ok.

The normalize_perform_result/1 table mirrors WorkflowProgressionWorker.normalize_progress_result/1 so all understood-but-ignored outcomes collapse to :ok at the Oban queue boundary.

Threats covered:

  • T-33-RETRY (DoS retry storm): stale lookups return :ok rather than raising.
  • T-33-PII (worker-side): only ingress_state, ignored_reason, processed_at are written; no raw job args or provider payload is persisted on the ingress row.
  • T-33-AUTH-LEAK (worker-side): String.to_existing_atom/1 used only on the bounded ~w(succeeded bounced failed) set after canonicalize_status/1. No String.to_atom/1.
  • T-33-IDEMPOTENT: :ignored and :processed branches return :ok without re-applying side effects, preventing double-attempt rows or double-signal emission on retries.

Backwards-compat shim (A6, deploy-safety): Two extra perform/1 heads handle the legacy %{"delivery_id" => …} and %{"provider_message_id" => …} arg shapes for one release cycle, protecting in-flight pre-Phase-33 Oban jobs. Drain the queue and remove these clauses in Phase 34 or v1.5.