Pro access tier: full app features, no backend#64
Merged
Conversation
Adds a real, grantable "Pro" access tier between regular users and admins, so a full-access account can use every app feature without any backend/admin reach. The tier hierarchy (admin > pro > beta > anonymous) already existed in useFeatureFlags but "pro" was unreachable — this makes it real. Backend (migrations, applied to prod): - app_role gains 'pro' (own migration; enum values can't be used in the txn that adds them). - pro_email_allowlist (admin-managed, RLS) + handle_new_user auto-grants Pro on sign-in for allowlisted emails (survives provider switches, like admin). - admin_set_pro(email, enabled) SECURITY DEFINER RPC keeps the allowlist and the user_roles grant in sync; admin-gated, anon EXECUTE revoked. - Pro grants NO new DB privileges: every Pro feature is already reachable by authenticated users at the data layer, so this is a pure UI-tier. Frontend: - useAccessTier() resolves admin/pro/beta/anonymous from user_roles; is the single source for feature gating (useIsAdmin stays the narrow admin check). - useFeatureFlags consumes the real tier; catalog_analysis, ml_recommendations, ai_lab, reports move from admin → pro. - AdminGate gains requirePro (admins included; no MFA step-up — Pro isn't backend). /catalog-analysis and /reports become Pro features; LeftNav nav items and the Index Teams section unlock for Pro; /admin/* stays admin-only. - Admin → Roles: per-user Make/Revoke Pro (via admin_set_pro) with a Pro badge; Settings shows the account's plan (Admin/Pro/Member). fmmusic821@gmail.com is pre-seeded into the Pro allowlist (keeps admin for now) so that when an admin later revokes their admin role, Pro access is already in place with no gap. Verified: tsc, eslint, 362 tests, production build; migrations applied live and reconciled (enum has 'pro', RPC admin-only/anon-blocked, fmmusic821 has pro+admin). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CN6KKo8XyF2N2wBLxno24C
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Updates to Preview Branch (claude/publisting-audit-hardening-ixpwf6) ↗︎
Tasks are run on every commit but only new migration files are pushed.
View logs for this Workflow Run ↗︎. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a real, grantable Pro tier between regular users and admins — full access to every app feature, no backend/admin reach. This is the prerequisite for later demoting a full-access account from admin → pro. The tier hierarchy (admin > pro > beta > anonymous) already existed in
useFeatureFlagsbut"pro"was unreachable; this makes it real.Design
Pro grants no new database privileges — every Pro feature (Catalog Analysis, AI Lab, AI/ML recommendations, Reports, Teams collaboration) is already reachable by any authenticated user at the data layer; only the frontend gated it. So Pro is a pure UI-tier: a role the UI reads to decide what to show.
/admin/*stays admin-only.Backend (migrations, already applied to prod, versions reconciled)
app_rolegains'pro'(its own migration — enum values can't be used in the transaction that adds them).pro_email_allowlist(admin-managed, RLS) +handle_new_userauto-grants Pro on sign-in for allowlisted emails (survives Google/provider switches, mirroring admin).admin_set_pro(email, enabled)SECURITY DEFINER RPC keeps allowlist +user_rolesin sync; admin-gated, anon EXECUTE revoked. Verified live: authenticated can execute, anon cannot.Frontend
useAccessTier()resolves admin/pro/beta/anonymous fromuser_roles— the single source for feature gating (useIsAdminstays the narrow admin check for backend gates + MFA step-up).useFeatureFlagsconsumes the real tier; the 4 premium features move admin → pro.AdminGategainsrequirePro(admins included; no MFA step-up since Pro isn't backend)./catalog-analysisand/reportsbecome Pro features; LeftNav items and the Index Teams section unlock for Pro.fmmusic821
Pre-seeded into the Pro allowlist and granted Pro while keeping admin, so a later admin-revoke leaves Pro in place with no access gap. Verified live: the account holds both
proandadmin.Verification
tsc -bclean · ESLint 0/0 · 362 tests green (newaccess-tier.test.ts+ expandedadmin-gate.test.tsxwith Pro cases) · production build succeeds · migrations applied + verified live.🤖 Generated with Claude Code
https://claude.ai/code/session_01CN6KKo8XyF2N2wBLxno24C
Generated by Claude Code