# Informes de problemas

> Cómo una automatización lista los informes de problemas abiertos enviados desde páginas de TradeCatalog conectadas.

Los empleados de proveedores y compradores identificados pueden enviar un error o una sugerencia desde cualquier página de la aplicación. Cada informe se almacena con el estado abierto y se envía por correo electrónico a Happy Webs.

Esta página es para la automatización que recoge estos informes. No es una clave de espacio de trabajo, y no está en el documento OpenAPI.

## Autenticar

La solicitud utiliza un token de portador. El token es el secreto del trabajador `FEEDBACK_REPORTS_TOKEN`.

Establézcalo una vez, fuera de git:

```bash
wrangler secret put FEEDBACK_REPORTS_TOKEN
```

Para desarrollo local, coloque el mismo nombre en `.dev.vars`. No confirme el valor.

Envíelo en cada solicitud:

```http
GET /api/feedback-reports?since=2026-10-15T00:00:00.000Z HTTP/1.1
Host: tradecatalog.app
Authorization: Bearer <FEEDBACK_REPORTS_TOKEN>
```

```bash
curl "https://tradecatalog.app/api/feedback-reports?since=2026-10-15T00:00:00.000Z" \
  -H "Authorization: Bearer $FEEDBACK_REPORTS_TOKEN"
```

Si el secreto falta, o el encabezado falta o es incorrecto, la respuesta es `401` con `WWW-Authenticate: Bearer realm="feedback-reports"`. No hay cookie, ninguna clave de API de espacio de trabajo y no hay CORS.

**GET** `/api/feedback-reports`

## Listar informes abiertos

`since` es necesario. Es una hora en formato ISO-8601 o un tiempo Unix en milisegundos. La lista es informes abiertos creados **después** de ese tiempo, en orden más antiguo primero, hasta 100.

| Nombre  | Tipo   | Requerido | Descripción                                                                                                                                                                             |
| ------- | ------ | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `since` | string | sí        | Límite inferior exclusivo en `createdAt`.                                                                                                                                               |
| `after` | string | no        | Identificador del informe. Con `since`, también devuelve informes que comparten ese tiempo exacto y se ordenan después de este identificador. Use ambos cuando `hasMore` sea verdadero. |

Un informe que se ha cerrado no está en esta lista, incluso si se creó después de `since`.

```json
{
  "reports": [
    {
      "id": "…",
      "kind": "bug",
      "status": "open",
      "message": "The price shows as zero.",
      "pageUrl": "https://tradecatalog.app/s/northgate/products",
      "tenantSlug": "northgate",
      "userId": "…",
      "role": "Owner",
      "email": "owner@example.com",
      "userAgent": "…",
      "viewport": "1440x900",
      "createdAt": "2026-10-15T12:00:00.000Z",
      "hasScreenshot": true,
      "screenshotUrl": "https://tradecatalog.app/api/feedback-reports/…/screenshot",
      "autoReplyText": null,
      "autoReplySentAt": null,
      "resolvedReplyText": null,
      "resolvedReplySentAt": null,
      "adminUrl": "https://tradecatalog.app/admin?section=reports&report=…"
    }
  ],
  "hasMore": false
}
```

Almacene el `createdAt` y `id` del último informe que guardó. La próxima consulta usa ese tiempo como `since`. Si la página estaba completa (`hasMore` es verdadero), también pase ese identificador como `after` y mantenga el mismo `since`, para que un informe guardado en el mismo milisegundo no se salte.

## Captura de pantalla

**GET** `/api/feedback-reports/{id}/screenshot`

El mismo token de portador. La respuesta es la imagen, o `404` cuando ese informe no tiene captura de pantalla. El identificador es el identificador del informe de la lista. No es una clave de objeto.

Los administradores de la plataforma también pueden abrir la captura de pantalla mientras están conectados en `/admin/feedback-reports/{id}` y resolver un informe en **Soporte → Informes**.

## Respuesta automática

Guardar un informe envía una nota breve al usuario conectado en su propia dirección. Resolverlo envía otra nota más, indicando que se ha solucionado y está en funcionamiento. Cada una se envía como máximo una vez por informe.

`autoReplyText` y `autoReplySentAt` son esa primera nota. `resolvedReplyText` y `resolvedReplySentAt` son la nota resuelta. Permanecen nulos hasta que se haya enviado el correo.

Establezca la variable Worker `FEEDBACK_AUTO_REPLY` en `off` para detener ambos. `AUTO_REPLY_BCC` es un secreto: la dirección copiada en esos correos. Deje que esté sin configurar y nada se copiará. El texto está redactado con el AI de Workers. Si ese borrador falla en una comprobación, se envía una nota fija en su lugar.

Cada informe también se convierte en un ticket numerado. Resolver ese ticket envía el mismo correo fijo y en funcionamiento una vez. El correo a soporte@ o info@tradecatalog.app se reenvía a `SUPPORT_FORWARD_TO` antes de que se lea, luego se archiva de la misma manera. Si esa dirección falta, o el reenvío falla, el mensaje se rechaza para que el remitente lo intente de nuevo. Se adjunta a una cuenta existente solo cuando `Authentication-Results` muestra un paso de DMARC, o ambos DKIM y SPF cuando DMARC esté ausente. De lo contrario, el ticket permanece sin enlazar y no se envía ninguna confirmación.
