Skip to content

feat(billing): add to my invoice — contract orgs upgrade at their AI limit - #7761

Merged
pedrofrxncx merged 2 commits into
mainfrom
feat/invoice-upgrade
Oct 6, 2026
Merged

pedrofrxncx merged 2 commits into
mainfrom
feat/invoice-upgrade

Conversation

@pedrofrxncx

@pedrofrxncx pedrofrxncx commented Oct 6, 2026 •

Copy link
Copy Markdown
Collaborator

"You've reached your AI usage limit" for our contract customers: Stripe, or "Adicionar à minha fatura". The gateway side is in decocms/ai-gateway#41.

What it does

deco.cx customers are placed on custom with a small hidden allowance and pay by boleto. Staff can flag one with invoice_upgrade in the org-admin UI. Once its bar is exhausted, the plan catalog shows Starter and Business, each with:

  • Stripe: the existing checkout, including Starter's free month.
  • Add to my invoice: after a confirm dialog, the plan switches now with no payment. It is billed on the org's next invoice.

AI_PLAN_INVOICE_UPGRADE

Same permission as AI_PLAN_SET (ai-providers:manage). It grants a paid plan without payment, so it fails closed instead of using requiresFeature, which fails open. It requires all of:

  • plans on and a gateway admin token
  • entitlements read fresh from the gateway (not the 60s cache)
  • features.invoice_upgrade === true
  • usage bar exhausted; an unreadable usage refuses
  • no Stripe subscription bound
  • not the current plan

It then places the plan via the gateway admin route with an audit note ("invoice upgrade by at — bill on next invoice"), clears the plan cache fleet-wide, and emits the PostHog event plan_invoice_upgrade (plan_id, previous_plan_id, org_slug, org_name). Finance needs a PostHog → Slack alert on that event, since neither repo has a Slack integration.

UI

  • Flagged custom / ai_service org: it sees the limit screen only when the bar is exhausted. Otherwise it keeps the "contact us" card.
  • Flagged org already on a self-serve plan with no Stripe subscription: non-current cards also get "Add to my invoice".
  • Copy: en + pt-br. Inert unless STUDIO_PLANS_ENABLED is on.

Tests

  • plan-change.test.ts: 8 tests for the guard. The ai-providers suite passes 36/36.
  • tsc for api, web and shared passes; oxlint and knip are clean.
  • The new screens have not been checked in a browser.

Summary by cubic

Allows deco contract orgs to upgrade to a paid plan at their AI limit and get billed on their next deco invoice instead of going through Stripe.

  • Adds AI_PLAN_INVOICE_UPGRADE, which fails closed: it requires plans enabled, invoice_upgrade set to true and read fresh from the gateway, the usage bar exhausted, no bound Stripe subscription, and a target plan the org is not already on.
  • The plan catalog shows the limit screen for a flagged custom org only once its usage is exhausted, with both Stripe and "Add to my invoice" buttons on the Starter and Business cards. Flagged orgs already on self-serve plans without a Stripe subscription get the invoice button on the other plans too.
  • The upgrade records an audit note on the gateway plan, clears the plan cache fleet-wide, and emits plan_invoice_upgrade on PostHog — finance needs a PostHog → Slack alert on that event.
  • The gateway side is in decocms/ai-gateway#GW_PR. The new screens haven't been checked in a browser.

Written for commit 49d558d. Summary will update on new commits.

Review in cubic Turn on auto-fix

Pedro França added 2 commits October 6, 2026 19:21
…limit

AI_PLAN_INVOICE_UPGRADE moves an org flagged invoice_upgrade onto Starter
or Business with no Stripe, once its usage bar is exhausted. Fails closed:
plans on, flag read fresh from the gateway, bar exhausted, no Stripe
subscription bound, not the current plan. Records an audit note on the
gateway plan row and emits plan_invoice_upgrade for finance.

The plan catalog shows a flagged custom org at its limit the Starter and
Business cards with both Stripe and 'Add to my invoice'.
…limit

Matches the server: the button needs invoice_upgrade AND an exhausted bar,
so a flagged org below its limit is never offered an upgrade it would be
refused.
@pedrofrxncx
pedrofrxncx enabled auto-merge (squash) October 6, 2026 22:41
@pedrofrxncx
pedrofrxncx merged commit 564f4a1 into main Oct 6, 2026
34 checks passed
@pedrofrxncx
pedrofrxncx deleted the feat/invoice-upgrade branch October 6, 2026 22:42
decocms Bot pushed a commit that referenced this pull request Oct 6, 2026
PR: #7761 feat(billing): add to my invoice — contract orgs upgrade at their AI limit
Bump type: minor

- decocms (apps/api/package.json): 4.442.0 -> 4.443.0
- @decocms/native (apps/native/package.json): 4.442.0 -> 4.443.0
- @decocms/shared (packages/shared/package.json): 0.135.0 -> 0.136.0

Deploy-Scope: both
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant