Combining & Testing Rules
Once you know how single-condition allow rules work (Policy Fundamentals), you can combine conditions inside rule bodies, chain reusable helper predicates, and verify your policy locally with inline tests.
Joining conditions with and
Section titled “Joining conditions with and”Use and when multiple conditions must hold at the same time. Repeating a variable name across conditions requires every occurrence to match the same value:
declare belongs_to(Document, Organization);declare has_role(User, string, Organization);
allow(user: User, "read", document: Document) if belongs_to(document, org: Organization) and has_role(user, "member", org);Here, org links the two conditions: the Organization that document belongs to must be the same Organization where user holds the "member" role.
Multiple paths and helper predicates
Section titled “Multiple paths and helper predicates”When there are multiple ways to qualify for access, write separate rules with the same head predicate (or combine conditions with or). Each rule provides an independent path for the conclusion to hold.
Rule heads do not have to be allow. You can define helper predicates such as has_permission to collect role and relationship grants before forwarding them to allow:
declare is_owner(User, Document);declare belongs_to(Document, Organization);declare has_role(User, string, Organization);
// Owners can read and edithas_permission(user: User, "read", document: Document) if is_owner(user, document);
has_permission(user: User, "edit", document: Document) if is_owner(user, document);
// Organization members can read documents in their organizationhas_permission(user: User, "read", document: Document) if belongs_to(document, org: Organization) and has_role(user, "member", org);
allow(actor, action, resource) if has_permission(actor, action, resource);Negation and comparisons
Section titled “Negation and comparisons”Use not to require that a disqualifying fact or derivation is absent, and comparison operators (=, !=, <, <=, >, >=) to check term values:
declare is_owner(User, Document);declare is_archived(Document);declare clearance_level(User, int);declare required_clearance(Document, int);
// Owners can edit a document only when it is not archivedallow(user: User, "edit", document: Document) if is_owner(user, document) and not is_archived(document);
// Users can read a document when their clearance meets its requirementallow(user: User, "read", document: Document) if clearance_level(user, user_level: int) and required_clearance(document, doc_level: int) and user_level >= doc_level;See Negation and missing facts for how not evaluates missing data versus explicit false values, and Attribute access for dot-syntax lookups (user.clearance >= document.required_clearance).
Testing rules in policy
Section titled “Testing rules in policy”Because a .vd policy is self-contained, you can verify your rules without starting a database or application server. Add test blocks directly to your .vd file with temporary fixture facts and assert / assert not checks:
test "organization members and owners can access unarchived documents" { belongs_to(Document:handbook, Organization:acme); has_role(User:alice, "member", Organization:acme); is_owner(User:bob, Document:handbook);
assert allow(User:alice, "read", Document:handbook); assert not allow(User:alice, "edit", Document:handbook); assert allow(User:bob, "edit", Document:handbook);}
test "archived documents cannot be edited" { is_owner(User:bob, Document:handbook); is_archived(Document:handbook);
assert not allow(User:bob, "edit", Document:handbook);}Run verdict test from the CLI to execute all test blocks in a policy file:
verdict test policy.vdFacts inside a test block are isolated to that test and are excluded when you publish the policy.
Next steps
Section titled “Next steps”- Connect your backend to Verdict Server in Integrate with Verdict Server.
- Explore common access control patterns in Designing Policies and Permissions.
- Learn more about validation and boundary testing in Testing & Validating Policies.