Policies and Access
Policy workflows add dynamic access rules to Brezel queries. They are powerful because they can restrict records by role, relation, current user, or operation.
Basic policy shape
Section titled “Basic policy shape”A policy workflow starts with event/policy and usually continues into query/where.
{ "identifier": "ProjectAccessPolicy", "title": "Project access policy", "async": false, "entry": "projectPolicy", "elements": [ { "name": "projectPolicy", "type": "event/policy", "options": { "module": "projects", "roles": ["employee"], "operations": ["read", "update"], "allow": ["admin", "manager"], "roleKey": "slug" }, "to": { "default": { "whereAssigned": ["default"] } } }, { "name": "whereAssigned", "type": "query/where", "options": { "where": [ [ { "left": { "type": "field", "value": "assigned_users.id" }, "operator": "=", "right": { "type": "recipe", "value": "user().id" } } ] ] } } ], "events": [ { "identifier": "projectPolicy", "type": "policy", "module": "projects", "roles": ["employee"], "operations": ["read", "update"], "allow": ["admin", "manager"], "roleKey": "slug" } ]}Users with admin or manager are allowed by the policy configuration. Users with employee receive the additional query constraint.
Read, update, delete
Section titled “Read, update, delete”Policies can target multiple operations, but the safest policy is often operation-specific. Reading a record and deleting a record can require different constraints.
Use separate entry elements when the logic differs:
projectReadPolicyprojectUpdatePolicyprojectDeletePolicy
This keeps each query path short and auditable.
Customer or external access
Section titled “Customer or external access”For customer-facing roles, filter by a relation to the current user instead of trusting request data.
{ "name": "whereOwnCustomer", "type": "query/where", "options": { "where": [ [ { "left": { "type": "field", "value": "customer.id" }, "operator": "IN", "right": { "type": "recipe", "value": "user().customers[*].id" } } ] ] }}Never grant access based only on IDs submitted by the browser.
Policy checklist
Section titled “Policy checklist”- The policy is synchronous.
- The module, roles, and operations are explicit.
- Privileged roles are listed in
allow. - Non-privileged roles receive a
query/whereconstraint. - The constraint is based on
user()or trusted relations, not request input. - Read/update/delete behavior is tested separately when the rules differ.
- Denied users see no records rather than records with hidden fields.