feat(billing): usage-based billing cutover#3482
Closed
adboio wants to merge 4 commits into
Closed
Conversation
Classify the gateway's usage-based billing denials (free-tier model gate 403, org credit-bucket 429, per-user valve 429) in shared error helpers and route sessions to the cause-aware upgrade gate instead of error states. Authenticate every gateway models fetch and honor the new allowed/restriction_reason marks: adapters annotate restricted models on session config options, never auto-select a restricted model as session default, and the cloud harness drops restricted models and falls back to an allowed default. Helper prompts route to the free-tier model proactively off the usage endpoint's code_usage_billed bit (403 retry as staleness backstop). Generated-By: PostHog Code Task-Id: bfbcd747-a365-429f-a5dc-622e2c2f7edf
…ng flag Behind the new flag: cause-aware usage limit modal (model gate / org limit / free-tier valve) with add-payment-method CTAs replacing the Pro-upgrade copy, a one-time blocking billing-change announcement recorded on the person profile, locked rendering + upgrade gate for plan-restricted models in every picker (GLM stays pickable as the free-tier model), a usage-based Plan & usage page (free-tier vs billed states, org-limit callout), free-tier gating of the titlebar usage card off code_usage_billed, and seat fetch/auto-provision skipped everywhere since seats are retired. Flag off keeps the seat-era UI byte-for-byte. Generated-By: PostHog Code Task-Id: bfbcd747-a365-429f-a5dc-622e2c2f7edf
|
Merging to
After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here |
|
React Doctor found no issues in the changed files. 🎉 Reviewed by React Doctor for commit |
Move usage-limit modal copy derivation into core (pure, unit-tested) and thin the component; persist the billing announcement via the shared electronStorage-backed persist middleware with a hydration guard; gate seat fetch/provision once in the seat store instead of at three call sites; share a GLM-visibility hook and a models-cache validity helper; name the code_usage_billed tri-state with isCodeUsageUnbilled; merge the session service's duplicated limit branches. Generated-By: PostHog Code Task-Id: bfbcd747-a365-429f-a5dc-622e2c2f7edf
Matches the gateway field rename: the bit is the org's subscription status (payment method on file), and "billed" next to is_pro read ambiguously. Mechanical rename across the schema, gateway service, limit-content derivation, and billing UI; is_pro semantics untouched. Generated-By: PostHog Code Task-Id: bfbcd747-a365-429f-a5dc-622e2c2f7edf
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.
Problem
PostHog Code is cutting over from seat-based plans to usage-based billing (PostHog/billing#2030, PostHog/posthog#70951). The app still speaks the seat era everywhere: anonymous models fetches that can't see the free-tier model gate, a premium default model that would 403 for free orgs on their first message, "Upgrade to Pro for 40× more usage" copy, per-seat plan cards, and no acknowledgment of the billing change.
Changes
Everything new activates off the
posthog-code-usage-billingfeature flag and the gateway's own signals (flip together withLLM_GATEWAY_POSTHOG_CODE_MODEL_GATE_ENABLED); flag off keeps the seat-era behavior unchanged, which is also the rollback lever.allowed/restriction_reasonmarks from feat(llm-gateway): gate posthog_code models for orgs not billed for Code usage posthog#70951 — restricted models render locked with an upgrade gate in all pickers, session defaults never land on a restricted model, and the cloud harness falls back to an allowed model. GLM stays pickable as the free-tier model regardless of its rollout flag.classifyGatewayLimitError) and open a cause-aware modal (add payment method / raise billing limit / free valve) instead of surfacing raw errors or tearing sessions down; helper prompts (commit messages, titles) proactively route to the free-tier model for unbilled orgs.code_usage_billedfield, and seat fetch/auto-provision skipped since seats are retired.Cutover companion: PostHog/posthog#71315 adds
code_usage_billedto the gateway usage endpoint (the app treats it as optional, so either side can ship first).Suggested follow-through on PostHog/posthog#70951 while it's open: attach structured
codes to the gate/limit error bodies so new clients can stop substring-matching server copy.How did you test this?
Automated only: new unit tests for the error classifier (incl. the ACP "Internal error:" wrapping that would otherwise classify the 403 as fatal), authed/marked models fetch +
pickAllowedModel, helper free-tier routing (proactive + 403 backstop + bare-detailparsing), codex restricted-model config options, and gateway usage schema fields. Full typecheck across all touched packages, Biome clean, host-boundary check clean; targeted suites green (agent 49 + 90, core sessions 304, harness posthog-provider 82, UI selector tests).Not covered by automation: visual pass over the new modals/plans page states (flag is off by default, so nothing renders differently until flip).
Automatic notifications
Created with PostHog Code