# 🤖 Managed payments — the payout model for paid access levels

Design doc, 2026-07-22. Status: **designed, not built** (umbrella issue links
the phases). Companion docs: `docs/community-and-tiers.md` (layer 3 — the tier
machinery money assigns into), `docs/tier-economics.md` (the hosting price
book; a different product, same Stripe account), `docs/pricing-bands.md`.
Decisions here are Paul's (2026-07-22); the VAT/OSS findings are research
summaries, not legal advice — a human review gates the go-live phase.

## The design in one sentence

> **Members pay the platform and the admin's share transfers structurally —
> no Stripe account required, commission pay-what-you-want between 5.5% and
> 11% all-in — while "bring your own Stripe" stays open to every space, with
> a pay-what-you-want commission (suggested 5.5%) on top of the admin's own
> fees.**

## Two providers, priced by who bears the risk

| | Managed (default) | BYO Stripe (open to every space) |
|---|---|---|
| Merchant of record | the platform | the space admin |
| Stripe account | ours; admin gets an **Express** account (payouts + KYC only) | admin's own (OAuth-linked Standard, today's live path) |
| Commission | **pay-what-you-want, 5.5–11%, suggested 11 — all-in** (card processing fees come out of our points, whatever the choice) | **pay-what-you-want, suggested 5.5%** + the admin's own Stripe fees |
| VAT on member subscriptions | ours (OSS from Ireland; Stripe Tax) | admin's |
| Disputes/refunds | ours (payout holds; transfer reversals) | admin's |
| Admin onboarding | minutes (Express account links: name, bank, KYC) | needs a real Stripe account |

Both commissions are the honor mechanism from `pricing-bands.md` applied to
our own cut: a suggestion, a one-tap choice, no eligibility test. The two
rails bound it differently because the costs differ:

- **Managed clamps to [5.5, 11]** because we bear real per-charge costs
  (processing, VAT handling, disputes). The 5.5 floor is roughly our cost
  line — on the €5.50 minimum ticket with an international card it dips a
  couple of points under, and that known loss is priced in rather than
  guarded against.
- **BYO is unbounded down to zero** because our marginal cost there is nil —
  the admin is the merchant, pays their own fees, runs their own books. Any
  commission they choose is honest margin; zero is a legitimate choice.

Why this split, in order of weight:

1. **Activation.** BYO filters monetization to admins who already run a
   business. A Family or Community admin has no Stripe account and never
   will; Express onboarding is a bank account and a KYC form. Managed is the
   95% case.
2. **"All-in, including payment fees" becomes structural.** On a
   destination charge we own the charge and pay Stripe's processing fee from
   our own take; the admin's share is set by `transfer_data` from their
   chosen commission, not reconciled after the fact. The
   refund-reconciliation and fee-prediction designs this supersedes are
   recorded below (§ Superseded) so they aren't reinvented.
3. **The cuts price the risk transfer — and both are the admin's call.**
   Managed bears processing + VAT + disputes, so its pay-what-you-want range
   floors at 5.5 (≈ our cost line); BYO bears all three itself, keeps its
   own books and negotiated rates, so its commission is open all the way to
   zero, suggested 5.5 (market-honest: Memberful charges 4.9% flat for the
   same shape; Substack takes 10 *plus* processing).

## Money mechanics (managed)

- Checkout Sessions on the **platform account** (no `Stripe-Account` header),
  `mode=subscription`, `subscription_data[transfer_data][destination]` = the
  space's Express account, `[amount_percent]` = 100 − the chosen commission
  (89–94.5). Stripe splits every invoice; processing fees land on the
  platform side by construction.
- **Level price floors: €5.50/month, €11/year** (enforced at level pricing
  time, both providers). Stripe's fixed €0.25/charge makes all-in economics
  negative below ~€2.60/charge and thin below €5; the floors keep the
  worst-case (international card) take ≥ ~3 points. Same fee logic that made
  Business and Family annual-only (`tier-economics.md`).
- Payouts ride Stripe Express schedules; a rolling payout delay (Stripe's
  default) is the fraud/dispute buffer. Disputes: transfer reversal claws
  back the transferred share; the €15 dispute fee is ours — priced into the
  commission.
- VAT: the platform is seller of record for an electronically supplied
  service. Consumer stickers are VAT-inclusive (the pricing-bands posture),
  so our net per subscription varies by buyer country; OSS (one Irish
  registration) covers the EU, Stripe Tax computes per-invoice. Non-EU
  registrations (UK first) ratchet on thresholds. **A human tax review gates
  the live flip** — same bar as pricing-bands Phase 1.

## Trust model (the two honest costs)

- **Privacy centralization.** Today each admin's Stripe sees only their own
  members' payment identity; managed payments concentrates every paying
  member of every space into one Stripe dashboard. Our own stores still hold
  only opaque ids (the billing.go rule), but the dashboard exposure is real
  and grows with the fleet. Named here deliberately; BYO remains the
  decentralized escape hatch, and that is part of why it stays.
- **Merchant of record for content we cannot see.** E2EE means we underwrite
  payments for communities whose content is structurally opaque to us.
  Mitigations: the existing report-to-admins/moderation surface, payout
  holds, and the standing right to off-board a space from *payments*
  (payouts stop; the space itself, being E2EE, was never ours to read).
  This asymmetry — we can stop paying out, we cannot inspect — is the
  design, not a gap in it.

## Implementation shape

- `subscriptions.go` already has the seam: `PayProvider` is an interface and
  "adding a provider never touches the state machine." `stripePlatform`
  (managed) lands beside `stripeConnect` (BYO). Normalized `SubEvent`s feed
  the same `applySubEvent`.
- Provider selection per space: managed is the default wherever platform
  creds exist; `stripe_connect_account` (BYO) stays available to every
  space — no tier gate. A space that links its own Stripe chooses the BYO
  rail by that act.
- Commission choices live in the space config: `managed_commission_pct`
  (clamped [5.5, 11], default 11) and, phase 3, the BYO percent (suggested
  5.5, floor 0). Changing a choice applies to new checkouts; existing
  subscriptions keep the split they were created with.
- Express account id lives in the space config (`stripe_express_account`),
  set by the onboarding flow (Account Links API; `account.updated` webhooks
  flip the payouts-ready bit). Until payouts-ready, levels can be drafted
  but not sold — never sell against an account that can't be paid.
- Level prices: managed levels create their Stripe Price on the platform
  account (BYO keeps creating them on the admin's). The floors apply in the
  level-pricing path, before any Stripe call.
- Existing BYO spaces (paulca) are grandfathered: linked accounts keep
  working; the 10% → pay-what-you-want change (suggested 5.5) applies from
  its deploy — a cut *reduction* at the suggestion, so no notice period.

## Lifetime access (single payment)

A level can price as **`interval: "once"`** — pay once, in for as long as the
space exists (PR #1290; both rails). The copy says "as long as the space
exists" deliberately: an admin can close a space, and we don't sell promises
admins can't keep. Mechanics: `mode=payment` checkouts with the commission as
a fixed amount (payment mode has no percent splits) — BYO takes its flat fee,
managed applies the chosen PWYW commission to the transfer. The grant has no
lifecycle — exempt from every renewal-shaped sweep — and the only exits are a
refund/chargeback (`charge.refunded` / `charge.dispute.created` revoke
immediately, with a payment-intent tombstone so redelivered grants can't
re-buy a refunded level) or an admin removal. **Floor: 11.00 one-time** —
the elevens' third coin (€5.50/month, €11/year, €11 once).

## Rollout phases (mirrored in the umbrella issue)

1. **Provider core (dark):** `stripePlatform` + destination-charge checkout
   + webhook parse + tests; config-gated off.
2. **Express onboarding:** account links flow, payouts-ready gating, admin
   UI (web + native surfaces per parity rule).
3. **Floors + BYO repricing:** €5.50/€11 level-price floors both
   providers; BYO's application fee becomes the pay-what-you-want config
   (suggested 5.5, floor 0) with its admin picker; changelog.
4. **Tax + go-live:** Stripe Tax on, OSS registration confirmed, human tax
   review, live platform creds, docs/status updates.

## Superseded designs (recorded so they stay dead)

- **Fee-refund reconciliation** (charge 11%, refund the actual
  `balance_transaction.fee` after `invoice.paid`): correct but only needed
  when the admin is MoR and we promise all-in — i.e. never, under this
  split. BYO makes no all-in promise; managed doesn't need reconciliation.
- **Fee prediction from the payment intent**: impossible before the first
  charge (no card yet), asymmetric on renewals (application fees refund
  down, never up). Reconciliation was prediction with the error bar
  collapsed; destination charges remove the need for either.
