-
Notifications
You must be signed in to change notification settings - Fork 0
04 Policy Language
rulegate.yaml is the human-readable source of authorization policy. RuleGate
loads the complete document, validates it, compiles it into typed policy
definitions, and activates it only when the entire candidate is valid.
schemaVersion: 1
application:
id: document-service
name: Document Service
policies:
- id: document-read
resourceType: document
action: read
requirement:
permission: DOC.READ| Member | Meaning |
|---|---|
schemaVersion |
Exact manifest schema; currently 1
|
application |
Stable application metadata |
policies |
Non-empty collection of policy definitions |
id |
Unique policy identifier used by tools and projections |
resourceType + action
|
Unique route selected by the engine |
requirement |
One built-in or logical requirement tree |
Every requirement may have an optional id. Add IDs to security-significant
leaves so tests and redacted diagnostics can identify them without exposing
values.
requirement:
all:
- id: approve-capability
permission: DOC.APPROVE
- id: approver-responsibility
role: DOCUMENT.APPROVERMatching is exact and case-sensitive. Empty or duplicate values in the runtime subject are normalized safely, but no wildcard or implicit hierarchy exists.
requirement:
all:
- any:
- permission: DOC.READ
- role: DOCUMENT.READER
- not:
role: DOCUMENT.BLOCKED| Operator | Meaning | Security behavior |
|---|---|---|
all |
Every child must be satisfied | One denied or indeterminate child denies |
any |
At least one child must be satisfied | Allows only after a satisfied child; indeterminate input cannot become allow by itself |
not |
Child must be conclusively not satisfied | Indeterminate stays indeterminate; missing data is not inverted into access |
Keep trees shallow enough to review. Manifest and runtime depth limits protect the application from unbounded input.
Read an attribute from subject, resource, or context and compare it to a
typed literal:
requirement:
attribute:
source: resource
name: status
operator: in
valueType: stringCollection
value: [draft, returned]| Family | Operators | Typical use |
|---|---|---|
| Equality |
equal, notEqual
|
status, organization, boolean flags |
| Ordering |
greaterThan, greaterThanOrEqual, lessThan, lessThanOrEqual
|
limits, classification, dates |
| String |
contains, startsWith, endsWith
|
normalized domains or prefixes |
| Collection |
contains, containsAny, containsAll, intersects
|
groups, labels, regions |
| Membership |
in, notIn
|
scalar in an approved/blocked set |
| Presence |
exists, notExists
|
whether a key was supplied |
| Null |
isNull, isNotNull
|
present explicit null state |
| Empty |
isEmpty, isNotEmpty
|
present collection state |
| Token | Runtime type |
|---|---|
string |
string |
boolean |
bool |
number |
integer or invariant decimal normalized as a number |
dateTimeOffset |
ISO 8601 value with Z or a numeric offset |
nullValue |
explicit null literal |
stringCollection |
homogeneous strings |
booleanCollection |
homogeneous booleans |
numberCollection |
homogeneous numbers |
dateTimeOffsetCollection |
homogeneous date/time values |
Not every operator accepts every type. For example, boolean ordering is invalid, and collection operations require compatible element kinds. The CLI rejects incompatible combinations.
String matching is ordinal and case-sensitive by default:
attribute:
source: subject
name: department
operator: startsWith
stringComparison: ordinalIgnoreCase
valueType: string
value: operationsUse ordinalIgnoreCase only when the business identifier is intentionally
case-insensitive. Do not use culture-sensitive display text as a security
identifier.
| Runtime state | exists |
notExists |
isNull |
isNotNull |
isEmpty |
|---|---|---|---|---|---|
| Key absent | no | yes | no | no | no |
| Key present with null | yes | no | yes | no | no |
| Empty collection | yes | no | no | yes | yes |
| Non-empty value | yes | no | no | yes | depends on kind |
Missing data never becomes implicit null. Use the operator that represents the domain state you actually intend.
Compare trusted values from two sources:
requirement:
all:
- attributeComparison:
left:
source: subject
name: organizationId
operator: equal
right:
source: resource
name: organizationId
- attributeComparison:
left:
source: subject
name: clearanceLevel
operator: greaterThanOrEqual
right:
source: resource
name: classificationLevelAn operand can be an attribute or a literal. This example caps an amount:
attributeComparison:
left:
source: resource
name: totalAmount
operator: lessThanOrEqual
right:
valueType: number
value: 50000Both values must have compatible types. Missing or incompatible values deny.
Canonical context properties give common request facts stable names:
requirement:
all:
- context:
property: networkZone
operator: in
valueType: stringCollection
value: [internal, vpn]
- context:
property: requestChannel
operator: equal
valueType: string
value: web
- context:
property: trustedDevice
operator: equal
valueType: boolean
value: trueCanonical properties include authentication method, request channel, network zone, tenant ID, organization ID, trusted device, and identity type. The application must still provide trustworthy values.
Use a normal attribute with source: context for application-specific facts
such as a validated risk score or correlation category.
requirement:
all:
- contextAge:
timestamp: authentication
maximumAge: '08:00:00'
- contextAge:
timestamp: mfa
maximumAge: '00:15:00'authentication reads the canonical authentication timestamp. mfa reads
the multi-factor timestamp. A missing, future, malformed, or too-old timestamp
does not satisfy the requirement.
timeWindow:
days: [monday, tuesday, wednesday, thursday, friday]
start: '08:00'
end: '18:00'
timeZone: Europe/IstanbulRuleGate converts the trusted evaluation time into the named time zone. Use
exact HH:mm values and lowercase day tokens. Overnight windows are supported
by the defined time semantics; test boundary instants, daylight-saving
transitions, and the host's available time-zone database.
An organization-specific schedule should not be hard-coded into a shared policy when every organization differs. A context provider can resolve the current organization's schedule into trusted attributes, or applications can maintain separate policy routes/snapshots when that is the clearer model.
dateTimeWindow:
startsAt: '2026-09-01T00:00:00Z'
endsAt: '2026-10-01T00:00:00Z'Use this for a release, campaign, emergency exception, or migration interval with fixed absolute boundaries. Always include a UTC marker or numeric offset.
schemaVersion: 1
application:
id: document-approval
name: Document Approval
policies:
- id: document-approve
resourceType: document
action: approve
requirement:
id: complete-approval-rule
all:
- permission: DOC.APPROVE
- role: DOCUMENT.APPROVER
- attribute:
source: resource
name: status
operator: equal
valueType: string
value: submitted
- attributeComparison:
left: { source: subject, name: organizationId }
operator: equal
right: { source: resource, name: organizationId }
- attributeComparison:
left: { source: resource, name: totalAmount }
operator: lessThanOrEqual
right: { source: subject, name: approvalLimit }
- not:
attributeComparison:
left: { source: subject, name: userId }
operator: equal
right: { source: resource, name: ownerId }
- context:
property: networkZone
operator: in
valueType: stringCollection
value: [internal, vpn]
- context:
property: trustedDevice
operator: equal
valueType: boolean
value: true
- contextAge:
timestamp: mfa
maximumAge: '00:15:00'
- timeWindow:
days: [monday, tuesday, wednesday, thursday, friday]
start: '08:00'
end: '18:00'
timeZone: Europe/IstanbulThe manifest states the rule. The host is responsible for supplying every referenced value from the correct trusted source.
rulegate validate rulegate.yaml
rulegate lint rulegate.yaml
rulegate test authorization.tests.yamlValidation proves structural correctness. Linting finds maintainability risks. Policy tests prove behavior for explicit subjects, resources, context, and times. None of these replaces endpoint integration tests.
Previous: First protected API · Next: ASP.NET Core integration
Canonical source: docs/guide · Documentation index · RuleGate 1.0.0
- Home
- 1. Authorization foundations
- 2. Packages and installation
- 3. First protected API
- 4. Policy language
- 5. ASP.NET Core integration
- 6. Trusted attributes and context
- 7. Identity and Keycloak
- 8. Frontend integration
- 9. CLI and policy lifecycle
- 10. Testing and diagnostics
- 11. Policy sources and reload
- 12. Extensibility
- 13. Real-world recipes
- 14. Production checklist
- Glossary