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

# Fact Definitions

> Facts are the input variables your rules evaluate against. Define, type, and manage them here.

## What is a Fact Definition?

A **Fact Definition** declares an input variable that your rules can reference in conditions and actions. Think of it like a function parameter — you define the name, type, and whether it's required before writing the logic.

Facts are **tenant-wide**: once defined, they're available across all policy groups and versions.

## Pre-registered Facts

Every tenant starts with 2 pre-registered facts, available immediately after account creation:

| Key         | Type         | Required | Description     |
| ----------- | ------------ | :------: | --------------- |
| `user_id`   | STRING       |          | User identifier |
| `user_tags` | LIST\_STRING |          | User tags       |

These are provided for convenience — they are regular facts, not protected. You can rename, retype, or delete them just like any custom fact. They can be used in conditions and actions immediately, with no registration needed.

## Custom Facts

Any input variable beyond the two pre-registered facts should be registered before use (see [Unregistered Facts](#unregistered-facts)). For example, `customer_tier`, `order_region`, or `product_category` are custom facts.

```bash theme={null}
lexq facts create --key customer_tier --name "Customer Tier" --type STRING
lexq facts create --key order_region --name "Order Region" --type STRING --required
lexq facts create --key customer_email --name "Customer Email" --type STRING --pii
```

## Supported Types

| Type          | JSON           | Example Value    |
| ------------- | -------------- | ---------------- |
| `STRING`      | `"string"`     | `"VIP"`          |
| `NUMBER`      | `number`       | `100000`         |
| `BOOLEAN`     | `true / false` | `true`           |
| `LIST_STRING` | `["a", "b"]`   | `["KR", "US"]`   |
| `LIST_NUMBER` | `[1, 2]`       | `[10000, 20000]` |

## Naming Conventions

Fact keys must follow `snake_case` naming. Keys are **case-sensitive**.

* ✅ `payment_amount`, `customer_tier`, `user_region`
* ❌ `paymentAmount`, `Payment-Amount`, `PAYMENT AMOUNT`

## Required vs Optional Facts

* **Required facts** must be present in every execution request. If missing, the engine returns an `INVALID_INPUT` error.
* **Optional facts** can be omitted. Rules referencing missing optional facts evaluate their conditions as `false` (no match).

## PII Facts

A fact can be marked as **PII** (personally identifiable information) in the Console under **Management → Fact Definitions**, or with the CLI's `--pii` flag. Marking changes how the value is read, not how rules run:

* Rules evaluate the real value as usual — masking is aimed at humans and integrations, not at the engine.
* On **every read surface** (Decision Provenance, execution history detail, exports) the value arrives masked as `••••••`, and `maskedKeys` lists what was masked.
* Revealing a masked value is console-only and audited: the audit row is written before the value is shown. See [Decision Provenance](/guides/decision-provenance) for the full contract.

<Tip>
  Mark facts like emails, phone numbers, and account identifiers as PII at creation time — masking starts the moment the flag is on, with no rule changes needed.
</Tip>

## Unregistered Facts

You can reference a fact key in a rule **before** registering it as a Fact Definition. LexQ does not force registration first — but whenever you save a rule, it tells you which referenced keys are not in the schema.

On every rule `create` or `update`, LexQ scans the rule's conditions and actions and returns any **unregistered facts** — keys that no Fact Definition declares — each with an inferred type, a suggested display name, and where it was referenced (condition or action).

This is **non-blocking by design**: saving, publishing, and deploying are never stopped by an unregistered fact. The rule is stored exactly as written and still runs — if the value is supplied at execution time the condition evaluates normally; if it is missing, the condition simply does not match.

What stays off until you register the fact:

| Unregistered                               | Registered                                                                 |
| ------------------------------------------ | -------------------------------------------------------------------------- |
| Value is not type-checked                  | Validated against the declared `STRING` / `NUMBER` / …                     |
| No autocomplete in the Console rule editor | Key suggested as you type                                                  |
| Not counted by the requirements analyzer   | Appears in `lexq analytics requirements` and the dry-run requirements view |

The warning surfaces on every authoring surface — the CLI (stderr), the Console rule editor and deploy dialog, and the MCP tools.

### Reviewing and registering

A save returns its unregistered facts inline, but you can also list them for an entire version at any time:

```bash theme={null}
lexq facts unregistered --group-id <gid> --version-id <vid>
```

Then register the ones you intend to keep:

```bash theme={null}
lexq facts create --key order_region --name "Order Region" --type STRING
```

<Info>
  Registration is always an explicit step — LexQ never auto-creates a fact from a rule reference. Your schema stays a deliberate contract, not a side effect of rule authoring.
</Info>

## Managing Facts

Facts are managed in the Console under **Management → Fact Definitions**, or via the CLI:

```bash theme={null}
lexq facts list
lexq facts create --key order_total --name "Order Total" --type NUMBER --required
lexq facts update --id <factId> --name "Total Order Amount"
lexq facts delete --id <factId>
```

<Tip>
  Use `lexq analytics requirements` (CLI) or the Engine API's `GET /groups/{groupId}/requirements` endpoint to see exactly which facts a deployed version needs.
</Tip>

<Warning>
  Deleting a fact does not automatically remove it from existing rules. Rules referencing a deleted fact will evaluate that condition as `false`. Always review rule dependencies before deleting.
</Warning>

## Next Steps

<CardGroup cols={2}>
  <Card title="Policy Rules" icon="list-check" href="/guides/policy-rules">
    Use facts in rule conditions and actions.
  </Card>

  <Card title="Policy Execution" icon="bolt" href="/api/execution">
    See how facts are passed during execution.
  </Card>
</CardGroup>
