Sigra.Workers.AuditForward (Sigra v1.0.0)

Copy Markdown View Source

Optional Oban worker for async audit forwarder dispatch.

Wrapped in if Code.ensure_loaded?(Oban.Worker) per D-18 — when Oban is absent from deps, this module does not exist and the :async dispatch path is a no-op (see Sigra.Audit.Forwarders.dispatch_async/3).

Thin Job Args (D-13)

Receives only three keys in job args — a thin reference, never a full payload (security: T-3-INFRA-01):

  • "forwarder" — forwarder module name string (e.g. "Elixir.Sigra.Audit.Forwarders.Threadline")
  • "audit_event_id" — UUID of the audit event row to reload
  • "occurred_at" — ISO8601 timestamp for tracing (not used to load the row)

The worker reloads the full audit row from the configured repo + audit_schema at perform time (D-13 — full payload from DB, not from job args).

Cancel Taxonomy (D-16)

  • {:cancel, :audit_event_not_found} — row deleted between enqueue and perform (e.g. retention cleanup raced the job). Non-retryable.
  • {:cancel, :unknown_forwarder} — forwarder module no longer compiled/loaded. Non-retryable (configuration change removed the dep).
  • {:cancel, :schema_mismatch} — Threadline shipped a breaking schema change or actor configuration error. Non-retryable.
  • {:error, reason} — network / timeout / transient failure. Retryable with exponential backoff.

Retry (D-14, D-15)

max_attempts: 5 — bumped from EmailDelivery's max_attempts: 3 because audit retries don't spam users. backoff/1 curve mirrors EmailDelivery verbatim (D-15): exponential with jitter.

Never Raises (D-17)

perform/1 NEVER raises. Non-:ok exits fire [:sigra, :audit, :forward, :error] telemetry. The originating audit/auth transaction already committed before this job was enqueued — failures here cannot roll it back (boundary doctrine D-21, Pitfall 2).

Config Resolution (D-27)

:repo is read from Application.fetch_env!(:sigra, :repo) — mirrors EmailDelivery exactly (:repo is a top-level :sigra key, not nested under :audit). :audit_schema is read from Application.get_env(otp_app, :sigra_config)[:audit][:audit_schema] following the single config-resolution idiom across all Sigra boot diagnostics.