5.5 KiB
Default roles and permissions matrix
Source of truth
The repository-owned source of truth for static seeded roles and permissions is packages/db/src/permissions-seed.server.ts and its pnpm run permissions:sync command:
defaultAdminRoleSeedsdefines defaultadmin.*roles, role descriptions, andassignToNewUserspolicy.defaultAppRoleSeedsdefines defaultapp.*account roles, role descriptions, andassignToNewUserspolicy.defaultPermissionSeedsdefines static permission names.- Explicit role assignment overrides in the DB package preserve the current admin/app role matrix during deploy sync.
The web seed path in apps/web/app/utils/services/rolesAndPermissionsService.ts still owns dynamic entity permission expansion because it reads entity metadata from the web runtime.
This document intentionally summarizes the public role and permission shape only. It must not include secrets, environment values, tokens, passwords, or seeded credential material.
Admin roles
| Role | Type | Assigned to new users by default? | Intended capability summary |
|---|---|---|---|
| SuperAdmin | admin |
No | Full admin surface owner. Receives every static admin.* permission and is also included in seed-time dynamic entity permissions. |
The operator/admin host intentionally seeds no additional default admin roles. Former default admin roles such as Product Designer, Developer, Auditor, Marketing, and Guest are removed during permission sync when they are still marked as default admin roles.
App roles
| Role | Type | Assigned to new users by default? | Intended capability summary |
|---|---|---|---|
| SuperUser | app |
No | Full app account owner. Receives all static app permissions, including account deletion, and is included in dynamic entity permissions. |
| Admin | app |
No | App administrator with all regular app settings permissions except account deletion; included in dynamic entity permissions. |
| Billing Admin | app |
No | Billing-specific app role for subscription view/update/delete and invoice visibility. |
| User | app |
Yes | Regular app user. Receives dashboard access and is included in dynamic entity permissions. |
Permission groups
admin.*
Static admin permissions cover dashboard, accounts, users, relationships, blacklist/IP inspection, roles, analytics, entities, API keys, audit trails, events/webhooks, pricing, email templates, onboarding, notifications, feature flags, prompts, formulas, metrics, knowledge bases, and settings. Forms, Surveys, Public Forms, and form-based Help Desk surveys are not Product Core permissions.
Group-level coverage:
- SuperAdmin is the only seeded operator role and receives all static
admin.*permissions. - Default operator users are assigned admin access intentionally; no read-only admin role is auto-assigned to new users.
app.settings.* and app.dashboard.*
Static app permissions cover the app dashboard, plugin usage/management, and account settings areas for members, roles, groups, subscriptions, account profile, accounts, API keys, and audit trails.
Group-level coverage:
- SuperUser receives all static app permissions, including
app.settings.account.delete. - Admin receives all static app permissions except account deletion.
- Billing Admin receives only subscription and invoice permissions.
- Billing Admin and User receive
app.plugins.useso installed plugin surfaces can be used without account-admin access. - User receives
app.dashboard.viewas the regular app baseline. app.settings.members.impersonateis defined as an app permission but currently targets SuperAdmin at seed time.app.plugins.manageis limited to SuperUser and Admin by default; it gates plugin install, capability grant, enable, and disable operations.
Entity dynamic permissions
During seedRolesAndPermissions, active entities from getAllEntities({ tenantId: null, active: true }) expand into dynamic permissions from getEntityPermissions(entity).
Each generated entity permission is seeded with role coverage for:
- SuperAdmin
- SuperUser
- Admin
- User
Seed behavior
seedRolesAndPermissions(adminEmail) performs the role and permission seed in these phases:
- Sync static admin roles, app roles, permissions, and role-permission links through
@toolctrl/db/permissions-seed.server. - Create dynamic entity permissions for active global entities and append them to the app permission set.
- Assign the seeded admin role to the seeded admin user matching
adminEmail. - Assign all app roles to tenant users for each tenant.
The seed path logs role phase counts only. Diagnostics should remain count-based and must not include password, token, or secret values.
Maintenance checks
packages/db/src/permissions-seed.server.test.tsis the static seed source-of-truth guard.apps/web/app/utils/services/rolesAndPermissionsService.role-matrix.test.tsverifies the web facade stays aligned with that DB package source.scripts/verify-role-permission-baseline.mjsis the milestone baseline gate referenced by Role Permission.- When adding or renaming a default role, update
DefaultAdminRolesorDefaultAppRoles, the corresponding DB packagedefault*RoleSeedsentry, this document, and the drift tests together. - When adding a
DefaultPermissionsentry, add a matchingdefaultPermissionSeedDescriptorsentry through the DB package seed catalog and verify everyinRolestarget exists. - When changing dynamic entity permission behavior, keep role coverage expectations explicit here and in tests.