Core concepts

The ledger

Append-only, and why that is not negotiable.

Every movement of money writes a ledger_entry. Entries are never updated and never deleted, a database trigger refuses both, so the guarantee survives a migration, a psql session, and a future role misconfiguration.

Entry types

TypeMeans
topupThe end user paid and their wallet was credited
grantCredit issued without a payment, a trial, a support gesture
usage_debitInference consumed, at raw upstream cost
refundMoney returned
reversalA top-up undone, a chargeback, or a duplicate
adjustmentA correction, including credit from an orphaned hold

Idempotency is a unique index, never application logic. A check-then-insert has a race window; a constraint does not.