Reportes
El panel permite reportar un error o proponer una idea sin salir de la pantalla en la que estás. El reporte llega al equipo de producto en Slack con el contexto de la pantalla ya adjunto: sección, persona que lo envía, último error de red y enlace a la grabación de la sesión en PostHog. Hay dos piezas. En el navegador vive el diálogo de reporte (src/features/feedback/). En Vercel vive una función serverless (api/reports.ts) que autentica al usuario, valida el reporte y lo publica en Slack como bot.
Cómo se abre el diálogo
Hay dos entradas. Cada una queda registrada en el camposource del reporte.
El botón del toast solo aparece si el diálogo está montado.
ReportDialog vive en PortalRoot y marca isAvailable en su store al montarse. Por eso no hay botón de reporte en /login ni en /forgot-password. Los toasts reportables duran 8 segundos en vez del valor por defecto.toast.error(mensaje, { reportable: false }). Así no se ofrece reportar un fallo al enviar un reporte.
Qué rellena el usuario
El formulario usa React Hook Form con el schema de
components/ReportDialog/schema.ts. Cada vez que se abre el diálogo se resetea el formulario y se vacían las capturas.
Qué contexto se adjunta
El bloque Se adjunta automáticamente del diálogo enseña al usuario lo que se va a enviar.useReportContext construye el objeto context en el momento del envío:
El servidor no usa
reporterEmail para identificar a quien reporta. La persona sale siempre del token verificado. El campo viaja en el payload, pero no aparece en el mensaje de Slack.Capturas
Puedes adjuntar hasta 3 capturas. Hay tres formas: arrastrarlas al recuadro Añadir, hacer clic en él o pegarlas con ⌘V / Ctrl+V en cualquier punto del diálogo. Antes de enviarlas,compressImage las reescala en el navegador:
- El lado largo queda en 1600 px como máximo.
- Se reexportan como JPEG con calidad 0,8.
- El fondo transparente pasa a blanco.
- El archivo se renombra a
.jpg.
Flujo de envío
multipart/form-data con dos campos. report lleva el reporte serializado en JSON. images se repite una vez por captura. La petición usa Axios directamente contra /api/reports, no apiClient, y adjunta el token de la sesión en Authorization.
Si la respuesta es correcta, se muestra el toast de éxito, se cierra el diálogo y se registra el evento feedback_report_submitted en PostHog.
La función api/reports.ts
Es una función de Vercel que exporta un handler POST(request) con la API estándar de Request y Response. Hace las comprobaciones en este orden:
1
Autenticación
authenticate() (api/_lib/auth.ts) lee el Bearer y verifica el JWT de Auth0 con jose. Usa el JWKS del dominio de Auth0 y comprueba issuer y audience. Del token saca el sub y el email (claim email estándar o el claim con namespace de VIVLA). Cualquier sesión válida del panel puede reportar: no hay restricción por permiso ni por dominio de email.2
Tamaño
Rechaza la petición si
content-length supera 4 MB.3
Schema
Valida el campo
report con el schema Zod de api/_lib/reportSchema.ts. Reutiliza los enums de src/core/feedback/models/Report.ts, así que cliente y servidor comparten los valores válidos de tipo, urgencia y origen. La descripción admite entre 1 y 5000 caracteres. Cada campo de contexto tiene su propio tope de longitud.4
Imágenes
Comprueba que no haya más de 3 y que todas tengan un tipo permitido y pesen 1,5 MB o menos.
5
Entrega
deliverReport() (api/_lib/delivery.ts) publica en Slack.Respuestas
Entrega a Slack
El reporte se publica en el canal de reportes configurado, como el bot Panel VIVLA.api/_lib/slackApi.ts llama a la Web API de Slack con fetch y un timeout de 5 segundos por llamada. La subida de cada archivo tiene 15 segundos.
1
Buscar a quien reporta
users.lookupByEmail busca el email del token en Slack. Si lo encuentra, el mensaje menciona a la persona. Si no, se escribe el email en texto plano.2
Mensaje principal
chat.postMessage publica el reporte con el formato de las peticiones de producto (buildProductRequestMessage). Los enlaces no se despliegan (unfurl_links y unfurl_media a false).3
Hilo de detalles técnicos
Si hay grabación o petición fallida,
buildTechnicalDetails publica una respuesta en el hilo con el título Detalles técnicos.4
Capturas en el hilo
Cada imagen se sube con
files.getUploadURLExternal. Después, files.completeUploadExternal las comparte en el mismo hilo, tituladas Captura 1, Captura 2 y Captura 3.202.
Formato del mensaje principal
El mensaje empieza con la cabecera “Petición enviada desde el panel” y sigue con estos campos:
Si
section es null, el enlace de la pantalla muestra la ruta de la URL.
Hilo de detalles técnicos
Solo se publica si hay al menos una de estas líneas:- Ver grabación en PostHog: enlace a la grabación, posicionado 30 segundos antes del envío.
- Última petición fallida: método y URL, estado HTTP (o “sin respuesta”), código de la API si lo hay, mensaje y hora del fallo en horario de Madrid.
&, <, >) antes de publicarse. Así no rompen el formato de Slack.
Configuración
Variables del entorno de la función en Vercel:SLACK_BOT_TOKEN y SLACK_CHANNEL_ID no están en env.template. Solo existen en el entorno de Vercel. Si faltan, la función responde 502 y deja el aviso en sus logs.