Sonda que verifica la entrega, no la disponibilidad
`GET /api/health/contact` responde 200 si un lead puede llegar a una persona ahora y 503 si no. Verifica dos cosas por separado: que el token del canal de notificación siga siendo válido (una petición real al proveedor, con timeout de 8 segundos) y que el registro de solicitudes sea escribible. La respuesta se compone solo de valores lógicos — nunca el token, el identificador del canal ni el nombre del bot. El resultado se mantiene en memoria 60 segundos, para que una sonda externa pulsada con frecuencia no se convierta ella misma en tráfico. Cuando el proveedor es inaccesible, el campo pasa a `null`, no `false`: «no sé» e «inválido» son estados distintos.
Registro escrito antes de la entrega, no después
Cada solicitud recibe un identificador y se escribe en un registro append-only, una línea JSON por evento, *antes* de intentar la notificación. La segunda línea, con el mismo identificador, dice qué ocurrió realmente: `delivered` o `failed`, con el motivo truncado a 300 caracteres. El directorio se crea con permisos `0700`, los archivos con `0600`, y la ruta se coloca deliberadamente fuera del directorio de versión, para que el historial sobreviva a una publicación.
Verificación de aceptación ejecutada después de la publicación
Un script de verificación abre cada página de producto, en grupos de tres, y falla si falta el código 200, el ancla de preguntas, el ancla de ejemplo o la dirección canónica. Luego comprueba el mapa del sitio — que no contenga variantes de idioma que no se puedan abrir y que contenga cada producto — y `robots.txt`, para que no bloquee los recursos necesarios para el renderizado. También falla si reaparece en la página contenido de un cliente antiguo. Es una lista de cosas que ya se rompieron una vez.
Actualizaciones con gate, no con esperanza
El script de publicación se niega a arrancar si el servidor tiene menos de 500 MB de memoria libre, ejecuta `npm audit --audit-level=high` y se detiene ante vulnerabilidades de nivel alto si no confirmas explícitamente, luego construye desde limpio — `.next` y `node_modules` eliminados, instalación desde el archivo de bloqueo. Si el proceso no aparece `online` tras el arranque, el script muestra las últimas 50 líneas del registro y sale con error, en lugar de informar éxito.
Reinicio con umbrales, no al azar
El proceso se reinicia automáticamente por encima de 500 MB de memoria, con una demora de 4 segundos entre intentos, crecimiento exponencial de la demora y parada después de 10 reinicios inestables — para que un bucle de caída se vuelva visible en lugar de consumir el servidor en silencio. Tiempo de gracia al detenerse: 5 segundos, luego terminación forzada. Los registros tienen fecha y zona horaria, en un solo flujo.
Duplicados tratados, no contados dos veces
La misma persona, el mismo mensaje, dos veces — un doble clic, una recarga de la página — producía dos notificaciones idénticas para una sola solicitud. Ahora la huella `sha256` del par dirección + mensaje se mantiene 10 minutos en memoria; el segundo envío recibe el mismo identificador de solicitud y la marca `duplicate`, y la notificación no se repite. Solo se suprimen los duplicados de una entrega exitosa; una fallida puede pasar de nuevo.
Códigos de error que dicen qué se rompió
400 para datos inválidos, 405 por método incorrecto, 500 para cuerpo de solicitud roto, 502 cuando el canal de entrega respondió mal, 503 cuando faltan credenciales. La diferencia importa a las 3 de la mañana: 502 significa «el proveedor», 503 significa «nuestra configuración». Al visitante se le dice de forma distinta «hemos recibido la solicitud, pero no pudimos notificar» — no un falso éxito.
Retención aplicada por código, no prometida en la política
La nota de confidencialidad publicada dice que las solicitudes del formulario se conservan 24 meses. El código aplica exactamente el mismo número: `LEAD_RETENTION_DAYS` por defecto 730, y los archivos más antiguos que el umbral se eliminan en cada escritura, sin un planificador que pueda olvidarse. La dirección IP se recorta al prefijo de red — `/24` en IPv4, `/48` en IPv6 — y se lee el último salto del encabezado, no el primero, porque el primero lo envía el cliente.
Encontramos también lo que nadie reclamó
El mismo recorrido por el código sacó a la luz dos cosas que ningún usuario había reportado: el límite de 10 solicitudes por minuto se podía eludir por completo, porque se leía el primer elemento del encabezado de direcciones redirigidas — el controlado por el cliente — y una ruta de iniciación de llamadas telefónicas estaba abierta de forma anónima, con nuestro coste y desde nuestro número, aunque el componente que la usaba ya no estaba montado en ningún sitio. Ambas reparadas y verificadas en producción.