@krizaka/webhooks
Des webhooks signés et idempotents, dans les deux sens : livrés avec reprises, vérifiés et appliqués une fois.
Installer
npm install @krizaka/webhooksLe README ci-dessous est celui du paquet sur npm, en anglais.
Signed and idempotent webhooks, both ways.
Out. An owner registers endpoints (https, public host; the secret is shown once and kept sealed); the product emits an event with a stable id, which is queued once per endpoint however often it is emitted; deliverDue sends what is due, signed (x-krizaka-signature: t=<s>,v1=<hmac of "<t>.<body>">), retries with a backoff, gives up after maxAttempts and keeps the log (deliveries).
In. receiveWebhook verifies the signature over the raw body (with a replay window), records the event id first, applies once; a replay is "duplicate"; if applying throws, the record is removed so the sender's retry applies it.
import { createWebhooks, webhooksMigration, receiveWebhook } from "@krizaka/webhooks";
await db.query(webhooksMigration("accounts")); // once, in your migrations (idempotent)
const hooks = createWebhooks({ query, rules: { events: ["booking.created", "invoice.paid"], maxAttempts: 6, backoffSeconds: [30, 300, 1800, 7200, 43200] }, secrets: { seal, open } });
await hooks.emit(ownerId, { id: `booking:${id}`, type: "booking.created", payload }, now);
await hooks.deliverDue(now, send); // from a tick: `send` is your fetch (no redirects, short timeout, refuses private addresses)The product keeps: the HTTP call (send), sealing the secret, when deliverDue runs, the quota per plan, its audit and its routes. Nothing here reads the clock.
Exports
Les 22 noms que le paquet exporte, lus dans ses types.
| Nom | Nature | Ce que c’est |
|---|---|---|
createWebhooks | fonction | Outgoing webhooks over the product's PostgreSQL (see webhooksMigration): endpoints, one queued delivery per endpoint and event, signed retries, a log. |
DeliveryView | type | |
endpointUrlProblem | fonction | |
EndpointView | type | |
EVENT_ID_HEADER | constante | |
EVENT_TYPE_HEADER | constante | |
newEndpointSecret | fonction | A new endpoint secret: shown once, kept sealed. |
OutgoingRequest | type | |
Query | type | A SQL executor: the rows of a statement and its parameters (the product's pool). |
receiveWebhook | fonction | An incoming webhook, applied exactly once: the signature is checked over the RAW body (a bad one is WEBHOOK_SIGNATURE), the event id is recorded first (a r… |
Send | type | The product's HTTP call: no redirects, a short timeout, and it refuses to connect to a private address. |
SIGNATURE_HEADER | constante | The signature of a webhook: t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<raw body>"> (the scheme payment processors use, so a receiver's code is the one e… |
signBody | fonction | Signing is @krizaka/payments' own (the same scheme, one implementation): this adds the header name and a verdict instead of a throw. |
VerifyResult | type | |
verifySignature | fonction | Checks a signature header over the raw body: well-formed, not older than the tolerance (or from the future), and equal in constant time. |
WEBHOOK_CODE | constante | |
WebhookCode | type | |
WebhookDeps | type | |
WebhookError | classe | |
WebhookRules | type | |
Webhooks | type | |
webhooksMigration | fonction | The tables of the webhooks: an owner's endpoints, the deliveries queued for them (one per endpoint and event — queuing twice is a no-op), and the inbound eve… |
Paquet
| Version sur npm | 0.2.0 (npm) |
| Licence | Apache-2.0 |
| Node.js | >=22 |
| Dépendances | date-fns ^4.4.0, @krizaka/payments ^0.1.0 |
| Code source | webhooks |
Journal des versions
0.2.0
Minor changes
- Signing and verification are
@krizaka/payments' own (one implementation of the scheme, no copy).
0.1.0
Minor changes
- First release: signatures and their verification, the endpoint address rules, outgoing endpoints / queue / delivery with retries and a log, incoming events applied once, the PostgreSQL migration.