StudyBoost Docs

Feature: Referral Ledger System (FEAT-54)

Metadata

  • Issue ID: FEAT-54
  • Status: Done
  • Owner: beansint
  • Related PRs: pending PR from branch 54-referral-code-comission-payout

Overview

FEAT-54 introduces referral attribution and commission-ledger infrastructure integrated into signup, checkout, and Stripe payment-confirmation webhooks. The system is payout-ready but does not execute payouts.


Frontend Behavior

  • Signup accepts referral code input and ?ref= prefill.
  • Pricing checkout accepts referral code input and ?ref= prefill.
  • Admin console has a referral operations page for settings, code controls, lifecycle run, and commission overrides.

Backend Behavior

  • New tables: referral_settings, referral_codes, referrals, payment_events, commissions, commission_status_events, payout_batches.
  • Commission lifecycle: pending -> locked -> ready_for_payout; cancelled on refund/fraud; paid reserved for future payout engine.
  • Stripe webhook integration now creates payment ledger rows and referral commission rows on successful invoices.
  • Admin endpoints under /admin/referrals/* manage settings/reporting/overrides.

QA Test Scenarios

Scenario IDDescriptionStepsInputExpected Result
FEAT-54-01Signup attribution happy pathOpen /signup?ref=<active_code>, complete signupValid new user + valid active codeUser is created, referral attribution row created with attribution_source=registration, user receives auto referral code
FEAT-54-02Checkout fallback attributionLogin without existing attribution, submit checkout with referral codeAuthenticated free user + valid codeAttribution row created with attribution_source=checkout before checkout URL response
FEAT-54-03Registration precedence over checkoutSignup with code, then submit checkout with another codeExisting attributed userOriginal attribution remains unchanged; checkout does not overwrite referral
FEAT-54-04Invalid or inactive code rejectionAttempt signup or checkout with malformed/inactive codereferralCode=INVALID@@ or deactivated codeRequest rejected with validation/business error; no attribution row
FEAT-54-05Self-referral blockUser attempts to use own referral codeReferred user == referrer userRequest rejected; no referral row created
FEAT-54-06Duplicate-account heuristic blockAttempt referral where canonicalized emails matchfirst.last+tag@example.com vs firstlast@example.comAttribution rejected and security event logged
FEAT-54-07Commission creation on successful paymentTrigger invoice.payment_succeeded webhook for referred userValid Stripe invoice eventpayment_events row inserted, commissions row inserted in pending, commission_status_events row written
FEAT-54-08Webhook idempotencyReplay same Stripe event idDuplicate event_idSecond processing is skipped; no duplicate payment/commission rows
FEAT-54-09Pending to locked transitionRun lifecycle transition after fraud window elapsesCommission with status=pending, available_at <= nowStatus moves to locked; transition recorded in commission_status_events
FEAT-54-10Admin sets ready_for_payoutCall admin override endpoint on locked commissionstatus=ready_for_payoutCommission status updated and transition event recorded with admin actor
FEAT-54-11Refund cancellationEmit charge.refunded for charge tied to referral commissionStripe refund eventMatching eligible commission rows move to cancelled; status event rows added
FEAT-54-12Fraud dispute cancellationEmit charge.dispute.created for charge tied to referral commissionStripe dispute eventMatching eligible commission rows move to cancelled; payment event marked fraud flag
FEAT-54-13Unauthorized admin access blockedHit /admin/referrals/* without valid admin authNo auth or non-admin role401/403 response; no state mutation
FEAT-54-14Session/auth dependency behavior (FEAT-31)Expire session then call protected referral endpointsExpired/invalid auth cookiesRequest rejected per FEAT-31 auth/session model
FEAT-54-15Logout/revocation behaviorLogout then retry referral/admin protected endpointsLogged-out sessionAccess denied until re-authentication
FEAT-54-16Abuse/rate-limit behaviorRepeated invalid referral attempts through auth/checkout routesBurst invalid requestsExisting auth throttles/abuse controls engage and block progression

Edge Cases

  • Existing attribution is never replaced by checkout input.
  • Fingerprint conflicts cancel commission but do not block payment capture.
  • Payout threshold is stored, not enforced yet.

Notes

  • Canonical feature doc: docs/features/FEAT-54-referral-ledger-system.md.
  • Migration: backend/prisma/migrations/202605120900_add_referral_ledger_system/migration.sql.
  • FEAT-31 auth/session dependency applies to protected endpoints.