Skip to content

feat(cli): handle plan-gate denials centrally - #7441

Draft
pamelachia wants to merge 6 commits into
developfrom
pamela/growth-1050-central-upgrade-event
Draft

pamelachia wants to merge 6 commits into
developfrom
pamela/growth-1050-central-upgrade-event

Conversation

@pamelachia

@pamelachia pamelachia commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

I moved plan-gate handling out of each command into shared code. Since #7271, mapHttpError attaches entitlement from the Management API's entitlement_required body, so the upgrade hint, the cli_upgrade_suggested event and the plan_limit classification now all come from that one field, with no per-command wiring and no extra requests.

Changed:

  • One hint and one event per gated denial, wired or not: the text error renderer prints the upgrade hint before the error message, and withCommandTelemetry captures cli_upgrade_suggested (same name, same {feature_key, org_slug} payload) after the command, just before cli_command_executed. Commands that never had wiring, such as branches unpause, now get both. vanity-subdomains check-availability now fires the event too; its no-event exception only existed for parity with the removed Go CLI.
  • No per-command gate code or follow-up lookups: I deleted the gateMapError/suggestUpgrade wrapping at branches create/update, the four domains commands and the three vanity-subdomains commands. branches update no longer fetches the project and org entitlements after a 4xx, since the persistent-branch 402 carries the envelope. Only the SSO commands keep the entitlements lookup.
  • plan_limit from the envelope: an error carrying entitlement classifies as plan_limit whatever its class declares, so gated denials from branches unpause, domains get/create/activate/reverify and vanity-subdomains get move from api_status to plan_limit (fingerprint suffix :api_status becomes :plan_limit).

Note: the event moved from mid-handler to post-run. Payload and identity stay the same; it uses the same capture context as cli_command_executed.

Linear

  • part of GROWTH-1050

@pamelachia pamelachia self-assigned this Nov 2, 2026
@pamelachia pamelachia changed the title feat(cli): fire the plan-gate upgrade event from the command wrapper feat(cli): render the plan-gate upgrade hint and event centrally Nov 2, 2026
withCommandTelemetry captures cli_upgrade_suggested once, before
cli_command_executed, when a failure carries the entitlement_required
envelope's entitlement. Commands with no per-command wiring (branches
unpause) now fire it too. suggestUpgrade keeps the event only on its
entitlements-lookup fallback. vanity-subdomains check-availability keeps
its no-event exception through a new trackUpgradeSuggested option.

Errors carrying an entitlement classify as plan_limit, whether or not
their class declares the field.
The text layer's fail prints the upgrade hint before the error message
whenever the error carries the entitlement_required envelope's
entitlement, so commands with no per-command wiring (branches unpause)
print it too. suggestUpgrade prints only on its entitlements-lookup
fallback. Handler tests assert the failure carries the entitlement.
The persistent-branch 402 carries the entitlement_required envelope, so the
central hint, event and plan_limit cover it. A 4xx without the envelope no
longer triggers the follow-up project and entitlements requests.
@pamelachia
pamelachia force-pushed the pamela/growth-1050-central-upgrade-event branch from 979e26a to 82f5088 Compare November 9, 2026 06:26
@pamelachia pamelachia changed the title feat(cli): render the plan-gate upgrade hint and event centrally feat(cli): handle plan-gate denials centrally Nov 9, 2026
@pamelachia

pamelachia commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor Author

Manual check from source against a Free-plan project (<ref>, org <org>), run on the earlier head that also added a source param to the link. That change is now dropped; the request count, the hint and the entitlement field don't depend on it.

  • branches create gate-probe --project-ref <ref> --yes --debug: one POST /v1/projects/<ref>/branches (402), then the hint printed once with the org's billing URL. Passed.
  • Same command with --output-format json: error.entitlement is {"feature":"branching_limit","upgrade_url":".../org/<org>/billing..."}. Passed.
  • branches update <branch> --persistent not run live: Pro and Team orgs have the persistent-branch entitlement and Free orgs can't create branches, so only a Free org that still has a branch reaches this 402, and no test org is in that state. update.integration.test.ts covers one PATCH carrying the 402 envelope.

@pamelachia
pamelachia force-pushed the pamela/growth-1050-central-upgrade-event branch from 82f5088 to 33a4c0e Compare November 9, 2026 08:09

This branch has not been deployed

No deployments
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