feat: first-class helper for Standard Webhooks (Svix) signature verification

未關閉
#4,928 0 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視

維護者通常 1 天內回覆

還沒有人認領這個 Issue。

評估

難度
4/5
預估耗時
3-5 天
新手友好度
52/100
Issue 類型
功能
描述清晰度
基本清楚
活躍度
活躍
技術堆疊
typescript
領域
security

研究方向

Start by locating the SDK's existing verifyRequestSignature helper and its tests to understand the API conventions and current result shape. Then determine where a Standard Webhooks helper fits and how its signature, raw-body, and timestamp checks should be tested; done means the helper verifies valid signatures, rejects invalid or expired ones, and returns the documented result shape.

由索引模型根據 Issue 內容生成。

描述

Title : feat: first-class helper for Standard Webhooks (Svix) signature verification

Labels : enhancement


Is your feature request related to a problem? Please describe.

I'm building event-driven automations where Trigger.dev jobs react to webhook events emitted by Composio (and a growing number of other providers that have adopted the Standard Webhooks spec — Stripe, GitHub, Slack, Linear, etc.). Composio sends three headers (webhook-id, webhook-timestamp, webhook-signature: v1,<base64>) and the signature is HMAC-SHA256 over ${id}.${timestamp}.${raw_body} with the secret base64-decoded and a tolerance window (default 300s).

The built-in verifyRequestSignature helper only covers single-header schemes (Stripe/GitHub/Cal.com/Novu style), so it can't validate Standard Webhooks signatures out of the box. I get why — supporting every provider's signature scheme isn't Trigger.dev's job, and the helper is the right escape hatch for ad-hoc cases.

The friction isn't the helper itself; it's that every Trigger.dev user integrating with a Standard Webhooks provider ends up writing the same ~50 lines of crypto + header parsing in their verify lambda. That's the part that feels like it could live in the SDK.

Describe the solution you'd like to see

A first-class helper that handles the Standard Webhooks signature scheme, roughly:

import { verifyStandardWebhooks, STANDARD_WEBHOOKS_TOLERANCE_SECONDS } from "@trigger.dev/sdk";

const endpoint = client.defineHttpEndpoint({
  id: "composio",
  source: "composio.dev",
  verify: async (request) => {
    return await verifyStandardWebhooks({
      request,
      secret: process.env.COMPOSIO_WEBHOOK_SECRET!,
      // optional, defaults to 300s per the Standard Webhooks spec
      tolerance: STANDARD_WEBHOOKS_TOLERANCE_SECONDS,
    });
  },
});

What the helper should cover:

  • Read webhook-id, webhook-timestamp, webhook-signature headers
  • Validate the v1, signature prefix (and tolerate future v1a,/v1b, variants if the spec adds them)
  • Base64-decode the secret before HMAC
  • Compute HMAC-SHA256(secret, ${id}.${timestamp}.${raw_body}) with crypto.timingSafeEqual
  • Enforce the timestamp tolerance window (anti-replay)
  • Return the same { success: true } / { success: false, reason: "..." } shape as verifyRequestSignature so it's a drop-in

Bonus if it also exposes the parsed, verified payload (mirroring what the Composio SDK does on its verifyWebhook return type) — that lets users skip the manual JSON.parse after success: true.

Describe alternate solutions

I considered a few:

  1. PR my own implementation into the SDK. I can do this, but the vouched-contributor + changesets + single-feature-per-PR process makes it heavier than a feature request first. And honestly I'd rather the maintainers pick the API shape — verifyStandardWebhooks vs. a generic verifyWebhook({ scheme: "standard-webhooks", ... }) flag, where in the helper tree it lives, etc.
  2. Publish a separate community package (@trigger-dev-community/standard-webhooks-verify). Viable, but the moment Trigger.dev ships its own helper, the community package dies. Putting it upstream also makes it discoverable next to verifyRequestSignature.
  3. Move the verification outside Trigger.dev. A small service in front of Trigger.dev that does the verification + republishes to a queue that Trigger.dev jobs subscribe to. Works, but it's exactly the kind of workaround that disappears when the gap closes. I'd rather not maintain it if I don't have to — and it pushes trust boundaries out of the SDK, which is the opposite of where they belong.

Additional information

Adoption is broader than it looks. Standard Webhooks isn't a niche format — it's becoming the de facto signature spec for SaaS webhooks:

  • Big-name migrations to Standard Webhooks: Stripe, GitHub, Slack, Linear, Shopify (via Svix)
  • Svix-native providers: most new B2B SaaS that use Svix as their delivery layer (Resend, Novu, Knock, Courier, ngrok, Composio, etc.)
  • Spec is actively maintained: the Standard Webhooks org publishes reference SDKs in Node, Python, Go, Ruby, Java, .NET, Rust, PHP — so wrapping one of those in a Trigger.dev helper is low-risk and well-tested upstream crypto

That means a single helper in the SDK would unblock integrations with every provider in the list above — not just one. The same ~50 lines of crypto currently written by hand per integration become write-once-for-everyone.

Why now : the Standard Webhooks spec keeps winning — Stripe and GitHub both migrated to it; Linear, Svix-hosted providers, and a long tail of "send us webhooks" SaaS follow. Every new Standard Webhooks integration in Trigger.dev costs ~50 lines of boilerplate that the SDK could own.

I'm not blocked on this — my workaround works — but it felt worth flagging since the cost of closing the gap is low and the gain compounds with every new Standard Webhooks integration anyone tries to build.

Spec references :

主要語言
TypeScript
星號
16.5k
分支
1.5k
平均合併
1 天 15 小時
30 天內合併 PR
17

環境準備

這個專案沒有提供開發容器、Dockerfile 或貢獻指南,環境需要你自己搭建:先看它的 README,通用步驟見我們的新手貢獻指南。

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

triggerdotdev/trigger.dev 的其他 Issue

查看 triggerdotdev/trigger.dev 的全部 Issue

相似的 Issue

更多 TypeScript Issue

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。