Expand description
Delivery of outgoing event webhooks.
The services write one row per matching webhook into webhook_deliveries
inside the transaction of the event (services::webhooks::emit), so a
delivery exists exactly when the event was committed. The background task
started by spawn sends the due rows:
POST <url>with the JSON payload and the headersX-TeamCraft-Event,X-TeamCraft-Delivery(the row id, the same for every retry) andX-TeamCraft-Signature: sha256=<hex HMAC-SHA256(secret, body)>;- a 2xx response is success; anything else (including a redirect, which is
never followed, and a timeout after
TIMEOUT) is retried with exponential backoff and jitter (retry_delay) up toMAX_ATTEMPTS; - a row is claimed with
FOR UPDATE SKIP LOCKEDand leased forLEASE, so several servers never send the same attempt and a crashed sender’s row is retried after the lease; - response bodies are neither read nor stored, only the status code.
Target guard (SSRF). Only http and https URLs without user
credentials are accepted. Every address a host name resolves to is checked
when the connection is made (a custom resolver, so DNS rebinding cannot
slip through) and IP literals are checked before: private, loopback,
link-local (cloud metadata), shared and unique-local addresses are
refused unless the host is listed in TEAMCRAFT_WEBHOOK_ALLOWED_HOSTS or
TEAMCRAFT_WEBHOOK_ALLOW_PRIVATE=true. A non-empty allow-list also
restricts webhooks to the listed hosts. Proxy variables are ignored so the
check sees the real target.
Structs§
- Dispatcher
- Sends webhook deliveries (cheap to clone).
- Outcome
- The result of one attempt.
- Report
- What one run did.
- Target
Policy - Which webhook targets are allowed (see the module documentation).
Constants§
- FIRST_
RETRY - Delay before the first retry; it doubles with every further attempt.
- LEASE
- How long a claimed delivery is reserved for its sender.
- MAX_
ATTEMPTS - Attempts per delivery before it is marked
failed. - MAX_
RETRY - Longest delay between two attempts.
- TIMEOUT
- Time limit of one HTTP request (connect, send, response head).
- WITHHELD_
ERROR - The text recorded on a withheld delivery.
Functions§
- absolutize
- URLs are stored relative (
/revisions/<id>,/api/v1/…) and made absolute with the public URL when they are sent, so a changedTEAMCRAFT_PUBLIC_URLapplies to pending deliveries as well. - hmac_
sha256 - HMAC-SHA256 (RFC 2104) on top of
sha2. - is_
internal - Addresses inside an organisation or the host itself: loopback, private (RFC 1918), shared (100.64/10), link-local (incl. 169.254.169.254), “this network” (0/8), benchmarking (198.18/15), IPv6 unique-local (fc00::/7), link-local (fe80::/10) and site-local (fec0::/10), and NAT64 and 6to4 addresses of such IPv4 addresses.
- purge_
finished - Removes sent and failed deliveries older than
days. Returns the count. - retry_
delay - Delay after the failed attempt number
attempts(1-based): one minute, doubling per attempt, capped atMAX_RETRY, plus 0–25 % jitter derived from the delivery id (deterministic, so the schedule of one delivery is reproducible while many deliveries do not retry in lockstep). - signature
- Value of the
X-TeamCraft-Signatureheader:sha256=<hex>; the key is the webhook secret as UTF-8 bytes. - spawn
- Starts the background delivery.
- system_
lookup - The operating system’s resolver.
- verify_
signature - Checks a signature header in constant time (what a receiver does).
Type Aliases§
- Lookup
- Name resolution for webhook connections: host name → addresses. The
system resolver in production (
system_lookup); tests pass their own answers toDispatcher::with_lookup(DNS rebinding without a DNS server).