Platform Admin β
Audience
This article is for GCM platform operators. Church admins should see Users & Roles instead β the Platform Admin console is the internal staff cockpit, not part of the per-church workspace.
Platform Admin is the operator-only surface that sits behind app.geniuschurchmanager.com/platform. It is how the GCM team manages every organisation on the platform: who is past due, why an edge function exploded last night, which landing-page headline ships in Spanish, what the renewal cron is doing tomorrow morning at 02:00. It is a separate React shell with its own sidebar (PlatformLayout), its own RBAC gate, and its own audit posture.

Who can sign in β
Only a user whose JWT carries is_platform_admin: true or is_superadmin: true can load any /platform/* route. Both PlatformLayout and PlatformAdmin.tsx check usePermissions().roles on mount and redirect non-staff back to /. The JWT claim is set by the auth-hook edge function from the user's profile, so promotions take effect on the next sign-in.
There are two tiers:
| Role | What it unlocks |
|---|---|
platform_admin | Full read/write on every org, every billing ledger, every audit row. Cannot promote other users to platform_admin or superadmin. |
superadmin | Everything above, plus the ability to grant platform_admin and superadmin. A DB trigger (trg_protect_platform_admin_role*) forbids demoting the last superadmin. |
If your account loses both flags you will be silently kicked back to / the moment you visit /platform β sign out and back in after any role change, since the JWT is what counts.
Demo account caveat
The shared demo account on app.geniuschurchmanager.com is no longer a platform admin. To follow along with the screenshots in this section you need a staff account that carries the platform_admin claim. Ask a superadmin to provision one if you do not have access.
The six navigation groups β
The sidebar is grouped to match the rhythm of operator work, not the alphabet:
- Overview β Overview KPIs, Organisations list.
- Plans & Modules β Plan catalogue, plan -> module mapping. Mostly read-only after launch.
- Billing β Billing operations console, gateway config, MRR / churn metrics.
- Content β Email templates, website templates, workflow templates, landing-page content overrides.
- Settings β Branding, PWA manifest, DNS, channels, email settings, reserved slugs.
- System β Users, Geography master data, Audit log, Error log.
What lives in which table β
Most surfaces in this section read from one of three platform-scoped tables:
platform_audit_logβ every staff action: org created, plan changed, refund issued, impersonation started, impersonation_failed. Captured byuseAppModeand by every billing-ops edge function.platform_settingsβ flat key/value store. Holds branding (brand_title,brand_logo), marketing copy (marketing_hero_title), social links, the guided-tour toggle. Noorganization_idcolumn β these are platform-wide.admin_impersonationβ the session row thestart_impersonationRPC creates socurrent_org_id()can transparently scope a staff user to the target org. The row is what makes RLS "just work" while impersonating.
Anything that looks like per-org data (orgs, payment_history, audit timeline, error_log) lives in the same multi-tenant tables a tenant admin would touch β staff just see every row instead of one org's worth.
Read-only by default, audit-every-write by design β
Platform Admin tabs lean hard on three patterns:
- Cached
useQueryfor reads, so refresh is free and consistent across tabs. - Reason fields on every destructive write β refunds, bulk deletes, subscription overrides all require a free-text reason that lands in
platform_audit_lognext to the actor email. - Dry-run before charge β the renewal dialog defaults to "Preview only" so you can see what the gateway would do before money moves.
If a future feature lets you change platform-wide state without a reason field, treat that as a bug.
Where to go next β
| You need to... | Article |
|---|---|
| Find an org by name, change its plan, or delete a duplicate | Organisations |
| Refund a payment, fix a stuck renewal, or trace a failed charge | Billing operations |
| Sign in to a customer's workspace to reproduce a bug | Impersonation flow |
| Triage a Sentry-style error spike | Error log |
| Investigate "who changed what, when" | Audit log |
| Add a missing country, state, or city to the address picker | Geography master data |
| Tweak the landing-page hero copy or upload a new OG image | Landing content overrides |