Bill the three-year term, and quote its rate to the console

FeatureBillingService
Shipped
August 31, 2026 at 2:12 AM UTC
Author
Kamo
Commit
214fdff

BillingCycles gains TRIENNIAL, expressed to Stripe as three YEARs rather than thirty-six MONTHs so the renewal tracks the signup anniversary — the same reason ANNUAL is one year. monthsIn now delegates to the enum, which owns the number: it was stated here and twice more in SubscriptionService, where both copies had it backwards. **************** annualised via `12 / monthsIn(cycle)` charges per year. That is integer division, correct only while every cycle divides into a year — a three-year term makes it 12/36 = 0 and annualises every plan to nothing. The invariant is about the ratio of amount to months, so it is expressed that way now and holds for a cycle of any length. A new test also pins interval x intervalCount to monthsIn, so the Stripe recurrence cannot drift from the span it claims to charge for. PlanCatalogService quotes the third term to the self-serve billing console. A term with neither a price row nor a plan column reports null rather than borrowing the monthly rate: quoting month-to-month against a three-year commitment would undercharge by a third.

All changes

Like what you see shipping?

Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.

Start Free ForeverView Pricing