---
title: "Configure dynamic access rules"
source: "https://docs.vertesiahq.com/security/dynamic-rules"
markdown: "https://docs.vertesiahq.com/llms/security/dynamic-rules.md"
---

# Configure dynamic access rules

Dynamic access rules grant content access based on principal and resource attributes. They are useful when identity
lists would be too large or when the same policy should follow organizational properties such as department,
clearance, region, or customer assignment.

## Before you start

- Configure the required [principal attributes](/security/principal-attributes).
- Configure resource fields as described in [Content security](/security/content-security).
- Decide whether the rule protects **documents**, **collections**, or both.
- Use an organization administrator account to create or modify access-control entries.

Dynamic rules grant access; they do not express explicit denies. Separate rules are additive, so a broad wildcard rule
can make a narrower rule ineffective as a restriction.

## Create a rule in Studio

1. Open **Project Settings → Permissions**.
2. Select **New**.
3. Under **Who**, choose one of:
   - **User / Group / API Key** for a fixed principal.
   - **Principal Set** to match principals by attributes.
4. If using a Principal Set, enter a descriptive name and its conditions.
5. Choose the content role:
   - `content:reader` — read matching resources.
   - `content:writer` — read and write matching resources.
   - `content:manager` — read, write, and delete matching resources.
6. Under **Target Resource**, choose **Resource Set**.
7. Select **Document** or **Collection** scope.
8. Enter a descriptive Resource Set name and its conditions.
9. Create the permission, refresh the test principal's token, and verify the result.

## Example: clearance-based document access

This rule allows every principal to read documents at or below the principal's clearance:

| Setting | Value |
| --- | --- |
| Principal | Principal Set named `All principals` |
| Principal conditions | `{}` |
| Role | `content:reader` |
| Scope | `document` |
| Resource Set | `Documents within clearance` |
| Resource conditions | `{ "sensitivity": { "$lte": "$principal.clearance" } }` |

Add a compartment requirement to require both conditions:

```json
{
    "sensitivity": { "$lte": "$principal.clearance" },
    "compartments": { "$in": "$principal.compartments" }
}
```

Conditions within this object use AND semantics: both sensitivity and compartment checks must match.

## Example: department isolation

Match Legal users to Legal documents:

**Principal conditions**

```json
{
    "properties.department": { "$eq": "legal" }
}
```

**Resource conditions**

```json
{
    "properties.department": { "$eq": "legal" }
}
```

For policies that compare the resource to each principal dynamically, use a principal reference:

```json
{
    "properties.department": { "$eq": "$principal.properties.department" }
}
```

## Restrict and open presets

The **Restrict Mode** preset creates a wildcard Principal Set and a deliberately non-matching Resource Set. Every
matching principal receives an ABAC condition, which removes the blanket `project:*` grant for document reads; real
granting rules then add back the intended access.

Safe rollout order:

1. Create and test the real granting rules.
2. Apply **Restrict Mode** to the intended principal population.
3. Refresh test tokens and verify allowed and denied cases.
4. Expand the rollout only after the test policy behaves correctly.

The **Open Mode** preset creates a wildcard principal and wildcard resource rule. It grants read access to all
documents through the dynamic policy system. Because grants are additive, leave this rule in place only when broad
read access is intentional.

An empty Principal Set matches users and API keys. To target only one kind, add `kind = user` or `kind = apikey`.

## Document and collection scope

Scopes are isolated:

- A document rule controls content objects and document searches.
- A collection rule controls collection lists and individual collections.

If users must see a collection and its documents under the same policy, create one rule in each scope. The roles may
be the same, but each rule has its own scope.

## Condition operators

| Operator | Meaning | Example |
| --- | --- | --- |
| `$eq`, `$ne` | Equality or inequality | `{ "properties.region": { "$eq": "eu" } }` |
| `$gt`, `$gte`, `$lt`, `$lte` | Numeric comparison | `{ "sensitivity": { "$lte": 2 } }` |
| `$in`, `$nin` | Membership comparison | `{ "compartments": { "$in": ["legal"] } }` |
| `$exists` | Field presence | `{ "properties.customer": { "$exists": true } }` |
| `$empty` | Missing, null, empty string, or empty array | `{ "compartments": { "$empty": true } }` |
| `$like` | Case-insensitive `*` wildcard matching | `{ "email": { "$like": "*@example.com" } }` |

`$like` is for Principal Set evaluation. Avoid numeric range conditions on custom `properties.*` fields used in
search; use root-level numeric fields such as `sensitivity` instead.

## Test a proposed rule with Studio Assistant

Studio Assistant can dry-run one Resource Set rule before you save it. Provide:

- the document or collection scope and requested operation;
- the proposed content role and principal/resource conditions;
- a representative principal context;
- sample objects with the fields used by the rule.

For example, ask: “Test whether a user with clearance 3 and the `finance` compartment can read these three sample
documents through this proposed rule.” The assistant reports every check for every sample and shows the resolved
`$principal.*` values.

The test is deliberately rule-local. It does not include other access-control entries, direct document or collection
grants, project defaults, or administrator bypasses. Use it to validate rule logic, then test the saved policy with a
fresh real token before rollout.

## Verify a rule

Test at least these cases after issuing fresh tokens:

- a principal that should match the Principal Set;
- a principal that should not match;
- a classified resource that should match;
- a classified resource that should not match;
- an unclassified resource;
- a direct user or group grant, if direct grants coexist with ABAC;
- both document and collection navigation when both scopes are used.

If a principal unexpectedly sees everything, look for a wildcard Resource Set or another broad rule. If a principal
sees nothing, verify the Principal Set, scope, content role, resource paths, and refreshed token.