Skip to content

feat: add rate limiting, OpenAPI documentation, query middleware and audit logging - #171

Open
arandomogg wants to merge 1 commit into
SwiftChainn:mainfrom
arandomogg:feat/rate-limiting-swagger-pagination-audit-log
Open

feat: add rate limiting, OpenAPI documentation, query middleware and audit logging#171
arandomogg wants to merge 1 commit into
SwiftChainn:mainfrom
arandomogg:feat/rate-limiting-swagger-pagination-audit-log

Conversation

@arandomogg

Copy link
Copy Markdown
Contributor

closes #106
closes #107
closes #108
closes #109

Summary

Implements four related backend concerns on top of the existing Express and
Mongoose skeleton, along with the domain layer they operate on.

Rate limiting and brute force protection (#106)

Adds src/middlewares/rateLimiter.ts exposing five limiters, each configurable
through environment variables documented in .env.example.

Scope Default Notes
API-wide 100 / 15 min Baseline safety net
POST /auth/login 5 / 15 min Keyed by IP and targeted account
POST /auth/register 10 / hour Curbs automated signup abuse
Escrow router 30 / 15 min Applies to all escrow endpoints
Escrow refund/release 10 / hour Irreversible fund movement

Two decisions worth calling out:

  • Auth attempts are keyed by source IP and the targeted account. Keying on
    IP alone lets an attacker rotate addresses to brute force a single account.
  • Successful logins do not consume the quota, so a legitimate user who signs in
    correctly is never locked out; only failed attempts count.

TRUST_PROXY is honoured so the real client IP is used behind a load balancer
rather than the proxy's address.

OpenAPI 3.0 documentation (#107)

Adds src/docs/ and serves Swagger UI at /api-docs, with the raw document at
/api-docs.json for client generators and contract tests.

All 15 endpoints are documented with request/response schemas, auth
requirements, rate limit responses and pagination parameters. Enumerations are
derived from the Mongoose models rather than restated, so the published
documentation cannot drift from what the API actually accepts. The spec is
validated by @apidevtools/swagger-parser in the test suite, so a broken $ref
fails the build instead of surfacing as a broken docs page.

Pagination, sorting and filtering (#108)

Adds src/middlewares/queryMiddleware.ts, which parses page, limit, sort,
search and filters into normalized options on req.queryOptions. Applied to
Deliveries and Users as required, and also to Escrows and Audit Logs.

Filters support eq, ne, gt, gte, lt, lte, in and nin in bracket
notation:

GET /api/v1/deliveries?status=pending&amount[gte]=100&sort=-amount&page=2&limit=20

Each route declares which fields it exposes; anything else is ignored or
rejected, which keeps unindexed and sensitive fields out of client-controlled
queries. Search terms are regex-escaped to prevent catastrophic backtracking.
Every paginated response returns totalItems, totalPages, currentPage,
limit and navigation flags.

Audit logging (#109)

Adds src/models/AuditLog.ts recording the acting admin, action type, target
type and id, timestamp, and a field-level before/after snapshot, plus IP and
user agent for forensics.

  • Update and delete hooks reject any mutation, so the trail is append-only.
  • The audit entry is written before the privileged change is persisted. If
    the audit write fails the action is abandoned, which guarantees no audited
    action can land unrecorded.
  • Wired to real admin operations: suspension, reinstatement, role changes, and
    escrow refund/release.

Supporting changes

main had no models, controllers or services, so these were added to satisfy
the "response data must come from the database" requirement:

  • User, Delivery and Escrow models with controllers, services, validators
    and versioned routes under /api/v1.
  • Extended the error handler to translate ApiError and Mongoose validation,
    cast and duplicate-key errors, while masking internal details on 5xx.
  • Consolidated src/middleware/ into src/middlewares/ to match the structure
    documented in the README.
  • Added .gitattributes normalizing line endings to LF. Without it a Windows
    checkout rewrites files to CRLF and Prettier reports whole untouched files as
    changed.

Testing

85 tests across 6 suites, all passing. Integration tests run against an
in-memory MongoDB (mongodb-memory-server), exercising real Mongoose queries,
indexes and validation rather than mocked data access.

Test Suites: 6 passed, 6 total
Tests:       85 passed, 85 total

Coverage includes: rate limit enforcement and header behaviour, per-account
keying, pagination/sorting/filter coercion and rejection paths, audit log
immutability, OpenAPI spec validation, and end-to-end API flows including
authorization and error cases.

pnpm build, pnpm lint and pnpm test all pass clean.

Notes for reviewers

  • The issues reference backend/src/..., but this repository's root is the
    backend (src/ at root, per the README structure), so files are placed
    accordingly.
  • Rate limits are disabled under NODE_ENV=test so integration suites are not
    throttled by earlier cases in the same run.

…ging

Implements four related backend concerns on top of the existing Express and
Mongoose skeleton, together with the domain layer they operate on.

Rate limiting and brute force protection
- Add src/middlewares/rateLimiter.ts exposing five configurable limiters.
- Key auth attempts by source IP and the targeted account so that a
  distributed attack against one account is still throttled.
- Skip successful logins so legitimate users are never locked out.
- Apply strict limits to auth, registration, escrow and escrow settlement.

OpenAPI 3.0 documentation
- Add src/docs with the assembled specification and serve Swagger UI at
  /api-docs and the raw document at /api-docs.json.
- Derive enumerations from the Mongoose models so the published docs cannot
  drift from what the API accepts.

Pagination, sorting and filtering
- Add src/middlewares/queryMiddleware.ts parsing page, limit, sort, search
  and whitelisted filters into normalized options.
- Support the comparison operators eq, ne, gt, gte, lt, lte, in and nin, and
  reject fields a route does not expose.
- Return total item and page counts on every paginated response.

Audit logging
- Add the AuditLog model recording admin, action, target, timestamp and a
  field level before/after snapshot.
- Block updates and deletes so the trail stays append only.
- Write the entry before the privileged change is persisted, so no audited
  action can land unrecorded.

Supporting changes
- Add User, Delivery and Escrow models with the controllers, services,
  validators and versioned routes under /api/v1.
- Extend the error handler to translate ApiError and Mongoose errors while
  masking internal details on 5xx responses.
- Add .gitattributes normalizing line endings to LF, which prevents Windows
  checkouts from reporting whole files as modified.
- Add 85 tests covering all four features against an in-memory MongoDB.
@drips-wave

drips-wave Bot commented Aug 30, 2026

Copy link
Copy Markdown

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant