Skip to main content

Primary backend components

  • app/api/v1/engage/rep/breakdown/route.ts
  • app/api/v1/engage/rep/ledger/route.ts
  • app/api/v1/engage/rep/earn/route.ts
  • app/api/admin/users/[userId]/rep/route.ts
  • server/rep-breakdown.ts
  • server/rep-ledger.ts (recordRepEarn, recordDirectRepGrant)
  • RepLedgerEntry in prisma/schema.prisma (optional reason)

Core model

RepLedgerEntry is the source of truth. Breakdown sums amount by repType: playerChallenge writes map to playerAmp on the ledger read path. Direct grants map to dsportsDirect. Direct earn kinds: Club rows may store a targetId. Only target IDs that resolve to a Team appear in clubRepByTeam. Daily-quest Club rows that target a quest id still count in clubRep but are dropped from the per-team list.

High-level flow

Architectural notes

  • Amount and repType are never client-authoritative.
  • Fan Rep is a separate ledger from PointsHistory.
  • Direct grants use a server-generated idempotency key. Each admin POST is a new grant.
  • Optional reason is stored on the ledger row and preferred on ledger reads.