Skip to content

Add Checkr, Doppler and Sendbird signature adapters (closes #788)#791

Merged
choraria merged 1 commit into
mainfrom
clear-issues
Jul 24, 2026
Merged

Add Checkr, Doppler and Sendbird signature adapters (closes #788)#791
choraria merged 1 commit into
mainfrom
clear-issues

Conversation

@choraria

Copy link
Copy Markdown
Contributor

Closes #788 by doing what the issue asks contributors to do, held to the same standard: every scheme verified against the provider's own signing documentation, cited in the test, with a doc-derived vector.

slug header scheme
checkr x-checkr-signature HMAC-SHA256 / hex, raw body
doppler x-doppler-signature HMAC-SHA256 / hex, raw body, required sha256= prefix
sendbird x-sendbird-signature HMAC-SHA256 / hex, raw body (master API token)

Registry 141 → 144. Slugs are appended, never interleaved: detectScheme is first-match in PROVIDERS order, so appending cannot change which scheme any existing request resolves to. All three headers are vendor-prefixed.

Deliberately not added

Recorded in the test so nobody re-researches them:

  • figma — verification is a shared passcode in the body, not a signature.
  • pipedrive — HTTP Basic, not a signature.
  • greenhouse — real HMAC-SHA256/hex, but the header is the bare Signature. Detection is first-match on header presence, so that row would claim any unknown provider sending a generic Signature header and report WRONG_SECRET instead of UNSUPPORTED_SCHEME. It needs a detection story before it can land.
  • gusto, courier, statsig — could not reach primary docs stating algorithm and encoding. Not guessed.

A wrong config row turns "unsupported" into "your signature is invalid", which is the worse answer — the same reasoning the existing S8 batch used for its own deferred list.

The count cascade

Driven by the repo's own guards rather than by hand: regenerated the recipes golden, the provider-docs dup-guard manifest, the OpenAPI spec and the SDK schema; added three directory rows; updated the 17 files published-counts.test.ts pins (141→144, config-driven half 108→111).

Two things the guards caught that a blind sed would have broken:

  1. comparisons.ts uses 141 for a competitor too — "Hookdeck documents 141 named platforms". Only our-side sentences were changed, and the script asserts both competitor facts survive. comparisons.test.ts already scopes its pin to the us column for exactly this reason.
  2. changelog.mdx states 141 as a historical release fact and is left alone. Updating it would falsify history, not refresh a claim.

Icon fetcher

The fetcher only accepted PNG, and Google's favicon service answers in JPEG for doppler.com — so a real provider ended up with no committed icon and a failing wall guard for a file that was never broken. cwebp decodes JPEG natively, so the sniff now accepts both. HTML is still refused, and there's a test proving the widening didn't turn the sniff into a rubber stamp.

Verification

pnpm lint, pnpm typecheck, pnpm test (29 tasks), pnpm build all exit 0. The three adapters have positive, wrong-secret and tampered-body cases, signed independently via crypto.subtle rather than through the verify path's own key import.

🤖 Generated with Claude Code

https://claude.ai/code/session_016XkxpR5GKp98W5qq2cgsSt

Closes #788 by doing what the issue asks contributors to do, to the same
standard: every scheme is verified against the provider's OWN signing
documentation, cited in the test, with a doc-derived vector.

  checkr   x-checkr-signature    HMAC-SHA256 / hex, raw body
  doppler  x-doppler-signature   HMAC-SHA256 / hex, raw body, `sha256=` prefix
  sendbird x-sendbird-signature  HMAC-SHA256 / hex, raw body (MASTER api token)

Registry 141 -> 144. Slugs are APPENDED, never interleaved: detectScheme is
first-match in PROVIDERS order, so appending cannot change which scheme any
existing request resolves to. All three headers are vendor-prefixed.

DELIBERATELY NOT ADDED, recorded in the test so the next person doesn't
re-research them:
  figma      — verification is a shared passcode in the BODY, not a signature.
  pipedrive  — HTTP Basic, not a signature.
  greenhouse — real HMAC-SHA256/hex, but the header is the bare `Signature`.
               Detection is first-match on header presence, so that row would
               claim any unknown provider sending a generic `Signature` header
               and report WRONG_SECRET instead of UNSUPPORTED_SCHEME.
  gusto, courier, statsig — could not reach primary docs stating algorithm and
               encoding. Not guessed. A wrong config row turns "unsupported"
               into "your signature is invalid", which is the worse answer.

The count cascade, all driven by the repo's own guards rather than by hand:
regenerated the recipes golden, the provider-docs dup-guard manifest, the
OpenAPI spec and the SDK schema; added three directory rows; updated the 17
files the published-counts guard pins (141->144, config-driven half 108->111).

TWO THINGS THE GUARDS CAUGHT THAT A SED WOULD HAVE BROKEN:
- comparisons.ts uses 141 for a COMPETITOR too ("Hookdeck documents 141 named
  platforms"). Only our-side sentences were changed; both competitor facts are
  asserted still present. comparisons.test.ts already scopes its pin to the
  `us` column for exactly this reason.
- changelog.mdx states 141 as a historical release fact and is left alone.
  Updating it would falsify history, not refresh a claim.

Also: the icon fetcher only accepted PNG, and Google answers in JPEG for
doppler.com — so a real provider ended up with no committed icon and a failing
wall guard for a file that was never broken. cwebp decodes JPEG natively, so
the sniff now accepts both. HTML is still refused, and there is a test proving
the widening did not turn the sniff into a rubber stamp.

Gate: lint, typecheck, test (29 tasks), build all green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016XkxpR5GKp98W5qq2cgsSt
@mintlify

mintlify Bot commented Jul 24, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
webhook-co 🟢 Ready View Preview Jul 24, 2026, 10:58 AM

💡 Tip: Enable Workflows to automatically generate PRs for you.

choraria added a commit to webhook-co/webhook-go that referenced this pull request Jul 24, 2026
…iders (#16)

webhook-co/webhook#791 adds three signature adapters, taking the provider
registry from 141 to 144. The provider enum appears in four places in the
spec, so the vendored copy here went stale the moment that PR regenerated it.

This matters beyond tidiness: the route-coverage ratchet in this repo
validates against testdata/openapi.json. A stale copy keeps passing against
an old route list, so a newly-shipped route could reach production with no Go
method and nothing would say a word — which is exactly what the guard in
webhook's ci.yml watches for, and why it blocks that PR until this lands.

Copied byte-for-byte from packages/openapi/src/openapi.json (verified with
cmp). `go build ./...` and `go test ./...` both pass against it.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@choraria
choraria merged commit 035fce3 into main Jul 24, 2026
72 of 81 checks passed
@choraria
choraria deleted the clear-issues branch July 24, 2026 12:06
@mintlify

mintlify Bot commented Jul 24, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
webhook-co 🟡 Building Jul 24, 2026, 10:57 AM

💡 Tip: Enable Workflows to automatically generate PRs for you.

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.

Add a webhook signature adapter for a provider we don't cover yet

1 participant