Repository navigation
Move billing to the shared billing engine with Lemon Squeezy - #207
Merged
Merged
Conversation
added 4 commits
October 8, 2026 20:39
Move subscription state to the shared billing system, add plan management and recent-auth billing actions, and remove legacy subscription fields.
…tions Compose the shared billing engine with Lemon Squeezy or Dodo, chosen by BILLING_PROVIDER, while every connected provider keeps handling webhooks, cancel, resume and the portal. Replace the Dodo-only checkout and webhook route with the shared provider setup. Add billing:adopt, which links Lemon Squeezy subscriptions started before the shared engine to MediaLit accounts. It is a dry run unless --apply --operator is given. Requires @codelitdev/billing and @codelitdev/platform 0.4.0. bun.lock is updated once that release is published.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
The next path was checked as a string, but browsers drop tabs and newlines from URLs, so /<tab>/evil.com passed and became //evil.com. Resolve it as a URL and accept it only on the same origin, in both the login page and the proxy.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ab7a371d1b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
The MCP tools now read maxStorage from the billing engine. The local stack runs the API in cloud mode with an unusual Basic storage limit, and the MCP suite checks that the test account, which has no subscription, gets exactly that limit.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Moves MediaLit's subscriptions onto the shared billing engine (
@codelitdev/billingand@codelitdev/platform0.4.1). The engine supports both Lemon Squeezy and Dodo. Today's Lemon Squeezy subscribers keep working, and a newbilling:adoptscript links them to their MediaLit accounts.What changes
Billing engine
profilesare dropped by migration0007_drop_legacy_subscription. Paid limits come from the engine's entitlements.BILLING_PROVIDERchooses where new checkouts go (lemonsqueezyordodo). Every provider whose credentials are set stays connected, so its existing subscribers can still renew, cancel and open the portal.<PUBLIC_API_URL>/webhooks/billing/<provider>. The Dodo-only webhook route in the web app and its old checkout, crypto and authorization code are removed.BILLING_RECENT_AUTH_MAX_AGE_SECONDS). Login supports?reauth=1&next=...to return the user to billing, andnextaccepts only same-site paths.Billing page
Adopting existing Lemon Squeezy subscriptions
bun --filter @medialit/api billing:adoptlists the store's live subscriptions and matches each to a MediaLit account by email. It's a dry run unless given-- --apply --operator <email>.Self-hosting
MEDIALIT_DEPLOYMENT_MODE=oss: no billing, and no upload or storage limits.Dependencies
@codelitdev/*packages are now on 0.4.1.Deploying to cloud
apps/api/.env.example:BILLING_PROVIDERBILLING_PRO_MONTH_PRODUCT_IDandBILLING_PRO_YEAR_PRODUCT_ID(Lemon Squeezy variant IDs)BILLING_DATA_ENCRYPTION_KEYLEMONSQUEEZY_API_KEY,LEMONSQUEEZY_STORE_IDandLEMONSQUEEZY_WEBHOOK_SECRETBILLING_CATALOG_REVISIONif the provider or product IDs changed.<PUBLIC_API_URL>/webhooks/billing/lemonsqueezy.billing:adoptas a dry run, review its report, then run it with--apply --operator <email>.Testing
do_not_billchange between billing periods is refused.past_due. Once a cancelledpast_duesubscription expires, the account returns to Basic.billing:adoptdry run.Known limitations
billing:adoptreports an already-adopted subscription as "would adopt", and during--applyone refused subscription stops the run.