Platform Roles & Permissions

Platform Roles

Access is controlled by a 5-tier role hierarchy. Roles are stored in user_roles with gym_id IS NULL — that null gym is what makes a role a platform role rather than a gym role. There is no platform_roles table, and roles are never stored on the profile.

Role Hierarchy (highest → lowest)

RoleRankAccess Level
Super Admin1Everything, plus the actions reserved to it alone: changing a gym's status, suspending a gym, marking a gym as demo, VAT settings, AI prompt configuration, error logs, email intercept, Zoom.
Admin2All configuration and money pages: billing, pricing, plans, discounts, disputes, Stripe health, feature flags, all template libraries, communications, settings, roadmap, tasks, planning, ideas.
Manager3Gyms and gym detail, gym leads, demo bookings, analytics, support tickets, knowledge base, platform help KB, media library, chat access log.
Editor4The internal help centre only (/platform/help and its category/article pages).
Ideas5Lowest rank. Ranked below Editor, so it reaches nothing that sets a minimum role.

Ranks come from get_platform_role_rank(). Routes are wrapped in <ProtectedRoute platformOnly minPlatformRole="…">; a role passes if its rank is at least as high as the one named.

Manager Variants

manager_sales and manager_support have identical data access and RLS to manager. The only difference is which dashboard sections render: a Sales Manager sees New Leads and Subscription Changes but not Support Tickets; a Support Manager sees the reverse. Never treat a variant as a security control.

UI guard versus real enforcement

minPlatformRole only decides whether a page renders. The real enforcement is RLS on each table, which is why a lower-ranked user may occasionally reach a page and see an empty or partial result set rather than an error.

Role Assignment

  1. Go to Settings → Platform Users.
  2. Select the user and choose the new role.
  3. The change is applied through the change_platform_role function rather than a direct table write, so it is validated and recorded. It takes effect on the user's next page load.

Grant the lowest role that does the job, and escalate temporarily rather than permanently.

What no platform role grants