Policy Authoring with DSL
Goal
Write policy expressions using the FQL expression language for ABAC and RADAC policies, and JavaScript for Dynamic policies. After completing this guide, you can construct conditions using the available context objects, operators, and value types, and apply common expression patterns to real authorization scenarios.
Audience
Developers writing policy conditions directly in the code editor who need to understand the expression syntax and available context.
Prerequisites
- Familiarity with the FQL code editor — this guide focuses on the language, not the editor
- Understanding of the policy types where expressions are used (ABAC, RADAC, Dynamic)
Before You Start
Three policy types use expression-based authoring:
| Policy Type | Language | Purpose |
|---|---|---|
| ABAC | FQL | Attribute-based conditions (declarative) |
| RADAC | FQL | Risk-adaptive conditions (declarative) |
| Dynamic | JavaScript | Custom evaluation logic (imperative) |
FQL expressions are declarative — they describe the condition that must be true for access to be granted. Dynamic policy scripts are imperative — they execute logic and call grant() or deny() explicitly.
Worked Example
In this guide, you write three expressions:
- An ABAC condition that restricts access by department and role
- A RADAC condition that combines risk score with location checks
- A Dynamic script that implements time-based access with custom logic
Steps
1. FQL expression basics
An FQL expression is a boolean condition built from field references, operators, and values.
Structure: field operator value
user.role == 'editor'
Compound expressions: Combine multiple conditions with logical operators.
user.role == 'editor' && resource.department == user.department
Grouping: Use parentheses to control evaluation order.
(user.role == 'admin' || user.role == 'manager') && context.time >= 900
2. Context objects and field access
FQL provides six context objects. Access their properties with dot notation.
| Object | Description | Example Fields |
|---|---|---|
user | Requesting user attributes | user.role, user.department, user.title, user.level |
resource | Target resource attributes | resource.type, resource.owner, resource.department |
token | Access token claims | token.aud, token.scope, token.exp |
context | Request context | context.ip, context.time, context.location |
org | Organization attributes | org.settings.isActive, org.name |
tenant | Tenant attributes | tenant.name, tenant.plan |
The available fields for each object depend on your configured policy vocabulary. The editor's Fields panel shows all available fields — see Policy DSL Tooling for details.
3. Comparison operators
| Operator | Meaning | Example |
|---|---|---|
== | Equal to | user.role == 'admin' |
!= | Not equal to | resource.status != 'archived' |
> | Greater than | user.level > 2 |
< | Less than | context.time < 1700 |
>= | Greater than or equal | user.level >= 3 |
<= | Less than or equal | token.exp <= 7200 |
contains | Contains value | user.groups contains 'engineering' |
4. Logical operators
| Operator | Meaning | Behavior |
|---|---|---|
&& | AND | Both conditions must be true |
|| | OR | At least one condition must be true |
! | NOT | Negates the condition |
Evaluation order: && binds tighter than ||. Use parentheses when the default order does not match your intent.
user.role == 'admin' || user.role == 'manager' && context.time >= 900
This evaluates as: admin OR (manager AND time >= 900). To require time for both roles:
(user.role == 'admin' || user.role == 'manager') && context.time >= 900
5. Value types
| Type | Syntax | Examples |
|---|---|---|
| String | Single or double quotes | 'admin', "editor" |
| Number | Integer or decimal | 900, 3.14 |
| Boolean | Unquoted keywords | true, false |
Do not mix quote styles in a single value. 'admin" produces an unclosed quote validation error.
6. Common ABAC patterns
Role-based restriction:
user.role == 'manager'
Department-scoped access:
resource.department == user.department
Multi-condition access:
user.role == 'editor' && resource.status != 'archived' && user.department == resource.department
Alternative roles:
user.role == 'admin' || user.role == 'superadmin'
Grouped conditions with fallback:
(user.role == 'manager' && user.department == resource.department) || user.role == 'admin'
7. Common RADAC patterns
RADAC expressions evaluate risk signals alongside access conditions.
Risk score range:
risk.score >= 0 && risk.score <= 5
Risk score with location exclusion:
risk.score >= 0 && risk.score <= 7 && context.location NOT IN ('restricted-zone')
Combined risk and attribute check:
risk.score <= 3 && user.role == 'admin'
8. Dynamic policy scripts (JavaScript)
Dynamic policies use JavaScript for custom evaluation logic. Your script has access to context objects and calls grant() or deny() to return the access decision.
Available objects:
| Object | Properties |
|---|---|
user | id, title, department, role |
resource | id, type, owner |
token | aud, scope, exp |
context | ip, time, location |
Decision functions:
| Function | Purpose |
|---|---|
grant() | Allow access |
deny() | Deny access |
Example — role and resource type check:
if (user.role === 'manager' && resource.type === 'report') {
grant();
} else {
deny();
}
Example — time-based access:
if (context.time >= 900 && context.time <= 1700) {
grant();
} else {
deny();
}
Example — combined conditions:
if (user.department === resource.department && user.role === 'editor') {
grant();
} else if (user.role === 'admin') {
grant();
} else {
deny();
}
Dynamic policy scripts run in a limited sandbox environment. Every script must include at least one grant() or deny() call. Scripts without a decision function fail validation.
9. Expression validation rules
Both FQL and JavaScript editors validate expressions in real time. Common validation errors:
| Error | Cause | Fix |
|---|---|---|
| Mismatched parentheses | Unbalanced ( and ) | Add the missing parenthesis |
| Unknown vocabulary | Field path not in vocabulary | Check the Fields panel for correct paths |
| Incomplete expression | Field without an operator | Add a comparison operator and value |
| Invalid operator | Unsupported operator (for example, ===) | Use == instead |
| Unclosed quote | Missing closing ' or " | Add the matching quote character |
Validation Scenario
Scenario
You write an ABAC expression with two conditions and a logical AND, then verify the expression validates and the policy saves.
Expected Result
- The FQL editor shows no validation errors
- The policy is created with the expression stored
- Reopening the policy in expression mode shows the saved expression
How to Verify
- UI evidence: Open the policy in the Admin Console, enable expression mode, and verify the expression text
- API evidence: Query the policies endpoint and verify the
expressionfield matches - Logs: Check the browser network tab for a successful mutation response
Troubleshooting
- Validation fails with "Unknown vocabulary" — The field path does not match any configured vocabulary item. Use the Fields panel in the editor to find the correct path. The editor may suggest similar field names as quick fixes.
- JavaScript validation fails with "Missing grant/deny" — Every Dynamic policy script must call
grant()ordeny()in at least one code path. - Expression works in editor but policy evaluation fails — The expression syntax is correct but the vocabulary field values do not match the runtime data. Verify that the attribute values in your expression match the actual values provided by the authorization context at evaluation time.
Next Steps
To use the editor's productivity features (auto-completion, formatting, field browser), see Policy DSL Tooling. To build conditions visually without writing expressions, see GUI-Based Policy Authoring.
Related Docs
Policy DSL Tooling
FQL code editor features: auto-completion, validation, and formatting.
GUI-Based Policy Authoring
Visual Expression Builder for drag-and-drop condition building.
Policy Management
Complete policy CRUD operations including all six policy types.
Attribute Management
Configure the policy vocabulary used by expressions.