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

# Canales y eventos

> El naming de canales de Pusher, el contrato de eventos de contratos y el endpoint de autorización de canales privados.

## Contrato de canales

Los nombres de canal se construyen mediante helpers en `pusher.client.ts` — la única fuente de
verdad compartida entre el publisher y el autorizador.

| Helper                        | Canal                           | Visibilidad | Auth requerida |
| ----------------------------- | ------------------------------- | ----------- | -------------- |
| `contractChannel(contractId)` | `private-contract-{contractId}` | Privado     | Sí             |
| `accountChannel(accountId)`   | `private-account-{accountId}`   | Privado     | Sí             |
| `totemChannel(codeRaspberry)` | `totem-{codeRaspberry}`         | Público     | No             |

<Note>
  Los canales privados (prefijo `private-`) requieren un token de autorización firmado
  antes de que un cliente pueda suscribirse. El canal de tótem es público a propósito para que las
  UIs táctiles y los dashboards de NOC se suscriban sin un handshake.
</Note>

## Contrato de eventos

Los eventos del dominio de contratos se enumeran en `ContractPusherEvent`:

| Evento                         | Emitido cuando                                     |
| ------------------------------ | -------------------------------------------------- |
| `contract.status_changed`      | Transición de etapa del contrato.                  |
| `contract.signature_requested` | Contrato enviado al firmante.                      |
| `contract.signed`              | Firma completada / contrato activado.              |
| `contract.cancelled`           | Contrato cancelado por un administrador.           |
| `contract.rejected`            | Firma rechazada por un firmante (internal signer). |
| `contract.pdf_generated`       | Reservado — aún no hay publisher conectado.        |

## Autorizador de canales privados

`POST /api/v3/realtime/pusher/auth`

<Steps>
  <Step title="Autoriza">
    Requiere el permiso `pusher:auth`.
  </Step>

  <Step title="Valida el cuerpo">
    `socket_id` y `channel_name` son ambos obligatorios (`400` de lo contrario).
  </Step>

  <Step title="Impone el namespace">
    El canal debe coincidir con `^private-(contract|account)-[0-9a-f-]{36}$`;
    cualquier otra cosa se rechaza con `403`.
  </Step>

  <Step title="Firma">
    Devuelve el payload de auth de Pusher desde
    `authorizeChannel(socket_id, channel_name)`. Cuando Pusher no está configurado
    el endpoint devuelve `403`.
  </Step>
</Steps>

<Warning>
  La regex del namespace es la frontera de seguridad: un llamante que tiene `pusher:auth`
  solo puede suscribirse a canales de contract/account. El alcance de propiedad (qué
  contrato puede observar un usuario) lo impone la capa de sesión de la propia app llamante
  antes de que llegue a este endpoint.
</Warning>

### Solicitud de ejemplo

```json theme={null}
{
  "channel_name": "private-contract-2f1c4e9a-3b7d-4a2e-9c88-0f1a2b3c4d5e",
  "socket_id": "123456.7890"
}
```

### Respuesta de ejemplo

```json theme={null}
{
  "auth": "<app_key>:<hmac_signature>"
}
```
