Permission scopes
Internal (dashboard) authority is expressed as scopes derived mechanically from the database schema — entities, their foreign-key containment tree, and declared column facets. Nothing is hand-named: adding a table registers its scopes automatically at the next boot.
Grammar
Section titled “Grammar”<root>.<resource-path>[.<facet>].<action>[:column op value]- 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). - 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 — Record →
create/update/delete, Badge → issuance verbs, Edge →add/remove, Credential →issue/revoke, Log → read-only, Config →update— plus declared domain verbs (e.g.org.setting.rotate_signing_key).
Protection layers
Section titled “Protection layers”Every scope belongs to exactly one of three layers, and wildcards never cross layers:
| Layer | Guards | Enforced at |
|---|---|---|
view | Page entry (the door) | route guard / nav |
read | Data reads (the drawer) | query endpoints |
action | Mutations (the stamp) | mutation endpoints |
Wildcards therefore carry a layer tag: org.*|view, org.*|read, org.*|action. An untagged .* does not exist. Holding org.app_group.*|action grants every mutation in that subtree — and no page access.
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 subsets of the derived library (EntitlementPresets.For) — a single source shared by the seeder and new-org creation. System-protected resources (seals, signing keys, credentials, audit, sessions) are never delegable and never enter a preset.
| Role | Holds |
|---|---|
ORG_OWNER / REPRESENTATIVE_DIRECTOR | org.*|view + org.*|read + org.*|action (all delegable) |
ORG_ADMIN | same three layer wildcards (billing refinement via deny-override) |
ORG_TEAM_LEAD | Member set + badge issuance verbs (org.member.*) + reporting edges (org.member.relationship.*) |
ORG_MEMBER | org.org.view + the whole org.app_group subtree (app work) + reporting view |
ORG_FREELANCER | same as ORG_MEMBER (joins with a personal email) |