SaaS Starter
Platform admin

Managing platform admins

Promote and demote super-admins from the console.

User.platformAdmin is a single boolean on every user. It's orthogonal to org-scoped roles — a platform admin is not automatically a member of any tenant org, and a tenant owner is not automatically a platform admin.

Promote a user

From /admin/users/[id], click Promote to admin. The mutation hits:

POST /api/v1/platform/admins/{userId}

Audit: platform.admin.promoted with { targetUserId }.

Demote a user

From /admin/admins, click Demote on any row. The mutation hits:

DELETE /api/v1/platform/admins/{userId}

Audit: platform.admin.demoted.

Invariants enforced server-side

These are guarded inside DemotePlatformAdminUseCase and the suspend / soft-delete paths in modules/iam/:

RuleWhere enforcedFailure
Cannot demote yourselfuse case + UI button disabledSelfDemoteError (HTTP 409)
Cannot demote the last platform adminatomic count under serializable txnLastAdminError (HTTP 409)
Suspending the last admin is also blockedSuspendUserUseCaseLastAdminError (HTTP 409)
Soft-deleting the last admin is also blockedSoftDeleteUserUseCaseLastAdminError (HTTP 409)

The "last admin" check is a single query — userRepository.countActivePlatformAdmins() — which counts only platformAdmin = true AND deletedAt IS NULL. Suspending an admin doesn't reduce this count (still platform admin, just inactive), but the gate is intentionally conservative: a platform admin who suspends themselves can't sign back in to undo it.

On this page