Repository navigation
Deliver signed webhooks on publish and revert from the job queue, with retries and a delivery log - #2623
Merged
Conversation
…h retries and a delivery log
…able secret, and test the delivery edge cases
… test types in the content model set
3 of 4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #2611
What
The second slice of F-WHK (#2431): delivery. When a change set is published or reverted, every enabled subscription that wants the event gets one signed request. It is sent from the job queue with retries, and each attempt is logged (API-05, SEC-05, ADR-0010).
[ExtensionPoint] IChangeSetEvents.PublishedAsync(published, reverted)is told about a publish inside its unit of work. A revert's publish also names the set it reverted.WebhookPayloadsbuilds the Standard Webhooks body:type,id(the delivery's id, which is also itswebhook-id),timestampanddata. The data holds the set's id, rationale, sources and adminlink, its items (kind, id, operation, version), and for a revert, the set it reverted.WebhookSignaturessigns it:v1,and the base64 HMAC-SHA256 ofid.timestamp.body, keyed with the secret's bytes. It goes inwebhook-id,webhook-timestampandwebhook-signature.IWebhookDirectorygainsDeliveriesAsync(the latest attempts) andSendTestAsync(awebhook.testdelivery that appendswebhook.test_requested). Both are for people only.ChangeSetDirectory.PublishAsynccalls the registered listeners just before it commits. This is a three-line edit in the F-CHG lane's file.WebhookPublishListenerqueues onewebhook.deliverjob per enabled subscription that wants the event. The job carries the body built at publish time with its own delivery id, so every attempt sends the same request under the same id.WebhookDeliveryJobchecks the subscription is still enabled and its host is still allow-listed, signs, and POSTs. The client behind the outbound allow-list handler follows no redirects and has a timeout.WebhookDeliverieslogs each attempt's status or error, duration and time, with migrations for both providers. It never holds the secret or the signature.Webhooks__AdminUrl,__Timeout(10 s) and__MaxAttempts(6), validated at startup./webhooksshows each subscription's three latest deliveries, and has a "Send test" button.Why
S1 in #2431: when the catalog sync set publishes, the endpoint receives one signed request with the set and its items within seconds, and the S3 revert sends a revert event. A failing endpoint is retried with backoff, with the failures visible, and delivery never blocks publish.
Choices worth a look:
ChangeSetDirectorystays at one loop.change_set.revertedevent naming both sets, not a published event as well, so a receiver sees one event per user-facing action.Webhooks__AdminUrlis set, since a job has no request to learn the admin's address from.Tests
Unit: the signature is HMAC-SHA256 of
id.timestamp.bodywith the secret's bytes, and a malformed secret is refused. The payload has the set, sources, items and link, absolute or as a path, and a revert names the set it reverted.Integration, each on SQLite and PostgreSQL, with a real host, its job queue, and an endpoint on this machine:
webhook-id.change_set.revertednaming the revert set and the set it reverted.Webhooks__Timeoutis a failed attempt, "did not answer in time".Admin: "Send test" queues a delivery, the endpoint receives it, and the list then shows it as delivered with its status.
The full suite ran locally against a
postgres:17container as well as SQLite, and markdownlint passes. No new package and no new project reference.Checklist
v2