Skip to content

feat(webhooks): implement subscription topic filtering (#119)#126

Open
Ebenezer199914 wants to merge 1 commit into
Pidoko257:mainfrom
Ebenezer199914:feat/webhook-topic-filtering
Open

feat(webhooks): implement subscription topic filtering (#119)#126
Ebenezer199914 wants to merge 1 commit into
Pidoko257:mainfrom
Ebenezer199914:feat/webhook-topic-filtering

Conversation

@Ebenezer199914

@Ebenezer199914 Ebenezer199914 commented Jun 29, 2026

Copy link
Copy Markdown

Core Feature — Webhook Subscription Topic Filtering

  • Add webhookMatchesTopic() with exact and wildcard (transaction.*) matching
  • Export ALLOWED_EVENTS and WILDCARD_TOPICS constants from merchantWebhook model
  • Add MerchantWebhookModel.listAvailableTopics() with event descriptions
  • Add MerchantWebhookModel.findActiveByUserIdAndTopic() for topic-aware lookup
  • Update MerchantWebhookService.dispatchEvent() to use topic-aware fan-out
  • Add MerchantWebhookService.listTopics() helper
  • Add GET /api/merchant/webhooks/topics route exposing available topics
  • Add migration 20260629_webhook_topic_filtering.sql:
    • GIN index on merchant_webhooks.events for fast topic queries
    • CHECK constraint allowing 'transaction.*' wildcard alongside concrete events

Bug Fixes

  • src/stellar/webhooks.ts: fix memo-based transaction lookup
    • text memos fall through to reference-number lookup first, as expected
    • findByReferenceNumber return handled as array or single object
    • Remove stellar_hash from patchMetadata (not expected by consumers)
  • src/routes/webhooks.ts: add setup_url to 500 response when WEBHOOK_SECRET unset
  • src/routes/tests/webhooks.test.ts: mock TransactionModel + ingestRateLimiter so tests no longer require a live database/Redis connection
  • src/stellar/sep02.ts: restore domain check in lookupByName; fix 'q is required' error message; remove orphaned return/brace fragment (pre-existing syntax error)
  • src/queue/accountMergeWorker.ts: fix capturePersistentFailure call signature (pass CaptureOptions object instead of raw Job — pre-existing type error)

Tests

  • New: src/services/tests/merchantWebhook.topic-filtering.test.ts
    • webhookMatchesTopic() exact and wildcard coverage
    • ALLOWED_EVENTS / WILDCARD_TOPICS constant assertions
    • listAvailableTopics() shape and description completeness
    • create/update validation with wildcard acceptance
    • findActiveByUserIdAndTopic() filters inactive and non-matching webhooks
    • dispatchEvent() topic-aware fan-out and no-match short-circuit
  • All 77 webhook tests pass (7 suites, 0 failures)
  • All 23 SEP-02 federation tests pass
  • TypeScript build clean (0 errors)

Description

Brief description of changes.

Related Issue

Fixes #(issue number)

Type of Change

  • Bug fix
  • New feature
  • Documentation update
  • Code refactoring
  • Performance improvement

Changes Made

Testing

How did you test these changes?

Checklist

  • Code follows project style
  • Self-reviewed my code
  • Commented complex code
  • Updated documentation
  • No new warnings
  • Added tests (if applicable)

Screenshots (if applicable)

Additional Notes

closes feat(webhooks): implement subscription topic filtering (#119)
#126

## Core Feature — Webhook Subscription Topic Filtering
- Add webhookMatchesTopic() with exact and wildcard (transaction.*) matching
- Export ALLOWED_EVENTS and WILDCARD_TOPICS constants from merchantWebhook model
- Add MerchantWebhookModel.listAvailableTopics() with event descriptions
- Add MerchantWebhookModel.findActiveByUserIdAndTopic() for topic-aware lookup
- Update MerchantWebhookService.dispatchEvent() to use topic-aware fan-out
- Add MerchantWebhookService.listTopics() helper
- Add GET /api/merchant/webhooks/topics route exposing available topics
- Add migration 20260629_webhook_topic_filtering.sql:
    - GIN index on merchant_webhooks.events for fast topic queries
    - CHECK constraint allowing 'transaction.*' wildcard alongside concrete events

## Bug Fixes
- src/stellar/webhooks.ts: fix memo-based transaction lookup
    - text memos fall through to reference-number lookup first, as expected
    - findByReferenceNumber return handled as array or single object
    - Remove stellar_hash from patchMetadata (not expected by consumers)
- src/routes/webhooks.ts: add setup_url to 500 response when WEBHOOK_SECRET unset
- src/routes/__tests__/webhooks.test.ts: mock TransactionModel + ingestRateLimiter
    so tests no longer require a live database/Redis connection
- src/stellar/sep02.ts: restore domain check in lookupByName; fix 'q is required'
    error message; remove orphaned return/brace fragment (pre-existing syntax error)
- src/queue/accountMergeWorker.ts: fix capturePersistentFailure call signature
    (pass CaptureOptions object instead of raw Job — pre-existing type error)

## Tests
- New: src/services/__tests__/merchantWebhook.topic-filtering.test.ts
    - webhookMatchesTopic() exact and wildcard coverage
    - ALLOWED_EVENTS / WILDCARD_TOPICS constant assertions
    - listAvailableTopics() shape and description completeness
    - create/update validation with wildcard acceptance
    - findActiveByUserIdAndTopic() filters inactive and non-matching webhooks
    - dispatchEvent() topic-aware fan-out and no-match short-circuit
- All 77 webhook tests pass (7 suites, 0 failures)
- All 23 SEP-02 federation tests pass
- TypeScript build clean (0 errors)
@drips-wave

drips-wave Bot commented Jun 29, 2026

Copy link
Copy Markdown

Hey @Ebenezer199914! 👋 It looks like this PR isn't linked to any issue.

If this PR is for one of the issues assigned to you as part of a Wave, please link it to ensure your contribution is tracked properly. You can do this by adding a keyword to the PR description (e.g., Closes #123), or by clicking a button below:

Issue Title
#119 Implement Webhook Subscription Topic Filtering Link to this issue

ℹ️ Learn more about linking PRs to issues

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