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

# Operaciones

> Variables de entorno de OneSignal, el runbook de DLQ/replay, el health probe y el checklist de integración móvil.

## Variables de entorno

| Variable                         | Requerida | Propósito                                |
| -------------------------------- | --------- | ---------------------------------------- |
| `INTEGRATION_ONESIGNAL_API_KEY`  | Sí        | REST API key (header `Key <api_key>`).   |
| `INTEGRATION_ONESIGNAL_APP_ID`   | Sí        | App ID de OneSignal.                     |
| `INTEGRATION_ONESIGNAL_BASE_URL` | No        | Por defecto `https://api.onesignal.com`. |

<Note>
  Sin `API_KEY` / `APP_ID` el cliente degrada a log-only (no lanza)
  y el health probe reporta el componente como caído.
</Note>

## Idempotencia, reintentos y observabilidad

* **Idempotencia**: el consumidor usa `queue_event_id` como
  `queue_event.source_event_id`; una reentrega duplicada es un no-op.
* **Reintentos**: backoff exponencial en errores transitorios (5xx / red).
  `NonRetryableNotificationError` se convierte en un skip registrado sin reintento.
* **Tipos de evento**: segmentados por canal
  (`vercel_queue.notification.push|in_app|sms|live_activity`, fallback `…unified`).
* **Contexto de éxito**: los handlers devuelven `context.oneSignalId` para la correlación.

## Runbook — DLQ y replay

Los fallos que agotan los reintentos aterrizan en la infraestructura compartida de DLQ
(`queue_dead_letter` + `queue_replay_job`).

<Steps>
  <Step title="Detecta">
    Consulta `queue_dead_letter` filtrando por
    `event_type LIKE 'vercel_queue.notification.%'`.
  </Step>

  <Step title="Diagnostica">
    Revisa `queue_event_attempt` (último error) y los logs del handler por
    `correlation` / `queue_event_id`.
  </Step>

  <Step title="Corrige la causa raíz">
    Credenciales de OneSignal, número de teléfono o payload.
  </Step>

  <Step title="Reprocesa">
    Encola un `queue_replay_job` para las filas de `queue_event` afectadas.
  </Step>

  <Step title="Verifica">
    La fila pasa a `processed` con `context.oneSignalId`.
  </Step>
</Steps>

<Note>
  Forzar una API key inválida en dev es la forma más rápida de observar el
  ciclo reintento → DLQ → replay de extremo a extremo.
</Note>

## Salud

Una probe activa barata (`GET /apps/{app_id}`, sin consumir cuota) combinada
con tráfico real pinta el heartbeat `INTEGRATION_ONESIGNAL` en la página de
estado.

## Checklist de integración móvil

<Steps>
  <Step title="Inicializa el SDK">
    Usa el App ID de OneSignal del entorno.
  </Step>

  <Step title="Enlaza al usuario">
    En la autenticación llama a `OneSignal.login(auth.users.id)` para establecer el
    `external_id`.
  </Step>

  <Step title="Renderiza in-app">
    Maneja el push solo de datos del canal `in_app`.
  </Step>

  <Step title="Registra el teléfono">
    Persiste el teléfono E.164 del usuario para SMS.
  </Step>

  <Step title="Respeta las preferencias">
    Lee `GET /v3/notification/preference/me` y persiste los cambios con
    `PUT/PATCH .../me`.
  </Step>
</Steps>
