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

# Architecture

> The horizon-api Pusher publisher, the lazily-loaded server client, and the best-effort degradation model.

## Components

| Component                     | Path                                             |
| ----------------------------- | ------------------------------------------------ |
| Lazy client + channel helpers | `lib/integration/pusher/pusher.client.ts`        |
| Publisher (single `trigger`)  | `lib/integration/pusher/pusher.publisher.ts`     |
| Event contract types          | `lib/integration/pusher/pusher.types.ts`         |
| Private-channel authorizer    | `app/api/v3/realtime/pusher/auth/route.ts`       |
| Shared React hook             | `@bbrandslab/ui` → `hooks/use-pusher-channel.ts` |

## Lazy server client

The `pusher` server SDK is imported **lazily** inside `getPusherClient()`. The
dependency stays out of the bundle until the four required environment
variables are present, so requests that never touch realtime remain
lightweight. The client is memoised per process.

```ts theme={null}
const client = await getPusherClient();
if (!client) {
  // No credentials → log-only no-op. The business flow continues.
  return;
}
await client.trigger(channels, event, data);
```

<Note>
  `getPusherClient()` returns `null` unless `INTEGRATION_PUSHER_APP_ID`,
  `INTEGRATION_PUSHER_KEY`, `INTEGRATION_PUSHER_SECRET` and
  `INTEGRATION_PUSHER_CLUSTER` are all set.
</Note>

## Best-effort publisher

`publishContractEvent()` is the single point that calls `trigger`. It swallows
its own failures with structured logging: a failed publish never breaks the
worker, webhook or admin action that produced it.

```mermaid theme={null}
flowchart TD
    call["publishContractEvent(payload)"] --> get{"getPusherClient()"}
    get -- null --> noop["Log info + return (no-op)"]
    get -- client --> trigger["client.trigger([contract, account], event, data)"]
    trigger -- ok --> health_ok["recordIntegrationOutcome('pusher', true)"]
    trigger -- throws --> classify{"5xx / network?"}
    classify -- yes --> health_down["recordIntegrationOutcome('pusher', false)"]
    classify -- no (4xx) --> health_ok2["recordIntegrationOutcome('pusher', true)"]
    trigger -. warn log .-> log["Structured warn (non-fatal)"]
```

A single event is fanned out to **both** the contract channel and the account
channel, so account-scoped and contract-scoped listeners receive the same
message.

## Health accounting

Only a **5xx or a network error** counts against Pusher's health verdict. A
`4xx` means our request was malformed (our bug), not that Pusher is down, so it
never flips the integration state. See [Operations](/realtime/operations) for
the health probe.
