Full-Access Plans for New Signups
Context
Section titled “Context”FOXY-1165: every new subscriber should pay on the high-risk lane (NMI/EMP, Cybersource for Apple Pay), while existing SFW subscribers keep renewing where they are. The SFW Starter and Creator plans (strtr, crtr) settle on Stripe; the Pro tiers (faxppr1..5) already ride the high-risk lane. What is missing is a Starter and a Creator that ride it too.
A first version put a per-user purchasable catalog into Sirloin (subscription lookup, checkout gate, Product.purchasable on ListProducts). Review on 10 September 2026 judged that too much change for the goal: the billing paths themselves need not change, a new signup simply buys a different product. This ADR records the agreed, smaller design.
Decision
Section titled “Decision”Two full-access twins of Starter and Creator exist in Chargebee and Sirloin: faxpst and faxpcr, same prices and credit counts as strtr/crtr, classified as full-access plans everywhere Sirloin reads a plan token (IsNSFWPlanToken, the tier ladder at ranks 7 and 8, throttle buckets, reservation limits, PostHog plan names, HasNsfwPurchase).
Who sees which pair is decided in Brisket’s tRPC layer, in listProducts, by the PostHog flag full-access-plans evaluated for the signed-in user. Flag true: faxpst, faxpcr and Pro; anything else: strtr, crtr and Pro. Which accounts the flag is true for is configured in PostHog’s release conditions: listProducts supplies the account’s signup date as the request-scoped person property signed_in_date from the existing x-account-created-at header. PosthogProvider still persists that property on identify. A percentage or a list of test users work the same way; the code carries no cutoff or cohort rule of its own. The flag is the kill switch: off means nobody is new and the catalog is exactly today’s, and any failure to reach PostHog answers “existing”.
Sirloin does not gate the purchase: a caller that bypasses the Brisket API can buy a plan its cohort is not shown. The team accepted that risk on 10 September 2026.
Apple Pay on full-access checkouts is gated by both PostHog flags — full-access-apple-pay and full-access-plans, the latter read in the browser for the same user the tRPC layer reads it for — and offered only on a session with no processor lock or a Cybersource lock. Tying it to the cohort flag keeps the wallet with the plans it was built for: a legacy 18+ subscriber sees no Apple Pay, and turning the plans flag off rolls back both at once. Cybersource is mapped on the NSFW lane for settle-then-lock so an Apple Pay full-access subscription locks to it and its Apple Pay renewals route there; inside that locked workflow Primer branches by payment method, so the same account’s card and Google Pay payments still go to EMP/NMI (FOXY-1179). Wallets stay vaulted for Cybersource-locked renewals as they do for NMI; the Strip admin override accepts cybersource.
Consequences
Section titled “Consequences”- Rollout is a PostHog release-condition change, rollback is turning the flag off. No deploy or restart is involved.
- “New” is whatever the flag targets; the agreed first rule is account creation date, so an account created before the cutoff that subscribes for the first time buys the SFW pair on Stripe. The share of first purchases from older accounts is the number to watch, and the rule can be widened in PostHog without a deploy.
- After a rollback (flag off), or while PostHog cannot be read, a twin holder is “existing”: their subscription keeps renewing and the billing page still shows it (the current-plan card resolves from the static plan list), but the Change Plan grid offers the SFW pair and Pro, and the tier ladder treats a move to the SFW pair as a downgrade. Accepted on 10 September 2026.
- A Cybersource-locked full-access checkout has no Sirloin per-ticket ceiling: Cybersource carries no processor limit, unlike EMP and NMI, and such a lock only arises from an Apple Pay settle. That account’s card payments branch to EMP/NMI in Primer, so a settle there differs from the locked psp by design; the lock-drift detector in
processorlock.gostill counts it. - Brisket surfaces that derive “next tier” and the 18+ paywall floor read the plan list the API returned for this account, not the static constants, so a twin holder is offered
faxpcrbefore Pro 1 and a new signup’s paywall floors onfaxpst. The Explore 18+ upsell keeps offering Pro 1 to everyone; it is a Pro promotion, not a catalog. - FOXY-1282 supersedes the first-load identify race accepted on 10 September:
isNewPlansEnabledvalidates the header’s positive epoch-millisecond timestamp, converts it to ISO 8601, and passes it inpersonPropertieswith the flag evaluation. A valid header removes the dependency on identify ingestion; a missing or malformed header leaves evaluation against PostHog’s stored properties unchanged. The header is client-provided and affects catalog presentation, not purchase authorization. This request-scoped property does not persist the person profile or change the PostHog rollout condition. - Chargebee production must carry the twins before the flag targets anyone (FOXY-1178); Primer’s full-access workflows must carry the Cybersource branch and route Apple Pay to Cybersource before
full-access-apple-payis enabled (FOXY-1179). The Cybersource entry in the NSFW lock table only acts on a settle that Primer labelsaccess=fulland routes to Cybersource; no full-access workflow does so until FOXY-1179, so merging this PR ahead of the Primer work changes no lock today. - Rollout telemetry (FOXY-1228) ships separately.
Alternatives Considered
Section titled “Alternatives Considered”- Per-user catalog in Sirloin (subscription lookup, checkout gate,
Product.purchasable): correct against direct RPC calls and against accounts with a live SFW subscription, but it grew into subscription-list pagination, pending-checkout semantics and plan-change changes. Rejected on 10 September 2026 as disproportionate; kept on branchbackup/foxy-1165-pr3513-full-catalogfor reference. - Cohort by live SFW subscription: needs a Chargebee lookup on every catalog read, and a Chargebee customer exists only after a first checkout, so a never-subscribed account has nothing to look up.
- A signup cutoff date parsed in code (from an environment variable or a flag payload): PostHog already knows each account’s creation date, so the rule belongs in its release conditions, not in a parser the code has to keep correct.