API Reference AshHooks v#0.2.2

Copy Markdown View Source

Modules

Webhooks for Ash Framework — inbound (receive, verify, dedup → domain events) and outbound (sign, deliver, retry, track).

Endpoint body_reader that caches the raw, pre-parser request bytes for signature verification.

The delivery runtime driver: one pending delivery row → signed HTTP send → reconciled ledger row. Pure functions over the consumer's resource modules and an injected HTTP adapter — Oban-free by construction; use AshHooks.Worker wraps this as an Oban worker inside the consuming app (ADR-0004's host-injection boundary).

The outbound fanout driver: one event → every matching subscription's endpoint → a durable per-endpoint delivery row (+ an enqueue handoff), with per-endpoint isolation — the outbound twin of AshHooks.Ingress.

Turns the consumer's resource into the outbound webhook Endpoint — the delivery target with its durable circuit-breaker state and its secret REFERENCES.

A reference to a consumer-held secret — never the secret itself.

An outbound webhook destination URL, validated at EVERY write path by living in the type: http(s) scheme, host not a known metadata name, and a literal-IP host (v4, v6, mapped/compatible v6) never in a private/loopback/link-local/reserved range (ADR-0005's registration-time floor — deterministic and offline-safe).

Splode error hierarchy for ash_hooks.

The invalid error class — the webhook input or its verification failed.

An inbound webhook's signature did not verify under the provider's scheme.

The webhook payload does not have the shape the provider expects.

The signing secret for an inbound webhook's provider is unconfigured or unavailable. The caller verifies nothing and does not run the handler.

The timestamp carried by a windowed provider's signature falls outside the allowed replay window.

The payload's event type is not one the provider knows.

The unknown error class — unrecognized failures inside ash_hooks.

An error ash_hooks did not recognize.

The outbound pipeline's unit of work — what a consumer emits and the fanout dispatcher delivers.

The HTTP adapter behaviour the delivery runtime sends through.

A minimal, memory-bounded HTTP/1.1 client over :gen_tcp/:ssl — the DEFAULT adapter (derisk-2): EVERY read is capped, under all framings, so no response — 2xx or not — can balloon a delivery worker's memory.

The default AshHooks.Http adapter: OTP's :httpc, hardened.

Turns the consumer's resource into the inbound webhook ledger — the durable, fenced dedup substrate of the inbound pipeline (ADR-0003).

A decoded inbound webhook body: a JSON object OR a JSON array.

Accessors for a resource's webhooks declarations, read via Spark.Dsl.Extension (the ash_age pattern — no generated getter in this spark version).

The inbound pipeline driver: verify → ingest → claim → handle → mark, over a ledger resource carrying the AshHooks.InboundDelivery extension.

The incumbent webhook envelope, reproduced byte-identically for the :dual migration mode (ADR-0002), with verify/5 as the in-package oracle proving that identity.

Turns the consumer's resource into the outbound delivery ledger — the durable, effect-once record of "this event owes this endpoint a delivery" (the outbound twin of AshHooks.InboundDelivery).

Behaviour for inbound webhook providers.

ComplyCube webhook verifier: lowercase-hex HMAC-SHA256 of the RAW request body under the webhook endpoint's secret, carried in the ComplyCube-Signature header — no timestamp, no replay window (verified against the vendor docs and all three official SDKs; the acceptance vector is the PHP SDK's own test fixture, quoted in test/ash_hooks/provider/comply_cube_test.exs).

Typed event echoed by AshHooks.Provider.ComplyCube.handle_event/2.

HubSpot v3 webhook verifier: HMAC-SHA256 over the concatenated canonical string requestMethod + requestUri + requestBody + timestamp (no separators), keyed with the app's client secret, base64-encoded — carried in the X-HubSpot-Signature-v3 header, with the millisecond timestamp in a SEPARATE X-HubSpot-Request-Timestamp header (verified against the vendor docs first-hand 2026-08-21; the acceptance vector is the docs page's own Java example, quoted in test/ash_hooks/provider/hub_spot_v3_test.exs). Sign the raw body bytes exactly as received and reconstruct the signed URI caller-side — Plug's conn.query_string excludes the ?, and conn.host excludes a non-default port, so join explicitly

Typed event echoed by AshHooks.Provider.HubSpotV3.handle_event/2.

Reference provider for tests and examples: HMAC-SHA256 over the raw body via the default implementation, event type from payload["type"], and an echoing typed event.

Typed event echoed by AshHooks.Provider.Mock.handle_event/2.

Standard Webhooks canon signing and verification — v1 (HMAC-SHA256) and v1a (ed25519) from day one (ADR-0006), over the canonical string msg_id.timestamp.payload.

The SSRF destination classifier (ADR-0005 — enforced at endpoint registration AND again at send time).

Turns the consumer's resource into the outbound Subscription — which events go to which endpoint, and with which signature envelope.

The package's telemetry surface (ADR-0005's telemetry floor): events carry ids, integers, fixed-vocabulary atoms, and classified reason strings ONLY — never secrets, bodies, or payloads. Where a consumer wants secret IDENTITY in an event, fingerprint/1 is the sanctioned 8-hex form; no package event needs it today.

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).

Mix Tasks

Installs ash_hooks into a host application