Skip to content

feat: add polytomic-webhooks skill - #209

Merged
garethx merged 2 commits into
hookdeck:mainfrom
garethx:feat/polytomic-webhooks
Oct 2, 2026
Merged

garethx merged 2 commits into
hookdeck:mainfrom
garethx:feat/polytomic-webhooks

Conversation

@garethx

@garethx garethx commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Adds the polytomic-webhooks skill: how to receive and authenticate the webhook
batches a Polytomic Webhook destination connection POSTs to your endpoint.

The scheme — Polytomic signs nothing

This is a no-signature provider, and the one thing a reviewer should check
first is that no HMAC was force-fitted. There is none in the verify path (a test
in each example asserts the absence):

  • The only authentication is a static shared bearer token:
    Authorization: Bearer <secret>, compared constant-time against the Secret
    Polytomic shows you during connection setup. Verbatim from the docs: "For now,
    this is the only request authorization and is a static value."
  • Polytomic-Signature-Timestamp is not a signature despite the name — it
    carries an RFC 3339 timestamp (2021-06-01T22:55:36Z), not a digest, and
    not epoch seconds. The examples use it for an optional, configurable freshness
    window (default 300s) and say plainly that this proves nothing about
    authenticity, because the timestamp is not covered by anything.
  • The documented sample token happens to decode as an HS256 JWT
    (aud: webhook, jti, iss), but it is signed with a key Polytomic does not
    give you and has no exp. The skill treats it as an opaque secret and warns
    against jwt.verify/jwt.decode.
  • A missing secret fails closed with 500. On a provider with no signature the
    bearer token is the whole security boundary.

Shape

One documented event, sync.records, and the payload is a batch
(object.records[], default 100 records, user-configurable) — so every handler
loops. records[].fields keys are user-defined by the sync configuration, so
nothing is typed against the docs' email / last_login example;
object.metadata may be an object, null, or absent. Unknown event values
return 200, because a 4xx/5xx "will cause the sync to appear as a failure" and
the docs anticipate future event types.

Hedged facts a reviewer may otherwise re-flag

  • gzip. The docs' sample request shows Accept-Encoding: gzip while the prose
    says payloads arrive "as a gzipped response". Those are in tension, so the
    skill states the operational consequence (the body may arrive compressed; most
    frameworks decompress transparently) rather than asserting a header nobody has
    observed. Marked unsettled pending a live capture.
  • Source IPs. The six addresses are real and quoted from
    docs.polytomic.com/docs/whitelist-ips, which the webhooks page links to — but
    that page frames the list for database/warehouse connections, and it does not
    apply to self-hosted Polytomic. Presented as a firewall convenience, not
    authentication.
  • No retry policy is documented, so none is claimed.
  • records[].hash is described as an idempotency key only; its algorithm and
    length are not asserted.

Testing

  • scripts/validate-provider.sh polytomic-webhooks — passes
  • Express (jest): 40 passed
  • Next.js (vitest, Node 24): 39 passed
  • FastAPI (pytest, fresh venv): 42 passed

Accuracy review: the generator approved with 4 suggestions (2 auto-fixed). My own
pass over the three verify paths confirmed no HMAC/hash primitive, no invented
signature header, and no invented event names — every such string in the skill is
a negative assertion. One genuine defect found and fixed in a follow-up commit: an
IP-allowlist caveat presented a paraphrase inside quotation marks, now quoted
verbatim from the source page. All other quoted claims were checked word-for-word
against https://docs.polytomic.com/docs/webhooks-connections.md.

No live Polytomic account was available, so the gzip question and the exact
Authorization value remain doc-sourced rather than capture-confirmed.

Left as a draft pending owner sign-off.

🤖 Generated with Claude Code

garethx and others added 2 commits October 1, 2026 18:43
The IP-allowlist caveat in SKILL.md and references/setup.md presented a
paraphrase inside quotation marks. Replaced with the verbatim sentence from
https://docs.polytomic.com/docs/whitelist-ips so the attribution matches the
source.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@garethx
garethx marked this pull request as ready for review October 2, 2026 14:46
@garethx
garethx merged commit 4280497 into hookdeck:main Oct 2, 2026
8 checks passed
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