El día que un parche menor de una dependencia tumbó el checkout de un cliente

Hace cosa de ocho meses actualizamos una librería de pagos en la tienda online de un cliente de moda infantil. Fue un npm update, ni siquiera un salto de versión mayor: de 4.2.1 a 4.2.3, dos parches. El changelog decía “bug fixes and performance improvements”, esa frase que no dice nada. Lo desplegamos un jueves por la tarde, sin pensarlo demasiado, porque llevábamos meses actualizando así sin problema.
Un parche menor de una dependencia puede tumbar producción sin que el changelog lo avise, sobre todo si toca timeouts o formatos de respuesta internos que la librería no considera parte de su “interfaz pública” — por eso ahora tratamos las actualizaciones de pagos, autenticación o envío de datos con más cuidado que las de un componente visual. Eso fue justo lo que nos pasó: el viernes a las diez de la mañana el cliente nos escribió porque el botón de “Finalizar compra” se quedaba cargando para siempre. No en todos los pedidos, solo en los que pagaban con un método de pago móvil concreto. Tardamos casi tres horas en encontrar que el parche había cambiado en silencio el formato de un timeout interno, y con conexiones lentas el SDK se moría antes de recibir la confirmación. Nada en el changelog lo mencionaba. Nada en los tests lo pillaba tampoco, porque nuestros tests de checkout usan una pasarela simulada que responde en 40 milisegundos, no en los 4 segundos reales de un móvil con mala cobertura en un pueblo cualquiera.
Desde entonces cambiamos la política, aunque me costó admitir que hacía falta cambiarla. Bueno, más que costar, tardé en aceptar que el problema no era mala suerte, era el proceso. Ahora cualquier librería que toque pagos, autenticación o envío de datos a terceros se actualiza a mano, se prueba en un dispositivo real con throttling de red, y espera al lunes. Las demás (utilidades, componentes de interfaz, cosas que si fallan se ven a simple vista) siguen el proceso automático de siempre.
No es una postura muy popular entre quien defiende que hay que estar siempre en la última versión por seguridad. Y en parte tienen razón: retrasar parches también tiene coste, sobre todo si el retraso es de meses en vez de días. Pero llevar cuatro años manteniendo webs de clientes me ha convencido de que “está en el changelog” y “lo vamos a notar” son cosas completamente distintas, y que el criterio para decidir qué actualizar rápido y qué no debería depender de qué se rompe si falla, no de lo fácil que sea automatizarlo.
Lo que todavía no tenemos resuelto es qué hacer con las dependencias transitivas, esas que ni siquiera aparecen en nuestro package.json y que trae otra librería de segundo o tercer nivel. Ahí Dependabot ni siquiera abre PR la mitad de las veces, y el fallo llega sin avisar, igual que cuando algo se rompe en producción y te enteras por una alerta en vez de por el changelog.