Skip to content

feat: persist webhooks to SQLite, add delivery UI, and switch event i…#826

Merged
joelpeace48-cell merged 2 commits into
FinesseStudioLab:mainfrom
Litezy:feat/webhook-sse-indexer
Jun 30, 2026
Merged

feat: persist webhooks to SQLite, add delivery UI, and switch event i…#826
joelpeace48-cell merged 2 commits into
FinesseStudioLab:mainfrom
Litezy:feat/webhook-sse-indexer

Conversation

@Litezy

@Litezy Litezy commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Closes #448
Closes #521
Closes #468

Summary

  • Webhook persistence — Migrated webhook storage from an in-memory Map to SQLite via a new 028_webhooks migration and sqliteWebhookRepository. Webhooks and delivery history now survive restarts.
  • Missing API routes — Added GET /webhooks/:id/deliveries/:deliveryId, POST /webhooks/:id/deliveries/:deliveryId/replay, POST /webhooks/:id/test, and POST /webhooks/verify (public, no auth required — for consumers verifying HMAC signatures).
  • Horizon SSE indexer — Replaced the missing polling timer in the event indexer with a Stellar Horizon SSE ledger stream. Each ledger close (~5s) triggers a targeted getEvents fetch instead of a 30s blind poll. Falls back to a 30s interval if HORIZON_URL is not configured.
  • Webhook management UI — New page at /admin/webhooks with create/edit/delete, event subscription checkboxes, one-click test delivery, and a delivery history modal with status badges and replay buttons.

What changed

File Change
backend/src/db/migrations/028_webhooks.js New migration: webhooks + webhook_deliveries tables with indexes
backend/src/dal/sqliteWebhookRepository.js SQLite-backed repo replacing in-memory WebhookRepository
backend/src/dal/index.js Swap WebhookRepositorycreateSqliteWebhookRepository
backend/src/jobs/eventIndexer.js Add startSse({ contractIds, horizonUrl }) with auto-reconnect
backend/src/index.js Wire SSE on startup; add replay/test/verify routes; remove dead import
frontend/src/lib/apiClient.js Add webhook API methods
frontend/src/pages/WebhookManagement.jsx New admin page — webhook CRUD + delivery history modal
frontend/src/App.jsx Add lazy route /admin/webhooks behind RequireAdmin

Test plan

  • Start backend; confirm webhooks and webhook_deliveries tables are created on first boot
  • POST /api/v1/webhooks — create a webhook; verify row appears in SQLite, secret returned once only
  • Restart backend; verify webhooks are still listed (persistence check)
  • POST /api/v1/webhooks/:id/test — sends a test delivery and records it in webhook_deliveries
  • GET /api/v1/webhooks/:id/deliveries — delivery history returns persisted rows
  • POST /api/v1/webhooks/:id/deliveries/:deliveryId/replay — replays a failed delivery
  • POST /api/v1/webhooks/verify — returns { valid: true/false } without auth
  • With HORIZON_URL set: confirm /health/indexer shows events processed within seconds of ledger close
  • Without HORIZON_URL: confirm fallback polling fires every 30s
  • Navigate to /admin/webhooks — create/edit/delete/test all work, delivery history modal shows with replay

🤖 Generated with Claude Code

…ndexer to Horizon SSE

- Migration 028: add `webhooks` and `webhook_deliveries` tables with cascade delete and retry index
- Replace in-memory Map WebhookRepository with sqliteWebhookRepository backed by better-sqlite3
- Add missing webhook routes: GET delivery by ID, POST replay, POST test, POST /verify (public, no auth)
- Wire event indexer to Horizon SSE ledger stream for near-instant indexing; fall back to 30s polling when horizonUrl is absent
- Frontend: add webhook management page at /admin/webhooks with create, edit, delete, test, and delivery history with one-click replay
- Remove dead import of unused createWebhookRoutes from routes/webhooks.js

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 29, 2026

Copy link
Copy Markdown

@Litezy is attempting to deploy a commit to the joelpeace48-cell's projects Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave

drips-wave Bot commented Jun 29, 2026

Copy link
Copy Markdown

@Litezy Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

Comment thread backend/src/index.js
Comment on lines +2273 to +2288
app.post(`${prefix}/webhooks/verify`, rateLimiter, (req, res) => {
const { signature, secret, payload } = req.body ?? {};
if (!signature || !secret || payload === undefined) {
return res.status(400).json({
error: 'signature, secret, and payload are required',
code: 'VALIDATION_ERROR',
});
}
try {
const payloadStr = typeof payload === 'string' ? payload : JSON.stringify(payload);
const valid = webhookService.verifySignature(signature, secret, payloadStr);
return res.json({ valid });
} catch {
return res.json({ valid: false });
}
});
@joelpeace48-cell joelpeace48-cell merged commit a14c6cb into FinesseStudioLab:main Jun 30, 2026
7 of 15 checks passed
joelpeace48-cell added a commit that referenced this pull request Jun 30, 2026
feat: persist webhooks to SQLite, add delivery UI, and switch event i…
joelpeace48-cell added a commit that referenced this pull request Jun 30, 2026
feat: persist webhooks to SQLite, add delivery UI, and switch event i…
joelpeace48-cell added a commit that referenced this pull request Jun 30, 2026
feat: persist webhooks to SQLite, add delivery UI, and switch event i…
joelpeace48-cell added a commit that referenced this pull request Jun 30, 2026
feat: persist webhooks to SQLite, add delivery UI, and switch event i…
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants