> ## 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 regras

> Escreva expressões CEL no motor de regras do Tracer para definir decisões de ALLOW, DENY e REVIEW em tempo real, e gerencie o ciclo de vida de DRAFT a ACTIVE.

O motor de regras é o que as equipes de risco e fraude usam para mudar como o Tracer aprova ou bloqueia transações, sem tocar no código da aplicação.

**O que muda na sua operação:** mudanças de regra saem por um endpoint de API, não por um release. Um analista pode publicar uma nova regra de manhã e vê-la avaliando transações reais em segundos. O Tracer registra cada correspondência, então você pode rastrear a ligação de um cliente negado seis meses depois até a regra exata que disparou.

**Contrapartida:** você precisa pensar em CEL (Common Expression Language) em vez de Go, Python ou Java. A curva de aprendizado é curta (a maioria das regras tem uma linha), mas o time que as escreve não é mais seus desenvolvedores de aplicação. A vantagem é nenhum deploy, auditoria completa, e as pessoas mais próximas da política são as responsáveis por ela.

> [!TIP]
>
> **Este guia é para** analistas de risco e fraude que vão escrever regras, desenvolvedores que integram a chamada de validação, e profissionais de compliance que leem a trilha de auditoria. Os exemplos em CEL ficam mais técnicos mais adiante, mas a lógica de ciclo de vida e de decisão é útil para qualquer pessoa avaliando o produto.

O **motor de regras do Tracer** avalia a lógica de validação escrita em CEL (Common Expression Language) (Uma linguagem de expressão leve para escrever regras de negócio, por exemplo, 'if transaction amount > 10000 then REVIEW'. O Tracer usa CEL para regras de validação.), uma linguagem de expressão type-safe do Google. O Tracer compila as expressões na criação da regra e as executa durante toda validação de transação. Você muda o comportamento atualizando regras pela API, sem fazer redeploy do código.

## Por que usar o motor de regras

***

* **Flexibilidade**: crie e modifique regras sem deploys de código
* **Modelo de execução**: o Tracer avalia expressões compiladas durante a validação
* **Segurança de tipos**: a sintaxe da expressão é validada na criação da regra
* **Sem short-circuit**: o Tracer avalia juntas as regras correspondentes, então a trilha de auditoria registra as regras que dispararam, independentemente da categoria vencedora
* **Baseado em escopo**: aplique regras a segmentos, contas ou esquemas de pagamento específicos

Ao final deste guia, você vai:

* Entender os conceitos do motor de regras e o fluxo de avaliação
* Criar e testar regras baseadas em expressões
* Gerenciar o ciclo de vida da regra (DRAFT, ACTIVE, INACTIVE, DELETED)
* Aplicar boas práticas de gerenciamento de regras

***

## O que é o motor de regras

***

O motor de regras é o componente do Tracer responsável por avaliar expressões durante a validação de transações. Ele permite que analistas de fraude e gerentes de risco configurem lógica de negócio que é executada em tempo real, sem exigir deploys de código ou suporte de engenharia.

### Como funciona

![Como o motor de regras avalia expressões configuradas em relação ao contexto da transação durante a validação e retorna uma decisão](https://mintcdn.com/lerian-49cb71fc/DzYecUhEaPz9p1hq/images/pt/d2/how-rules-works.svg?fit=max\&auto=format\&n=DzYecUhEaPz9p1hq\&q=85\&s=d8d59cb773785fa71878f95785957d08)

Figura 1. Fluxo de avaliação do motor de regras

Neste fluxo:

* **Carregar regras** busca regras ativas do cache
* **Avaliar expressões** executa a expressão CEL de cada regra cujo escopo corresponde à transação, até `MAX_RULES_PER_REQUEST` regras
* **Coletar correspondências** reúne todas as regras que corresponderam e determina a decisão

### Padrão de avaliação

**Precedência de decisão** (da mais alta para a mais baixa):

1. **DENY**: qualquer regra `DENY` correspondente vence diretamente.
2. **Limite excedido**: se nenhuma regra DENY correspondeu, mas a transação excede algum limite aplicável, a decisão é DENY. A precedência de regras se aplica primeiro, e os limites entram em jogo apenas quando nenhuma regra DENY correspondeu.
3. **REVIEW**: se nenhuma regra DENY correspondeu e a transação não excedeu nenhum limite, qualquer regra `REVIEW` correspondente vence. Uma regra cuja expressão falha para a requisição também gera REVIEW, com o motivo `rule_evaluation_error`. Em vez disso, uma chave ausente não gera correspondência.
4. **ALLOW**: se apenas regras `ALLOW` corresponderam, a decisão é ALLOW.
5. **Padrão**: se nenhuma regra correspondeu, a validação retorna o `DEFAULT_DECISION_WHEN_NO_MATCH` configurado (`ALLOW`, a menos que explicitamente definido como `DENY`). O Tracer aceita apenas `ALLOW` e `DENY`. `REVIEW` deliberadamente não é um padrão válido para ausência de correspondência, e qualquer outro valor faz o serviço falhar na inicialização.

Quando o ledger do Midaz reserva uma transação, o Tracer roda as mesmas regras com uma entrada menor. Veja [Regras em uma reserva](https://docs.lerian.studio/pt/products/tracer/integration-guide.md#rules-on-a-reserve).

> [!NOTE]
>
> **Por que DENY vence REVIEW que vence ALLOW.** A precedência nunca muda e você não pode configurá-la, de propósito. Isso elimina a ambiguidade de "qual regra DENY vence?" em tempo de execução e torna a auditoria trivial. A resposta sempre identifica a ação mais restritiva que disparou. O custo é que você não pode escrever "regras ALLOW que sobrepõem DENYs". Se precisar desse padrão, a resposta certa é tornar a regra DENY mais específica.

> [!NOTE]
>
> O Tracer retorna decisões. Ele não bloqueia transações diretamente. Seu sistema recebe a decisão e deve tomar a ação apropriada (por exemplo, bloquear, permitir ou colocar em fila para revisão).

***

## Conceitos básicos

***

Antes de criar regras, entenda os elementos fundamentais.

### Regras

Uma regra é uma unidade de lógica de negócio composta por:

* **Expressão** - uma expressão type-safe que avalia para verdadeiro ou falso
* **Ação** - qual decisão retornar quando a expressão é verdadeira
* **Escopos** - a quais transações a regra se aplica
* **Status** - o estado de ciclo de vida da regra

### Expressões

Você escreve expressões em **CEL (Common Expression Language)**, uma linguagem type-safe que avalia o contexto da transação e retorna um valor booleano (verdadeiro ou falso). O CEL oferece validação em tempo de compilação, então erros de sintaxe aparecem quando você cria a regra, não quando o Tracer processa as transações.

Exemplos de expressões:

```
amount > 10000
```

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

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

(`merchant.category` é o código MCC de 4 dígitos da ISO 18245. `"7995"` é o MCC para apostas/cassino. O Tracer aceita tanto `merchant.category` quanto `merchant["category"]`. Os exemplos de produção usam a notação de colchetes por convenção. Se você precisar corresponder a um rótulo de texto como `"gambling"`, armazene-o em `metadata` e corresponda a esse campo.)

As expressões leem a requisição de validação por meio de onze variáveis. Para os tipos e formatos de campo por trás de cada uma, veja o [esquema ValidationRequest](https://docs.lerian.studio/pt/reference/products/tracer/validate-transaction.md) na referência da API.

| Variável | Tipo | O que você normalmente usa na correspondência |
| - | - | - |
| `amount` | number | O valor da transação, nas mesmas unidades que você envia na requisição: `"1500.00"` chega a uma expressão como `1500`. O intervalo seguro é `±2^53`. |
| `scheme` | string | O esquema de pagamento, em maiúsculas (por exemplo, `"PIX"`). String vazia quando a requisição não traz nenhum. |
| `transactionType` | string | O nome obsoleto de `scheme`, com o mesmo valor. |
| `subType` | string | Texto livre, em minúsculas (por exemplo, `"international"`, `"debit"`). String vazia quando não fornecido. |
| `asset` | string | De 1 a 100 letras maiúsculas (por exemplo, `"BRL"`). |
| `transactionTimestamp` | int | Horário da transação em nanossegundos Unix. Divida por `1000000000` para obter segundos. |
| `account` | map | `accountId`, `type`, `status`, `metadata`. |
| `segment` | map | `segmentId`, `name`, `metadata`. |
| `portfolio` | map | `portfolioId`, `name`, `metadata`. |
| `merchant` | map | `merchantId`, `name`, `category`, `country`, `metadata`. |
| `metadata` | map | Campos customizados que sua integração passa no payload da requisição. |

Valores de campo que vale a pena conhecer antes de escrever uma condição:

* `account.status` e `account.type` são texto livre, com até 50 e 256 caracteres. Sua expressão os recebe como você os envia.
* `merchant.category` recebe um código MCC de 4 dígitos da ISO 18245. `merchant.country` recebe um código ISO 3166-1 alpha-2.
* Esses quatro campos são opcionais na requisição. Uma condição que testa um campo omitido para um valor específico não se cumpre.
* `segment.segmentId`, `portfolio.portfolioId`, `account.accountId` e `merchant.merchantId` são strings UUID.

> [!NOTE]
>
> `segmentId` e `portfolioId` vivem nas variáveis de nível superior `segment` e `portfolio`, não em `account`. Para corresponder por segmento, escreva `segment.segmentId == "..."`, não `account.segmentId == "..."`.
>
> Quando a própria presença é a condição que você quer, escreva `size(segment) > 0` ou `"risk_score" in metadata`.

> [!NOTE]
>
> O Tracer limita o custo da expressão com `CEL_COST_LIMIT` (padrão `10000`). A verificação roda em tempo de compilação (na criação, na atualização da expressão e novamente na ativação), não apenas na ativação. O Tracer rejeita uma expressão cujo custo estimado no pior caso excede o limite, na primeira vez que você a envia, com o código de erro `0342` (limite de custo excedido). Erros de sintaxe aparecem como `0340`, erros de tipo (incluindo uma expressão que não retorna um booleano) como `0341`, e uma falha total ao estimar o custo como `0345`.

### Exemplos de expressões por caso de uso

Aqui estão exemplos práticos por cenário de negócio:

#### Regras baseadas em valor

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

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

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

#### Regras baseadas em comerciante

```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
```

#### Regras baseadas em conta

```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"
```

#### Condições combinadas

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

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

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

#### Regras baseadas em tempo

```cel theme={null}
// Review late-night card transactions above BRL 5,000
scheme == "CARD" && amount > 5000 && timestamp(transactionTimestamp / 1000000000).getHours("UTC") >= 22

// Review weekend transactions above BRL 10,000
timestamp(transactionTimestamp / 1000000000).getDayOfWeek("UTC") in [0, 6] && amount > 10000
```

#### Usando metadados

```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]
>
> Sua integração fornece campos de metadados. Projete seu payload para incluir o contexto que suas regras precisam.

### Ações

As ações determinam a decisão quando uma expressão avalia para verdadeiro:

| Ação | Descrição |
| - | - |
| `ALLOW` | Permite a transação |
| `DENY` | Nega a transação |
| `REVIEW` | Encaminha para revisão manual |

### Escopos

Escopos definem a quais transações uma regra se aplica. Uma regra sem `scopes` é **global** e é avaliada em relação a toda transação. Uma regra com um ou mais objetos de escopo é avaliada apenas quando a transação corresponde a pelo menos um deles (semântica OR entre objetos de escopo).

Dentro de um único objeto de escopo, os campos aceitos são:

* `segmentId` - corresponde a transações de um segmento específico
* `portfolioId` - corresponde a transações de um portfólio específico
* `accountId` - corresponde a transações de uma conta específica
* `merchantId` - corresponde a transações para um comerciante específico
* `scheme` - corresponde a um esquema de pagamento, como `CARD` ou `PIX`. `transactionType` é o nome obsoleto desse campo
* `subType` - corresponde a subtipos específicos (debit, credit, instant etc.)

**Semântica de correspondência:**

* **Dentro de um objeto de escopo:** os campos se combinam com AND. Um campo que você omite funciona como coringa (corresponde a qualquer valor). Você deve definir pelo menos um campo. O Tracer rejeita objetos de escopo vazios (`{}`) com o código de erro `0358`.
* **Entre múltiplos objetos de escopo na mesma regra:** eles se combinam com OR. A regra corresponde se qualquer objeto de escopo corresponder à transação.

Por exemplo, uma regra com dois escopos (um direcionado a `scheme: CARD` e outro a `scheme: PIX`) roda tanto para transações de cartão quanto de Pix. Um único escopo com `segmentId` E `accountId` exige que a transação corresponda ao segmento E à conta.

***

## Ciclo de vida da regra

***

As regras avançam por um ciclo de vida definido para garantir um deploy seguro.

![Ciclo de vida de regras e limites no Tracer, mostrando as transições de status que uma definição percorre da criação até a aplicação ativa](https://mintcdn.com/lerian-49cb71fc/TGLv2g3qhXqf0dqb/images/pt/d2/rules-limits-lifecycle-tracer.svg?fit=max\&auto=format\&n=TGLv2g3qhXqf0dqb\&q=85\&s=dd2a8bcdc09f13bfa1f595facd3f8857)

Figura 2. Ciclo de vida das regras e transições de status

### Estados

| Estado | Descrição |
| - | - |
| `DRAFT` | Não avaliada; a expressão pode ser modificada livremente |
| `ACTIVE` | Avaliada durante as validações; a expressão é imutável |
| `INACTIVE` | Não avaliada; preservada para a trilha de auditoria; pode ser reativada. A expressão continua imutável nesse estado. Para editá-la, mova a regra de volta para DRAFT via `POST /v1/rules/{id}/draft`. |
| `DELETED` | Excluída em soft-delete; não é retornada pelas listagens e não pode ser recuperada pela API, mas a linha é preservada no banco de dados para a trilha de auditoria. |

### Transições

| Transição | De | Para | Descrição |
| - | - | - | - |
| `activate` | DRAFT, INACTIVE | ACTIVE | Inicia a avaliação (valida a expressão) |
| `deactivate` | ACTIVE | INACTIVE | Para a avaliação |
| `draft` | INACTIVE | DRAFT | Reedita uma regra previamente desativada antes de reativar |
| `delete` | DRAFT, INACTIVE | DELETED | Remoção permanente (não é possível excluir regras ACTIVE) |

> [!NOTE]
>
> Você deve desativar regras ativas antes da exclusão. Isso evita a remoção acidental de regras que o Tracer ainda avalia.

***

## Criar uma regra

***

Crie regras usando `POST /v1/rules`. Por padrão, o Tracer cria regras no status `DRAFT`.

Uma regra exige:

* **name**: um nome descritivo, único dentro do seu contexto. Os escopos da regra decidem o contexto (o menor `segmentId` entre eles), e regras sem escopo compartilham um único contexto global. Então o mesmo nome de regra pode coexistir entre dois segmentos diferentes, mas não duas vezes dentro de um mesmo segmento. A comparação diferencia maiúsculas de minúsculas e preserva espaços em branco internos, e o Tracer remove espaços em branco no início e no fim antes de armazenar. Uma colisão retorna `409 Conflict` com o código de erro `0441`. Referencie a regra pelo `ruleId` da resposta.
* **expression**: uma expressão CEL que avalia para verdadeiro ou falso
* **action**: a decisão a retornar quando a expressão corresponde (ALLOW, DENY ou REVIEW)
* **scopes** (opcional): limita a quais transações a regra se aplica

Para a estrutura completa do payload e detalhes dos campos, veja a [referência da API](https://docs.lerian.studio/pt/reference/products/tracer/create-rule.md).

***

## Ativar e desativar regras

***

Depois de criar uma regra, ative-a para começar a avaliação. Desative regras para parar a avaliação sem excluí-las.

| Operação | Endpoint | Descrição |
| - | - | - |
| Ativar | `POST /v1/rules/{id}/activate` | Começa a avaliar esta regra |
| Desativar | `POST /v1/rules/{id}/deactivate` | Para a avaliação (preserva para auditoria) |

> [!NOTE]
>
> Desativar uma regra a preserva para fins de auditoria. Use a exclusão apenas quando quiser remover uma regra permanentemente.

***

## Listar e consultar regras

***

Consulte regras para gerenciamento e auditoria usando `GET /v1/rules`.

### Parâmetros de consulta

| Parâmetro | Tipo | Descrição |
| - | - | - |
| `name` | string | Filtra por nome (correspondência parcial sem diferenciar maiúsculas de minúsculas) |
| `status` | string | Filtra por status (DRAFT, ACTIVE, INACTIVE). `DELETED` não é um valor de filtro válido. |
| `action` | string | Filtra por ação (ALLOW, DENY, REVIEW) |
| `account_id` | UUID | Filtra por escopo: ID da conta |
| `segment_id` | UUID | Filtra por escopo: ID do segmento |
| `portfolio_id` | UUID | Filtra por escopo: ID do portfólio |
| `merchant_id` | UUID | Filtra por escopo: ID do comerciante |
| `scheme` | string | Filtra por escopo: esquema de pagamento, como `CARD` ou `PIX`. `transaction_type` é o nome obsoleto desse filtro |
| `sub_type` | string | Filtra por escopo: subtipo (por exemplo, debit, credit) |
| `limit` | integer | Itens por página (padrão: 10, máximo: 100) |
| `cursor` | string | Cursor de paginação da resposta anterior |
| `sort_by` | string | Campo de ordenação: `created_at`, `updated_at`, `name`, `status` (padrão: `created_at`) |
| `sort_order` | string | Direção de ordenação: `ASC`, `DESC` (padrão: `DESC`) |

### Obter uma regra específica

Use `GET /v1/rules/{id}` para recuperar a definição completa da regra, incluindo expressão e escopos.

***

## Atualizar uma regra

***

Atualize uma regra com `PATCH /v1/rules/{id}`. Uma regra com status `DRAFT`, `ACTIVE` ou `INACTIVE` aceita mudanças no nome, na descrição, na ação e nos escopos. A expressão tem uma restrição:

> [!WARNING]
>
> O campo `expression` é imutável nos estados ACTIVE e INACTIVE. Desativar uma regra não é suficiente. Para editar uma expressão, mova a regra de ACTIVE → INACTIVE (`POST /v1/rules/{id}/deactivate`), depois de INACTIVE → DRAFT (`POST /v1/rules/{id}/draft`). Apenas regras DRAFT aceitam atualizações de expressão. Depois de editar, reative com `POST /v1/rules/{id}/activate`.

***

## Excluir uma regra

***

Exclua regras que você não precisa mais. Você pode excluir apenas regras DRAFT e INACTIVE. Desative regras ACTIVE primeiro.

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

> [!WARNING]
>
> A exclusão é permanente. Você não pode recuperar regras excluídas, e elas não aparecem em nenhuma listagem.

***

## Boas práticas

***

Siga estas práticas para regras eficazes e fáceis de manter.

### Nomenclatura

* **Use nomes descritivos** - o nome deve deixar claro o que a regra faz
* **Inclua contexto** - mencione o cenário ou tipo de transação
* **Evite abreviações** - prefira clareza a brevidade

| Menos claro | Mais 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` |

### Design de expressões

* **Mantenha as expressões simples** - lógica complexa é mais difícil de manter
* **Use escopos para filtragem** - não repita condições de escopo nas expressões
* **Teste casos extremos** - considere valores limite e campos nulos

### Gerenciamento do ciclo de vida

* **Comece em DRAFT** - teste antes de ativar
* **Volte para DRAFT antes de editar a expressão** - a expressão é imutável em ACTIVE e INACTIVE. Mova a regra para DRAFT via `POST /v1/rules/{id}/draft` para editar, depois reative
* **Arquive regras não usadas** - mantenha a trilha de auditoria intacta
* **Exclua apenas quando tiver certeza** - a exclusão é permanente

### Monitoramento

* **Revise as regras correspondentes** - verifique quais regras disparam
* **Monitore as taxas de DENY** - taxas altas de negação podem indicar regras excessivamente agressivas
* **Audite regularmente** - garanta que as regras ainda estejam alinhadas com os requisitos de negócio

> [!WARNING]
>
> **Armadilhas comuns ao trabalhar com regras:**
>
> * **"Editei a expressão, mas a mudança não teve efeito."** A expressão é imutável nos estados ACTIVE e INACTIVE. Mova a regra de volta para DRAFT via `POST /v1/rules/{id}/draft`, edite e depois reative. Apenas INACTIVE não basta.
> * **"Minha regra está ACTIVE, mas outra instância do Tracer ainda não está avaliando essa regra."** A ativação tem efeito imediato na instância que atendeu a chamada de ativação. Quando você roda várias instâncias atrás de um load balancer, as outras pegam a mudança na próxima sincronização de regras (`RULE_SYNC_POLL_INTERVAL_SECONDS`, padrão `10`). A desativação se propaga da mesma forma. Planeje os testes de integração considerando essa janela quando as chamadas podem cair em instâncias diferentes.
> * **"Quero excluir uma regra ACTIVE."** Não é possível. Chame `POST /v1/rules/{id}/deactivate` primeiro, depois `DELETE /v1/rules/{id}`. Isso força um passo visível em que a regra deixa de afetar o tráfego antes de desaparecer das listagens.
> * **"Meu escopo vazio `{}` é rejeitado com o código de erro `0358`."** Todo objeto de escopo deve ter pelo menos um campo definido. Para rodar uma regra globalmente (contra toda transação), omita o array `scopes` completamente. Não envie `{}`.

***

## Referência rápida

***

Principais endpoints, ações e informações de status.

### Endpoints

| Operação | Método | Endpoint |
| - | - | - |
| Criar regra | POST | `/v1/rules` |
| Listar regras | GET | `/v1/rules` |
| Obter regra | GET | `/v1/rules/{id}` |
| Atualizar regra | PATCH | `/v1/rules/{id}` |
| Excluir regra | DELETE | `/v1/rules/{id}` |
| Ativar regra | POST | `/v1/rules/{id}/activate` |
| Desativar regra | POST | `/v1/rules/{id}/deactivate` |
| Mover regra para draft | POST | `/v1/rules/{id}/draft` |

### Status

| Status | Avaliado | Editável | Pode excluir |
| - | - | - | - |
| `DRAFT` | Não | Sim | Sim |
| `ACTIVE` | Sim | Parcial (expressão imutável) | Não (desative primeiro) |
| `INACTIVE` | Não | Parcial (expressão imutável; volte para DRAFT primeiro) | Sim |
| `DELETED` | Não | Não | N/A |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.