> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hopae.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Workflow Conditions

> Reference for writing conditions used in IF and EVALUATE nodes.

`IF` and `EVALUATE` nodes use **conditions** to make decisions based on the verification output. This page explains the condition syntax and how to reference data fields.

## Input Data

Conditions evaluate against the **userinfo** object returned by the `VERIFICATION` node. This data is wrapped under the `input` key, so all field references start with `input.`.

### Example userinfo structure

```json theme={null}
{
  "sub": "ooKdYHyhGFRADJYXU2mlmL-hgJWsjNu4",
  "amr": ["smartid"],
  "missing_claims": [],
  "user": {
    "birthdate": "1905-04-04",
    "name": "OK TESTNUMBER",
    "given_name": "OK",
    "family_name": "TESTNUMBER",
    "nationality": "LT",
    "personal_code": "PNOLT-40504040001-MOCK-Q"
  },
  "provenance": {
    "presentation": {
      "channel": {
        "type": "centralized_idp",
        "transport": "internet"
      },
      "credentials": [
        {
          "type": "smartid",
          "issuer": {
            "id": "urn:hopae:issuer:ee:smartid",
            "authority_name": "SK ID Solutions AS",
            "is_government": false
          },
          "claims": {
            "name": "OK TESTNUMBER",
            "birthdate": "1905-04-04"
          }
        }
      ]
    },
    "_metadata": {
      "verification_id": "e668e763ab114a61aa3c9ccd89788139",
      "verified_at": "2026-01-23T10:13:52.807Z",
      "status": "completed"
    }
  }
}
```

## Dot Notation

Fields are referenced using **dot notation**. Array elements are accessed by their numeric index (zero-based).

| Expression                                                         | Resolved value                 |
| ------------------------------------------------------------------ | ------------------------------ |
| `input.sub`                                                        | `"ooKdYHyhGFRADJYXU2mlmL-..."` |
| `input.amr.0`                                                      | `"smartid"`                    |
| `input.user.nationality`                                           | `"LT"`                         |
| `input.user.birthdate`                                             | `"1905-04-04"`                 |
| `input.provenance.presentation.channel.type`                       | `"centralized_idp"`            |
| `input.provenance.presentation.credentials.0.type`                 | `"smartid"`                    |
| `input.provenance.presentation.credentials.0.issuer.is_government` | `false`                        |

## Condition Rule

A single condition rule compares a field value against a target value.

```json theme={null}
{
  "field": "input.amr.0",
  "operator": "eq",
  "value": "smartid"
}
```

### Fields

| Field      | Type                          | Description                                                  |
| ---------- | ----------------------------- | ------------------------------------------------------------ |
| `field`    | `string`                      | Dot-notation path to the value (always starts with `input.`) |
| `operator` | `string`                      | Comparison operator (see below)                              |
| `value`    | `string \| number \| boolean` | Target value to compare against                              |

### Operators

| Operator     | Description                     | Example                               |
| ------------ | ------------------------------- | ------------------------------------- |
| `eq`         | Equals                          | `input.user.nationality` eq `"LT"`    |
| `neq`        | Not equals                      | `input.amr.0` neq `"password"`        |
| `gt`         | Greater than (numeric)          | `input.loa` gt `2`                    |
| `gte`        | Greater than or equal (numeric) | `input.loa` gte `3`                   |
| `lt`         | Less than (numeric)             | `input.loa` lt `4`                    |
| `lte`        | Less than or equal (numeric)    | `input.loa` lte `3`                   |
| `exists`     | Field exists and is not null    | `input.user.email` exists             |
| `not_exists` | Field is missing or null        | `input.user.phone_number` not\_exists |

<Info>
  For `exists` and `not_exists` operators, the `value` field is ignored but still required in the JSON structure.
</Info>

## Condition Group

Rules can be combined using `and` / `or` combinators. Nesting is supported for complex logic.

```json theme={null}
{
  "combinator": "and",
  "rules": [
    { "field": "input.amr.0", "operator": "eq", "value": "smartid" },
    { "field": "input.user.nationality", "operator": "eq", "value": "LT" }
  ]
}
```

### Nested conditions

Groups can be nested for expressions like `(A AND B) OR (C AND D)`:

```json theme={null}
{
  "combinator": "or",
  "rules": [
    {
      "combinator": "and",
      "rules": [
        { "field": "input.amr.0", "operator": "eq", "value": "smartid" },
        { "field": "input.user.nationality", "operator": "eq", "value": "LT" }
      ]
    },
    {
      "combinator": "and",
      "rules": [
        { "field": "input.amr.0", "operator": "eq", "value": "bankidse" },
        { "field": "input.user.nationality", "operator": "eq", "value": "SE" }
      ]
    }
  ]
}
```

## Using Conditions in Nodes

### EVALUATE node

Evaluates the condition and stores the boolean result in a named field under `computed`.

```json theme={null}
{
  "id": "nd_eval",
  "type": "evaluate",
  "next": "nd_resp",
  "config": {
    "outputField": "is_lithuanian",
    "conditions": {
      "combinator": "and",
      "rules": [
        { "field": "input.user.nationality", "operator": "eq", "value": "LT" }
      ]
    }
  }
}
```

After execution, the userinfo will contain `computed.is_lithuanian: true` (or `false`).

### IF node

Routes the flow based on condition evaluation. Uses `next` as an array of routes:

```json theme={null}
{
  "id": "nd_if",
  "type": "if",
  "next": [
    {
      "when": {
        "combinator": "and",
        "rules": [
          { "field": "input.amr.0", "operator": "eq", "value": "smartid" }
        ]
      },
      "nextNodeId": "nd_smartid_path"
    },
    {
      "when": null,
      "nextNodeId": "nd_default_path"
    }
  ]
}
```

<Info>
  The route with `"when": null` is the **default (fallback) route**, used when no other condition matches. Always include a default route to prevent the workflow from terminating unexpectedly.
</Info>

## Common Patterns

### Check which provider was used

```json theme={null}
{ "field": "input.amr.0", "operator": "eq", "value": "bankidse" }
```

### Check if a claim exists

```json theme={null}
{ "field": "input.user.email", "operator": "exists", "value": true }
```

### Check nationality

```json theme={null}
{ "field": "input.user.nationality", "operator": "eq", "value": "SE" }
```

### Check if government-issued credential

```json theme={null}
{ "field": "input.provenance.presentation.credentials.0.issuer.is_government", "operator": "eq", "value": true }
```
