Por qué las APIs del navegador están migrando de imperativo a declarativo
El cambio de interceptar peticiones de red línea por línea a declarar reglas por adelantado no es una moda de sintaxis. Es una respuesta directa a un problema de seguridad y rendimiento.
Durante años, interceptar y modificar el tráfico de red desde una extensión de navegador significaba escribir código imperativo: una función que se ejecutaba por cada petición, inspeccionaba sus datos, y decidía en tiempo real si bloquearla, redirigirla o dejarla pasar. Esa API es flexible, potente y, vista desde la perspectiva de quien diseña la plataforma del navegador, un riesgo de seguridad y rendimiento difícil de contener.
El problema del modelo imperativo
Un modelo donde código arbitrario de un tercero se ejecuta por cada petición de red tiene dos costos que crecen con el uso. El primero es de rendimiento: cada petición paga el costo de ejecutar ese código, sin importar qué tan simple o compleja sea la lógica, lo cual limita cuánto puede optimizar el navegador el pipeline de red en general. El segundo es de seguridad: código con esa capacidad de inspección puede, en principio, leer y modificar cualquier tráfico, lo cual convierte a cada extensión instalada en una superficie de ataque potencial sobre datos sensibles del usuario.
La alternativa declarativa
El modelo declarativo invierte la relación: en lugar de ejecutar código por cada petición, la extensión registra por adelantado un conjunto de reglas ("si la URL coincide con este patrón, bloquéala" o "si coincide con este otro, redirígela") y es el navegador, no el código de la extensión, quien evalúa esas reglas de forma nativa y optimizada. La extensión ya no necesita ejecutarse en el camino crítico de cada petición de red, lo cual elimina buena parte del costo de rendimiento, y las reglas registradas son auditables como datos, no como código arbitrario, lo cual reduce drásticamente la superficie de seguridad.
Lo que se gana y lo que se pierde
El modelo declarativo no es estrictamente superior, es un trade-off distinto. Se gana rendimiento predecible y una superficie de seguridad mucho más pequeña y auditable. Se pierde la capacidad de tomar decisiones verdaderamente dinámicas basadas en lógica de negocio compleja evaluada en el momento exacto de cada petición, como analizar el contenido completo de una respuesta antes de decidir qué hacer con la siguiente.
Esto obliga a un cambio real en cómo se diseña sobre esta API: en lugar de escribir lógica de decisión en código, hay que anticipar los casos posibles y expresarlos como reglas declaradas de antemano, gestionando además el ciclo de vida de esas reglas (identificadores únicos, actualización, límites en la cantidad de reglas activas) como si fueran datos de configuración, no como efectos secundarios de ejecutar una función.
Por qué esto se repite en otros dominios
Este mismo movimiento (de código imperativo ejecutado en el camino crítico, a reglas declarativas evaluadas por una capa de plataforma optimizada) aparece en otros contextos con motivaciones parecidas: reglas de firewall declaradas en lugar de filtros de paquetes escritos a mano, políticas de autorización declaradas en lugar de checks de permisos dispersos por el código, configuración de infraestructura declarada en lugar de scripts imperativos de aprovisionamiento. En todos los casos, el patrón de fondo es el mismo: cuando una plataforma necesita razonar, optimizar o auditar un comportamiento a gran escala, prefiere que ese comportamiento se exprese como datos declarados, no como código arbitrario que solo se entiende ejecutándolo.
La lección
Elegir entre un diseño imperativo y uno declarativo no es una preferencia estética. Es una decisión sobre quién necesita razonar acerca del comportamiento del sistema, y con qué garantías. Cuando ese "quién" es una plataforma que necesita optimizar, auditar o dar garantías de seguridad a gran escala, declarativo casi siempre gana, aunque cueste más expresividad en el corto plazo.