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

# Eventos de domínio

> Um barramento interno, escrito na mesma transação das linhas que descreve.

Toda mutação de domínio publica um evento. Não para te dar um webhook hoje — para
impedir que os módulos que vão consumi-los se acoplem uns aos outros diretamente.

## O contrato do outbox

Um evento é escrito **na mesma transação das linhas que ele descreve**.

Essa única regra compra a garantia que importa: um evento nunca descreve uma escrita
que sofreu rollback, e uma escrita que comitou nunca deixa de produzir seu evento.
Publicar depois do commit tornaria os dois possíveis, e os dois são o tipo de bug
que aparece como "o contador está errado às vezes".

Depois do commit, a API cutuca a fila para drenar o outbox. A cutucada é
best-effort: ela compra latência. Uma varredura periódica é o que de fato garante a
drenagem, mesmo quando toda cutucada se perde.

## O que é publicado hoje

| Tipo                                   | Agregado       | Quando                                                                                                              |
| -------------------------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------- |
| `organization.created`                 | `organization` | Uma organização é criada, por cadastro ou por um usuário logado                                                     |
| `member.invited`                       | `invitation`   | Um convite é criado                                                                                                 |
| `member.role_changed`                  | `membership`   | O papel de um membro muda                                                                                           |
| `member.removed`                       | `membership`   | Um membro perde o acesso — removido, ou saiu. O payload diz qual dos dois                                           |
| `organization.usage_threshold_reached` | `organization` | Os contatos ativos do mês cruzaram 80% ou 100% do limite gratuito                                                   |
| `contact.identified`                   | `contact`      | Um contato deixa de ser só um visitante                                                                             |
| `contact.merged`                       | `contact`      | Um contato é absorvido por outro                                                                                    |
| `contact.signed_in`                    | `contact`      | Uma sessão autenticada foi emitida para um contato identificado, com como (`method`) e de onde (`ip`, `user_agent`) |

Todo evento carrega a organização a que pertence; os do plano de clientes carregam
também o ambiente.

### `contact.identified` dispara uma vez

Só na transição de verdade. Um segundo magic link é um login, não uma segunda
identificação — o SQL que marca o contato como identificado informa se mudou alguma
coisa, e o evento só é publicado quando mudou.

## Payloads carregam ids

```json theme={null}
{
  "type": "member.invited",
  "organization_id": "…",
  "aggregate_type": "invitation",
  "aggregate_id": "…",
  "payload": { "role_id": "…", "invited_by": "…" }
}
```

Ids, não valores. Consumidores releem a linha, o que mantém endereços de e-mail e
nomes fora de toda fila, log e buffer de retry por onde o envelope passa. Também
significa que um consumidor atrasado lê o estado *atual* em vez de uma cópia velha.

## Entrega é ao menos uma vez, e fora de ordem

Duas propriedades que já valem hoje, e que vão continuar valendo quando esses
eventos virarem webhooks: a mesma entrega pode chegar duas vezes, e a ordem de
chegada não é a ordem dos fatos. Cada envelope carrega uma sequência global
atribuída no commit — é ela que ordena, não o relógio da chegada.

## Webhooks de saída

Ainda não. O barramento interno é a fundação sobre a qual eles vão ser construídos:
quando os webhooks de saída chegarem, eles viram mais um consumidor dos mesmos
eventos, em vez de um segundo caminho de publicação costurado por todo handler.

Nada da lista acima muda de formato quando isso acontecer — é justamente esse o
motivo de ter o barramento primeiro.
