Skip to content

feat(cli): envelope-first plan-gate upgrade hints#5943

Draft
pamelachia wants to merge 4 commits into
developfrom
pamela/growth-958-cli-surface-entitlement-upgrade-hint-from
Draft

feat(cli): envelope-first plan-gate upgrade hints#5943
pamelachia wants to merge 4 commits into
developfrom
pamela/growth-958-cli-surface-entitlement-upgrade-hint-from

Conversation

@pamelachia

Copy link
Copy Markdown
Contributor

Paid-feature denials now read the management API's entitlement_required error envelope straight off the failed response and print the upgrade hint with zero extra API calls. Previously the suggest path made 2 extra round-trips (project lookup + entitlements) per gated failure, and only 9 commands were wired at all.

Changed:

  • Wired commands stop making extra API calls on denial: the shared suggest functions (Go plan_gate.go, TS legacy-upgrade-suggest.ts) parse { error: { code: "entitlement_required", feature, upgrade_url } } first; the entitlements round-trip stays as the fallback for gates that do not emit the envelope yet (v1 SSO carries no server-side gate at all).
  • domains create/get/activate/reverify and vanity-subdomains get newly show the hint: envelope-only, no fallback, because the custom_domain entitlement key is plan-level while the gate is a per-project add-on, so the old round-trip would tell Free orgs to upgrade on unrelated 404s.
  • cli_upgrade_suggested reports the server-authoritative feature: feature_key comes from the envelope (fixes a branching_persistent denial being logged as branching_limit); org_slug is parsed from upgrade_url.
  • Go mirror kept 1:1 per the legacy-shell parity doctrine; AGENTS.md telemetry table and the affected SIDE_EFFECTS.md files updated to match.

Note: the envelope's upgrade_url is server-built and printed without a host check. This trusts the management API host the same way every authenticated call already does; a host allowlist would silently suppress valid hints on profiles whose dashboard URL differs from the CLI default.

To test

Requires a Free-org project ref (to hit the gates).

Tested locally against prod (bun src/legacy/main.ts, Free org):

  • domains get --project-ref <free-ref> --agent no prints "Upgrade your plan: .../org//billing" on stderr; --debug shows exactly one HTTP request, no project/entitlements lookups
  • vanity-subdomains get shows the same hint via the decorated server gate
  • Plain 4xx without the envelope on the newly wired commands produces no hint (integration tests pin the false-positive guard)
  • Envelope-less denials on previously wired commands still run the entitlements fallback unchanged

Linear

  • fixes GROWTH-958

@pamelachia pamelachia self-assigned this Jul 24, 2026
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