feat(api): add webhook subscription lifecycle management (closes #531) - #551
Merged
Xhristin3 merged 1 commit intoAug 24, 2026
Conversation
…eamRollz#531) Expose list, update, delete, and manual redelivery for webhook subscriptions, reusing the existing active flag and retry budget instead of a delete-plus-recreate workflow. The signing secret stays creation-time-only. Extend the shared contracts and SDK with the new surface so provider/consumer suites pin the wire shape, and align GET /streams list serialization with the string-id contract.
gbengaeben
force-pushed
the
feat/issue-531-webhook-subscription-management
branch
from
August 24, 2026 14:48
3534c3f to
a4edcde
Compare
8 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.
Summary
Adds the missing lifecycle management surface for webhook subscriptions (issue #531). Today a subscription can be created and its deliveries inspected, but never changed or stopped — the only escape hatch was a direct database update or a delete-plus-recreate (which loses delivery history and the signing secret). This PR closes that gap by reusing the schema's existing
activeflag, the repositories, and the retry schedule rather than inventing a parallel mechanism.What changed
API (
api/src/webhooks)GET /webhooks?streamId=&page=&limit=— paginated list of the caller's subscriptions, newest first, with an optionalstreamIdfilter. Owner-scoped by theuser_idfilter itself.PATCH /webhooks/:id— partial update ofurl,events, and/oractive. The signing secret is deliberately not updatable: it is creation-time-only, returned exactly once byPOST /webhooks. Deactivating stops new fan-out immediately (dispatchStreamEventonly matchesactive = true) and the retry sweep skips pending deliveries; reactivating resumes both. Pending deliveries of a deactivated subscription are left pending (not cancelled) so reactivation resumes their retry schedule unchanged — documented once in the controller JSDoc.DELETE /webhooks/:id— removes the subscription and, via the schema's ON DELETE CASCADE, its entire delivery history; returns 204.POST /webhooks/:id/deliveries/:deliveryId/retry— manually re-queues a failed/pending delivery (next_attempt_at→ now). The attempt count is kept, so a manual retry still operates inside the existingMAX_RETRIESbudget. 404 for unknown webhook/delivery or a mismatched pairing; 409 for an already-delivered delivery.subscription.userIdcheck → 403) and Swagger-documented.Repositories
webhook-subscriptions-db.repository.ts/ in-memory twin: addedlistByUser(with stream filter + pagination) andupdate(only fields present inchanges, parameterised — nosecretkey exists on the path) anddelete.webhook-deliveries-db.repository.ts/ in-memory twin: addedrequeue.Contracts & SDK
tests/contracts: newwebhooks.contract.tscovering create, list, update, retry, retry-404, and delete, plus the matching schemas (the creation response is the only one containingsecret). Provider verification (api/src/contract-provider.spec.ts) and consumer verification (xstreamroll-sdk/__tests__/contract.consumer.test.ts) both exercise them.xstreamroll-sdk: newlistWebhooks,updateWebhook,deleteWebhook,retryWebhookDeliveryclient methods,PATCH/DELETEsupport inHttpClient,WebhookSubscriptionSummaryandUpdateWebhookDtotypes, and a README walkthrough of the full lifecycle (create → manage → deactivate/reactivate → redeliver → delete).GET /streamslist now serializes ids to strings viatoStreamResponse, matching the single-stream endpoints and the shared@xstreamroll/types#Streamstring-id contract.Testing
Verification run locally:
Out of scope (unchanged)
Secret rotation, delivery-signature format changes, and webhook URL SSRF protections remain separate issues, as noted in #531.
Closes #531