Policy rules · Policy rules
Composite — admin OR (manager AND finance)
A nested rule combining `any`, `all`, and equality leaves. Demonstrates arbitrary nesting and short-circuit evaluation.
- gate
- role-based
- composite
Tested against:policyEngine: 1.0.0
Use case
Either: the user is a global admin, OR the user is a manager and in the finance department. Express this as any of two children, the second of which is itself an all.
Rule
{
"any": [
{ "fact": "role", "operator": "equal", "value": "admin" },
{
"all": [
{ "fact": "role", "operator": "equal", "value": "manager" },
{ "fact": "department", "operator": "equal", "value": "finance" }
]
}
]
}Facts shape
data class OrgFacts(val role: String, val department: String)Short-circuit behaviour
any short-circuits on the first child that returns pass. So if the user is admin, the all block is never evaluated. This matters when child evaluations have a non-trivial cost (fact gathering, IO).
Trace — ALLOW (manager + finance)
{
"decision": "ALLOW",
"trace": [
{ "any": [
{ "fact": "role", "operator": "equal", "value": "admin", "actual": "manager", "result": "fail" },
{ "all": [
{ "fact": "role", "operator": "equal", "value": "manager", "actual": "manager", "result": "pass" },
{ "fact": "department", "operator": "equal", "value": "finance", "actual": "finance", "result": "pass" }
],
"result": "pass"
}
],
"result": "pass"
}
]
}When to use
- Composite RBAC where one branch is broad (
admin) and the other is narrow (managerANDdepartment) - Audit reviewers want a single rule per surface, not 5 rules with overlapping logic
When not to use
- The same logic can be expressed as a flat
any/all— flat is easier to reason about