Repository navigation
feat(webhooks): customer webhooks on @profullstack/webhooks 0.2.1 (v1.1.0) - #67
Merged
Merged
Conversation
….1.0) Listing owners can register HTTPS endpoints and SaaSRow POSTs signed CloudEvents (Standard Webhooks headers) when their listings are approved, rejected, featured, upvoted or commented on, or their karma changes. - Hub on a supabase-js WebhookStore (hub_webhook_* tables, SKIP LOCKED claim RPC, service-role only), copied from ugig.net #659. - Events come from Postgres triggers into a hub_webhook_events outbox, since most happen outside Next (edge functions, CoinPay, karma SQL); the server pumps them into hooks.emit() and drains deliveries (instrumentation.ts). - /api/v1/webhooks behind the existing API-key / management-token / member auth. - Manage page Webhooks panel, `saasrow webhooks` CLI (0.4.0), 7 MCP tools. - /api/autoblog-webhook now verifies with @profullstack/webhooks verifyAndParse, keyed with the secret's UTF-8 bytes (what the autoblog sender signs with), and keeps the bearer + post envelope checks; tested against the autoblog sender. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| id: "wh_1", | ||
| owner: "user-1", | ||
| url: "https://hooks.example.com/", | ||
| secret: "whsec_abc=", |
| const h = harness( | ||
| { | ||
| 'GET /api/v1/webhooks': () => [200, { endpoints: [endpoint], event_types: ['product.approved', 'karma.changed'] }], | ||
| 'POST /api/v1/webhooks': () => [201, { endpoint, secret: 'whsec_abc' }], |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
ThreatCrush Security Scan15 finding(s) HIGH/CRITICAL: 1 | MEDIUM: 12 | LOW: 2
Snippets are redacted; ThreatCrush never prints matched credential material. |
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Customer webhooks for SaaSRow on
@profullstack/webhooks0.2.1 (pinned exactly).What a listing owner gets
Register an HTTPS endpoint and SaaSRow POSTs a signed CloudEvent (Standard Webhooks
webhook-id/webhook-timestamp/webhook-signature) when:product.approvedlisting_owner())product.rejectedproduct.featuredproduct.upvotedproduct.commentedkarma.changedRetries with backoff for about three days, auto-pause after 20 failures in a row, delivery log, test pings, secret show/rotate.
How
src/lib/webhooks/supabase-store.ts, the supabase-jsWebhookStorefrom ugig.net #659 (no pg connection string here). Tables areschemaSql('pg','hub_'); due rows claimed withFOR UPDATE SKIP LOCKEDinclaim_hub_webhook_deliveries; RLS on, no policies, service_role only.hub_webhook_eventsoutbox row (only when the owner has an enabled endpoint; a trigger error never fails the original write). The server pumps the outbox intohooks.emit()with event idevt_saasrow_<row id>(stable across a crash re-emit) and the hub drains deliveries. Both start once ininstrumentation.ts./api/v1/webhooks(webhooksApi) behind the existingrequirePrincipal(API key, management token, or signed-in member). 401 without one.saasrow webhooksCLI (0.4.0); MCP toolslist_webhooks,create_webhook,update_webhook,delete_webhook,test_webhook,rotate_webhook_secret,webhook_deliveries;/api/v1index documents it.Autoblog receiver
/api/autoblog-webhooknow verifies with@profullstack/webhooksverifyAndParse(src/lib/autoblogReceiver.ts). The autoblog sender signs with the secret string's UTF-8 bytes; the webhooks package would base64-decode awhsec_secret, so the receiver passes the secret as bytes (same key for any format; prod's is 64 hex). The bearer check and the post-envelope check are kept. Tests sign with@profullstack/autoblog's ownsignRequest/buildEvent(moved to devDependencies) for a hex and awhsec_secret.Migration
supabase/migrations/20261028160000_webhooks_hub.sql, idempotent. Dry-run on the dev2 DB inside a rolled-back transaction fired all six events with the expected payloads.Tests
bun run test:unit298 pass,tsc --noEmitclean,next buildok, CLInode --test36 pass.🤖 Generated with Claude Code