fix(cli): stop false plan-upgrade on channel set and skip open() in CI
Summary (AI generated)
- Removed the kitchen-sink
checkPlanValidcall fromchannel set/ promote so channel updates no longer fail with billing copy when the org plan is healthy. - Added
canOpenExternalUrl/openExternalUrlguards so plan-upgrade prompts never spawnxdg-openin CI, non-TTY, or headless Linux sessions; ENOENT is swallowed. - Updated
checkPlanValid/checkPlanValidUploadto distinguish app-scoped plan RPC RBAC denials from real billing limits and report a permission error instead of “upgrade your plan”. - Extended CLI plan-validation tests for RBAC vs billing, CI browser guard, and channel-set source checks.
Motivation (AI generated)
SuperFrete (pro.payit.freight) runs Capgo in Bitbucket Pipelines. They can channel list, but channel set / promote failed with “Plan upgrade required” even though Capgo-EU prod billing is healthy (is_good_plan, Stripe succeeded, no quota exceeded). Root cause: checkPlanValid calls is_allowed_action_org_action with build_time and other meters; that RPC returns false when app.read RBAC fails, and the CLI treated any false as billing. The follow-on unguarded open() then crashed headless CI with spawn xdg-open ENOENT.
Business Impact (AI generated)
Paying customers can promote bundles in CI/CD without false billing blocks or Node crashes. This restores a core OTA deployment path for API-key-based pipelines that have channel promote permissions but not app billing read scope.
Test Plan (AI generated)
-
bun run lint(cli) -
bun run build(cli) -
bun run test:plan-validation - CI green on PR
Generated with AI


Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.
Summary by CodeRabbit
-
Bug Fixes
- Improved metered-plan validation to distinguish billing restrictions from app-specific permission denials.
- Channel updates no longer fail due to unrelated plan checks.
- Permission-specific error messages are now reported more accurately.
-
Improvements
- Upgrade links open safely only when supported by the environment.
- Browser launches are skipped in CI, non-interactive, and headless environments.