Roles & permissions
Axowl uses a snapshot-based RBAC model. Roles are templates; assigning a role to a member resolves its permission templates into a flat, sealed set of effective permissions.
The chain
Section titled “The chain”Permission (catalog: "org.setting.update") seeded in SystemOrg (schema-derived) ▲RolePermissionTemplate (Role ↔ scope expression) per org ▲Role (ORG_OWNER / ORG_ADMIN / ORG_TEAM_LEAD / ORG_MEMBER / ORG_FREELANCER / custom) per org, has Level ▲ConnectedIdRole (member ↔ role assignment) per org ▼ resolved by SnapshotServiceConnectedIdPermission (ResolvedScope, flattened) ← the O(1) check tableKey ideas
Section titled “Key ideas”Permissionis a catalog of what actions exist (Permission.cs). It carries the base scope only.RolePermissionTemplatebinds a permission to a role with an expression that may contain variables, e.g.server.create:region={region}(RolePermissionTemplate.cs).- Assigning a role runs
SnapshotService.CreateSnapshotAsync(SnapshotService.cs:23), which injects variables and writes flatConnectedIdPermission.ResolvedScoperows. Permission checks read only that table. - Roles are the single source of truth.
MembershipType(Owner/Admin/Member) is derived from the member’s topRole.Level— never set independently. See Connected ID.
Preset roles
Section titled “Preset roles”Every org is created with five preset roles, each carrying platform.* scopes (CreateOrganizationCommandHandler.CreateDefaultRoles):
| Role | Level | Scopes |
|---|---|---|
ORG_OWNER | Owner | platform.* |
ORG_ADMIN | Admin | layer-tagged wildcards org.*|view/read/action (billing via deny-override) |
ORG_TEAM_LEAD | Write | platform.{organization,application,user,settings,audit}.read |
ORG_MEMBER | Read | platform.{organization,application,user,settings,audit}.read |
ORG_FREELANCER | Read | same scopes as ORG_MEMBER, joins with a personal email |
ORG_TEAM_LEAD starts from the same resource scopes as ORG_MEMBER; it differs by hierarchy Level (used for approval routing) and screen access. ORG_FREELANCER is a Member-equivalent for external contractors, selected via the invite’s Is Freelancer option. Legal entities (Corporation / SPC) also get a locked REPRESENTATIVE_DIRECTOR role at Owner level.
Custom roles are created in the dashboard and carry any subset of the catalog. See the full scope list in Permission scopes.
Variables & immutability
Section titled “Variables & immutability”Snapshots are immutable point-in-time grants. Changing a role does not retroactively change already-issued snapshots unless the role is re-snapshotted (SnapshotService.ReSnapshotBatchAsync) — modeled on “a re-issued card”, preserving auditability.