Agent Wranglers

Roles and permissions Recommended

Start with roles and add record rules only when needed

Start with a few roles per organisation. Add conditions on the record only for rules that need them, such as "only the author may edit a draft".

How to do it

Role-based access control (RBAC) gives each member one role. Four roles cover most products, such as owner, admin, member and viewer. Attribute-based access control (ABAC) adds conditions on the user, the record or the time. Relationship-based control, as in Google's Zanzibar paper, follows links such as "member of this folder's team". Keep every condition inside the policy module, never in route handlers. Move to a policy engine, such as OPA, Cedar, Casbin or OpenFGA, when the rules outgrow one file.

Example

const RECORD_RULES = {
  'draft.edit': (user, membership, draft) => draft.authorId === user.id || can(membership, 'draft.edit_any'),
};

export const canOnRecord = (user, membership, permission, record) =>
  can(membership, permission) && (RECORD_RULES[permission]?.(user, membership, record) ?? true);
RECORD_RULES = {
    "draft.edit": lambda user, membership, draft: draft.author_id == user.id or can(membership, "draft.edit_any"),
}

def can_on_record(user, membership, permission: str, record) -> bool:
    rule = RECORD_RULES.get(permission)
    return can(membership, permission) and (rule is None or rule(user, membership, record))

How to check

Each organisation has at most 6 roles, or a written reason for more. A search finds conditions on record fields only inside the policy module.

For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers accounts playbook: https://agentwranglers.se/playbook/accounts/roles-and-permissions/rbac-then-abac.