Skip to content

feat(backend): harden Admin Dashboard Service — rate limiting, signature verification, SQL optimization, error recovery#1006

Merged
emdevelopa merged 1 commit into
emdevelopa:mainfrom
Akanimoh12:feature/be-admin-dashboard-rate-limit-signature-sql-error-recovery
Jun 25, 2026
Merged

feat(backend): harden Admin Dashboard Service — rate limiting, signature verification, SQL optimization, error recovery#1006
emdevelopa merged 1 commit into
emdevelopa:mainfrom
Akanimoh12:feature/be-admin-dashboard-rate-limit-signature-sql-error-recovery

Conversation

@Akanimoh12

Copy link
Copy Markdown
Contributor

Summary

This PR hardens the Admin Dashboard Service (the /api/metrics/* revenue/volume reporting endpoints and their backing metricService) across four areas: rate limiting, request signature verification, SQL query efficiency, and DB error recovery.

  • Rate limiting ([Backend] Implement rate limiting for Admin Dashboard Service #927): Added createDashboardMetricsRateLimit / getDashboardMetricsRateLimitKey in lib/rate-limit.js, following the same per-merchant (falling back to hashed API key, then IP) keying pattern already used for merchant security actions and SEP-10 endpoints. Wired into /api/metrics/summary, /api/metrics/revenue, and /api/metrics/volume via a Redis-backed store when Redis is available, matching the existing wiring in app.js.
  • Signature verification ([Backend] Add cryptographic signature verification to Admin Dashboard Service #928): All three dashboard routes now require requireApiKeyAuth({ requireSignature: true }), enforcing the existing HMAC x-api-signature / x-api-timestamp request-signing scheme (already used by sensitive merchant routes) instead of relying on the API key alone.
  • SQL optimization ([Backend] Optimize SQL queries in Admin Dashboard Service #929):
    • Fixed a missing metricService import in routes/metrics.js — the route referenced metricService without importing it, which meant /api/metrics/summary and /api/metrics/revenue would throw a ReferenceError on every request.
    • Removed a duplicated inline SQL query in the /api/metrics/volume handler that re-implemented metricService.getVolumeOverTime instead of calling it.
    • Merged the two sequential last-month/current-month queries in metricService.getMonthlySummary into a single query using conditional aggregation (FILTER (WHERE ...)), halving the DB round trips for that endpoint while still using the existing (merchant_id, status, created_at) index.
  • Error recovery ([Backend] Enhance error recovery for Admin Dashboard Service #930): All metricService DB calls now go through retry-with-backoff and the shared circuit breaker from lib/db.js (the same circuit breaker already protecting auth and audit-log writes), so transient connection errors are retried instead of surfacing as hard failures to the dashboard.

Also converted routes/metrics.js from a static router export to a createMetricsRouter factory so the rate limiter can be injected, matching the existing factory pattern used by routes/payments.js and routes/merchants.js.

Test plan

  • Added lib/rate-limit.test.js coverage for createDashboardMetricsRateLimit / getDashboardMetricsRateLimitKey
  • Added services/metricService.test.js covering the combined summary query, zero-activity asset filtering, retry-then-succeed, and non-retryable failure paths
  • Added routes/metrics.test.js covering signature enforcement, rate-limit rejection (429), and successful delegation to metricService for all three routes
  • Maintainer to run full CI (npm test in backend/) to confirm no regressions

Closes #927
Closes #928
Closes #929
Closes #930

…nature verification, SQL optimization, and error recovery

- Require signed, rate-limited requests on /api/metrics/* (revenue summary,
  revenue by asset, volume over time) via requireApiKeyAuth({ requireSignature: true })
  and a new per-merchant dashboard metrics rate limiter (Redis-backed when available).
- Add createDashboardMetricsRateLimit / getDashboardMetricsRateLimitKey to lib/rate-limit.js.
- Fix a missing metricService import in routes/metrics.js (route threw ReferenceError
  on every call) and remove a duplicated inline SQL volume query in favor of the
  shared metricService.getVolumeOverTime implementation.
- Merge the two sequential last-month/current-month revenue queries in
  metricService.getMonthlySummary into a single conditional-aggregation query,
  halving DB round trips for that endpoint.
- Add retry-with-backoff and circuit-breaker protection (reusing the existing
  lib/db.js circuit breaker) around all metricService DB calls so transient
  connection errors no longer surface as hard failures.
- Convert routes/metrics.js to a router factory (createMetricsRouter) for
  rate-limiter dependency injection, matching the existing payments/merchants pattern.
- Add unit/route tests covering the new rate limiter, signature requirement,
  combined summary query, and retry/circuit-breaker behavior.
@vercel

vercel Bot commented Jun 25, 2026

Copy link
Copy Markdown

@Akanimoh12 is attempting to deploy a commit to the Emmanuel's projects Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave

drips-wave Bot commented Jun 25, 2026

Copy link
Copy Markdown

@Akanimoh12 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

@emdevelopa emdevelopa merged commit 4dda621 into emdevelopa:main Jun 25, 2026
1 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants