# Decision rules

> JSONLogic rules over check results decide approved, declined or review — or fall through to the default outcome.

Source: https://docs.okyc.stream/concepts/rules

After the applicant submits, checks run and the workflow's rules are evaluated. In the builder, open
**Decision rules** on the canvas: each rule has a condition and an outcome (**Approve**, **Decline**, **Review**
or **No effect**).

## Evaluation

1. Every rule is evaluated.
2. If any matching rule says `declined`, the session is declined.
3. Otherwise, if any says `review`, it goes to review.
4. Otherwise the workflow's **default outcome** applies (`approved` unless you change it).

A check that ends in `error` after its retries sends the session to review. Every rule that fired is stored with
the decision and shown in the dashboard.

## Conditions

Conditions are [JSONLogic](https://jsonlogic.com) over a normalised context:

| Variable                    | Example                                                                                         |
| --------------------------- | ----------------------------------------------------------------------------------------------- |
| `checks.<generic key>.*`    | `checks.tax_id.verify.status`, `checks.face.match.score`, `checks.screening.sanctions.hits`     |
| `checks.<country key>.*`    | `checks.in.pan.verify.*` — more detail, less portable                                           |
| `match.*`                   | `match.name.tax_id_vs_national_eid` — fuzzy name score 0–1; also `match.dob.*`, `match.address` |
| `applicant.*` / `session.*` | The normalised person, and session fields                                                       |

```json
[
  { "id": "r1", "if": { ">": [{ "var": "checks.screening.sanctions.hits" }, 0] }, "then": "review" },
  { "id": "r2", "if": { "<": [{ "var": "checks.face.match.score" }, 0.6] }, "then": "declined" },
  { "id": "r3", "if": { "!=": [{ "var": "checks.tax_id.verify.status" }, "passed"] }, "then": "declined" },
  { "id": "r4", "if": { "<": [{ "var": "match.name.tax_id_vs_national_eid" }, 0.85] }, "then": "review" }
]
```

Each rule may carry a `reason_code`, returned with the decision. The builder has a form for common conditions
and a **Condition JSON** editor for anything else.

## Cross-source matching

`match.name.<a>_vs_<b>` compares names from two sources with India-aware fuzzy matching (honorifics, initials,
token order, transliteration). `match.dob.*` is exact or year-only; `match.address` compares tokens and PIN
code. Document fields with `match_with` take part too, for example
`match.name.documents_vs_national_eid` (see [documents](https://docs.okyc.stream/concepts/documents.md)).
