Skip to content

Latest commit

Β 

History

History
400 lines (305 loc) Β· 11.6 KB

REVIEWER_CHECKLIST.md

File metadata and controls

400 lines (305 loc) Β· 11.6 KB

Issue #383 - Reviewer Checklist

Overview

This PR implements comprehensive abuse controls for public pay and verify endpoints, addressing all 8 scenarios from docs/ABUSE-CONTROLS.md.

Quick Stats:

  • πŸ†• 9 new files (middleware, tests, docs)
  • ✏️ 15 modified files (handlers, routes, storage)
  • πŸ“ ~1,500 lines of production code
  • πŸ“š ~2,250 lines of documentation
  • βœ… 0 new dependencies
  • ⚠️ 1 breaking change (cancel requires signature in production)

Critical Security Fixes

πŸ”΄ Priority 1: Review These First

  1. Unauthenticated Cancellation Fix

    • File: backend/src/utils/signature-verification.ts
    • Risk: HIGH (anyone could cancel any invoice)
    • Fix: Cryptographic signature required over cancel:${invoiceId}:${timestamp}
    • Test: backend/tests/abuse-controls.test.ts (lines 8-30)
    • Action: βœ… Verify signature validation logic is sound
  2. Cancel Handler Update

    • File: backend/src/routes/invoice.handlers.ts (lines 195-245)
    • Risk: HIGH (breaking change)
    • Fix: Requires signature in production, optional in dev
    • Action: βœ… Verify backward compatibility for dev mode
  3. Verification Amplification Fix

    • Files:
      • backend/src/middleware/rate-limit.ts (lines 100-150)
      • backend/src/middleware/verify-cache.ts (lines 40-90)
    • Risk: MEDIUM (Horizon quota exhaustion)
    • Fix: Per-invoice rate limit + result caching
    • Action: βœ… Verify cache TTL (72 hours) is appropriate

Code Review Checklist

Middleware Implementation

  • Rate Limiting (backend/src/middleware/rate-limit.ts)

    • Token bucket algorithm implemented correctly
    • Redis fallback to memory works
    • Retry-After header calculated correctly
    • Lua script is atomic and correct
    • Client IP extraction handles X-Forwarded-For
  • Verification Caching (backend/src/middleware/verify-cache.ts)

    • Cache key is unique per (invoice, txHash)
    • TTL matches invoice expiry window
    • Both verified and rejected results are cached
    • Redis fallback to memory works
  • Invoice Ceiling (backend/src/middleware/invoice-ceiling.ts)

    • Count check happens before invoice creation
    • 503 response includes Retry-After
    • getInvoiceCount() called correctly
  • Body Limit (backend/src/middleware/body-limit.ts)

    • 16 KB limit enforced before JSON parsing
    • Request is drained to prevent connection hang
    • 413 response is structured correctly

Handler Changes

  • Cancel Handler (backend/src/routes/invoice.handlers.ts)

    • Signature verification integrated correctly
    • Production mode enforces signatures
    • Dev mode falls back to claimed key
    • Error messages are clear (401 vs 429)
  • Verify Handler (backend/src/routes/invoice.handlers.ts)

    • Per-invoice rate limit checked first
    • Cache middleware runs before handler
    • Results cached after Horizon lookup
    • Failed lookups cached to prevent retry

Storage Layer

  • Invoice Count Interface (backend/src/storage/invoice-storage.ts)

    • getInvoiceCount() added to interface
    • Optional to maintain backward compatibility
    • Return type is Promise
  • Memory Storage (backend/src/storage/memory-storage.ts)

    • getInvoiceCount() returns Map.size
    • Proxied through service and adapter layers
  • Postgres Storage (backend/src/services/invoice.service.ts)

    • getInvoiceCount() uses COUNT(*) query
    • Result parsed as integer

Route Configuration

  • Middleware Wiring (backend/src/routes/invoice.routes.ts)

    • Rate limits applied to correct endpoints
    • Verify has both rate limit and cache
    • Cancel has rate limit
    • Create has ceiling check
    • Middleware order is correct
  • Server Setup (backend/src/server.ts, backend/src/server-mvp.ts)

    • Body limit middleware applied before JSON parser
    • Express limit option set to '16kb'
    • Both servers configured identically

Testing Review

Unit Tests

  • Abuse Controls Tests (backend/tests/abuse-controls.test.ts)

    • All 8 scenarios have test coverage
    • Rate limit boundary conditions tested (10th vs 11th)
    • Signature validation tested (stale timestamp, invalid format)
    • Production guard tested (simulate-payment)
  • Existing Tests

    • Run full test suite: npm test
    • Verify no regressions
    • Shared handler tests still pass

Manual Testing

  • Rate Limiting

    # Test per-invoice limit (11th verify blocked)
    for i in {1..11}; do
      curl -X POST http://localhost:3001/api/invoices/test-id/verify \
        -H "Content-Type: application/json" \
        -d '{"txHash": "test-'$i'"}' &
    done
    # Expected: 11th returns 429 with Retry-After
  • Body Limit

    # Test 17 KB payload rejected
    dd if=/dev/zero bs=17000 count=1 | base64 | \
    curl -X POST http://localhost:3001/api/invoices \
      -H "Content-Type: application/json" -d @-
    # Expected: 413 Payload Too Large
  • Signature Required

    # Test cancel without signature (production)
    NODE_ENV=production \
    curl -X POST http://localhost:3001/api/invoices/test-id/cancel \
      -H "Content-Type: application/json" -d '{}'
    # Expected: 401 Signature required
  • Invoice Ceiling

    # Set low ceiling and exceed it
    INVOICE_CEILING=5
    # Create 6 invoices
    # Expected: 6th returns 503 INVOICE_STORE_FULL

Documentation Review

  • Implementation Guide (docs/ABUSE-CONTROLS-IMPLEMENTATION.md)

    • All scenarios addressed
    • Configuration documented
    • Deployment checklist complete
    • Monitoring recommendations clear
  • Migration Guide (docs/ABUSE-CONTROLS-MIGRATION.md)

    • Breaking changes explained
    • Frontend integration examples provided
    • Backward compatibility documented
    • Rollback plan included
  • Completion Report (ISSUE_383_COMPLETION_REPORT.md)

    • All deliverables met
    • Technical decisions justified
    • Performance impact documented
    • Future enhancements scoped out
  • Quick Reference (ABUSE_CONTROLS_IMPLEMENTATION.md)

    • Testing instructions clear
    • Configuration examples correct
    • File changes summarized

Configuration Review

  • Environment Variables

    • INVOICE_CEILING defaults to 5000
    • REQUIRE_SIGNATURES defaults to false (dev) / true (production)
    • REDIS_URL optional, fallback works
    • env.mvp.example updated with new vars
  • Production Settings

    • Signature enforcement automatic in production
    • Body limit enforced at 16 KB
    • Rate limits are reasonable for demo load
    • Redis recommended but not required

Security Review

Cryptography

  • Signature Verification
    • Uses ed25519 (Stellar's native curve)
    • Message format: cancel:${invoiceId}:${timestamp}
    • Timestamp window: 5 minutes (reasonable)
    • Signature encoding: base64 (standard)
    • No timing side channels in validation

Attack Surface

  • Unauthenticated Endpoints

    • All endpoints still public (by design)
    • Rate limits prevent abuse
    • Ownership proofs on sensitive operations (cancel)
    • Stats/list are seller-scoped (acceptable exposure)
  • Resource Exhaustion

    • Invoice ceiling bounds memory (5000 default)
    • Body limit prevents payload attacks (16 KB)
    • Verification caching prevents Horizon amplification
    • Rate limits prevent flooding

Fail-Open Design

  • Error Handling
    • Redis failure falls back to memory
    • Rate limit failure allows request (logged)
    • Cache failure allows Horizon lookup
    • Middleware errors don't block legitimate traffic

Performance Review

  • Overhead

    • Rate limit check: <1ms (acceptable)
    • Cache check: <1ms (acceptable)
    • Signature verification: ~2ms (acceptable for infrequent operation)
    • Invoice count: <5ms (acceptable for create path)
  • Scalability

    • Redis supports distributed state
    • Memory fallback works for single-instance MVP
    • Lua scripts are atomic and efficient
    • Cache hit rate expected 70-90% (based on typical patterns)

Breaking Changes Review

Cancel Endpoint (Production)

Before:

POST /api/invoices/:id/cancel
Body: {} or { "sellerPublicKey": "GXXX..." }

After (Production):

POST /api/invoices/:id/cancel
Body: {
  "invoiceId": "123",
  "sellerPublicKey": "GXXX...",
  "timestamp": 1234567890,
  "signature": "base64-encoded"
}
  • Impact Assessment

    • Frontend: Must implement signature generation
    • Integration tests: Must mock signature or set REQUIRE_SIGNATURES=false
    • Third-party integrations: Will get 401 until updated
    • Dev/test: Can opt-out via REQUIRE_SIGNATURES=false
  • Migration Path

    • Documented in docs/ABUSE-CONTROLS-MIGRATION.md
    • Frontend example code provided
    • Rollback plan documented
    • Phased deployment recommended

Deployment Checklist

Pre-Deployment

  • Tests pass: npm install && npm test
  • TypeScript compiles: npm run typecheck
  • Redis configured (recommended): REDIS_URL=...
  • Environment variables reviewed
  • Frontend signature support ready (or 401 handling)

Deployment

  • Deploy backend first (controls activate automatically)
  • Monitor for 401s (cancel without signature)
  • Monitor for 429s (rate limit triggers)
  • Deploy frontend with signature support
  • Verify 401s drop to zero

Post-Deployment

  • Rate limit logs reviewed (should be minimal)
  • Cache hit rate monitored (should trend to 70-90%)
  • Invoice ceiling not hit (503s should be zero)
  • No unexpected 413s (body size rejections)

Quick Approval Checklist

If you're short on time, focus on these:

  1. βœ… Critical Security Fix: Review backend/src/utils/signature-verification.ts
  2. βœ… Cancel Handler: Review changes in backend/src/routes/invoice.handlers.ts
  3. βœ… Rate Limits: Review backend/src/middleware/rate-limit.ts (Lua script)
  4. βœ… Tests Pass: Run npm test (requires npm install first)
  5. βœ… Documentation: Skim ISSUE_383_COMPLETION_REPORT.md
  6. βœ… Breaking Changes: Read docs/ABUSE-CONTROLS-MIGRATION.md (frontend impact)

Time Estimate:

  • Full review: 2-3 hours
  • Quick approval: 30-45 minutes

Questions for Reviewer

  1. Are the rate limits appropriate for expected demo load?

    • Current: 10 creates/10min, 30 verifies/min
    • Can be adjusted in backend/src/middleware/rate-limit.ts
  2. Is the invoice ceiling (5000) reasonable for MVP?

    • Can be adjusted via INVOICE_CEILING env var
    • Postgres mode has no ceiling
  3. Is 72-hour cache TTL appropriate for verification results?

    • Matches invoice expiry window
    • Can be adjusted in backend/src/middleware/verify-cache.ts
  4. Should we require signatures in dev/test, or keep optional?

    • Currently: Optional in dev, required in production
    • Can enforce always via REQUIRE_SIGNATURES=true
  5. Is the 5-minute timestamp window for signatures appropriate?

    • Prevents replay attacks
    • Can be adjusted in backend/src/utils/signature-verification.ts

Approval Sign-Off

  • Code reviewed and approved
  • Tests reviewed and pass
  • Documentation reviewed and complete
  • Breaking changes acceptable
  • Security concerns addressed
  • Performance acceptable
  • Ready for deployment

Reviewer: _______________ Date: _______________ Comments: _______________


Post-Review Actions

After approval:

  1. Merge PR
  2. Deploy to staging
  3. Run smoke tests
  4. Deploy to production
  5. Monitor for 24 hours
  6. Update frontend (if needed)
  7. Close issue #383

Review Priority: HIGH (fixes critical security bug) Estimated Review Time: 30-180 minutes Deployment Risk: LOW (fail-open design, backward compatible in dev)