Skip to content

feat(backend): Audit Logger — signature verification, SQL optimization, circuit-breaker error recovery, security hardening#848

Merged
emdevelopa merged 1 commit into
emdevelopa:mainfrom
gboigwe:fix/audit-logger-security-optimization-769-770-771-772
May 28, 2026
Merged

feat(backend): Audit Logger — signature verification, SQL optimization, circuit-breaker error recovery, security hardening#848
emdevelopa merged 1 commit into
emdevelopa:mainfrom
gboigwe:fix/audit-logger-security-optimization-769-770-771-772

Conversation

@gboigwe
Copy link
Copy Markdown
Contributor

@gboigwe gboigwe commented May 28, 2026

Summary

This PR addresses all four Audit Logger backend issues assigned from the Stellar Wave Program:

Issue Title
Closes #769 Add cryptographic signature verification to Audit Logger
Closes #770 Optimize SQL queries in Audit Logger
Closes #771 Enhance error recovery for Audit Logger
Closes #772 Conduct security audit on Audit Logger

Changes

#769 — Cryptographic Signature Verification (audit-security.js)

  • Added verifyAuditSignature(payload, signature, secret) which recomputes the expected HMAC and compares with the stored value using crypto.timingSafeEqual (constant-time comparison). This prevents timing-oracle attacks where an attacker could deduce a valid signature byte-by-byte by measuring response times.
  • The function returns false for null signatures, missing secrets, or length-mismatched values — no exceptions leak information.

#770 — SQL Query Optimization (auditService.js)

  • Replaced the previous two-query approach (SELECT COUNT(*) + SELECT … LIMIT … OFFSET) in getAuditLogs with a single query using COUNT(*) OVER() (PostgreSQL window function).
  • One DB round-trip instead of two per page request — roughly halves latency under load.
  • The existing composite index on (merchant_id, timestamp) (migration 20260425000000) is used by the ORDER BY timestamp DESC clause, keeping query plans efficient as the table grows.
  • The synthetic total_count column is stripped from returned row objects before the response is sent.

#771 — Enhanced Error Recovery (audit.js + auditService.js)

  • Added a circuit-breaker to both insertAuditLog implementations.
  • After AUDIT_CIRCUIT_FAILURE_THRESHOLD (default 5) consecutive DB failures the circuit opens; all subsequent write attempts bypass the DB and route directly to the fallback file log for AUDIT_CIRCUIT_RESET_MS (default 60 s).
  • After the reset window, the circuit enters a half-open state and allows a single probe attempt; a successful write closes the circuit and resets the failure counter.
  • Both thresholds are configurable via environment variables so operations teams can tune without code changes.

#772 — Security Audit Hardening (audit-security.js + audit.js + auditService.js)

  • Added validateAuditAction(action) with an explicit allowlist of permitted action identifiers (login, update, create, delete, payment_initiated, etc.).
  • Both logLoginAttempt and auditService.logEvent now reject any action value not in the allowlist before it reaches the DB, blocking log-injection attacks via crafted action strings.
  • Confirmed: all DB writes use parameterized queries ($1, $2, …) — no SQL injection surface.
  • Confirmed: sensitive field values are already redacted via sanitizeAuditKey and sanitizeAuditValue.
  • Signature verification uses timingSafeEqual — no timing-oracle leakage.

Test Coverage

35 tests passing across three files:

  • audit-security.test.js: verifyAuditSignature (valid, tampered payload, tampered signature, null signature, no secret, length mismatch), validateAuditAction (allowed, disallowed, case-insensitive, null/undefined)
  • audit.test.js: circuit-breaker opens after repeated failures, fallback routing when circuit is open, circuit resets on success
  • auditService.test.js: single window-function query for getAuditLogs, zero-row edge case, page/limit clamping, action validation drop, circuit-breaker opens and routes to fallback

All pre-existing tests continue to pass.

…n, error recovery, security audit

- Add verifyAuditSignature() using crypto.timingSafeEqual for constant-time
  HMAC comparison to prevent timing-oracle attacks (issue emdevelopa#769)
- Add validateAuditAction() with an allowlist of permitted action identifiers
  to block log-injection through crafted action strings (issue emdevelopa#772)
- Replace two-query COUNT + SELECT pattern in getAuditLogs with a single
  COUNT(*) OVER() window-function query, halving round-trips to the DB;
  leverages the existing (merchant_id, timestamp) composite index (issue emdevelopa#770)
- Add circuit-breaker state to insertAuditLog in both audit.js and
  auditService.js: after a configurable failure threshold the circuit opens
  and all writes route directly to the fallback log for a reset window before
  the next probe attempt, preventing DB overload cascades (issue emdevelopa#771)
- Expand test coverage: 35 tests across audit-security, audit, and
  auditService — all passing

Closes emdevelopa#769
Closes emdevelopa#770
Closes emdevelopa#771
Closes emdevelopa#772
@vercel
Copy link
Copy Markdown

vercel Bot commented May 28, 2026

@gboigwe 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
Copy link
Copy Markdown

drips-wave Bot commented May 28, 2026

@gboigwe 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 73b1fe6 into emdevelopa:main May 28, 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