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

# Eventos de Reporter

> Suscríbete a los eventos de informes y plazos de Reporter: la operación de manifiesto de streaming, el envelope de CloudEvents, las políticas de entrega y qué transporta cada payload.

Reporter publica un evento de negocio cada vez que una plantilla, un informe o un plazo cambia de estado. Suscríbete a esos eventos y sabrás que un informe terminó sin sondear `GET /v1/reports/{id}` para averiguarlo.

`GET /v1/streaming/events` describe el contrato en formato legible por máquina. Esta página cubre el lado del consumidor: qué te dice el manifiesto, qué llega por el cable y qué transporta cada evento.

## La operación de manifiesto

***

[Streaming events](/es/reference/products/reporter/get-streaming-events) devuelve el catálogo estático de eventos. Requiere autenticación como cualquier otra operación. Responde con `Cache-Control: no-store`, y responde independientemente de si este despliegue publica eventos o no. Léelo al arrancar para confirmar que tu consumidor y Reporter coinciden en el contrato.

La respuesta expone la identidad de la aplicación y el catálogo:

| Campo       | Qué transporta                                                                                                                                                                                                            |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `version`   | Versión semántica del formato de cable del manifiesto.                                                                                                                                                                    |
| `publisher` | Quién publica: `serviceName` y `source` son `reporter`, `routePath` es esta operación y `outboxSupported` es `true`, además de las versiones de la aplicación y de la librería.                                           |
| `events`    | Una entrada por definición de evento, con su clave, `eventKey`, tipo de recurso, tipo de evento, `class`, versión de esquema, descripción y política de entrega predeterminada. Reporter emite únicamente eventos `fact`. |
| `routes`    | Omitido. Reporter no publica la topología del broker a través de la API.                                                                                                                                                  |

## Enrutamiento del broker

***

El manifiesto no revela un tema ni la topología del broker. Vincula tu cola al exchange nombrado por `RABBITMQ_REPORT_EVENTS_EXCHANGE`. Cada mensaje usa la clave de la definición de evento tal cual como su routing key de AMQP: `report.finished`, `deadline.delivery_reverted`, guiones bajos incluidos.

## El catálogo de eventos

***

Existen doce definiciones de evento entre los dos modos de ejecución.

| Evento                       | Se emite cuando                                                                 | Perfil de entrega |
| ---------------------------- | ------------------------------------------------------------------------------- | ----------------- |
| `template.created`           | Se sube una plantilla.                                                          | Importante        |
| `template.updated`           | Cambia el archivo o los metadatos de una plantilla.                             | Importante        |
| `template.deleted`           | Se elimina una plantilla, con el conteo de plazos que se eliminaron en cascada. | Importante        |
| `report.requested`           | Se acepta y encola una solicitud de informe.                                    | Importante        |
| `report.finished`            | Todas las secciones de datos tuvieron éxito y el artefacto queda almacenado.    | Crítico           |
| `report.partial`             | Algunas secciones fallaron. Existe un artefacto.                                | Crítico           |
| `report.errored`             | El informe terminó en error.                                                    | Crítico           |
| `deadline.created`           | Se crea un plazo.                                                               | Importante        |
| `deadline.updated`           | Cambia un plazo.                                                                | Importante        |
| `deadline.deleted`           | Se elimina un plazo.                                                            | Importante        |
| `deadline.delivered`         | Se marca un plazo como entregado.                                               | Crítico           |
| `deadline.delivery_reverted` | Se revierte una marca de entrega.                                               | Crítico           |

Este canal es solo de publicación. Reporter emite estos eventos y no consume ninguno de ellos.

## Entrega

***

Todo evento del manifiesto tiene la clase `fact`. El perfil de entrega de la tabla anterior selecciona su política de entrega.

| Perfil de entrega | Publicación directa | Outbox                                       | DLQ de ruta    |
| ----------------- | ------------------- | -------------------------------------------- | -------------- |
| Importante        | Sí                  | Recurre al outbox cuando el circuito se abre | No configurado |
| Crítico           | No                  | Siempre                                      | No configurado |

Por lo tanto, un evento con el perfil de entrega `Critical` nunca se publica directamente al broker. Reporter lo escribe en el outbox de streaming durable de Mongo después del commit del estado de negocio, y un dispatcher lo reproduce tras una interrupción del broker.

La escritura del estado y la inserción en el outbox son operaciones separadas, no una única transacción atómica de aplicación. Ese hueco es una ventana de falla: una caída o una inserción fallida en el outbox después del commit del estado pierde el evento. Ninguna conciliación lo recupera. La pérdida deja solo un registro de error y una métrica. Una vez que la fila está en el outbox, el dispatcher reintenta hasta lograr la entrega.

La política solicita manejo de dead-letter para las fallas enrutables, pero las rutas actuales de RabbitMQ no proveen un destino explícito de DLQ. Esa falla se expone y se registra, sin ninguna copia forense en dead-letter.

La emisión ocurre después del commit y nunca hace fallar el trabajo. Un problema de publicación no convierte un informe almacenado en uno con error.

<Warning>
  La entrega es al menos una vez. Deduplica según `(ce-source, ce-id)`. Solo los hechos terminales de informe (`report.finished`, `report.partial` y `report.errored`) y las transiciones críticas de plazo (`deadline.delivered` y `deadline.delivery_reverted`) usan identificadores deterministas. Los eventos de plantilla, `report.requested` y los eventos de creación, actualización y eliminación de plazos dejan el identificador a cargo de `lib-streaming`.
</Warning>

## El envelope de CloudEvents

***

Los mensajes viajan en modo binario de CloudEvents, versión 1.0. Los atributos de contexto viajan como headers del mensaje.

| Header             | Valor                                                                                             |
| ------------------ | ------------------------------------------------------------------------------------------------- |
| `ce-specversion`   | `1.0`                                                                                             |
| `ce-id`            | Id opaco definido por el productor; determinista solo para las clases de evento descritas arriba  |
| `ce-source`        | `reporter`                                                                                        |
| `ce-type`          | `studio.lerian.reporter.<resource>.<event>`, por ejemplo `studio.lerian.reporter.report.finished` |
| `ce-time`          | Marca de tiempo de emisión en RFC 3339                                                            |
| `ce-subject`       | El identificador del informe, la plantilla o el plazo                                             |
| `ce-resourcetype`  | `report`, `template` o `deadline`                                                                 |
| `ce-eventtype`     | `finished`, `created`, `delivery_reverted`, y así sucesivamente                                   |
| `ce-schemaversion` | `1.0.0`                                                                                           |
| `ce-tenantid`      | El tenant propietario del cambio                                                                  |

Reporter marca los mensajes como persistentes. Un despliegue de un solo tenant igual estampa un valor de tenant, de modo que un consumidor maneja ambas formas de despliegue con el mismo código.

## Qué transporta un payload

***

Las claves del payload son `snake_case`, a diferencia de la superficie REST en camelCase. Un cuerpo de `report.finished`:

```json theme={null}
{
  "report_id": "019826f4-6a9c-7b31-9d40-2f1e8c5a4b77",
  "template_id": "8f2c1a9e-4b30-4c02-9a1b-2d5e6f7a1c33",
  "output_format": "pdf",
  "status": "Finished",
  "artifact_object_key": "org-01abc/reports/8f2c1a9e-4b30-4c02-9a1b-2d5e6f7a1c33/019826f4-6a9c-7b31-9d40-2f1e8c5a4b77.pdf",
  "artifact_content_type": "application/pdf",
  "completed_at": "2026-07-29T14:22:08Z",
  "duration_ms": 8421,
  "section_count": 3
}
```

`artifact_object_key` es la clave de objeto exacta que informa el almacenamiento después de la escritura, no una ruta que los consumidores deban reconstruir. En modo de un solo tenant tiene la forma `reports/<templateId>/<reportId>.<format>`. El modo multi-tenant antepone el mismo camino con el segmento de tenant. Usa el valor tal cual.

Si validas su segmento de tenant, compáralo con el tenant vinculado a tu suscripción autenticada, no con otro campo del mismo mensaje. Una clave vacía en `report.finished` o `report.partial` es una violación del contrato. [Descargar un informe](/es/reference/products/reporter/download-report) sigue siendo la forma admitida de obtener un informe en estado `Finished`.

`report.partial` agrega `section_failures` y `failed_section_count` junto a los mismos campos de artefacto. Una clave resoluble no significa que el informe esté completo. Enruta la entrega regulatoria solo desde `report.finished`, y decodifica estrictamente el campo `status` en lugar de usar la presencia de la clave como discriminador.

`report.errored` reemplaza los campos de artefacto por `error_code` y `error_summary`. Que le falte un campo de artefacto no demuestra que no se escribió ningún objeto: el almacenamiento puede tener éxito antes de que falle la persistencia del estado terminal, dejando un objeto que ningún evento nombra. Ambos campos de error provienen de un vocabulario fijo: `report_generation_failed`, `report_generation_timeout` o `report_generation_canceled`. Cada código tiene un resumen fijo. El texto de error crudo nunca viaja por el cable, de modo que un payload no puede filtrar una consulta, una cadena de conexión ni datos de tenant. Ramifica la lógica según `error_code`.

## Habilitar la publicación de eventos

***

La publicación de eventos es una decisión de despliegue, que se configura con `STREAMING_ENABLED`. Actívala y Reporter exige tres ajustes más al arrancar:

| Ajuste                            | Valor                                                                                                          |
| --------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `RABBITMQ_REPORT_EVENTS_EXCHANGE` | El exchange que transporta los eventos. Lo configura el operador; el valor de referencia es `reporter.events`. |
| `STREAMING_BROKERS`               | Debe estar presente y no vacío.                                                                                |
| `STREAMING_CLOUDEVENTS_SOURCE`    | Debe ser exactamente `reporter`; el arranque rechaza cualquier otro valor.                                     |

Cuando la publicación está apagada, `STREAMING_CLOUDEVENTS_SOURCE` puede quedar sin definir. Si está definido, igual debe ser exactamente `reporter`. Reporter rechaza cualquier otro valor no vacío al arrancar aun con la publicación apagada. Cuando la publicación está encendida, Reporter también se niega a arrancar si alguno de los tres ajustes está en blanco, de modo que un despliegue mal configurado falla al arrancar en lugar de descartar eventos en silencio.

## Próximos pasos

***

<CardGroup cols={2}>
  <Card title="API REST de Reporter" icon="code" href="/es/products/reporter/reporter-rest-api">
    Las 28 operaciones, la autenticación, la paginación y los errores.
  </Card>

  <Card title="Referencia de API" icon="list" href="/es/reference/introduction">
    La operación de manifiesto de streaming, con la forma completa de su respuesta.
  </Card>

  <Card title="Variables de entorno" icon="gear" href="/es/products/reporter/reporter-environment-variables">
    Cada ajuste detrás de las superficies de streaming, exchange y modo de ejecución.
  </Card>

  <Card title="¿Qué es Reporter?" icon="book" href="/es/products/reporter/what-is-reporter">
    Plantillas, informes, plazos y dónde encajan.
  </Card>
</CardGroup>
