policies overview
When and why to use ABAC policies — time, IP, attribute, and dynamic deny rules that go beyond what RBAC roles can express.
When to Use Policies
Roles cover the common case: "editors can update posts." Some requirements need more than roles can express:
- Time-based restrictions — deny writes on weekends or outside business hours
- IP/geo-fencing — allow access only from trusted networks
- Cross-attribute checks — allow updates only when subject and resource share a department
- Dynamic deny rules — block specific users or flag suspicious behavior without changing role assignments
- Maintenance mode — deny all writes globally when a feature flag is on
ABAC policies share the role evaluation pipeline. The engine AND-combines policies — a deny from any policy is final.
Reading order
Each topic has its own page:
| Page | Covers |
|---|---|
| building policies | policy() builder, defineRule(), wildcards, hierarchical resources |
| rules | Rule structure, effect, priority, scopes, metadata |
| conditions | The When builder — operators, semantic shortcuts, field paths |
$-variable references | Compare two fields on the same request via $subject.id etc. |
| nesting and/or/not | Compose AND/OR/NOT groups, whenAny(), depth limit |
| policy targets | Pre-filter policies by action, resource, or role |
| combining algorithms | deny-overrides, allow-overrides, first-match, highest-priority |
| layered example | Full RBAC + ABAC example, evaluation walkthrough |
Quick example
import { policy } from '@gentleduck/iam'
const weekendDeny = policy('deny-weekends')
.name('Deny on Weekends')
.desc('Block all write operations on weekends')
.version(1)
.algorithm('deny-overrides')
.rule('r-deny-weekends', (r) =>
r
.deny()
.on('create', 'update', 'delete')
.of('*')
.when((w) => w.env('dayOfWeek', 'in', [0, 6])),
)
.build()import { policy } from '@gentleduck/iam'
const weekendDeny = policy('deny-weekends')
.name('Deny on Weekends')
.desc('Block all write operations on weekends')
.version(1)
.algorithm('deny-overrides')
.rule('r-deny-weekends', (r) =>
r
.deny()
.on('create', 'update', 'delete')
.of('*')
.when((w) => w.env('dayOfWeek', 'in', [0, 6])),
)
.build()This policy:
- Has algorithm
deny-overrides(any deny rule that matches → policy returns deny) - Targets writes only (not reads)
- Uses
env('dayOfWeek', 'in', [0, 6])— Sunday or Saturday → deny