[Traits](https://oods-foundry.com/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

- [list](https://oods-foundry.com/contexts/list)

  `RoleBadgeList`

- [detail](https://oods-foundry.com/contexts/detail)

  `MembershipPanel`

- [form](https://oods-foundry.com/contexts/form)

  `RoleAssignmentForm`

## Parameters

- `defaultRoleId` `string`

  Role identifier applied when tenants are provisioned without an explicit role (R21.2 §2.3).

- `hierarchyDepthLimit` `number`

  Maximum recursion depth when traversing role hierarchies for derived permissions.

## Objects that use it

- [Organization](https://oods-foundry.com/objects/organization)
- [User](https://oods-foundry.com/objects/user)

## 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"
```
