> For the complete documentation index, see [llms.txt](https://govplane.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://govplane.gitbook.io/docs/documentation/basic-concepts/conditional-rules.md).

# Conditional Rules

### Overview

Every rule supports an optional `when` clause — a condition AST evaluated client-side against the context you supply at call time. The server compiles and distributes the AST as part of the bundle; it never executes it.

Effect resolution:

```
when is absent          → always apply effect
when evaluates to true  → apply thenEffect   (fallback: effect)
when evaluates to false → apply elseEffect   (fallback: skip rule entirely)
```

### Rule shape

```ts
{
  id: string;
  status: "active" | "disabled";
  priority: number;
  target: { service: string; resource: string; action: string };

  when?:       ConditionAST;  // optional condition
  thenEffect?: Effect;        // applied when when == true  (defaults to effect)
  elseEffect?: Effect;        // applied when when == false (defaults to skip)
  effect:      Effect;        // unconditional / fallback effect
}
```

### Condition operators

#### Comparison — `eq`, `neq`, `gt`, `gte`, `lt`, `lte`

Compares the value at `path` in the evaluation context with a scalar `value`.

```json
{ "op": "eq",  "path": "role",  "value": "admin" }
{ "op": "neq", "path": "plan",  "value": "free" }
{ "op": "gte", "path": "amount","value": 1000 }
{ "op": "lt",  "path": "amount","value": 50 }
```

`value` may be string, number, boolean, or null.

#### Membership — `in`

True when the value at `path` equals one of the entries in `values`.

```json
{ "op": "in", "path": "role", "values": ["admin", "superuser", "moderator"] }
```

#### Existence — `exists`

True when the value at `path` is present and is not null or undefined.

```json
{ "op": "exists", "path": "requestTier" }
```

#### Logical — `and` / `or`

Short-circuit combinators over a non-empty `conditions` array.

```json
{
  "op": "and",
  "conditions": [
    { "op": "eq",     "path": "isAuthenticated", "value": true },
    { "op": "exists", "path": "plan" }
  ]
}
```

```json
{
  "op": "or",
  "conditions": [
    { "op": "eq", "path": "role", "value": "admin" },
    { "op": "eq", "path": "role", "value": "superuser" }
  ]
}
```

#### Negation — `not`

Inverts a single child condition.

```json
{
  "op": "not",
  "condition": { "op": "eq", "path": "role", "value": "banned" }
}
```

### `path` notation

`path` is a dot-separated key path resolved against the context object:

```ts
client.evaluate({
  target: { service: "api", resource: "export", action: "create" },
  context: {
    /* Example */
    role:   "editor",          // → "role"
    plan:   "enterprise",      // → "plan"
    amount: 250,               // → "amount"
  },
});
```

{% hint style="info" %}
The `ctx.` prefix is optional and stripped automatically. `ctx.plan` and `plan` are equivalent.
{% endhint %}

### Examples

#### Simple boolean flag

```json
{
  "id": "r_beta",
  "status": "active",
  "priority": 10,
  "target": { "service": "app", "resource": "feature/beta-dashboard", "action": "read" },
  "when":       { "op": "eq", "path": "isAuthenticated", "value": true },
  "thenEffect": { "type": "allow" },
  "elseEffect": { "type": "deny" },
  "effect":     { "type": "deny" }
}
```

#### Role-based access using `in`

```json
{
  "id": "r_admin_write",
  "status": "active",
  "priority": 5,
  "target": { "service": "control", "resource": "settings", "action": "write" },
  "when": {
    "op": "in",
    "path": "role",
    "values": ["admin", "superuser"]
  },
  "thenEffect": { "type": "allow" },
  "effect":     { "type": "deny" }
}
```

Evaluated with context `{ role: "viewer" }` → **deny** (elseEffect absent → rule skipped → falls to policy default or next rule).

Evaluated with context `{ role: "admin" }` → **allow**.

#### Plan-gated throttling

Free-plan users are throttled; paid users are allowed freely:

```json
{
  "id": "r_plan_throttle",
  "status": "active",
  "priority": 20,
  "target": { "service": "api", "resource": "export", "action": "create" },
  "when": { "op": "eq", "path": "plan", "value": "free" },
  "thenEffect": {
    "type": "throttle",
    "throttle": { "limit": 5, "windowSeconds": 3600, "key": "tenant" }
  },
  "elseEffect": { "type": "allow" },
  "effect":     { "type": "allow" }
}
```

#### Compound condition — nested `and` / `or`

```json
{
  "id": "r_report_export",
  "status": "active",
  "priority": 15,
  "target": { "service": "app", "resource": "report", "action": "export" },
  "when": {
    "op": "and",
    "conditions": [
      { "op": "eq", "path": "isAuthenticated", "value": true },
      {
        "op": "or",
        "conditions": [
          { "op": "eq", "path": "role", "value": "admin" },
          { "op": "eq", "path": "plan", "value": "enterprise" }
        ]
      }
    ]
  },
  "thenEffect": { "type": "allow" },
  "effect":     { "type": "deny" }
}
```

### Context at call time

```ts
client.evaluate({
  target: { service: "app", resource: "report", action: "export" },
  context: {
    isAuthenticated: true,
    role:            "admin",
    plan:            "pro",
  },
});
```

{% hint style="warning" %}
Only keys declared in your `ContextPolicy.allowedKeys` are permitted. Passing undeclared keys throws a validation error at evaluation time. See Context Policy.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://govplane.gitbook.io/docs/documentation/basic-concepts/conditional-rules.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
