Payment, entitlement, attendance/delivery, rights, refund, and takedown states are reconciled but not conflated. Provider receipts and durable entitlement/ rights records govern what the member and creator see.
V3 ("Lilith") takes real money in three different rooms — a stadium ticket to a Saraswati concert, a tip dropped into a yoga instructor's jar mid-class, and a recurring pass that unlocks a club venue — and it sells one thing that has to unwind cleanly: a limited signed edition of an AI-generated track. The hard part was never 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 cancellation has to know the difference between a user changing their mind an hour out and a Pixel-Streaming outage that wasn't the user's fault; and when a track is taken down for a rights violation, every ticket, replay, and signed edition that touches it has to flag itself within a day, with royalties paused. This page is the product-feature view of that discipline — the commerce primitives a fan touches, the cancellation and refund rules that govern them, and the rights/takedown machinery that can reverse a sale. It is the consumer-facing half of the architecture-side commerce & royalties companion; the deep settlement and split-math treatment lives there. For the full V3 feature map this slots into, start at the hub: ../V3_features.md.
What ships, honestly#
The commerce engine is real, tested Rust, not a checkout spec.
apps/v3/lilith-commerce-service is a ~14.8 K-line crate — thirteen domain flow
modules plus the Tara split engine in lib.rs — and it carries 151 #[test]
cases (counted in-tree; the architecture companion records
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 tip routes 100/901 with the rounding remainder
deliberately handed to the recipient, a track waterfall that doesn't total
exactly 10,000 bps is rejected. The crate's SERVICE_DESCRIPTOR (port 43105,
lib.rs:206) advertises twelve capabilities — ticket-ledger, tip-route,
saraswati-club-pass-billing, saraswati-signed-edition-drop,
royalty-waterfall, and so on — each backed by a module.
Everything money-shaped settles on the shared Aje payment substrate,
@oshun/payments-bridge (libs/oshun/payments-bridge): a substantive library
with Ed25519 receipt signing (@noble/curves, src/receipt-signer/), a
cold-spend co-signing queue, an admin/refund surface, and an entitlement bus
(src/entitlement-bus/topics.ts) whose three topics —
payment.invoice.confirmed, payment.invoice.settled,
payment.refund.broadcast — carry structurally identical envelopes across four
fiat processors and a long V1_PAYMENT_ASSETS list of crypto rails (BTC
on-chain/Lightning, LTC, XMR, five EVM chains, SOL, TON, Cardano, Ergo, plus
stablecoins). The entitlement service never learns whether a payment was fiat or
crypto; it grants on invoice.settled.
Two honest qualifications. First, the commerce crate's job is the
ledger, not the wire. Its flow functions validate the request, compute the
routes, and emit a provider-shaped receipt with deterministic IDs 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). Read a Settled status as "the ledger
says settle here," with rail execution on the bridge. Second, the Year-1
catalog — which concerts, which drops, which passes — is a schedule the engine
executes, not an artifact in the repo. The machinery is shipped; the merchandise
is operations.
Selling access: tickets, tips, and subscriptions#
Three commerce primitives cover the ways a fan pays into Lilith, and each is its own module with its own anti-abuse posture.
Tickets — named, capped, signed-return-only resale#
lilith_ticket_issuance.rs (2.1 K lines, 15 tests) is the anti-scalp ticket
ledger. A ticket is named on issue (bound to the buyer's V1 account) and
capped at four per fan (LILITH_TICKET_PER_FAN_CAP = 4, :4). The only
legal transfer is a LilithTicketResaleMode::SignedReturnOnly flow: the holder
returns the ticket to the platform, which re-issues it to the next eligible
buyer at the original price. Two checks make that anti-scalp, not advisory — the
resale cannot exceed the original face value
("anti-scalp signed-return resale cannot exceed original face value", :493)
and the buyer can't cross the per-fan cap (:481). The capacity bands map
exactly onto the Stadium-tier seating plan: front-256
(LILITH_TICKET_FRONT_256_CAPACITY = 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 (:620) inside a 15-minute-pre /
10-minute-post-start window, and a canceled front-256 ticket promotes the next
eligible mezzanine holder via the stadium band-reshuffle path.
Tips — three receipts, remainder to the creator#
lilith_tip_routing.rs (589 lines, 6 tests) routes a tip to an Instructor,
Artist, or SessionHost at 10% platform / 90% recipient
(LILITH_TIP_PLATFORM_BPS = 1_000 / LILITH_TIP_RECIPIENT_BPS = 9_000), over
Stripe or Aje, and writes three receipts per tip — payer, recipient, and
platform — so all three parties have a record. The rounding is a deliberate
domain choice, not an accident: the test
tip_routing_preserves_total_with_rounding_remainder_to_recipient (:502)
feeds 1_001 cents and asserts the recipient gets 901 — the leftover cent
favors the creator. saraswati_concert_tips.rs (413 lines, 5 tests) is the
concert variant (SARASWATI_CONCERT_TIP_PLATFORM_BPS = 1_000 /
..._ARTIST_BPS = 9_000, settled inside a 60-minute window).
Subscriptions, passes, and the free tier#
lilith_subscription_billing.rs (832 lines, 10 tests) bills the recurring
products — TaraPass, SaraswatiClubPass, CommonsMembership — on monthly
cycles over Stripe or Aje, with month length bounded to 28–31 days and a post-GA
7-day proration window (LILITH_SUBSCRIPTION_PRORATION_WINDOW_MS).
saraswati_club_pass.rs is the club 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 — the same point the
fan-economy page makes about where
each tier ships.
Fan tokens — access, never yield#
lilith_fan_token_boundaries.rs (828 lines, 9 tests) keeps fan tokens an
access primitive, not an investment. A valid access config must assert
no_yield, no_transferable_security_claim, and access_only simultaneously
(:72) — a token that grants queue priority or special-venue entry passes; a
token that promises a return does not. Availability sits behind a per-region
legal-review gate (LILITH_FAN_TOKEN_REQUIRED_REGION_PROFILE_COUNT = 5), and
in a token-restricted region the same benefits are delivered through the V1
account primitive instead — a fan loses the token wrapper, never the benefit.
Store-billing bridges — compliance parity#
lilith_platform_billing_bridges.rs (514 lines, 6 tests) 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
(LILITH_APPLE_IAP_POLICY_REF = "apple-app-review-guideline-3.1.1-iap", plus
the Google Play and PSN refs): it forbids external payment links for in-app
digital goods (:264 →
"platform store policy gate forbids external payment links for in-app digital goods"),
and requires a signed receipt, a passed certification case, and confirmed
entitlement delivery. The point is reconciliation parity — a PSN-wallet purchase
and a Stripe purchase grant an identical entitlement downstream.
Cancellation, refund, and no-show#
lilith_cancellation_refunds.rs (2.3 K lines, 22 tests) encodes the policy as a
real classifier, not prose. classify_refund_tier resolves a user-initiated
cancellation into three tiers: a full refund at ≥ 24 h before start, a
half-refund / half-credit between 1 h and 24 h, and no refund inside the
hour or on a no-show. The credit half lands in a 90-day Lilith credit ledger
(LILITH_CREDIT_VALIDITY_MS = 90 * DAY_MS, :7).
The asymmetry between "the user changed their mind" and "we let the user down" is machine-enforced:
- Platform / instructor cancellation adds a 50% goodwill credit
(
LILITH_PLATFORM_CANCELLATION_GOODWILL_CREDIT_BPS = 5_000) and must complete within a 24 h SLA (the report carries acompleted_within_24hflag). - Provider-outage cancellation — a payment rail or Pixel-Streaming fault —
issues a 100% credit (
LILITH_PROVIDER_OUTAGE_CREDIT_BPS = 10_000), fires an operator alert, and pauses the affected concert's royalty waterfall pending review. Commerce and royalties are one ledger here, by construction. - Signed-edition drop cancellation. If editions were issued in advance, a
holder chooses
KeepAsHistoricalArtifactorBurnForFullRefundthrough a Lilith-Rights review queue (saraswati_signed_edition.rs) — a canceled concert never strips a holder of the artifact without consent. - Subscriptions cancel at any time with access through the end of the current period; post-GA, a renewal canceled inside the 7-day proration window is pro-rated.
- Chargebacks and tax are first-class: the module owns refund tax reversal
across jurisdiction profiles and a chargeback-handling path
(
LILITH_CHARGEBACK_HANDLING_POLICY_ID) with a confirmed-fraud route into the V1 anti-abuse list and an appeal window.
Waitlist promotion ties back to the ticket ledger: a no-show seat vacated inside the 15-min-pre / 10-min-post window is offered to the next active waitlist holder at the original price, never auctioned.
Rights and takedown#
A sale in Lilith is reversible because the underlying artifact's rights are. When a track's provenance is withdrawn, the money it touched has to unwind — and that is a coded cascade on a bounded clock, not a manual cleanup.
The 24-hour takedown cascade#
lilith_rights_takedown_cascade.rs (970 lines, 11 tests) is the unwind engine.
execute_lilith_rights_track_takedown_cascade (:179) fans a track-level
withdrawal across the surfaces the artifact touches, within a hard SLA:
LILITH_RIGHTS_TAKEDOWN_CASCADE_SLA_MS = 24 * 60 * 60 * 1_000 (:5). The
surface kinds and actions are typed, not freeform — InWorldReplay,
OffPlatformReshare, and the archived-performance surface resolve to
FlagHistorical, PauseReplay, and MarkSignedEditionHistorical, and the
report records each outcome (PerformanceFlaggedHistorical, ReplayPaused,
SignedEditionMarkedHistorical). The cascade is driven from V1:
initiate_lilith_rights_v1_takedown_pipeline (:313) takes a
v1_takedown_action_id and a target list, so a withdrawal initiated in the V1
takedown pipeline fans out into V3 automatically — V3 does not run a
separate takedown machine.
The honest seam: what is coded and asserted here is the cascade report and the V1-pipeline contract — that a withdrawal produces flagged-historical performances, paused replays, marked editions, and disabled off-platform reshares, all inside 24 h. The actual replay-pausing and off-platform takedown notices ride the V1 event bus; this module is the deterministic V3-side contract that computes and bounds the fan-out. The persona-policy & provenance architecture makes the same honesty line: the Themis adjudication, the catalog-license pause, the royalty-waterfall pause, and the 24-hour deadline are the coded-and-gated core.
Signed editions and the historical flag#
saraswati_signed_edition.rs (2.2 K lines, 23 tests) mints limited editions
of 250 (SARASWATI_SIGNED_EDITION_DROP_SUPPLY = 250) via the Aje primitive
aje.signed-edition.mint.v1 inside a 6 h window, and enforces a 10%
secondary-sale royalty
(SARASWATI_SIGNED_EDITION_SECONDARY_ROYALTY_BPS = 1_000) that routes back to
creators on every resale. When a track is taken down, its outstanding editions
are marked Historical and resale-royalty routing pauses — but a holder is
not stripped of the edition. This is the same royalty-protective logic the
fan-economy page describes from the
tenant-library side; here it is the commerce ledger's enforcement of it.
Where adjudication and provenance live#
The takedown the cascade executes is the output of a rights decision made
elsewhere. Ownership and unlicensed-use disputes route through Themis in
libs/v3/saraswati-stage/src/themis-rights-adjudication.ts, whose
enforceSaraswatiThemisRightsDecision throws if enforcement lands outside
SARASWATI_THEMIS_RIGHTS_MAX_ENFORCEMENT_MS = 86_400_000 (24 h) — the same
bound the commerce cascade honors. The provenance bundle and forensic watermark
that make an off-platform reshare traceable back to a session and recipient live
in libs/shared/content-security (a plan/verify layer) and the V3 track bundle
in libs/v3/isis-music. The detailed treatment of consent ledgers, the C2PA
signature path, and crisis/persona policy is the
governance, safety, recording & consent page
and its architecture companion.
Settlement, audit, and DSAR#
Every ticket, tip, subscription, edition mint, and refund converges on the
shared Aje plane so a purchase reconciles identically whether it arrived as fiat
or crypto: the @oshun/payments-bridge entitlement bus grants on
payment.invoice.settled, its state-mapper.ts maps a crypto confirmation
depth to the V1 event types, and refunds flow back through
payment.refund.broadcast and the admin-surface refund-initiation path.
Receipts are Ed25519-signed against the V1 audit-platform key and canonicalized
deterministically, so a receipt verifies off-box.
Every commerce action — issuance, route, cancellation, credit, takedown — is
audit-logged into V1 @oshun/audit-platform, and the full ticket / refund /
credit ledger is DSAR-covered. The same hash-chained, tamper-evident trail
that the rights side produces is what an investigation or a data-subject request
reads, so commerce, rights, and compliance share one evidentiary spine rather
than three.
Edge cases and failure modes#
- Resale can't scalp. A signed-return resale above original face value is refused, and a buyer already at the four-per-fan cap can't acquire a fifth through the resale path.
- The remainder favors the creator. A
1_001-cent tip splits100/901— the rounding cent is assigned to the recipient by tested intent, not left to the platform. - 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 — and it pauses the affected concert's royalty waterfall.
- A store purchase can't dodge the rail. A platform-billing receipt carrying an external payment link for in-app digital goods is rejected at the gate.
- Takedown is bounded, not eventual. The cascade and the Themis enforcement it follows both carry a 24-hour SLA as a coded invariant; "paused, eventually" is not a valid state.
- A holder is never stripped silently. A taken-down edition is flagged historical with resale-royalty routing paused, and the holder chooses keep or burn-for-refund through a review queue.
- 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 shared substrate, not the split math.
Where this connects#
- Governance, safety, recording & consent — the Themis adjudication, consent ledgers, provenance bundle, and persona policy that decide when a rights withdrawal fires and feed this cascade.
- Saraswati Stage: fan economy, voice, genre & rights — where the four fan-participation tiers, the signed-edition secondary royalty, and the remix-rights modes that this page settles and unwinds are authored.
- ../architecture/commerce-and-royalties.md
— the architecture-side deep dive into the Rust
lilith-commerce-service, the royalty waterfall encoded at generation, quarterly on-chain settlement, and the@oshun/payments-bridgerails and receipts. - The feature hub: ../V3_features.md.