feat(mobile,trpc,auth): gate mobile behind a paid plan
Mobile launches as a Pro perk (user decision — limits users while we iterate, avoids clawing back free access later). Externally-billed subscription gating with no IAP, per guideline 3.1.3(b) multiplatform services — the Netflix/Slack pattern.
The gate is one wall, twice
- Client: a new
Stack.Protectedtier in mobile's RootLayout — signed-in + not-pending-deletion + no paid plan →paywallscreen.planalready rides the session viacustomSession, so no extra query. - Server: one
protectedProceduremiddleware —mobile client + no plan on the active org → FORBIDDEN, allowlisting only account self-management (user.me/deleteAccount/reactivateAccount/myOrganizations). Keyed on thex-superset-clientheader, which mobile now actually sends (the header parsing existed but no client ever adopted it — this also turns on the per-client API telemetry for mobile). Other clients are never gated.
No per-feature plan checks anywhere — nothing to remember as the product grows.
The paywall screen
Steering-safe copy ("Manage your plan from the Superset desktop app" — no external purchase link, valid on every storefront), plus: org switcher (a member whose active org is their free personal org but who belongs to a paid org can switch right there — otherwise real customers would hit a dead wall), Refresh, Contact support, Log out, and Delete account (grace-period flow) so guideline 5.1.1(v) survives the gate.
App Store review access
- Credential sign-in enabled in production (
emailAndPassword.enabledalways;disableSignUpoutside dev/preview so nobody can register) - Quiet "Sign in with email" link on the sign-in screen (prompt-based, same pattern as the dev options)
bun run db:seed-review(APP_REVIEW_EMAIL/APP_REVIEW_PASSWORD) idempotently provisions the demo account: credential login, onboarded, Pro-subscribed personal org (subscription row only, no Stripe charge)store.config.jsonreview-notes/demoRequired update rides #6408; the credentials themselves go into ASC's App Review sign-in fields by hand, never the repo
Known residuals
The relay/host path is not plan-gated (client gate covers the UX; a determined free user scripting the relay directly isn't a launch concern). Desktop/web remain ungated by design.
Testing
- turbo typecheck (mobile, trpc, auth) + lint green
- Full paywall→upgrade→refresh loop exercisable on TestFlight with the seeded review account
Summary by cubic
Gate Superset Mobile behind a paid plan and add a paywall screen. Previously any signed-in user could use mobile; now only sessions with a paid plan on the active org can proceed, and unpaid sessions land on the paywall. Desktop/web behavior is unchanged.
- Client: RootLayout adds a
Stack.Protectedtier keyed onsession.plan; unpaid sessions route topaywall(no extra query; plan is in the session). - Server:
protectedProcedureforbids mobile without a plan exceptuser.me,user.deleteAccount,user.reactivateAccount, anduser.myOrganizations. Gating is keyed by thex-superset-clientheader, which the mobile client now sends asmobile/<version>(also enables per-client API telemetry). - Paywall: org switcher (to move to a paid org), Refresh, Contact support, Log out, and Delete account. Copy avoids external purchase links (App Store 3.1.3(b)); deletion remains accessible (5.1.1(v)).
- Sign-in: Quiet email/password option added to the sign-in screen. Credential sign-in is enabled in production; sign-up remains disabled outside dev/preview.
Rollout
- Create the App Review demo account in each environment: APP_REVIEW_EMAIL=… APP_REVIEW_PASSWORD=… bun run db:seed-review (idempotent), then add credentials in App Store Connect review details.
- No schema/data migrations. Other clients are not gated.
Summary by CodeRabbit
- New Features
- Added a Pro subscription paywall with plan messaging, organization switching, support contact, sign-out, and account deletion.
- Added email and password sign-in with loading states and clearer error messages.
- Added account deletion with confirmation, progress feedback, and automatic sign-out.
- Access & Authentication
- Paid-plan checks now guide eligible mobile users to protected areas or the paywall.
- Email/password sign-in is available in production.
- Improvements
- Mobile requests now report the app version for improved service compatibility.