Skip to main content

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. Hay dos entradas. Cada una queda registrada en el campo source 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.
Los errores del propio flujo de reporte usan 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.
Los límites se comprueban en los dos lados:
Si el navegador no puede comprimir la imagen (sin contexto 2D o toBlob falla), compressImage devuelve el archivo original. Una captura original de más de 1,5 MB hace que el servidor rechace el reporte entero con invalid_images. El usuario solo ve el toast genérico de error.

Flujo de envío

El cliente envía un 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

Si faltan VITE_AUTH0_DOMAIN o VITE_AUTH0_AUDIENCE en el entorno de la función, getAuthConfig() lanza una excepción fuera del try. La función no devuelve un JSON controlado: la respuesta es un error del runtime de Vercel.

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.
Solo el mensaje principal es obligatorio. Si fallan el hilo de detalles o la subida de capturas, el error se registra en los logs de la función y la respuesta sigue siendo 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.
El texto del usuario y los datos técnicos se escapan (&, <, >) 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.
yarn dev solo levanta Vite, que no ejecuta las funciones de api/. En local, el envío de un reporte falla con el toast de error. Para probar el flujo completo, usa un deploy de Vercel.

Analítica

Evolución

Código