Add, debug, and manage webhook providers in the joelclaw webhook gateway. Use when: adding a new webhook integration (GitHub, Stripe, Vercel, etc.), debugging webhook signature failures, checking webhook delivery, testing webhook endpoints, registering webhooks with external services, or reviewing webhook provider implementations. Triggers on: 'add a webhook', 'new webhook provider', 'webhook not working', 'webhook signature failed', 'register webhook', 'webhook debug', 'verify webhook', 'add Vercel/GitHub/Stripe webhook', 'webhook 401', 'test webhook endpoint', or any external service webhook integration task.
76
96%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Low
Low-risk findings worth noting
Manage the joelclaw webhook gateway — add providers, debug delivery, register with external services.
External Service → hooks.joelclaw.com → narrow Vercel raw-body proxy
→ Flagg Tailscale Funnel :10000 → Worker :3111 → /webhooks/:provider
→ verifySignature() → normalizePayload() → (queue pilot or direct Inngest event) → notify function → gatewayStable provider URL target:
https://hooks.joelclaw.com/webhooks/<provider>The ingress is intentionally narrow: it preserves raw bodies/signature headers and only proxies /webhooks/:provider. Provider registrations still using Panda are migration work; do not declare a provider migrated until a real signed delivery succeeds through the stable URL.
gateway push/gateway test patterns for delivery checks| Provider | Events | Signature | Legacy/current registration until verified migrated |
|---|---|---|---|
| todoist | comment.added, task.completed, task.created | HMAC-SHA256 (x-todoist-hmac-sha256) | https://panda.tail7af24.ts.net/webhooks/todoist |
| front | message.received, message.sent, assignee.changed | HMAC-SHA1 (x-front-signature) | https://panda.tail7af24.ts.net/webhooks/front |
| vercel | deploy.succeeded, deploy.error, deploy.created, deploy.canceled | HMAC-SHA1 (x-vercel-signature) | https://panda.tail7af24.ts.net/webhooks/vercel |
| github | workflow_run.completed, package.published | HMAC-SHA256 (x-hub-signature-256) | https://panda.tail7af24.ts.net/webhooks/github |
Current ADR-0217 pilot note: when QUEUE_PILOTS=github, the webhook gateway enqueues normalized github/workflow_run.completed events into the shared Redis queue instead of posting them directly to Inngest. The Restate drainer then forwards the concrete event name github/workflow_run.completed. github/package.published still goes direct.
See references/new-provider-checklist.md for the full 8-step checklist.
Quick summary:
providers/{name}.ts implementing WebhookProvider interfaceserver.ts provider mapfunctions/{name}-notify.tsfunctions/index.ts and add to functions/index.host.ts (or index.cluster.ts when cluster-owned)agent-secrets → add lease to start.shjoelclaw inngest restart-worker --registercurl + real webhook| File | Purpose |
|---|---|
packages/system-bus/src/webhooks/types.ts | WebhookProvider interface, NormalizedEvent type |
packages/system-bus/src/webhooks/server.ts | Hono router — dispatches to providers, rate limiting |
packages/system-bus/src/webhooks/providers/ | Provider implementations (one file per service) |
packages/system-bus/src/inngest/functions/*-notify.ts | Gateway notification functions per provider |
packages/system-bus/src/inngest/functions/index.ts | Function exports barrel |
packages/system-bus/src/inngest/functions/index.host.ts | Host worker function registration (current active role) |
packages/system-bus/src/inngest/functions/index.cluster.ts | Cluster worker function registration (future/role split) |
packages/system-bus/src/serve.ts | Worker role selection + health endpoint + webhook provider list |
~/Code/joelhooks/joelclaw/packages/system-bus/start.sh | Secret leasing on host worker startup |
# Watch worker logs
joelclaw logs worker --follow --grep webhook
# Or directly
curl -s http://localhost:3111/ | jq .webhooks
# → { endpoint: "/webhooks/:provider", providers: ["todoist", "front", "vercel"] }# Test with manual HMAC (SHA1 example for Vercel)
SECRET="your-webhook-secret"
BODY='{"type":"test-webhook","payload":{}}'
HMAC=$(echo -n "$BODY" | openssl dgst -sha1 -hmac "$SECRET" -binary | xxd -p)
curl -X POST http://localhost:3111/webhooks/vercel \
-H "Content-Type: application/json" \
-H "x-vercel-signature: $HMAC" \
-d "$BODY"Common failures:
client_secret (not "Verification token"), Vercel uses the secret from webhook creation, Front uses the rules-based secretjoelclaw runs --count 5
# Look for vercel-deploy-*, todoist-*, front-* function runsjoelclaw gateway status
joelclaw gateway events # Peek pending events# Via Vercel dashboard: Settings → Webhooks → Create
# Or via API:
VERCEL_TOKEN="your-api-token"
curl -X POST "https://api.vercel.com/v1/webhooks" \
-H "Authorization: Bearer $VERCEL_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://panda.tail7af24.ts.net/webhooks/vercel",
"events": ["deployment.created", "deployment.succeeded", "deployment.error", "deployment.canceled"]
}'The response includes a secret — store it: secrets add vercel_webhook_secret --value "..."
Set up via repo Settings → Webhooks:
https://panda.tail7af24.ts.net/webhooks/githubapplication/jsongithub_webhook_secretConfigured at https://hooks.joelclaw.com/webhooks/todoist via Todoist App Console → Webhooks tab.
Uses client_secret as HMAC key (not the "Verification token").
Configured at https://hooks.joelclaw.com/webhooks/front as a Front application webhook.
Initial validation is a signed challenge. Application events use HMAC-SHA256 over timestamp:rawBody; legacy Rules events use HMAC-SHA1 over compact JSON. Keep their secrets separate.
| Provider | Algorithm | Encoding | Header | Secret Source |
|---|---|---|---|---|
| Todoist | HMAC-SHA256 | base64 | x-todoist-hmac-sha256 | App Console → client_secret |
| Front application | HMAC-SHA256 | base64 over timestamp:rawBody | x-front-signature, x-front-request-timestamp | joelclaw-front-app-secret |
| Front rules | HMAC-SHA1 | base64 over compact JSON | x-front-signature | front_rules_webhook_secret |
| Vercel | HMAC-SHA1 | hex | x-vercel-signature | Webhook creation response |
| GitHub | HMAC-SHA256 | hex (prefixed sha256=) | x-hub-signature-256 | Webhook config secret |
| Stripe | HMAC-SHA256 | hex | stripe-signature (structured) | Endpoint signing secret |
:3111, not through Caddyjoelclaw inngest restart-worker --register after deploy — ensures restart + registration in one stephooks.joelclaw.com is registered as the application webhook.--raw flag979b138
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.