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

# Motor de reglas

> Guía para usar el motor de reglas de Tracer para construir lógica de validación dinámica basada en expresiones.

export const GMetadata = ({children}) => <Tooltip headline="Metadatos" tip="Información adicional en formato clave-valor adjunta a entidades como cuentas o transacciones — como IDs externos, números de referencia o códigos de departamento." cta="Ver glosario" href="/es/glossary">
    {children}
  </Tooltip>;

export const GCEL = ({children}) => <Tooltip headline="CEL (Common Expression Language)" tip="Lenguaje de expresiones ligero y seguro diseñado por Google. Tracer utiliza CEL para definir reglas de validación de transacciones en tiempo real, sin despliegues de código." cta="Ver glosario" href="/es/glossary">
    {children}
  </Tooltip>;

El motor de reglas es lo que los equipos de riesgo y fraude usan para cambiar cómo las transacciones se aprueban o bloquean, sin tocar el código de la aplicación. Cada regla es una pequeña expresión que se ejecuta en cada transacción que Tracer valida — "bloquear este MCC para este segmento", "enviar todo lo superior a R\$ 50 mil a revisión manual", "denegar si la cuenta está suspendida".

**Qué cambia en tu operación:** los cambios en reglas se publican por un endpoint de API, no por una release. Un analista puede publicar una nueva regla en la mañana y verla evaluando transacciones reales en segundos. Cada coincidencia queda registrada, así una llamada de cliente reclamando seis meses después puede rastrearse hasta la regla exacta que disparó.

**El trade-off honesto:** tienes que pensar en CEL (Common Expression Language) en vez de Go, Python o Java. La curva es corta — la mayoría de las reglas tiene una línea — pero el equipo que las escribe ya no es el de aplicación. La contrapartida es cero despliegue, auditoría completa, y quien está más cerca de la política es dueño de ella.

<Tip>
  **¿Para quién es esta guía?** Analistas de riesgo y fraude que van a escribir reglas, devs integrando la llamada de validación, y oficiales de cumplimiento leyendo el rastro de auditoría. Los ejemplos en CEL se ponen técnicos más adelante, pero el ciclo de vida y la lógica de decisión son útiles para cualquiera evaluando el producto.
</Tip>

El **motor de reglas de Tracer** evalúa lógica de validación escrita en <GCEL>CEL (Common Expression Language)</GCEL> — un lenguaje de expresiones con seguridad de tipos de Google. Las expresiones se compilan al crear la regla y se ejecutan en cada validación de transacción; el comportamiento se cambia actualizando las reglas vía API, sin redespliegue de código.

## Por qué usar el motor de reglas

***

* **Flexibilidad**: Crea y modifica reglas sin despliegues de código
* **Rendimiento**: Las expresiones compiladas se evalúan en menos de 1ms cada una
* **Seguridad de tipos**: Sintaxis de expresiones validada al crear la regla
* **Toda regla activa corre**: Todas las reglas coincidentes se evalúan, así el rastro de auditoría registra todos los disparadores, no solo la categoría ganadora
* **Basado en alcances**: Aplica reglas a segmentos, cuentas o tipos de transacción específicos

Al final de esta guía, podrás:

* Comprender los conceptos del motor de reglas y el flujo de evaluación
* Crear y probar reglas basadas en expresiones
* Gestionar el ciclo de vida de las reglas (DRAFT, ACTIVE, INACTIVE, DELETED)
* Aplicar mejores prácticas para la gestión de reglas

***

## Qué es el motor de reglas

***

El motor de reglas es el componente de Tracer responsable de evaluar expresiones durante la validación de transacciones. Permite a los analistas de fraude y gestores de riesgo configurar lógica de negocio que se ejecuta en tiempo real—sin requerir despliegues de código o soporte de ingeniería.

### Cómo funciona

<Frame caption="Figura 1. Flujo de evaluación del motor de reglas">
  <img src="https://mintcdn.com/lerian-49cb71fc/SEOef3JqTInYAAau/images/es/d2/how-rules-works.svg?fit=max&auto=format&n=SEOef3JqTInYAAau&q=85&s=e12f8f310a578d7b3abbd38f4450af35" alt="Cómo el motor de reglas evalúa las expresiones configuradas contra el contexto de la transacción durante la validación y devuelve una decisión" width="1224" height="284" data-path="images/es/d2/how-rules-works.svg" />
</Frame>

En este flujo:

* **Load rules** obtiene todas las reglas activas desde la cache (o base de datos si no hay cache)
* **Evaluate expressions** ejecuta todas las expresiones CEL contra el contexto de la transacción
* **Collect matches** recopila todas las reglas que coincidieron y determina la decisión

### Patrón de evaluación

Todas las reglas activas se evalúan contra cada transacción. No hay ordenamiento por prioridad ni evaluación de cortocircuito. Esto asegura:

* Rastro de auditoría completo (todas las reglas coincidentes se registran)
* Sin pérdida de información (los analistas pueden ver todos los disparadores)
* Lógica simple (sin conflictos de prioridad)

**Precedencia de decisión** (de mayor a menor):

1. **DENY** — cualquier regla `DENY` que coincida gana de inmediato.
2. **Límite excedido** — si ninguna regla DENY coincide pero algún límite aplicable es excedido, la decisión es DENY (la precedencia de las reglas aplica primero; los límites entran solo cuando ninguna DENY coincidió).
3. **REVIEW** — si ninguna regla DENY coincide y ningún límite es excedido, cualquier regla `REVIEW` que coincida gana.
4. **ALLOW** — si solo coinciden reglas `ALLOW`, la decisión es ALLOW.
5. **Predeterminado** — si ninguna regla coincide, Tracer devuelve el `DEFAULT_DECISION_WHEN_NO_MATCH` configurado (`ALLOW`, a menos que esté establecido explícitamente como `DENY` para despliegues fail-closed).

`matchedRuleIds` en la respuesta contiene todas las reglas que coincidieron, independientemente de la categoría ganadora, para que los consumidores de auditoría vean todos los disparadores.

<Info>
  **Por qué DENY le gana a REVIEW, y REVIEW le gana a ALLOW.** La precedencia es fija y no configurable, a propósito: elimina la ambigüedad de "¿cuál regla DENY gana?" en runtime y vuelve trivial la auditoría — la respuesta siempre identifica la acción más estricta que disparó. El costo es que no puedes escribir "reglas ALLOW que sobrescriben DENYs"; si necesitas ese patrón, la respuesta correcta es volver la regla DENY más específica.
</Info>

<Note>
  Tracer devuelve decisiones; no bloquea transacciones directamente. Tu sistema recibe la decisión y es responsable de tomar la acción apropiada (ej., bloquear, permitir, o enviar a revisión).
</Note>

***

## Conceptos principales

***

Antes de crear reglas, comprende los elementos fundamentales.

### Reglas

Una regla es una unidad de lógica de negocio compuesta de:

* **Expression** - Una expresión con seguridad de tipos que evalúa a true o false
* **Action** - Qué decisión devolver cuando la expresión es verdadera
* **Scopes** - A que transacciones se aplica la regla
* **Status** - El estado del ciclo de vida de la regla

### Expresiones

Las expresiones se escriben en **CEL (Common Expression Language)**, un lenguaje con seguridad de tipos que evalúa el contexto de la transacción y devuelve un valor booleano (true o false). CEL proporciona validación en tiempo de compilación, por lo que los errores de sintaxis se detectan cuando creas la regla—no cuando se están procesando las transacciones.

Ejemplos de expresiones:

```
amount > 10000
```

```
segment.segmentId == "high-risk-segment-uuid" && amount > 5000
```

```
merchant["category"] == "7995"
```

(`merchant.category` es el código MCC ISO 18245 de 4 dígitos — `"7995"` es el MCC de apuestas/casino. Tanto `merchant.category` como `merchant["category"]` son aceptados; los ejemplos en producción usan la notación con corchetes por convención. Si necesitas hacer match con una etiqueta textual como `"gambling"`, guárdala en `metadata` y haz match por ahí.)

Las expresiones tienen acceso al contexto completo de la solicitud de validación. Las variables más usadas están listadas abajo. Para el catálogo completo de cada campo anidado, tipo y caso borde (formato UUID, valores de enum, comportamiento `omitempty`), consulta el [schema ValidationRequest](/es/openapi/v3-current/tracer.yaml) en la referencia de la API.

| Variable            | Tipo        | Para qué típicamente sirve                                                         |
| ------------------- | ----------- | ---------------------------------------------------------------------------------- |
| `amount`            | number      | Valor decimal convertido a `float64` para la evaluación CEL (máx. `±2^53`).        |
| `transactionType`   | string      | Uno de `CARD`, `WIRE`, `PIX`, `CRYPTO`.                                            |
| `subType`           | string      | Texto libre (ej., `"international"`, `"debit"`). Cadena vacía cuando no se provee. |
| `currency`          | string      | Código ISO 4217 (ej., `"BRL"`).                                                    |
| `account.status`    | string      | Uno de `active`, `suspended`, `closed`.                                            |
| `merchant.category` | string      | Código MCC ISO 18245, 4 dígitos.                                                   |
| `merchant.country`  | string      | ISO 3166-1 alpha-2 (ej., `"BR"`).                                                  |
| `segment.segmentId` | string UUID | Alcance de segmento de la transacción.                                             |
| `metadata.<clave>`  | any         | Campos personalizados que tu integración pasa en el payload de la solicitud.       |

<Note>
  `segmentId` y `portfolioId` están en las variables de primer nivel `segment` y `portfolio`, **no** en `account`. Para filtrar por segmento, usa `segment.segmentId == "..."`, no `account.segmentId == "..."`. Los mapas `segment`, `portfolio` y `merchant` solo están presentes cuando la solicitud los incluye — protege con `has(segment)` si tu regla debe correr incluso cuando la solicitud no carga uno.
</Note>

<Note>
  La evaluación de expresiones está limitada por `CEL_COST_LIMIT` (predeterminado `10000`). Las expresiones que exceden este costo son rechazadas al activar la regla con el código de error `0342` (límite de costo excedido); los errores de tipo en la expresión aparecen como `0341`.
</Note>

### Ejemplos de expresiones por caso de uso

Aquí hay ejemplos prácticos organizados por escenario de negocio:

#### Reglas basadas en monto

```cel theme={null}
// Block transactions above a threshold
amount > 10000

// Block high-value international transfers
transactionType == "WIRE" && subType == "international" && amount > 50000

// Review large cryptocurrency transactions
transactionType == "CRYPTO" && amount > 5000
```

#### Reglas basadas en comercio

```cel theme={null}
// Block gambling merchants
merchant.category == "7995"

// Block high-risk merchant categories
merchant.category in ["7995", "5967", "5966"]

// Review transactions from new merchant countries
merchant.country != "BR" && amount > 1000
```

#### Reglas basadas en cuenta

```cel theme={null}
// Block suspended accounts
account.status == "suspended"

// Review transactions from newly created accounts
metadata.accountAgeDays < 30 && amount > 500

// Block closed accounts
account.status == "closed"
```

#### Condiciones combinadas

```cel theme={null}
// High-value transaction from high-risk segment
segment.segmentId == "high-risk-segment-uuid" && amount > 5000

// International PIX above threshold
transactionType == "PIX" && subType == "international" && amount > 10000

// Large card transaction to foreign merchant
transactionType == "CARD" && merchant.country != "BR" && amount > 3000
```

#### Usando metadata

```cel theme={null}
// Block transactions from untrusted devices
metadata.deviceTrust == "untrusted"

// Review first-time purchases above threshold
metadata.isFirstPurchase == true && amount > 1000

// Block transactions outside business hours (using metadata)
metadata.isBusinessHours == false && amount > 5000

// VIP customers bypass certain restrictions
metadata.customerTier == "vip" && amount < 50000
```

<Note>
  Los campos de metadata son proporcionados por tu integración. Diseña tu payload para incluir el contexto que tus reglas necesitan.
</Note>

### Acciones

Las acciones determinan la decisión cuando una expresión evalúa a true:

| Acción   | Descripción              |
| -------- | ------------------------ |
| `ALLOW`  | Permitir la transacción  |
| `DENY`   | Denegar la transacción   |
| `REVIEW` | Enviar a revisión manual |

### Alcances

Los alcances definen a qué transacciones se aplica una regla. Una regla sin `scopes` es **global** y evalúa contra cualquier transacción. Una regla con uno o más objetos de alcance solo evalúa cuando la transacción coincide con al menos uno de ellos (semántica OR entre objetos de alcance).

Dentro de un único objeto de alcance, los campos soportados son:

* `segmentId` - Coincidir transacciones de un segmento específico
* `portfolioId` - Coincidir transacciones de un portafolio específico
* `accountId` - Coincidir transacciones de una cuenta específica
* `merchantId` - Coincidir transacciones hacia un comercio específico
* `transactionType` - Coincidir tipos de transacción específicos (CARD, WIRE, PIX, CRYPTO)
* `subType` - Coincidir subtipos específicos (debit, credit, instant, etc.)

**Semántica de coincidencia:**

* **Dentro de un objeto de alcance:** los campos se combinan con AND. Un campo no especificado funciona como comodín (coincide con cualquier valor). Al menos un campo debe estar definido — objetos de alcance vacíos (`{}`) son rechazados con el código de error `0358`.
* **Entre múltiples objetos de alcance en la misma regla:** se combinan con OR. La regla coincide si **cualquier** objeto de alcance coincide con la transacción.

Por ejemplo, una regla con dos alcances — uno filtrando `transactionType: CARD` y otro filtrando `transactionType: PIX` — se ejecuta tanto para transacciones de tarjeta como para PIX. Un único alcance con `segmentId` Y `accountId` requiere que la transacción coincida con el segmento Y con la cuenta.

***

## Ciclo de vida de las reglas

***

Las reglas progresan a través de un ciclo de vida definido para asegurar un despliegue seguro.

<Frame caption="Figura 2. Ciclo de vida y transiciones del motor de reglas">
  <img src="https://mintcdn.com/lerian-49cb71fc/ZrZBZTM4DWnrahSd/images/es/d2/rules-limits-lifecycle-tracer.svg?fit=max&auto=format&n=ZrZBZTM4DWnrahSd&q=85&s=7abfad053b78d3ca81f0783dfa91a2c8" alt="Ciclo de vida de las reglas y los límites en Tracer, con las transiciones de estado por las que pasa una definición desde su creación hasta su aplicación activa" width="531" height="1050" data-path="images/es/d2/rules-limits-lifecycle-tracer.svg" />
</Frame>

### Estados

| Estado     | Descripción                                                                                                                                                                                                    |
| ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `DRAFT`    | No se evalúa; la expresión puede modificarse libremente                                                                                                                                                        |
| `ACTIVE`   | Se evalúa durante las validaciones; la expresión es inmutable                                                                                                                                                  |
| `INACTIVE` | No se evalúa; preservada para el rastro de auditoría; puede reactivarse. La expresión sigue siendo inmutable en este estado — para editarla, mueve la regla de vuelta a DRAFT vía `POST /v1/rules/{id}/draft`. |
| `DELETED`  | Eliminada vía soft delete; no devuelta en listados y no puede recuperarse vía API, pero la fila se preserva en la base de datos para el rastro de auditoría.                                                   |

### Transiciones

| Transición   | Desde           | Hacia    | Descripción                                                     |
| ------------ | --------------- | -------- | --------------------------------------------------------------- |
| `activate`   | DRAFT, INACTIVE | ACTIVE   | Iniciar evaluación (valida la expresión)                        |
| `deactivate` | ACTIVE          | INACTIVE | Detener evaluación                                              |
| `draft`      | INACTIVE        | DRAFT    | Reeditar una regla previamente desactivada antes de reactivarla |
| `delete`     | DRAFT, INACTIVE | DELETED  | Eliminación permanente (no se puede eliminar reglas ACTIVE)     |

<Note>
  Las reglas activas deben desactivarse antes de eliminarse. Esto previene la eliminación accidental de reglas que se están evaluando actualmente.
</Note>

***

## Crear una regla

***

Crea reglas usando `POST /v1/rules`. Las reglas se crean en estado `DRAFT` por defecto.

Una regla requiere:

* **name**: Un nombre único y descriptivo
* **expression**: Una expresión CEL que evalúa a true o false
* **action**: La decisión a devolver cuando la expresión coincide (ALLOW, DENY o REVIEW)
* **scopes** (opcional): Limita a qué transacciones se aplica la regla

Para la estructura completa del payload y detalles de campos, consulta la [Referencia de API](/es/reference/tracer/create-rule).

***

## Activar y desactivar reglas

***

Después de crear una regla, actívala para iniciar la evaluación. Desactiva las reglas para detener la evaluación sin eliminarlas.

| Operación  | Endpoint                         | Descripción                                  |
| ---------- | -------------------------------- | -------------------------------------------- |
| Activar    | `POST /v1/rules/{id}/activate`   | Iniciar evaluación de esta regla             |
| Desactivar | `POST /v1/rules/{id}/deactivate` | Detener evaluación (preserva para auditoría) |

<Note>
  Desactivar una regla la preserva para propósitos de auditoría. Usa eliminar solo cuando quieras remover permanentemente una regla.
</Note>

***

## Listar y consultar reglas

***

Consulta reglas para gestión y auditoría usando `GET /v1/rules`.

### Parámetros de consulta

| Parámetro          | Tipo    | Descripción                                                                                        |
| ------------------ | ------- | -------------------------------------------------------------------------------------------------- |
| `name`             | string  | Filtrar por nombre (coincidencia parcial, case-insensitive)                                        |
| `status`           | string  | Filtrar por estado (DRAFT, ACTIVE, INACTIVE). `DELETED` no es un valor válido para este filtro.    |
| `action`           | string  | Filtrar por acción (ALLOW, DENY, REVIEW)                                                           |
| `account_id`       | UUID    | Filtrar por alcance: ID de la cuenta                                                               |
| `segment_id`       | UUID    | Filtrar por alcance: ID del segmento                                                               |
| `portfolio_id`     | UUID    | Filtrar por alcance: ID del portafolio                                                             |
| `merchant_id`      | UUID    | Filtrar por alcance: ID del comerciante                                                            |
| `transaction_type` | string  | Filtrar por alcance: tipo de transacción (CARD, WIRE, PIX, CRYPTO)                                 |
| `sub_type`         | string  | Filtrar por alcance: subtipo (ej.: debit, credit)                                                  |
| `limit`            | integer | Elementos por página (predeterminado: 10, máx: 100)                                                |
| `cursor`           | string  | Cursor de paginación de la respuesta anterior                                                      |
| `sort_by`          | string  | Campo de ordenamiento: `created_at`, `updated_at`, `name`, `status` (predeterminado: `created_at`) |
| `sort_order`       | string  | Dirección: `ASC`, `DESC` (predeterminado: `DESC`)                                                  |

### Obtener una regla específica

Usa `GET /v1/rules/{id}` para recuperar la definición completa de la regla incluyendo expresión y alcances.

***

## Actualizar una regla

***

Actualiza reglas usando `PATCH /v1/rules/{id}`. Las reglas pueden actualizarse en cualquier estado, con una restricción importante:

<Warning>
  El campo `expression` es inmutable en los estados **ACTIVE** e **INACTIVE** — desactivar la regla no basta. Para editar una expresión, mueve la regla de ACTIVE → INACTIVE (`POST /v1/rules/{id}/deactivate`) y luego de INACTIVE → DRAFT (`POST /v1/rules/{id}/draft`). Solo las reglas DRAFT aceptan cambios en la expresión. Después de editar, reactívala con `POST /v1/rules/{id}/activate`.
</Warning>

***

## Eliminar una regla

***

Elimina las reglas que ya no se necesitan. Solo las reglas DRAFT e INACTIVE pueden eliminarse. Las reglas ACTIVE deben desactivarse primero.

```http theme={null}
DELETE /v1/rules/{id}
X-API-Key: {api_key}
```

Respuesta: `204 No Content`

<Warning>
  La eliminación es permanente. Las reglas eliminadas no pueden recuperarse y no aparecen en ningún listado.
</Warning>

***

## Mejores prácticas

***

Sigue estas prácticas para reglas efectivas y mantenibles.

### Nomenclatura

* **Usa nombres descriptivos** - El nombre debe indicar claramente qué hace la regla
* **Incluye contexto** - Menciona el escenario o tipo de transacción
* **Evita abreviaturas** - Prefiere claridad sobre brevedad

| Menos claro  | Más claro                                  |
| ------------ | ------------------------------------------ |
| `Rule 1`     | `Block night transactions above BRL 5,000` |
| `Block high` | `Deny high-value weekend transactions`     |
| `PIX rule`   | `Review PIX transfers to new recipients`   |

### Diseño de expresiones

* **Mantén las expresiones simples** - La lógica compleja es más difícil de mantener
* **Usa alcances para filtrar** - No repitas condiciones de alcance en las expresiones
* **Prueba casos límite** - Considera valores límites y campos nulos

### Gestión del ciclo de vida

* **Comienza en DRAFT** - Prueba antes de activar
* **Vuelve a DRAFT antes de editar la expresión** - La expresión es inmutable en ACTIVE e INACTIVE; mueve la regla a DRAFT vía `POST /v1/rules/{id}/draft` para editar, después reactívala
* **Archiva reglas no usadas** - Mantiene el rastro de auditoría intacto
* **Elimina solo cuando estés seguro** - La eliminación es permanente

### Monitoreo

* **Revisa las reglas coincidentes** - Verifica qué reglas se están disparando
* **Monitorea las tasas de DENY** - Tasas altas de denegación pueden indicar reglas demasiado agresivas
* **Audita regularmente** - Asegura que las reglas sigan alineadas con los requisitos de negocio

<Warning>
  **Tropezones comunes al trabajar con reglas:**

  * **"Edité la expresión pero el cambio no surtió efecto."** La expresión es inmutable en los estados ACTIVE e INACTIVE. Mueve la regla de vuelta a DRAFT vía `POST /v1/rules/{id}/draft`, edita y reactiva. INACTIVE solo no basta.
  * **"Mi regla está ACTIVE pero Tracer todavía no la está evaluando."** El cache de reglas se refresca cada \~10 segundos (`RULE_SYNC_POLL_INTERVAL_SECONDS`). Las reglas recién activadas tardan hasta esa ventana en comenzar a correr. Planifica las pruebas de integración con ese delay.
  * **"Quiero eliminar una regla ACTIVE."** No puedes — `POST /v1/rules/{id}/deactivate` primero, después `DELETE /v1/rules/{id}`. Esto fuerza un paso visible donde la regla deja de afectar el tráfico antes de desaparecer de los listados.
  * **"Mi alcance vacío `{}` está siendo rechazado con el código de error `0358`."** Todo objeto de alcance necesita tener al menos un campo definido. Para correr una regla globalmente (contra cualquier transacción), omite el array `scopes` completo — no pases `{}`.
</Warning>

***

## Referencia rápida

***

Endpoints, acciones e información de estados clave.

### Endpoints

| Operación         | Método | Endpoint                    |
| ----------------- | ------ | --------------------------- |
| Crear regla       | POST   | `/v1/rules`                 |
| Listar reglas     | GET    | `/v1/rules`                 |
| Obtener regla     | GET    | `/v1/rules/{id}`            |
| Actualizar regla  | PATCH  | `/v1/rules/{id}`            |
| Eliminar regla    | DELETE | `/v1/rules/{id}`            |
| Activar regla     | POST   | `/v1/rules/{id}/activate`   |
| Desactivar regla  | POST   | `/v1/rules/{id}/deactivate` |
| Volver a borrador | POST   | `/v1/rules/{id}/draft`      |

### Estados

| Estado     | Evaluada | Editable                                                 | Puede eliminarse        |
| ---------- | -------- | -------------------------------------------------------- | ----------------------- |
| `DRAFT`    | No       | Sí                                                       | Sí                      |
| `ACTIVE`   | Sí       | Parcial (`expression` inmutable)                         | No (desactivar primero) |
| `INACTIVE` | No       | Parcial (`expression` inmutable; volver a DRAFT primero) | Sí                      |
| `DELETED`  | No       | No                                                       | N/A                     |
