# Commerce & Royalties

V3 ("Lilith") sells three different things to three different rooms: a stadium
ticket to a Saraswati concert, a tip dropped into a yoga instructor's jar
mid-class, and a limited signed edition of an AI-generated track. The hard part
is not charging the card — it is making the money land correctly afterward. A
concert ticket has to be named-on-issue, capped per fan, and resalable only as a
no-markup signed return so scalpers can't farm it. A track's revenue has to
split — at _generation time_, before a single stream plays — between the artist,
the producer, the platform reserve, and the **human voice contributors and
rights-holders whose work the AI persona depends on**, then settle to each of
them per quarter, on-chain, in fiat or crypto depending on where they live. And
when a track is taken down for a rights violation, every ticket, replay, and
signed edition that touches it has to unwind within a day, with royalties paused
and restitution routed. Commerce in Lilith is therefore not a checkout button —
it is a ledger discipline.

That discipline lives in one real Rust service,
`apps/v3/lilith-commerce-service`, which computes every split, receipt, route,
and refund deterministically and audits each one into V1; and it settles through
the **shared Aje payment substrate** (`libs/oshun/payments-bridge`, composing
`libs/aje/*`) so a fiat Stripe charge and an on-chain crypto invoice grant the
same entitlement through the same bus. This page is the architecture-side
companion for the commerce and creator-monetization story in the "Trust, Rights,
Commerce, and Operations" set; the section hub is
[../V3_ARCHITECTURE.md](../V3_ARCHITECTURE.md).

## What ships, honestly

The commerce engine is **real, tested Rust**, not a spec.
`lilith-commerce-service` is a ~14.8 K-line crate of thirteen domain flow
modules plus the Tara split engine in `lib.rs`, and it carries **151 unit tests
that pass green** (`cargo test -p lilith-commerce-service` →
`151 passed; 0 failed`, verified on box). The tests are not truthiness checks —
they assert exact computed ledger amounts: a 10,000-cent paid class routes
`2_000` to platform and `8_000` to the instructor; a 1,001-cent donation routes
`100`/`901` with the rounding remainder deliberately assigned to the creator; a
track waterfall that doesn't total exactly 10,000 bps is rejected. The split
math, validation, anti-scalp checks, refund-tier classifier, store-policy gate,
and audit-event derivation are all domain-specific and exercised against
known-correct values.

The **shared Aje payments-bridge is also real**: `@oshun/payments-bridge`
(`libs/oshun/payments-bridge`) is a substantive library with Ed25519 receipt
signing (`@noble/curves`), a cold-spend co-signing queue, an admin/refund
surface, and an 18-rail entitlement bus that makes four fiat processors (Stripe,
Adyen, PayPal, generic) and fourteen crypto chains emit structurally identical
entitlement events. The TS-side V3 royalty surfaces — `isis-music`'s track
provenance bundle (which stamps the `aje:royalty-waterfall:saraswati-stage-v1`
policy at generation), `tara-studio`'s TTS voice-royalty distribution, and
`saraswati-stage`'s Themis rights adjudication — are real basis-point code with
their own tests.

**Two honest qualifications.** _First_, the commerce crate's job is the
**ledger**, not the wire. Functions like
`complete_tara_stripe_connect_onboarding` and
`withdraw_tara_instructor_aje_native` validate the request (supported region,
valid `aje_` wallet, sufficient balance), compute the routes, and emit a
**provider-shaped receipt** with deterministic IDs (`acct_tara_us_…`,
`po_tara_test_…`, `aje:withdrawal:lilith-royalty:…`, a `network_receipt_id`) and
a `Settled`/`Paid`/`Complete` status. They do **not** call the live Stripe API
or broadcast an Aje transaction from the pure-function path — that execution is
the shared substrate's responsibility (Stripe Connect; the payments-bridge
cold-spend queue and entitlement bus). The boundary is honest: real money math
and a typed settlement contract on this side, real rail execution on the other.
_Second_, the **Year-1 catalog** — which concerts, which signed-edition drops,
which Tara passes — is a schedule the engine executes, not an artifact in the
repo. The machinery is shipped; the merchandise is operations.

## The commerce surfaces

The crate's `SERVICE_DESCRIPTOR` (port `43105`) advertises twelve capabilities,
each backed by a module. They divide into the four things a creator economy
needs: sell access, accept gratitude, sell ownership, and unwind cleanly.

### Tickets — named, capped, signed-return-only resale

`lilith_ticket_issuance.rs` (2.1 K lines, 15 tests) is the anti-scalp ticket
ledger. Tickets are **named on issue** and **capped at four per fan**
(`LILITH_TICKET_PER_FAN_CAP = 4`), and the only legal transfer is a
`LilithTicketResaleMode::SignedReturnOnly` flow: the resale **cannot exceed the
original face value** ("anti-scalp signed-return resale cannot exceed original
face value") and the buyer can't cross the per-fan cap. Returns are
cryptographically tagged with two signature prefixes —
`sig:lilith-ticket-return:` (holder) and `sig:lilith-commerce-return:` (issuer)
— so a return is provable, not assertable. The capacity bands map exactly onto
the Stadium-tier seating plan the monolith defines: front-256 (`256`),
hall/mezzanine (`768`), crowd (`3_072`), and a 128-seat master class. A no-show
seat is reclaimed by `promote_lilith_waitlist_no_show_seat` inside a
15-minute-pre / 10-minute-post-start window, splitting the upgrade fee 20/80
platform/instructor.

### Tips and concert gratitude

`lilith_tip_routing.rs` routes a tip to an Instructor, Artist, or SessionHost at
**10% platform / 90% recipient** (`1_000`/`9_000` bps), over Stripe or Aje, and
writes **three receipts per tip** — payer, recipient, and platform — so all
three parties have a record. `saraswati_concert_tips.rs` is the concert-specific
variant (10% platform / 90% artist, settled inside a 60-minute window). The math
is the same basis-point engine used everywhere, and the rounding test
(`1_001 → 100`/`901`) proves the remainder favors the creator.

### Subscriptions, passes, and the free tier

`lilith_subscription_billing.rs` (832 lines) bills the recurring products — Tara
passes, Saraswati Club passes, Commons memberships — on monthly cycles with
proration, over Stripe or Aje. `saraswati_club_pass.rs` is the club-only
admission path, and `saraswati_free_tier.rs` models the no-charge experience
(catalog browse, follow, batched light-emoji, small-concert admission) so the
free attendee is a first-class commerce state, not an absence of one.
`lilith_fan_token_boundaries.rs` keeps fan-token access benefits behind a
per-region legal-review gate — tokens grant access perks, never unregistered
financial instruments.

### Cancellation, refund, and the 90-day credit ledger

`lilith_cancellation_refunds.rs` (2.3 K lines, 22 tests) encodes the three-tier
schedule as a real classifier (`classify_refund_tier`): a **full refund** at ≥
24 h before start, a **half-refund-half-credit** between 1 h and 24 h, **no
refund** inside the hour, and **no-show**. Credit lands in a **90-day Lilith
credit ledger** (`LILITH_CREDIT_VALIDITY_MS = 90 days`). The asymmetry is
deliberate and machine-enforced: a **platform-fault** cancellation adds a 50%
goodwill credit (`5_000` bps) and must complete within a 24 h SLA, and a
**provider outage** (payment rail or Pixel Streaming) issues a 100% credit
(`10_000` bps) and pages the `lilith-commerce-ops` queue. The module also owns
refund tax reversal (across five jurisdiction profiles) and chargeback handling
(48 h ops SLA, 14-day appeal window). Critically, a platform-fault cancellation
**pauses the affected concert's royalty waterfall** — commerce and royalties are
one ledger.

### Platform billing bridges — store compliance

`lilith_platform_billing_bridges.rs` is the store-policy gate. Where Apple,
Google, or Sony require their own billing flow, the bridge validates an **Apple
IAP / Google Play Billing / PSN Wallet** receipt against the real policy
references (`apple-app-review-guideline-3.1.1-iap`,
`google-play-payments-policy-billing`, `playstation-store-psn-wallet`): it
**forbids external payment links** for in-app digital goods, requires a signed
receipt, a passed certification case in the platform's cert namespace, and
confirmed entitlement delivery. The point is reconciliation parity — the
entitlement is delivered through the same commerce ledger regardless of rail, so
a PSN-wallet purchase and a Stripe purchase look identical downstream.

## The royalty and revenue-split model

This is where Lilith's creator-economy thesis lives: AI personas are built on
human work, so the people whose voices and rights-holdings feed a persona get
paid automatically, by construction, not by goodwill.

### The Tara split engine

`lib.rs` hosts `apply_tara_default_platform_split`, the instructor-economy core.
A `TaraCommercePaymentKind` of `PaidClass` splits 20/80 platform/instructor;
`Tip`/`Donation` splits 10/90. An instructor can opt a slice of their share into
a **Lineage Fund** endowment, capped at 10% of the instructor share
(`TARA_LINEAGE_FUND_MAX_INSTRUCTOR_SHARE_BASIS_POINTS = 1_000`) — a structured
way to fund the teaching tradition. Every split produces a `TaraPayoutRoute` per
recipient and a `v1-audit:v3-tara-commerce-split:…` event id. Instructor payouts
reach a bank via `complete_tara_stripe_connect_onboarding` (KYC, supported
regions `AU/CA/DE/FR/GB/NL/US`) or a wallet via
`withdraw_tara_instructor_aje_native` (crypto regions
`BR/CA/GB/IN/KE/NG/PH/SG/US`, token `aje-native-usdc`).

### The Saraswati track royalty waterfall

`lilith_royalty_waterfall.rs` (1.2 K lines, 14 tests) is the heart of the page.
A track's split is **encoded at generation time** —
`encode_lilith_track_royalty_waterfall_at_generation` must run within 60 minutes
of generation (`LILITH_TRACK_ROYALTY_WATERFALL_ENCODING_WINDOW_MS`) and is
anchored to an Aje contract (`aje:royalty-waterfall:saraswati:…`). The split is
validated hard: it must total **exactly 10,000 bps**, have at least two payees,
and **include both an `Artist` and a `PlatformReserve` role**; payees must use
the `artist:` / `producer:` / `contributor:` / `platform:` namespace. The five
`LilithRoyaltyWaterfallRole` variants — `Artist`, `Producer`,
**`VoiceContributor`**, **`PromptContributor`**, `PlatformReserve` — are the
mechanism by which the human contributor share is first-class. Revenue then
flows in two stages: `route_lilith_track_stream_payout` pays per-stream events
(namespace `stream:saraswati:`) against the persisted waterfall, asserting the
routes match the config; and `settle_lilith_quarterly_royalties` does the
on-chain quarterly true-up (below).

### Signed editions and remix rights — secondary royalties

`saraswati_signed_edition.rs` (2.2 K lines, 23 tests) mints **limited editions
of 250** via the Aje primitive `aje.signed-edition.mint.v1` inside a 6 h mint
window, and — the key creator-protection — **enforces a 10% secondary-sale
royalty** (`SARASWATI_SIGNED_EDITION_SECONDARY_ROYALTY_BPS = 1_000`) that routes
back to creators on every resale. It imports the waterfall roles directly from
`lilith_royalty_waterfall` (cross-module composition, not duplication). A track
takedown cascades to outstanding editions within a 24 h SLA, marking them
`Historical` and **pausing resale-royalty routing**; a holder whose edition is
withdrawn chooses to `KeepAsHistoricalArtifact` or `BurnForFullRefund` through a
Lilith-Rights review queue. `saraswati_remix_rights.rs` applies the same
discipline to licensed remixes: secondary royalty splits must total 10,000 bps
and **include the original artist and the remixer**.

### TTS voice-contributor royalties

On the TypeScript side,
`libs/v3/tara-studio/src/tts-voice-royalty-distribution.ts` settles a separate
**5%** added royalty (`basisPointShareCents(…, 500)`) to a voice contributor
whenever their cloned voice is used in a payable context (on-demand Aja cue
playback, localized dub stream) — and pointedly _not_ for unsupported uses
(arbitrary TTS prompts). This is the consent-to-compensation loop the provenance
layer promises, expressed as money.

## Settlement through the shared Aje substrate

Every rail converges on one settlement plane so a purchase reconciles
identically whether it arrived as fiat or crypto.

```mermaid
flowchart TD
    subgraph Buy[Purchase surfaces]
      FIAT[Stripe / Adyen / PayPal]
      CRYPTO[14 Aje crypto rails]
      STORE[Apple IAP / Google Play / PSN]
    end
    FIAT --> BRIDGE
    CRYPTO --> BRIDGE
    STORE -->|store-policy gate| LEDGER
    BRIDGE[payments-bridge<br/>entitlement bus · Ed25519 receipts] -->|invoice.settled| LEDGER
    LEDGER[lilith-commerce-service ledger<br/>v3 Postgres schema] --> SPLIT{Split engine}
    SPLIT -->|tickets / tips / subs| ROUTES[Payout routes]
    GEN[Track generation] -->|encode waterfall ≤60 min| WF[Aje waterfall contract]
    WF --> STREAM[Per-stream payout]
    STREAM --> QTR[Quarterly on-chain settlement<br/>89–92 day window · 6 h grace]
    ROUTES --> PAYOUT[Stripe Connect · Aje native withdrawal]
    QTR --> PAYOUT
    QTR -->|aje:royalty-settlement-audit| CHAIN[(On-chain audit)]
    ROUTES --> AUDIT[(V1 @oshun/audit-platform)]
    PAYOUT --> AUDIT
    QTR --> AUDIT
```

### Rails, receipts, and the entitlement bus

`@oshun/payments-bridge` exists to make settlement rail-agnostic. Its
entitlement bus defines three topics — `payment.invoice.confirmed`,
`payment.invoice.settled`, `payment.refund.broadcast` — whose envelopes are
**structurally identical** across a `rail` field spanning four fiat rails and
fourteen crypto rails (BTC on-chain/Lightning, LTC, five EVM chains, XMR, SOL,
TON, Cardano, Ergo, TRON). The entitlement service never learns whether a
payment was fiat or crypto; it just grants on `invoice.settled`. Receipts are
signed with Ed25519 against the V1 audit-platform key and canonicalized
deterministically (sorted keys, bigints as decimal strings), so a receipt
verifies off-box.

### Quarterly on-chain settlement

`settle_lilith_quarterly_royalties` is the true-up. It refuses to run unless the
period covers one real calendar quarter (`89–92` days), the settlement was
scheduled at or after quarter close, the actual run lands inside a **6 h grace
window**, and there is a **visible Aje on-chain audit id**
(`aje:royalty-settlement-audit:…`). It re-derives each role's settlement amount
from the same waterfall, emits an `aje:settlement-transfer:quarterly:…` per
route, and only reports `completed` when it ran on schedule, the on-chain audit
is visible, and a positive amount settled. Royalties are thus **bounded and
provable**, not best-effort.

### Payouts: Stripe Connect and Aje native

Both the Tara split engine and the royalty waterfall expose dual payout legs:
`process_lilith_royalty_stripe_connect_payout` for fiat contributors in
supported regions, and `process_lilith_royalty_aje_native_withdrawal` for
crypto, each validating region eligibility and balance and emitting a typed
receipt. The region lists differ by design — crypto reaches markets where Stripe
payouts don't — which is itself the creator-access argument for the Aje rail.

## Edge cases and failure modes

- **Splits can't drift.** A waterfall that doesn't total exactly 10,000 bps, or
  omits an artist or platform-reserve split, is rejected at encode time — there
  is no "approximately 100%."
- **Resale can't scalp.** A signed-return resale above original face value is
  refused, and a buyer at the per-fan cap can't acquire a fifth ticket through
  the resale path.
- **Settlement can't run early or stale.** The quarterly settler rejects a
  period shorter than 89 days, a run before quarter close, a run past the 6 h
  grace window, or a missing on-chain audit id.
- **A takedown unwinds money.** `lilith_rights_takedown_cascade.rs` (24 h SLA)
  flags archived performances historical, pauses in-world replays, marks signed
  editions historical and **pauses their resale-royalty routing**, and fires
  off-platform takedown notices — and a Themis-adjudicated unlicensed-use claim
  triggers track unrelease plus royalty restitution.
- **Provider outage is a credit, not a loss.** A payment-rail or Pixel-Streaming
  outage yields a 100% credit and an operator page, distinct from a user's own
  late cancellation.
- **The ledger seam is explicit.** Stripe/Aje/store receipts are typed contracts
  emitted by pure functions; the live charge, on-chain broadcast, and
  cryptographic store-receipt validation happen in the rail layer, not the split
  math. Read a `Settled` status as "ledger says settle here," with execution on
  the bridge.

## How it connects

Commerce is downstream of generation and rights. The royalty waterfall is
encoded by the [Saraswati stage pipeline](./saraswati-stage-pipeline.md) at
track-generation time and stamped into the `isis-music` provenance bundle, which
is why a split exists before the first stream. Every commerce action audits into
V1 `@oshun/audit-platform` and the ticket/refund/credit ledger is DSAR-covered,
tying this page to
[persona policy, provenance, and rights](./persona-policy-provenance-and-rights.md):
the same takedown machinery that withdraws a track is what pauses its editions'
royalties here. The financial telemetry, release gates, and abuse posture for
these flows live in
[observability, performance, security, and launch](./observability-performance-security-and-launch.md).
And the shared substrate — `@oshun/payments-bridge`, `@oshun/billing-support`,
`@oshun/audit-platform`, and the `libs/aje/*` rails — sits in the platform map
at
[../../platform/oshun-domain-libraries.html](../../platform/oshun-domain-libraries.html).

## Related

- [Saraswati Stage Pipeline](./saraswati-stage-pipeline.md) — where the royalty
  waterfall is encoded at generation and signed editions originate
- [Persona Policy, Provenance & Rights](./persona-policy-provenance-and-rights.md)
  — the takedown cascade and consent records that gate and unwind commerce
- [Observability, Performance, Security & Launch](./observability-performance-security-and-launch.md)
  — financial telemetry, store-compliance gates, and abuse posture
- [Oshun Domain Libraries](../../platform/oshun-domain-libraries.html) — where
  `@oshun/payments-bridge`, `@oshun/billing-support`, and the `@aje/*` rails sit
- The section hub: [../V3_ARCHITECTURE.md](../V3_ARCHITECTURE.md)
