Attributes
Access often depends on properties of the entities involved in addition to their roles and relationships, such as requiring an organization member to hold a sufficient security clearance to read a sensitive document. In Verdict, you store those properties as facts and compare them inside your rules.
Modeling property facts with has_attribute
Section titled “Modeling property facts with has_attribute”The has_attribute(entity, key, value) convention records an entity property as a three-term fact. You can specify concrete key strings in declare declarations to document the expected value type for each attribute key:
declare has_attribute(User, "clearance", int);declare has_attribute(Document, "required_clearance", int);
has_attribute(User:alice, "clearance", 3);has_attribute(Document:handbook, "required_clearance", 2);Dedicated predicates such as clearance_level(user, level) are also valid when a specific property is central to your domain vocabulary. Use has_attribute when multiple attributes benefit from a shared predicate and dot-syntax lookups.
Comparing attribute values and units
Section titled “Comparing attribute values and units”To compare an actor’s property against a resource’s threshold, match both facts and compare their values:
has_attribute(user, "clearance", user_level: int) andhas_attribute(document, "required_clearance", required_level: int) anduser_level >= required_levelBoth facts must be present for the comparison to succeed; missing facts never default to 0 or false. Because Verdict integers are signed 64-bit whole numbers, represent fractional or time-based domain quantities in a consistent integer base unit (such as cents for currency or epoch seconds for timestamps).
Combining attribute checks with relationships
Section titled “Combining attribute checks with relationships”Layer attribute comparisons onto relationship checks with and so that neither condition grants access on its own:
allow(user: User, "read", document: Document) if belongs_to(document, organization: Organization) and member(user, organization) and has_attribute(user, "clearance", user_level: int) and has_attribute(document, "required_clearance", required_level: int) and user_level >= required_level;- An organization member whose clearance is below
required_levelis denied. - An outside user with high clearance is denied because they do not belong to the document’s organization.
Writing a separate allow rule that checked clearance without belongs_to and member would create an independent grant path, allowing cleared users to read documents across every organization. See Combining conditions for how additive rules interact, and Permissions for applying resource-qualified guards across multiple access paths.
Reading attributes with dot syntax
Section titled “Reading attributes with dot syntax”Dot syntax (variable.attribute) is a concise shorthand for has_attribute lookups inside rule bodies:
meets_clearance_shorthand(user: User, document: Document) if user.clearance >= document.required_clearance;- Multivalued attributes: Each
variable.attributeexpression performs an independent lookup. When multiple comparisons must check the same attribute value (such as a numeric range), bind the value to a variable once; see Attribute access. - Single-valued updates: To overwrite an existing attribute value in Verdict Server, delete the old value and insert the new one atomically with
batchFacts. - Boolean flags vs. absence: See Negation and missing facts for when to use
not is_archived(document)versusdocument.archived = false.
Next steps
Section titled “Next steps”- Learn how dot syntax evaluates and how to bind shared values in Attribute access.
- Test clearance thresholds and relationship boundaries in Testing & Validating Policies.
- Synchronize and replace property facts from your backend in Managing Facts.