You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(subscription): restrict Neo purchase on web, show full new catalog (#9974)
## What
Restrict the deprecated **Neo** (`unlimited`) plan from the **web**
purchase catalog, and make web render the full new plan lineup.
Web (`X-App-Platform: web`) previously hid nothing from the catalog, so
Neo was offered for purchase alongside the new tiers — even though Neo
is already hidden on mobile and desktop. This closes that gap and shows
the intended catalog on web.
### Backend (`utils/subscription.py`)
- Added `WEB_PLATFORMS = {'web'}`.
- `should_show_new_plans('web')` → always `True` (web is an
always-latest, version-agnostic client) → no legacy adaptation, so plans
render under canonical titles.
- `_platform_hidden_plans('web')` → `{unlimited}` (Neo only).
- Net result: web shows **Plus + Unlimited + Operator + Architect**; Neo
is hidden from purchase but stays visible to existing Neo subscribers
via `filter_plans_for_user`'s current-plan / ever-purchased escapes (so
they can still manage/cancel).
### Web frontend
Now that web renders the full new catalog, an Operator/Architect
subscriber's current plan reaches web as its real id (Plus/Unlimited
still wire to `unlimited`). To avoid mis-showing them as Free:
- `types/user.ts` — widened the `Subscription.plan` union.
- `lib/api.ts` — `is_unlimited` = any paid tier (for the
Manage-vs-Choose-Plan UI gate).
- `SettingsPage.tsx` — display labels for the new plans.
## Why
Consistency + product intent: Neo is deprecated everywhere; web was the
only surface still selling it. Existing Neo subscribers are untouched
(migration handled separately).
## Reusable guard
Adds `test_neo_hidden_from_purchase_on_every_client_platform` — asserts
Neo is hidden from purchase for a new user on **every** real client
platform (ios/android/macos/windows/web). The same cause (a platform
omitted from the Neo-hidden set) previously shipped for **Windows**
(`test_filter_plans_hides_neo_on_windows_for_new_user`); this pins the
invariant so the next platform added can't silently reintroduce the
deprecated-plan-for-sale bug.
## Testing
- Backend: added web catalog tests + the all-platforms guard; inverted
the stale `keeps_neo_on_web` test (it conflated web with
`platform=None`; real web sends `'web'`). All affected tests pass
individually, and the pre-existing mobile/desktop/windows catalog tests
still pass.
- Note: the whole-file `pytest` run fails locally on a **pre-existing**
Prometheus re-registration artifact under the local 3.12 venv (verified
identical failures on clean `main` with the same venv); the 3.11 CI
runner handles it.
- Web: `tsc --noEmit` → exit 0.
- Not run end-to-end: the live web→Stripe checkout (needs the running
Next.js app + Stripe). The added tests exercise the exact
catalog-resolution functions both `/v1/payments/available-plans` and
`/v1/users/me/subscription` call.
## Product invariants
None affected (`scripts/pr-preflight --suggest` → `none`).
Failure-Class: none
<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/BasedHardware/omi/pull/9974?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
0 commit comments