Permission scopes
Dashboard authority is expressed as scopes derived mechanically from the data model — resources, their containment tree, and declared column facets. Resource scopes are not hand-named: a new resource gets its scopes automatically.
Grammar
Section titled “Grammar”<root>.<resource-path>[.<facet>].<action>[:column op value]view.<screen>- Roots (3):
org(tenant tree — Organization is recursive, so a sub-org is justorg.org.*),user(the person’s own subtree: credentials, linked identities),platform(Axowl operator). - Page access is a separate namespace,
view.<screen>— one scope per dashboard screen, not per resource:view.organization,view.applications,view.members,view.roles,view.reporting,view.settings,view.billing,view.audit,view.seals,view.devices,view.enduser_directory,view.customers,view.integrations,view.notifications,view.business,view.suborg,view.roost. - Resource path follows foreign-key containment:
org.app_group.app.create. An org never contains aUser— its only reach into a person is the membership badge (org.member.*) with issuance verbs (invite,suspend,revoke,role), never CRUD. - Facets are declared column groups that map 1:1 to UI cards:
org.app_group.branding.updategrants editing the Branding card only. - Actions come from each entity’s declared kind — every resource has
readandlist; Record addscreate/update/delete, Badge the issuance verbs, Edgeadd/remove, Projectiongrant/revoke, Credentialissue/revoke, Configupdate, Log nothing (read-only) — plus declared domain verbs (e.g.org.setting.rotate_signing_key). - Conditions narrow a grant to matching rows:
org.org_file.*.delete:creator!=self,org.app_group.*:app_group={app_group}.
Protection layers
Section titled “Protection layers”There are two axes, and a wildcard never crosses from one to the other:
| Axis | Scopes | Guards |
|---|---|---|
| Page access | view.<screen> | Entering a dashboard screen (the door) |
| Resource — read tier | ….read, ….list | Data reads (the drawer) |
| Resource — write tier | every other action | Mutations (the stamp) |
Wildcards:
| Wildcard | Expands to |
|---|---|
view.* | Every page-access scope |
org.app_group.* | Every read and write scope in that subtree |
org.app_group.*.read | The read tier of that subtree only |
org.app_group.*.write | The whole subtree — write includes read |
Holding org.* grants every resource scope — and no page access; that takes view.* or individual view.<screen> scopes.
Runtime decision
Section titled “Runtime decision”Grants are stored concrete (wildcards expand at grant-compile time). A permission check is a single indexed lookup — pure YES/NO — plus a clock compare: every entitlement carries ExpiresAt (null = permanent; a timestamp makes it a just-in-time temporary grant that lapses automatically).
Preset-role grants
Section titled “Preset-role grants”Presets are computed from the derived library — a single source shared by seeding and new-org creation. A preset can carry deny entries, which take away part of what a wildcard grants. System-protected resources are never delegable.
| Role | Holds |
|---|---|
ORG_OWNER / REPRESENTATIVE_DIRECTOR | org.* + view.* |
ORG_ADMIN | org.* + view.*, minus the owner-only scopes: view.billing, org.org.billing_manage, and the Roost scopes |
ORG_TEAM_LEAD | The Member set, plus view.members, org.member.* (badge issuance verbs and reporting edges), full management of approval forms and documents, end users (view.enduser_directory, org.end_user.*), devices (org.device_identity.*), read access to settings and webhooks (view.settings, org.setting.read), the link-sharing policy (org.setting.block_external_sharing), org-wide audit records of the agent, project and reporting systems, promoting an app to production (org.app_group.promote), managing meeting locations, and connecting data sources and Git repositories |
ORG_MEMBER | view.organization, view.applications, view.reporting, org.org.read, the whole org.app_group.* subtree (deleting only what they created; not promoting an app to production), read access to approval documents and to the reporting tree, creating and editing approval forms (deleting only their own), their own files and their own audit records (view.audit), read access to devices (view.devices), data sources and Git repositories (plus org.git_repository.propose_change), and reading the documentation (platform.doc_page.read) |
ORG_FREELANCER | Same as ORG_MEMBER, with the app-group subtree limited to the app group named on the invitation |
ORG_DIRECTOR | The Member set, plus view.business and read access to meetings (org.meeting.read, org.meeting.list) and meeting locations |
ORG_GUEST | view.organization and org.org.read only |
PROJECT_GUEST | view.organization, org.org.read, and org.project.read / org.project.list limited to the one project named on the invitation |
MEETING_GUEST | view.business, org.org.read, and org.meeting.read / org.meeting.list limited to the one meeting named on the invitation |