Agency RBAC Persistence Model
Ownership boundaries
orgUsersowns organization membership, role, member capability mode, and client-access mode.orgRolePoliciesowns organization-wide default capabilities for non-owner roles.clientAccessAssignmentsowns the selected-client set for memberships in Selected clients mode.org/access/*owns team management, invitations, hierarchy checks, and capability resolution.clients/scope.tsresolves client visibility for client-scoped application data.
Do not introduce a second client-scope persistence model.
Membership state
orgUsers stores:
organizationIdanduserIdemail,role, andstatusclientAccessModeasallorassignedcapabilityModeas role default or custom- optional
capabilityOverrides
The product label for the persisted assigned value is Selected clients. Owners resolve as All clients regardless of stored legacy values.
Selected-client rows
clientAccessAssignments stores:
organizationIdmemberUserIdclientAccountIdactive- assignment actor and timestamps
Rows are validated against the active organization. Updating a selected set activates, deactivates, or inserts only the necessary rows. Switching to All clients deactivates active selected-client rows so stale selections cannot unexpectedly reappear as effective access.
Provisional memberships created for pending invitations may also have selected-client rows. Revoking an unaccepted invitation removes those rows. An expired invitation is never active access, and an attempted expired-token consumption also removes the provisional state.
Resolution order
For an authenticated organization request:
- Resolve the active
orgUsersmembership. - Resolve the role policy and any supported per-member capability override.
- Resolve client scope: owners and
allmemberships have global client access;assignedmemberships use active assignment rows. - Require both the operation capability and client visibility at the backend boundary.
- Apply ownership and hierarchy invariants for team-management operations.
Role checks are reserved for invariants such as ownership and management hierarchy. Operational authorization should use capabilities plus client scope.
Write rules
- Team access writes are centralized in
org/access/*; client pages do not mutate assignment rows. - Selected client IDs must belong to the active organization before any synchronization occurs.
- No-op updates should not patch membership or assignment rows.
- A role change returns the member to role-default capabilities unless an explicit privileged flow says otherwise.
- Non-owners may not self-manage, manage peers or superiors, promote to their rank or above, or grant capabilities they do not possess.
- Invitation creation must reject an email that is already an active organization member.
- Membership, invite, role, and access-scope changes must remain auditable.
Migration compatibility
The storage value remains assigned; V1 changes its user-facing meaning to Selected clients without requiring a data migration. Existing all and assigned memberships therefore keep their effective behavior.