# Playbook Rules

Footprint’s rules engine enables you to customize user onboarding decisioning to fit your business’s risk model.

When you create a playbook from a template, rules nodes are preloaded with a default set of rules. Businesses may find this default set of rules sufficient, or they may choose to customize the onboarding flow using the Footprint rules editor.

## Rule evaluation

Rules enable businesses to express custom logic for risk decisioning or data collection. For example, rules can be used for each of the following:

* Assign final user statuses based on different risk signals.
* Split an onboarding flow based on user attributes (e.g. different onboarding flows for U.S. and international users).
* Define Enhanced Due Diligence (EDD) or step-up flows.

Rules are evaluated during onboarding using vaulted data and risk signals derived from verification checks on that data. Each branch of a rules node in a Playbook configuration has a set of associated rules. Branches are evaluated in the order they are displayed (left-to-right or top-to-bottom), and a branch is followed if any of the associated rules evaluates to `true`. If no branches have a rule that evaluates to `true`, the default branch is taken. A default branch is required and is always displayed last (right-most or bottom-most).

## Footprint Rules Language

Rules are expressions written in the Footprint Rules Language that evaluate during onboarding to either `true` or `false`. They are composed of input features, comparison expressions, and boolean operators.

Input features have the format `<category>.<feature>` . There are two categories of features:

* `risk_signal`: Risk signals derived from verification checks
* `vault_data`: Data vaulted during onboarding

Within each of the categories is a number of features (for example, `risk_signal.watchlist_hit_ofac`, `risk_signal.device_high_risk` and `vault_data.id.country`).

Features available to a rule are suggested as you type in the rules editor:

Hovering your mouse over a feature displays documentation:

### Risk signal expressions

Risk signal input features in the `risk_signal` category take on boolean values (`true` or `false`), indicating whether that risk signal was triggered by a verification check. Therefore, the simplest rule is a single risk signal. For example:

````sql filename="Rule"
risk_signal.watchlist_hit_ofac```

This rule evaluates to `true` if the verification checks yielded this risk signal.

The `not` operator negates risk signals, meaning the following evaluates to `true` if the verification checks did not yield this risk signal:

```sql filename="Rule"
not risk_signal.watchlist_hit_ofac```

The complete list of risk signals available can be found in the [Risk Signal Glossary](https://dashboard.onefootprint.com/home?rsg=open).

### Vault data expressions

Vault data input features in the `vault_data` category take on string values. The features in this category map one-to-one to the vault fields listed [here](https://docs.onefootprint.com/articles/vault/fields). For example `id.zip` is available to rules in the feature `vault_data.id.zip` and `business.country` is available to rules in the feature `vault_data.business.country`.

Since rules are boolean expressions and vault data features are strings, vault data features must be compared to a specific value. For example:

```sql filename="Rule"
vault_data.id.country = "US"```

This would evaluate to `true` if the country entered during onboarding is `US`.

Vault data also supports inequality checks with the `!=` operator. For example:

```sql filename="Rule"
vault_data.id.country != "CA"```

### Compound rule expressions

Expressions can be composed together with the logical operators `not`, `and`, and `or` and grouped using parentheses to express more complex conditions. For example:

```sql filename="Rule"
risk_signal.device_high_risk and (not risk_signal.attested_device_apple or vault_data.id.country != "US")```

The `and` operator takes precedence over the `or` operator, and the `not` operator has highest precedence. Take for example this rule without parentheses:

```sql filename="Rule"
not risk_signal.attested_device_apple or vault_data.id.country != "US" and not risk_signal.device_high_risk```

Formatted with parentheses to clarify the order of operations, the above rule is equivalent to:

```sql filename="Rule"
(not risk_signal.attested_device_apple)
or
(
	vault_data.id.country != "US"
	and
	(not risk_signal.device_high_risk)
)```

Parentheses are added to rules automatically when saving to reduce ambiguity and to help you check your work.

## Best practices

To keep your rules easy to understand, you may split up top-level `or` expressions into multiple rules. Take for example this compound rule:

```sql filename="Rule"
not risk_signal.document_ocr_name_matches or not risk_signal.document_selfie_matches```

This rule can be split up into two rules on the same branch:

```sql filename="Rule"
not risk_signal.document_ocr_name_matches```

```sql filename="Rule"
not risk_signal.document_selfie_matches```

Since a branch is followed if any one of the associated rules matches, these two rule sets express the same logic.
````