Skip to content

Telling another system

Something happens in your data and another piece of software must know: an invoice is paid, a loan is overdue. You write neither the sending loop, nor the signature, nor the retries.

A subscription

from kewos.webhooks import register_subscription
register_subscription(
engine,
url="https://example.test/hook",
events=("loan.overdue",), # () = every event
secret=secret, # shared with the receiver
)

Then, when it happens:

dispatcher.dispatch_event(event_name="loan.overdue", payload={"loan_id": 19, "days_late": 3})

The kernel walks the active subscriptions whose event list matches, signs the body with each one’s secret, and posts.

What arrives at the receiver

Run against a real HTTP server:

POST /hook
{"event":"loan.overdue","payload":{"days_late":3,"loan_id":19}}
X-Kewos-Event: loan.overdue
X-Kewos-Signature: fde0817d51fd55e21c613193...
X-Kewos-Delivery-Id: 9e01348d23e44f27b6b12f38...
  • X-Kewos-Event spares the receiver opening the body to route.

  • X-Kewos-Signature is an HMAC SHA-256 of the body, under the subscription’s secret. The receiver recomputes and compares:

    from kewos.webhooks import verify_signature
    verify_signature(body, signature=signature, secret=secret) # True
    verify_signature(body, signature=signature, secret="other") # False

    The comparison is constant-time. The kernel has one HMAC implementation, used to sign and to verify: a mismatch between the two sides is impossible.

  • X-Kewos-Delivery-Id is minted once per dispatch and shared by every receiver of the same event. It serves twice: correlating a fan-out on the operations side, and deduplicating a retry on the receiver side (same id = same attempt).

What happens when it fails

The receiver is down, slow, or answers 500. Three mechanisms, none to write:

  1. One row per attempt in kws_webhook_delivery: status, attempt count, next retry time. A delivery is never an event lost in a log.
  2. A spaced catch-up: 1 min, 5 min, 30 min, 2 h, 12 h, 24 h. A service that restarts gets its event; a dead service does not drown yours in attempts.
  3. Automatic deactivation past the failure threshold, with an event emitted so the application can warn the tenant’s administrator. A dead subscription called forever is a resource leak, and a silence.

And a replay: re-fire a recorded delivery, freshly signed, from the interface. It is the answer to “I never got it” that does not require replaying the business operation.