Skip to content

feat: deliver signed webhooks#122

Closed
felixvippp-ai wants to merge 7 commits into
Agentpay-Org:mainfrom
felixvippp-ai:codex/webhook-signed-delivery
Closed

feat: deliver signed webhooks#122
felixvippp-ai wants to merge 7 commits into
Agentpay-Org:mainfrom
felixvippp-ai:codex/webhook-signed-delivery

Conversation

@felixvippp-ai

Copy link
Copy Markdown

Closes #32

Summary

  • Added real HTTP webhook delivery when recordEvent() emits matching events.
  • Added wildcard * event matching.
  • Generated a per-webhook whsec_... secret at registration and returned it only once.
  • Hid webhook secrets from list and update responses while surfacing deadLetters.
  • Added HMAC-SHA256 signatures in X-AgentPay-Signature plus delivery/event headers.
  • Added bounded retry for transient failures and permanent dead-letter counting.
  • Updated POST /api/v1/webhooks/:id/test to perform a real signed delivery.
  • Added SSRF protection that rejects private, loopback, and link-local targets unless ALLOW_PRIVATE_WEBHOOKS=true.
  • Added docs/webhooks.md documenting payloads, headers, signatures, retry behavior, dead letters, and SSRF controls.

Validation

  • npm.cmd run build
  • $env:NODE_ENV='test'; node --test dist/webhooks/deliver.test.js
  • $env:NODE_ENV='test'; node --test dist/*.test.js dist/**/*.test.js
  • npm.cmd run lint
  • npx.cmd prettier --check src/events.ts src/routes/webhooks.ts src/store/state.ts src/routes/operational.test.ts src/webhooks/deliver.ts src/webhooks/deliver.test.ts docs/webhooks.md
  • git diff --check

Full post-clean rebuild test result:

tests 74
suites 6
pass 74
fail 0
cancelled 0
skipped 0
todo 0

Note: the repository npm test script uses POSIX NODE_ENV=test syntax, which Windows cmd.exe cannot execute directly. I ran the same built test set with PowerShell's $env:NODE_ENV='test' before invoking node --test.

Security Notes

  • Webhook targets are restricted to http and https.
  • Private, loopback, and link-local addresses are rejected by default, including DNS names that resolve to private addresses.
  • ALLOW_PRIVATE_WEBHOOKS=true is intended only for controlled local/test environments.
  • The signature covers the exact JSON request body sent to subscribers.
  • verifyWebhookSignature() uses constant-time comparison for receiver-side checks.
  • Webhook secrets are not returned after creation and are not included in list/update responses.

@mikewheeleer

Copy link
Copy Markdown
Contributor

thanks for the effort @felixvippp-ai 🙏 this issue isn't assigned to you — please claim an open unassigned issue first, then open your PR. closing for now, hope to see it back 🙌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Deliver webhooks over HTTP with signed payloads and retry/backoff

2 participants