Traits / Authable
Authable
Role-based access control extension pack grounded in the R21.2 membership pattern.
Generated from @oods/foundry 0.10.1
- Group
- core
- Maturity
- experimental
- Contexts
- detail, form, list
Encodes roles, permissions, memberships, and adjacency edges for tenant-aware RBAC.
Fields it adds
| Field | Type | Required | Description |
|---|---|---|---|
role_catalog | AuthzRoleDocument[] | yes | Canonical RBAC roles (R21.2 Part 4.2 TABLE 1). |
permission_catalog | AuthzPermissionDocument[] | yes | Atomic permissions following resource:action notation (TABLE 2). |
role_permissions | Record<string, string[]> | yes | Junction map for role→permission edges (TABLE 3). |
membership_records | AuthzMembershipDocument[] | yes | SaaS membership triple (user_id, organization_id, role_id) with UNIQUE constraint (TABLE 4). |
role_hierarchy_edges | AuthzRoleHierarchyEdge[] | no | Parent→child adjacency list for hierarchical RBAC (Part 3.1). |
session_roles | string[] | no | Materialized roles granted within the current session/token exchange. |
What it shows in each context
Parameters
defaultRoleIdstring- Role identifier applied when tenants are provisioned without an explicit role (R21.2 §2.3).
hierarchyDepthLimitnumber- Maximum recursion depth when traversing role hierarchies for derived permissions.
Objects that use it
The trait file
traits/core/Authable.trait.yaml
trait:
name: Authable
version: 1.0.0
description: |
Role-based access control extension pack grounded in the R21.2 membership pattern.
Encodes roles, permissions, memberships, and adjacency edges for tenant-aware RBAC.
category: core
tags:
- authorization
- rbac
- membership
- saas
- security
parameters:
- name: defaultRoleId
type: string
required: false
description: Role identifier applied when tenants are provisioned without an explicit role (R21.2 §2.3).
validation:
pattern: "^[0-9a-fA-F-]{32,36}$"
- name: hierarchyDepthLimit
type: number
required: false
description: Maximum recursion depth when traversing role hierarchies for derived permissions.
default: 5
validation:
minimum: 1
maximum: 10
schema:
role_catalog:
type: AuthzRoleDocument[]
required: true
description: Canonical RBAC roles (R21.2 Part 4.2 TABLE 1).
examples:
[
[
{
"id": "11111111-1111-4111-8111-111111111111",
"name": "Owner",
"description": "Full tenant access + invoice approval (R21.2 Table 1).",
},
{
"id": "22222222-2222-4222-8222-222222222222",
"name": "Approver",
"description": "Workflow approver for compliance-sensitive documents.",
},
{
"id": "33333333-3333-4333-8333-333333333333",
"name": "Editor",
"description": "Contributor allowed to create + update documents in scope.",
},
],
]
default: []
permission_catalog:
type: AuthzPermissionDocument[]
required: true
description: Atomic permissions following resource:action notation (TABLE 2).
default: []
role_permissions:
type: Record<string, string[]>
required: true
description: Junction map for role→permission edges (TABLE 3).
default: {}
membership_records:
type: AuthzMembershipDocument[]
required: true
description: SaaS membership triple (user_id, organization_id, role_id) with UNIQUE constraint (TABLE 4).
default: []
role_hierarchy_edges:
type: AuthzRoleHierarchyEdge[]
required: false
description: Parent→child adjacency list for hierarchical RBAC (Part 3.1).
default: []
session_roles:
type: string[]
required: false
description: Materialized roles granted within the current session/token exchange.
default: []
semantics:
membership_records:
semantic_type: authorization.memberships
token_mapping: tokenMap(authorization.memberships)
ui_hints:
component: MembershipMatrix
uniqueConstraint: user_id+organization_id+role_id
role_catalog:
semantic_type: authorization.roles
token_mapping: tokenMap(authorization.roles)
ui_hints:
component: RoleCatalogPanel
permission_catalog:
semantic_type: authorization.permissions
token_mapping: tokenMap(authorization.permissions)
ui_hints:
component: PermissionList
view_extensions:
list:
- component: RoleBadgeList
position: after
props:
rolesField: session_roles
fallbackRoleParameter: defaultRoleId
detail:
- component: MembershipPanel
position: main
priority: 75
props:
membershipsField: membership_records
hierarchyField: role_hierarchy_edges
roleField: role_catalog
permissionField: permission_catalog
form:
- component: RoleAssignmentForm
position: main
props:
availableRolesField: role_catalog
membershipField: membership_records
defaultRoleParameter: defaultRoleId
tokens:
auth.roles.badge.bg: "var(--sys-surface-neutral)"
auth.roles.badge.text: "var(--sys-text-strong)"
auth.membership.card.border: "var(--sys-border-strong)"
auth.membership.card.bg: "var(--sys-surface-raised)"
dependencies: []
metadata:
created: "2025-11-19"
owners:
- security@oods.systems
- platform@oods.systems
maturity: experimental
accessibility:
keyboard: RoleAssignmentForm keeps add/remove buttons in reading order.
screenreader: MembershipPanel announces organization, role, and permission counts per entry.
regionsUsed:
- list
- detail
- form
examples:
- User
- Organization
references:
- "R21.2 Canonical Data Models for Authorization Systems"