Primary backend components
app/api/v1/engage/rep/breakdown/route.tsapp/api/v1/engage/rep/ledger/route.tsapp/api/v1/engage/rep/earn/route.tsapp/api/admin/users/[userId]/rep/route.tsserver/rep-breakdown.tsserver/rep-ledger.ts(recordRepEarn,recordDirectRepGrant)RepLedgerEntryinprisma/schema.prisma(optionalreason)
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
repTypeare 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
reasonis stored on the ledger row and preferred on ledger reads.
