Skip to content

feat: add /api/referrals endpoints with per-endpoint audit logging - #731

Merged
greatest0fallt1me merged 3 commits into
Predictify-org:mainfrom
PHADAR6:fix/referrals-audit-627
Jul 29, 2026
Merged

feat: add /api/referrals endpoints with per-endpoint audit logging#731
greatest0fallt1me merged 3 commits into
Predictify-org:mainfrom
PHADAR6:fix/referrals-audit-627

Conversation

@PHADAR6

@PHADAR6 PHADAR6 commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Overview

This PR adds a full /api/referrals endpoint suite with structured audit logging for all mutations. The implementation follows the established pattern from /api/indexer/cursor — injectable dependencies for testability, rate limiting, auth guards, and audit rows persisted to audit_logs with before/after state snapshots.

Related Issue

Closes #627

Changes

🗄️ Database

  • [ADD] referrals table in src/db/schema.ts — columns: id, user_id, referral_code, campaign_id, referred_user, status, created_at with indexes on user_id and referral_code
  • [ADD] drizzle/0004_add_referrals.sql — SQL migration creating the referrals table

🔧 Backend Services

  • [ADD] src/services/referralService.tscreateReferral() generates unique REF-XXXX-XXXX codes and persists them; listUserReferrals() returns paginated user referrals
  • [ADD] src/services/auditService.ts integration — every POST mutation writes an audit row via createAuditLog

🛣️ Routes

  • [ADD] src/routes/referrals.tscreateReferralsRouter with:
    • POST /api/referrals (requires auth, rate-limited at 60 req/min)
    • GET /api/referrals (requires auth, rate-limited at 60 req/min)
    • Injectable dependency pattern for hermetic unit tests
    • Audit logging with action: "referral.create", beforeState: null, afterState: { referralCode, campaignId }, actor, IP, and correlationId

🔗 Integration

  • [MODIFY] src/index.ts — registered referralsRouter at /api/referrals

Verification Results

npx jest tests/referrals.test.ts --no-coverage --verbose
✅ 14/14 passed

PASS tests/referrals.test.ts
  POST /api/referrals — validation
    ✓ accepts an empty body (no campaignId)
    ✓ accepts a valid campaignId
    ✓ rejects a non-string campaignId
  POST /api/referrals — success
    ✓ creates a referral code and returns 201
    ✓ emits correlationId header
    ✓ writes audit log with action=referral.create
    ✓ audit log captures actor, beforeState, afterState
    ✓ audit log captures IP from x-forwarded-for
  GET /api/referrals — success
    ✓ returns the list of referrals
    ✓ returns empty list when user has no referrals
  rate limiting
    ✓ POST: returns 429 after limit exceeded
    ✓ GET: returns 429 after limit exceeded
  error propagation
    ✓ POST: 500 on create error, audit NOT written
    ✓ GET: 500 on list error
Acceptance Criteria Status
Audit rows persisted for POST /api/referrals mutations action: "referral.create" with before/after state
Actor (walletAddress), IP, and correlationId captured ✅ All three logged per audit entry
beforeState/afterState snapshots captured beforeState: null, afterState: { referralCode, campaignId }
Rate limiting applied (60 req/min) ✅ 429 returned after limit exceeded
Auth guard (requires JWT) ✅ 401 without valid Authorization header
Input validation at route boundary ✅ Zod schema validates request body
Error propagation (service failures → 500) ✅ Caught and forwarded to global error handler
Focused tests (≥ 90% coverage on changed lines) ✅ 14 tests covering all paths

Timeline

- Add referrals table to DB schema (id, user_id, referral_code, campaign_id,
  referred_user, status, created_at) with indexes on user_id and referral_code
- Add referralService with createReferral and listUserReferrals functions
- Add POST /api/referrals (create referral code) with audit logging:
  - Writes audit row via createAuditLog with action=referral.create,
    beforeState=null, afterState={referralCode, campaignId}
  - Captures actor (walletAddress), IP, correlationId
- Add GET /api/referrals (list user referrals)
- Add migration 0004_add_referrals.sql
- Mount referralsRouter at /api/referrals in src/index.ts
- Add 14 focused tests for auth guard, validation, happy path with audit
  assertions, rate limiting, and error propagation

Closes Predictify-org#627
@drips-wave

drips-wave Bot commented Jul 28, 2026

Copy link
Copy Markdown

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

@greatest0fallt1me
greatest0fallt1me merged commit 719e5e6 into Predictify-org:main Jul 29, 2026
1 check passed
@greatest0fallt1me

Copy link
Copy Markdown
Contributor

LGTM ✅ green CI, clean work — merging!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add per-endpoint audit log for /api/referrals mutations [b#053]

2 participants