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

# Operación

> Sincronización del catálogo, entregas de prueba, el sink de desarrollo, señales de dashboard y salud, permisos y límites conocidos del primer release.

## Sincronización del catálogo

La tabla `event` debe reflejar el catálogo generado antes de que los
suscriptores puedan elegir eventos. Dos mecanismos lo garantizan:

| Cuándo                             | Qué se ejecuta                                                                                                                                                                               |
| ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| En cada pull request               | `webhook:catalogue:generate --check` y `webhook:catalogue:docs --check` en la puerta **Quality** de CI — ni el catálogo en código ni esta documentación pueden desviarse del árbol de rutas. |
| En cada despliegue con migraciones | El job `catalogue-sync` de `database-migrate.yml` ejecuta `webhook:catalogue:sync --env <tier>` justo después de las migraciones Drizzle.                                                    |
| A demanda                          | `pnpm --filter @bbrandslab/horizon-api webhook:catalogue:sync --env development` (o `certification`, `production`).                                                                          |

Verifica con:

```bash theme={null}
curl https://api.bbrands.io/api/v3/webhook/catalogue/status \
  -H "Authorization: Bearer $TOKEN"
```

```json theme={null}
{
  "data": {
    "generated_count": 1438,
    "in_sync": true,
    "missing_internals": [],
    "stale_internals": [],
    "synced_count": 1438
  }
}
```

`missing_internals` lista eventos presentes en código pero aún no en la base
de datos; `stale_internals` lista filas de la base de datos que ninguna ruta
produce ya (siguen siendo suscribibles hasta que un operador las desactive).

## Entrega de prueba

`POST /api/v3/webhook/webhook/{id}/test` encola una entrega sintética
`webhook.test` hacia ese suscriptor y devuelve el `dispatch_id`. Síguela en
`GET /api/v3/webhook/dispatch/{dispatch_id}` o en la pantalla de detalle de
Horizon Enterprise. El webhook **no** necesita estar suscrito a
`webhook.test` para que la acción funcione; suscribirse solo permite
filtrar esas entregas después.

## Sink de desarrollo

`POST /api/v3/webhook/sink` es un endpoint suscriptor integrado que solo se
monta cuando `APP_ENV` es `development` o `certification` **y**
`WEBHOOK_SINK_SECRET` está definido. Verifica la firma con ese secreto,
registra `Webhook sink delivery accepted` con las cabeceras del sobre y
responde `200`, de modo que una fila de dispatch pasa a `success` sin ningún
sistema externo.

<Steps>
  <Step title="Crea un webhook apuntando al sink">
    `url = https://<host de la api>/api/v3/webhook/sink`, `is_global = true`.
    Copia el secreto `whsec_…` devuelto.
  </Step>

  <Step title="Comparte el secreto con la API">
    Define `WEBHOOK_SINK_SECRET` con ese valor en el entorno del tier y
    redespliega (o reinicia en local).
  </Step>

  <Step title="Envía una prueba">
    `POST /api/v3/webhook/webhook/{id}/test`, luego revisa la fila de
    dispatch y los logs de la API.
  </Step>
</Steps>

Producción nunca monta el sink: la ruta responde `404` allí sin importar la
variable.

## Dashboard y salud

| Señal                 | Dónde                                                         | Contenido                                                                                                                                                                                                  |
| --------------------- | ------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Resumen del dashboard | `GET /api/v3/webhook/dashboard/summary` (`webhook:dashboard`) | Entregas por estado en las últimas 24 h, webhooks activos vs desactivados automáticamente, conteos del catálogo y los 10 fallos más recientes. Se muestra en la portada de Webhooks de Horizon Enterprise. |
| Componente de salud   | `GET /api/v3/health/component/integration/webhook-out`        | `operational`, o `degraded` cuando las últimas 24 h muestran ≥ 10 entregas exhausted o algún webhook desactivado automáticamente. Basado en el libro mayor; nunca informa `down`.                          |
| Métricas              | `webhook_out_deliveries_total{status}`                        | Conteo histórico de entregas por estado, publicado por el job de métricas en la página de estado.                                                                                                          |

## Variables de entorno

| Variable                 | Propósito                                                                      |
| ------------------------ | ------------------------------------------------------------------------------ |
| `ENABLE_API_EVENT_QUEUE` | Interruptor maestro de la publicación. `false` = ningún evento sale de la API. |
| `WEBHOOK_SINK_SECRET`    | Secreto del webhook que apunta al sink de development/certification.           |

La tolerancia de firma (300 s), el calendario de backoff, el tope de
intentos (5) y el umbral de desactivación automática (20) son constantes de
código en `lib/webhook/outbound/webhook-out.constants.ts` y
`webhook-signature.ts`, no variables de entorno — forman parte del contrato
público y solo cambian con un release.

## Permisos

Todos los permisos de webhook se conceden únicamente al rol `administrator`
en este release. Los tokens de automatización deben portar los internals
concretos:

| Acción                                 | Permiso                                                                             |
| -------------------------------------- | ----------------------------------------------------------------------------------- |
| Listar / leer webhooks                 | `webhook:find-all`, `webhook:find-one`                                              |
| Crear / actualizar / eliminar / purgar | `webhook:create`, `webhook:update`, `webhook:delete`, `webhook:purge`               |
| Activar / desactivar                   | `webhook:active`                                                                    |
| Rotar secreto, entrega de prueba       | `webhook:rotate-secret`, `webhook:test`                                             |
| Exportar                               | `webhook:export`                                                                    |
| Dashboard, estado del catálogo         | `webhook:dashboard`, `webhook:catalogue-status`                                     |
| Reemplazar el conjunto de eventos      | `webhook-event:set` (más el CRUD `webhook-event:*`)                                 |
| Leer el libro mayor, replay            | `webhook-dispatch:find-all`, `webhook-dispatch:find-one`, `webhook-dispatch:replay` |
| Explorar el catálogo                   | `event:find-all`, `event:find-one`                                                  |

## Límites conocidos

* **Sin IP de egreso fija.** Las entregas salen del runtime serverless de la
  API; filtra por firma, no por dirección.
* **Cuerpo fino.** El payload nunca incluye el recurso; hace falta una
  segunda llamada a la API para leerlo.
* **Al menos una vez.** Reintentos y replays pueden repetir una entrega;
  deduplica por `id`.
* **Sin garantía de orden** entre eventos, incluso del mismo recurso.
* **La rotación de secreto no tiene ventana de solape.**
* **Los eventos de purga** llevan `data.account = null` y solo llegan a
  suscriptores globales.

## Relacionado

* Runbook interno del primer despliegue (pasos por tier, rollback, señales
  de día 2): `docs/initiatives/webhook/outbound/11-rollout-and-operations.md`
  en el monorepo.
* Referencia API: [Webhook](/api-reference/webhook/webhook/find-all),
  [Webhook Event](/api-reference/webhook/webhook-event/find-all),
  [Webhook Dispatch](/api-reference/webhook/webhook-dispatch/find-all),
  [Event](/api-reference/webhook/event/find-all).
