Published in openvibe-contracts v0.33.0 (docs/adr/ADR-012-economic-classification.md), rendered as is.

ADR-012: Billing vs loyalty, credits and currency classification

Status: Accepted 2026-09-22. Gates Wave 8 (OpenVibe.Billing), Wave 9 (Tips) and Wave 10 (VIP).

Context and current evidence

A code survey on 2026-09-22 found twenty economic units across Live, Network and Games (the full inventory with file references is docs/economic-inventory.md in OpenVibe.Billing). The findings that drive this decision:

Decision

Every unit belongs to exactly one class. The class decides which system owns it and what it may ever be converted into.

| Class | Meaning | Units | Owner | |---|---|---|---| | MONEY | Real-money value received, owed or paid out | provider receipts and payment orders; Vibes cashout balances (creator payable); cashout requests; site-routed PowerChat donations; subscription payments; platform revenue (purchase spread, retained subscription share, site-route fee) | OpenVibe.Billing | | CREDIT | Prepaid value bought with money, spendable only on OpenVibe, never withdrawable by the buyer | Vibes spendable balance | OpenVibe.Billing (a liability until spent) | | ENTITLEMENT | A right granted by a payment (or by a plan), with a start and an end | channel subscriptions; future VIP perks | OpenVibe.Billing holds the entitlement truth; OpenVibe.VIP holds plans and perks | | LOYALTY | Earned by activity, no cash value, not bought, not withdrawable, not transferable between people | OpenCoins; channel points; Arena XP | Network (OpenCoins) and Live (channel points) until Billing's loyalty ledger exists; never mixed with MONEY/CREDIT accounts | | COSMETIC-ENTITLEMENT | An unlocked item, no balance, not tradable | global cosmetics; chat tags | the product that renders it (Live today) | | GAME-STATE | Gameplay truth inside a game world | bottle caps, inventory, reputation, unlocks, market stock | OpenVibe.Games | | LEGACY-ARCHIVE | Frozen; kept for reconciliation and claims only | Live openvibe_coins_balance ("gold"), Camp Funds, Hobo Coins, old Live game tables, hobo-quest backups | read-only in place | | EXTERNAL | Money that never touches OpenVibe | direct PowerChat tips to a streamer's own account | recorded as an interaction by Tips; no Billing liability |

Rules that follow

  1. Only Billing moves MONEY and CREDIT. Balances become ledger accounts in a balanced, append-only double-entry journal (user_credit:<subject>, creator_payable:<subject>, provider_clearing:<provider>, platform_revenue, payouts_pending, refunds). No product keeps a mutable money column once Billing is authoritative.
  2. Every provider event is recorded once. Webhooks land in Billing, are stored as immutable receipts keyed by (provider, provider_event_id), and settle with idempotency keys; replays produce no second effect. Refunds, reversals and chargebacks are first-class journal entries that trace to the original transaction; a chargeback on credit that was already donated leaves the recipient's payable intact and books the loss against platform revenue, pending review.
  3. CREDIT → MONEY happens only by giving it to someone else (a tip or paid interaction). The buyer can never withdraw it. Self-dealing is refused by subject, not by local id.
  4. MONEY → CREDIT (recycle) stays allowed as an explicit journal entry, or is retired by product decision; it is never an unrecorded balance swap.
  5. LOYALTY never converts to MONEY or CREDIT, is never bought, and is not transferable between people. Network's network.coins.transfer grant is revoked; the endpoint stays only for staff tooling. Loyalty ledgers keep idempotency keys that are deterministic per event (no Date.now()/random keys).
  6. Cosmetics are not tradable. The dormant "deactivate to game item for trading" path stays dead. A future paid cosmetic is an ENTITLEMENT bought through Billing.
  7. Game state never bridges to MONEY, CREDIT or LOYALTY without a new ADR.
  8. Legacy balances are never shown as live. Frozen "gold" stays for a future claim flow and is removed from live displays.
  9. Test money is marked, not mixed. Test transactions carry a test flag in Billing and never count toward creator or platform totals.
  10. Payouts are a separately controlled capability. Approving a cashout requires a payout reference from the provider; the escrow period is enforced by Billing, not only displayed.
  11. Freeze switch first. Billing ships with an economy freeze (writes refused, reads served) before any balance moves.

Alternatives considered

Migration consequences

Rollback

Until cutover, Live remains authoritative and Billing only shadows (imports and reconciles). After cutover, rollback means freezing Billing, exporting its journal, and re-deriving Live's columns from it; the cutover runbook keeps the last Live snapshot.

Acceptance tests