Skip to content

Add webhook-worker example: one-click Cloudflare Worker for Tango webhooks to Slack - #14

Merged
vdavez merged 1 commit into
mainfrom
feature/webhook-worker
Jul 7, 2026
Merged

Add webhook-worker example: one-click Cloudflare Worker for Tango webhooks to Slack#14
vdavez merged 1 commit into
mainfrom
feature/webhook-worker

Conversation

@makegov-mark

@makegov-mark makegov-mark Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

What

A new cookbook example, examples/webhook-worker/: a dependency-free Cloudflare Worker that turns Tango webhook deliveries into Slack messages, deployable with a one-click Deploy to Cloudflare button. It verifies the X-Tango-Signature HMAC (Web Crypto, no SDK), dedupes on delivery_id via Workers KV, walks events[].matches.new[], and posts one Slack message per match. Registration and subscription are handled by a small register.mjs using the Node SDK (@makegov/tango-node); the Worker runtime itself stays dependency-free.

Also reconciles two correctness bugs this work surfaced in the existing webhook-receiver example:

  • server.py deduped on a top-level event_id that the real payload never sends. Now it parses the batch envelope and dedupes on delivery_id, matching the Webhooks payload format (section 6).
  • register.py sent query_type="opportunities" (plural), which the Tango API rejects with Invalid request parameters. Now the singular "opportunity", with validated filters.

Why

Webhooks are a high-value Tango feature with a cold-start problem: standing up a public, signature-verifying, idempotent receiver is a lot of yak-shaving. This collapses it to a button plus two secrets. It also makes the cookbook demonstrate both SDKs cleanly (Python in webhook-receiver, Node here) instead of one example borrowing the other's registration script.

Testing

  • just webhook-worker-smoke: offline. Signs the sample delivery and asserts signature verification, tamper rejection, and Slack-block building. Passing.
  • Deployed live via the button to a Cloudflare account and verified end-to-end: a signed delivery returns 200 with two Slack messages; a re-sent delivery is deduped (200 duplicate); a bad signature returns 401. Dashboard screenshots are in docs/img/.
  • register.mjs verified against the real @makegov/tango-node API surface (method names, argument shapes, the singular query_type).

Risks / notes

  • Examples are not run in CI (they need a Cloudflare account and the live Tango API). The offline smoke test covers the pure logic.
  • The Deploy button URL targets tree/main/..., so it resolves once this merges.
  • Includes ~1.2 MB of dashboard screenshots under docs/img/ and a package-lock.json for reproducible installs.

[skip changelog] this cookbook keeps no CHANGELOG.md.

🤖 Generated with Claude Code

One-click "Deploy to Cloudflare" Worker that posts Tango alert matches to
Slack: HMAC signature verify (Web Crypto), delivery_id dedupe via Workers KV,
pluggable Slack sink. Registration/subscription via a small Node-SDK
register.mjs (@makegov/tango-node); the Worker runtime stays dependency-free.

Also reconciles two correctness bugs this surfaced in webhook-receiver:
- server.py deduped on a top-level event_id the real payload never sends; now
  parses the batch envelope and dedupes on delivery_id (payload format §6).
- register.py sent query_type="opportunities" (plural), which the API rejects;
  now the singular "opportunity" with validated filters.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vdavez
vdavez merged commit 16766c8 into main Jul 7, 2026
4 checks passed
@vdavez
vdavez deleted the feature/webhook-worker branch July 7, 2026 17:43
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.

1 participant