The host-injected Oban worker (ADR-0004): the consuming app defines ONE
module, and the Oban beam compiles only where Oban exists — this macro
expands use Oban.Worker inside the HOST's compilation, so the package
itself never references a loaded Oban module and compiles Oban-free
(the CI no-optional leg's proof).
defmodule MyApp.WebhookDeliveryWorker do
use AshHooks.Worker,
deliveries: MyApp.OutboundDelivery,
endpoints: MyApp.WebhookEndpoint,
secret_resolver: {MyApp.Secrets, :webhook_secret},
queue: :webhooks,
oban: MyApp.Oban
endConsumers pass enqueue: {MyApp.WebhookDeliveryWorker, :enqueue} to
AshHooks.dispatch/4 — the generated enqueue/2 IS that seam.
Options:
:deliveries,:endpoints(required) — the consumer's resource modules carrying theAshHooks.OutboundDelivery/AshHooks.Endpointextensions.:secret_resolver(required,{m, f}) — resolves an endpoint's secret REFERENCE:f(ref) :: {:ok, secret_binary} | {:error, term}. The returned value ALWAYS signs the Standard Webhooks envelope (itswhsk_/whsec_prefix only selects the key slot for rotation); legacy envelopes, when the signing mode uses them, are signed from the endpoint'slegacy_secret_ref/legacy_previous_secret_refreferences through this same resolver.:snippet_redactor({m, f}, optional) — a consumer callback run on the RAW captured body ahead of the package's snippet floor (domain-specific tokens need raw input). Only consulted on per-callsnippet_capture: truediagnostic runs; a crash or invalid return degrades to the sanitized summary, never raw bytes. The capture flag itself is deliberately NOT a macro option (ADR-0005's snippet amendment: compile-time knobs are broad and quiet) — pass it in theAshHooks.Delivery.run/2config for a one-row diagnostic re-drive.:http— theAshHooks.Httpadapter (defaultAshHooks.Http.Bounded).:oban— the Oban instance name (default the unnamed instance).:queue,:timeout,:max_attempts— Oban Worker options (the job's timeout defaults to 30s; its max_attempts is advisory only — snoozes extend it, the ROW's ceiling governs dead-letter).:delivery_max_attempts(default 10),:base_backoff_seconds(2),:max_backoff_seconds(3600),:retry_after_cap_seconds(86_400) — the row-driven retry policy.
Uniqueness (verified against deps/oban 2.23.1, ADR-0007):
fields: [:args], keys: [:endpoint_id, :event_uuid], period: :infinity, states: :all — the defaults (60s / :successful) would re-admit a
duplicate trigger after success or window expiry; both are overridden.
A uniqueness conflict is {:ok, %Oban.Job{conflict?: true}} — the
generated enqueue/2 maps it to :ok (a conflict IS dedup success).