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

# Tiempo real (Pusher)

> Cómo B Brands entrega eventos en tiempo real sobre Pusher Channels: eventos de dominio best-effort publicados por horizon-api y consumidos por los frontends a través de un único hook compartido.

<Info>
  Esta sección documenta la **capa de tiempo real de B Brands** construida sobre
  [Pusher Channels](https://pusher.com/channels). `horizon-api` publica eventos de
  dominio tipados (ciclo de vida de contratos digitales, telemetría de Maihue Street / NOC) a
  canales por entidad; los frontends se suscriben y reaccionan a ellos.
</Info>

## Qué es esto

El tiempo real es una **mejora de UX best-effort superpuesta sobre el estado autoritativo
REST/query — nunca una fuente de verdad**. Cuando una acción del backend debería
llegar a un cliente conectado de inmediato (un contrato se firma, un tótem envía un
frame de telemetría, se dispara una alerta NOC), el servidor dispara un evento de Pusher en el
canal que posee esa entidad. El cliente reacciona, típicamente invalidando una
query cacheada.

<CardGroup cols={2}>
  <Card title="Lo que el tiempo real hace" icon="bolt">
    Empuja una notificación ligera para que la UI se refresque sin esperar al
    próximo poll.
  </Card>

  <Card title="Lo que el tiempo real NO hace" icon="circle-xmark">
    Nunca transporta estado autoritativo y nunca garantiza la entrega. Si un
    mensaje se pierde, la capa REST/query sigue siendo correcta.
  </Card>
</CardGroup>

## Degradación elegante

Las credenciales de Pusher son **opcionales en cada entorno**:

* Sin credenciales del servidor, el publisher corre en modo **log-only** (el
  trigger es un no-op) y nunca lanza.
* Sin una key del cliente, el hook de suscripción reporta `status: "disabled"` y
  los consumidores recurren al polling.

<Warning>
  Nunca trates un evento de Pusher como una señal transaccional. Cada consumidor debe
  permanecer correcto si el evento se descarta, se duplica o llega fuera de orden.
</Warning>

## Cómo fluye la señal

```mermaid theme={null}
flowchart LR
    subgraph api [horizon-api]
        producer["Worker / webhook / admin service"]
        publisher["publishContractEvent()"]
        authz["POST /api/v3/realtime/pusher/auth"]
    end
    subgraph pusher [Pusher Channels]
        channel["private-contract-{id}<br/>private-account-{id}<br/>totem-{code}"]
    end
    subgraph client [Browser]
        hook["usePusherChannel"]
        query["Invalidate React Query"]
    end

    producer --> publisher --> channel
    hook -->|"subscribe (private → authz)"| authz
    channel --> hook --> query
```

## Adónde ir después

<CardGroup cols={2}>
  <Card title="Arquitectura" icon="sitemap" href="/es/realtime/architecture">
    El publisher, el cliente perezoso y el modelo de degradación.
  </Card>

  <Card title="Canales y eventos" icon="list" href="/es/realtime/channels-and-events">
    El naming de canales, el contrato de eventos y el autorizador de canales privados.
  </Card>

  <Card title="Integración de clientes" icon="plug" href="/es/realtime/client-integration">
    El hook compartido `usePusherChannel` y el contrato de env del cliente.
  </Card>

  <Card title="Operaciones" icon="book" href="/es/realtime/operations">
    Variables de entorno, health probe y solución de problemas.
  </Card>
</CardGroup>
