Mawu · Features

The Economy Firewall, Commerce & Rights

A focused page within the Mawu Features documentation. The full map and every sibling page live in the Features hub.

6sections12 minread1diagram

On this page

Mawu invites a stranger to write executable code, host it on hardware Oshun does not control, and earn real money when other players show up. That single invitation is also the entire fraud surface. A creator republic only survives if two questions have hard, coded answers: can a community operator's in-realm play-money ever become real money in someone's bank account — and is the payout pool cheap to farm with bot lobbies and self-dealing rings? V7's answers are "no, by construction" and "no, farming costs verified real spend and lights up a relationship graph." Abundantia is the platform-owned plane that enforces both. It distributes content over a content-addressed CDN, computes every creator's payout to the cent across three revenue rails, and settles through the shared Aje substrate — and it wraps that machinery in two non-negotiable defenses: an economy firewall that keeps the real-money economy strictly one-directional, and an anti-fraud layer that makes the engagement pool expensive to game.

This page is the feature view of the half of Abundantia that exists to stop value moving where it must not: the currency firewall and commerce-ledger isolation, the verified-spend and fraud-graph anti-fraud levers, the commerce primitives a creator sells (and the ones the platform refuses to sell), and the rights and provenance machinery that can reverse a publish. It sits exactly on V7's trust boundary — the catalog, the payout formula, and both firewalls are platform-controlled and never delegated to a realm process, while a realm keeps only its own non-fungible play economy. The distribution and full payout-formula deep-dive it composes with lives in the creator-republic page; the parameters the firewall and pool expose to community amendment live in Eunomia governance and trust & safety. For the full V7 feature map, start at the hub: ../V7_features.md.

What ships, honestly#

The economy firewall, anti-fraud, commerce, and rights logic is real, tested TypeScript in one module: apps/v7/abundantia-market-service/src/service.ts is a ~4.5 K-line service whose descriptor (abundantiaMarketServiceDescriptor, service.ts:1030, port 47301) advertises 49 capabilities — among them currency-firewall-eval, verified-spend-payout-eligibility, fraud-graph-eval, rights-provenance-gate, known-infringing-hash-block, and themis-ip-dmca-routing — and satisfies V7ServiceDescriptor. Its sibling service.test.ts carries 21 tests (counted in-tree; the architecture companion records vitest runTests 21 passed, verified on box). They are not truthiness checks — they assert exact computed amounts and exact graph verdicts: a 6_999-bps direct split (one basis point under the 70% floor) is rejected outright, a synthetic 15-node fraud graph resolves to exactly two flags, and an operator_redemption_request from a realm wallet to an Aje payout account is blocked with no leaking path surviving.

Four honest qualifications, stated up front:

  • Abundantia is the ledger, not the wire. Every clear settlement emits a typed AbundantiaAjeSettlementReceipt with deterministic aje:v7:abundantia:<24-hex> transfer ids (createAjeTransfer, service.ts:3589) — it does not import @oshun/payments-bridge or broadcast a transaction. The real Aje plane (libs/oshun/payments-bridge: Ed25519 receipt signing, the cross-rail entitlement bus, the cold-spend co-signing queue) is the substrate that actually settles. Abundantia decides who gets how much; the bridge decides how the money moves.
  • The in-realm economy health controls are architecture, not yet code. The Nàná crate (libs/v7/nana/src/lib.rs) is 128 lines that define NanaCharacterRecord, NanaBalances (cash/bank/society in minor units), and a validate() rejecting negative balances; its own doc-comment says it "intentionally starts small." The realm-scoped double-entry ledger, the faucet/sink primitives, and the inflation-band auto-balancer that the feature brief lists under in-realm economy health are designed but not yet in that crate. (That is fine here — the firewall's job is to keep that play economy walled off from real money, not to run it.)
  • The learned engagement-quality model is spec. The eligibility weighting and the fraud-graph flags are deterministic heuristics that ship and are tested; the ML classifier that would score engagement quality from retention-predictive signals is future work, labeled as such in the arch companion.
  • The Year-1 catalog is operations, not a repo artifact. Which realms get flagged infringing, which creators are spotlighted — that is a schedule the service executes; the machinery ships, the merchandise is ops.

The economy firewall#

flowchart TD subgraph Realm["REALM PLANE — non-fungible play economy (Nàná)"] PLAY[realm_play_currency / realm_inventory_item] OPW[realm_operator_wallet] end subgraph Plat["PLATFORM PLANE — real money, one-directional"] BUY["Purchase · Stripe / Adyen / PayPal / 14 crypto rails"] ENT[platform_entitlement] POOL["Engagement pool · default 40% net"] DIRECT["Direct sale / subscription · ≥70% floor"] PAYOUT[creator_payout_account] end BUY -->|real_money_purchase| ENT ENT -->|realm_currency_grant| PLAY PLAY -. operator sweep allowed .-> OPW OPW -. operator_redemption_request .-> BLOCK(("BLOCKED<br/>blockedCurrencyTransfer")) FRAUD["runFraudGraphEval<br/>self-dealing + RMT topology"] -. flags .-> ELIG ELIG["runPayoutEligibilityEval<br/>verified-spend + retention weight"] --> POOL POOL --> FORMULA["evaluateAbundantiaPayoutFormula"] DIRECT --> FORMULA FORMULA --> RCPT["AjeSettlementReceipt<br/>aje:v7:abundantia:…"] RCPT -->|typed seam| AJE["shared @oshun/payments-bridge<br/>Ed25519 · entitlement bus"] AJE --> PAYOUT

The firewall has two halves, both enforced in code, and the diagram's one deliberately missing arrow — from the realm plane to creator_payout_account — is the whole point.

The currency firewall — realm value cannot reach real money#

runCurrencyFirewallEval (service.ts:1843) classifies every economic node as realm-value (isRealmValueNode: realm_play_currency, realm_inventory_item, realm_operator_wallet) or real-money (isRealMoneyValueNode: platform_real_money_account, platform_entitlement, creator_payout_account) and proves no value can flow from the first class to the second. It does so two ways. A per-transfer guard, blockedCurrencyTransfer (service.ts:3967), blocks any realm-value → real-money edge and any operator_redemption_request originating from realm value. Then — and this is what a naive single-edge check misses — findCurrencyFirewallLeaks (service.ts:4005) runs a depth-first reachability search from every realm-value node over the surviving (non-blocked) transfers, and the eval pushes realm_currency_can_reach_real_money if any path reaches a real-money node, catching laundering that hops through intermediaries. The test pins the intent: an operator may sweep play-currency around inside their own realm (allowed), but the instant they try to operator_redemption_request from the operator wallet to an Aje payout account, that transfer is blocked, no leaking path survives, and the report is clean. This is the line that keeps in-realm casinos and loot mechanics clear of gambling and lootbox regulation: with no real-money cash-out by construction, the in-realm economy is non-convertible value, and age-gating obligations stay clean — jurisdiction-specific counsel confirms the line per market, but the code makes the line structural rather than promised.

Commerce-ledger isolation and the no-paywall-on-free rule#

runRealMoneyCommerceSurfaceEval (service.ts:1872) keeps the platform real-money ledger and the realm play-currency ledger physically separate, hashing each independently and refusing to record real money in a realm ledger (realm_ledger_cannot_record_real_money:<entry>), and it composes the currency firewall so isolation and non-convertibility are checked together. It also enforces a creator-protection invariant the test names directly: a release that shipped free cannot later be paywalled. freeReleasePaywallBlockReasons (service.ts:2532) sets freeReleasePaywallRejected, and the surface is only clean when that rejection holds and the ledgers are isolated — so a creator cannot bait-and-switch a community that already adopted their free content. (The 2015 Steam paid-mods rollback and the recurring Bethesda Creations controversy are the studied cautionary tales.)

Anti-fraud#

Payout fraud is the predictable consequence of paying for engagement, so V7 attacks it at two layers — the eligibility gate above the pool, and a relationship graph beside it.

The eligibility layer — verified-spend, retention-weighted#

Before a single cent enters the engagement pool, runPayoutEligibilityEval (service.ts:1951) decides which play counts. A session is excluded if the account has never spent real money (verified_spend_required) or is a flagged CCU-inflation bot (ccu_inflation_bot) — verified real spend is the single strongest anti-farm lever because a farm cannot cheaply fake it. Surviving sessions are weighted by buildPayoutEligibilityWeightedSession (service.ts:3022) as engagementMinutes × (retentionMultiplier + cohortBonus) / 10_000, where each retained active day adds 1_000 bps capped at seven (PAYOUT_ELIGIBILITY_RETENTION_DAY_BONUS_BASIS_POINTS, PAYOUT_ELIGIBILITY_RETENTION_DAY_CAP) and a new or reactivated payer earns a 2_500-bps bonus. The test pins the math: a 40-minute session from a four-day-retained new payer weights to exactly floor(40 × (14_000 + 2_500) / 10_000) = 66, while a 200-minute never-spent session and a 999-minute bot both weight to zero — raw concurrency buys nothing. The full three-rail split this gate feeds is deep-dived on the creator-republic page.

The fraud graph — self-dealing and gold-farming topology#

runFraudGraphEval (service.ts:2000) builds indexes over account↔realm↔device↔payment edges, computes a degree-centrality score per account, and runs two detectors. findSelfDealingFraudGraphFlags (service.ts:2275) catches a creator farming their own realm — a realm whose owner shares a device or payment instrument with a cluster of never-spent players (threshold FRAUD_GRAPH_SELF_DEALING_NEVER_SPENT_THRESHOLD = 2) — and flags it block. findRmtFraudGraphFlags (service.ts:2330) catches the gold-farming topology: a recipient receiving one-directional "free money" from ≥3 source accounts, ≥2 of them never-spent, exceeding 10_000 units, with anomalous centrality (degree ≥5). The four thresholds are named constants (service.ts:1024-1028), and the test drives a synthetic 15-node graph to exactly two flags — the self-deal ring (creator plus two never-spent alts on a shared console and card, neverSpentAccountCount: 2) and the RMT broker (degree 6, four never-spent farm accounts wiring 4_000 units each for 16_000 total inflow). The detector reports the central account, the implicated devices and payment instruments, and the specific transfer edges — actionable evidence, not a bare score.

What's real vs. spec#

The graph-topology detectors above are real, tested code: degree centrality, one-directional-flow detection, and never-spent / shared-device clustering. The ML engagement-quality classifier the brief alludes to is spec — the shipping eligibility weighting is the deterministic retention/cohort formula, and the graph detectors are deterministic heuristics, not a trained model. The in-realm auto-balancer that holds a realm's inflation inside a target band, and the sink-coverage / wealth-inequality realm-health metrics, are Nàná architecture (see "What ships, honestly") — not yet code. The honest boundary: structural anti-fraud (verified-spend gating, topology flags) ships and is exercised; the learned models and the in-realm health governor are future work.

Commerce#

What is sold, and what is never sold#

Abundantia's real-money commerce sells realms, mods, Collections, assets, and creator subscriptions, alongside cosmetic platform items and optional creator-support tips. In-realm play-currency is strictly separate from this surface — the currency firewall above is precisely what keeps the two apart. What the platform never sells is the trust spine: a player's identity, a character's memory, a governance outcome, a moderation decision, or a safety-floor exemption. And it never paywalls a creator's free release. These are not policy prose layered over a permissive engine — runRealMoneyCommerceSurfaceEval encodes the free-release rule, and the identity / memory / governance / moderation boundaries are owned by the platform-plane subsystems (Iris, Eunomia, Kuanyin/Themis) that a realm process cannot reach across the trust boundary.

Creator royalties and the three rails#

Creators earn three ways, all reconciled by one formula, evaluateAbundantiaPayoutFormula (service.ts:1741): the engagement pool (default 40% of eligible net, governance-set), direct sale / subscription (with a hard ≥70% creator floor), and dependency-revenue chains. The 70% floor is the one rate hard-coded as an invariant — validatePayoutFormulaInput (service.ts:3258) rejects any line whose creatorShareBasisPoints < 7_000 (service.ts:3313), which is why the 6_999-bps test case is rejected with no transfers. Dependency revenue is not declared by hand: computeDependencyRevenueSharesFromLockFile (service.ts:1805) derives the dependency set straight from a realm's resolved Ixchel lock file — the same content-addressed closure the resolver pins — so the makers of what a realm builds on are paid by construction from the dependency graph. The worked test exercises it end to end: Ada's 10_000-cent sale (net 8_000, 70% share, 25% dependency carve) routes 4_200 to Ada and 1_400 to her dependency Cy; a 100-cent engagement pool splits to 33/17/16/34.

The Aje substrate — settlement, KYC/tax/reserve#

A computed route is not a cashable payout. buildCreatorPayoutSettlements (service.ts:3448) walks each route through complianceGateReasons (service.ts:3560): missing KYC, an incomplete tax interview, an unverified payout method, a reserve hold, or an unmet minimum each hold the entire payable amount. In the worked case Ada clears (3_733 after a 500 reserve hold) and Cy clears (1_416), while accounts gated kyc_required, tax_interview_required or payout_method_required cash out zero, and a subscription still inside its refund_window_open is computed but fully held. payoutSettlementStatus (service.ts:3662) reports this honestly — partially_held whenever anything is held, rejected (no transfers) on validation failure, settled only when every cent is clear. Each clear settlement becomes an AbundantiaAjeTransfer wrapped in an AbundantiaAjeSettlementReceipt — the typed contract handed to @oshun/payments-bridge, whose entitlement bus normalizes four fiat processors and fourteen crypto rails into one payment.invoice.settled envelope (entitlement-bus/topics.ts) and whose receipt-signer signs each payout with Ed25519. Optional tamper-evident on-chain governance recording is available through the same Aje integration where a community wants it.

Rights and provenance#

Every asset and layer carries attribution and provenance, forks retain revenue-share links to their parents, and a rights claim can reverse a publish — and that, too, is a coded gate rather than a support-inbox process. runRightsProvenanceEval (service.ts:1912) does four things in one pass. It blocks the re-upload of a known-infringing content hash: a match in knownInfringingAssetHashes (the V5-lineage block list) produces known_infringing_asset_hash:<hash> plus a rights_block_case:<caseRef> and sets reuploadRejected — the path that keeps source-franchise and trademarked content from being re-published under a new name. It walks the attribution chain (input.upload.provenance, sorted deterministically) so every derivative records what it derives from. It preserves fork-revenue links (forkRevenueLinks) so a creator who forks another's work carries the revenue connection forward — the dependency-revenue chain made rights-aware. And it routes any DMCA claim to Themis (routeDmcaClaimToThemisroutedTo: 'themis-ip-dmca'), so a rights-holder's takedown lands in the adjudication path. The eval only reports clean when the re-upload was rejected, the DMCA routed to Themis, and both the attribution chain and fork-revenue links are non-empty — provenance is required, not optional.

What is coded here is the publish-time and claim-time gate: hash-block, attribution, fork-link preservation, and DMCA routing. The downstream unwind — flagging in-world replays historical, pausing resale royalties, sending off-platform takedown notices — is the platform pipeline's job, and V3 already ships the prior-art pattern for it: the bounded 24-hour rights cascade in apps/v3/lilith-commerce-service (lilith_rights_takedown_cascade.rs), whose Themis enforcement throws if it lands outside an 86_400_000-ms (24 h) bound. V7's rights eval is the gate that decides whether an artifact may publish and where a claim is adjudicated; the time-bounded fan-out across surfaces is the established cascade the gate feeds, not a second takedown machine reinvented here.

Where this connects#

  • Abundantia: The Creator Republic — the distribution layer (content-addressed catalog, console authorization, atomic Collection install) and the full three-rail payout formula whose firewall, fraud graph, and rights gate this page details.
  • Eunomia governance and trust & safety — the five-tier governance process that amends the 40% engagement pool, the dependency-share percentage, and the firewall's policy parameters, and the Kuanyin/Themis safety floor the commerce boundaries sit above.
  • ../architecture/abundantia-economy-firewall-and-anti-fraud.md — the engineering companion: every cited function, the reachability-search firewall, the topology detectors, and the exact typed seam to the shared @oshun/payments-bridge Aje plane that executes settlement.
  • The feature hub: ../V7_features.md.