Paridad
La matriz de paridad clasifica las 120 filas de referencia de HAProxy 3.4.6 LTS, nginx 1.27.1, ingress-nginx y Envoy API v3: 61 de HAProxy, 20 de nginx, 19 de ingress-nginx y 20 de Envoy. Ninguna queda sin clasificar, y ninguna clasificación se apoya en «compila, luego funciona».
Resultado de v0.9.1: 11 E1 · 88 E2 · 21 E3 · 0 sin clasificar. Eso no es paridad completa y la página no lo pretende.
Qué significa cada clase
| Clase | Significado | Evidencia exigida |
|---|---|---|
| E1 | Misma semántica observable que la referencia | Un caso del corpus diferencial que corre contra la referencia y EQProxy y pasa |
| E2 | Equivalente con una diferencia conocida y documentada | Un test del comportamiento y la diferencia nombrada en la fila |
| E3 | Fuera de alcance por decisión | Un ADR público y una alternativa |
Un E1 solo se acepta si el corpus diferencial lo ejecuta: no se infiere de un test unitario ni de que el código parezca equivalente. Una fila cuyas semánticas compartidas están cubiertas pero cuyo conjunto de directivas no, conserva el E1 por lo cubierto y nombra lo que falta en la columna de diferencia.
Recuento por referencia
| Referencia | Filas | E1 | E2 | E3 |
|---|---|---|---|---|
| HAProxy 3.4.6 | 61 | 3 | 49 | 9 |
| nginx | 20 | 3 | 15 | 2 |
| ingress-nginx | 19 | 3 | 11 | 5 |
| Envoy API v3 | 20 | 2 | 13 | 5 |
| Total | 120 | 11 | 88 | 21 |
Las once filas E1 son: enrutamiento por host, ruta, cabecera y método, reescritura de URL y cabeceras y redirecciones de HAProxy (C3, C4, C5); hosts virtuales, location y cabeceras con X-Forwarded-For en nginx (B-N2, B-N3, B-N4); host y ruta, PROXY y X-Forwarded-*, y redirecciones y reescrituras en ingress-nginx (B-I2, B-I4, B-I6); enrutamiento avanzado y manipulación de cabeceras en Envoy (B-E3, B-E17).
Qué queda fuera
Lo que EQProxy no hace, por decisión escrita en un ADR:
- Pasarelas que no son HTTP: FastCGI, uwsgi, scgi (ADR-0032), AJP (ADR-0038), filtros Lua (ADR-0041).
- UDP: no hay listeners, balanceo ni checks UDP; lo único UDP es QUIC para HTTP/3 (ADR-0037).
- WAF y ModSecurity/CRS (ADR-0040); el rate limit no es anti-DDoS.
- Snippets de configuración (ADR-0042) y TPROXY /
original_dst(ADR-0039). - Almacén compartido entre instancias: stick-tables,
peers, rate limit global (ADR-0046/0047). - xDS y descubrimiento nativo: sin cliente xDS (ADR-0027), sin Consul ni Eureka ni watch del API server (ADR-0044).
- Algoritmos que no existen:
static-rr,random,RING_HASH/MAGLEV,lb_subset_config. - Actualización de binario y despliegue multi-instancia: reinicio escalonado detrás de un balanceador.
Lagunas conocidas y semántica más estrecha
Además de lo anterior, v0.9.1 tiene límites que conviene leer antes de probar nada:
| Punto | Estado |
|---|---|
| HTTP/3 | Experimental: navegadores y curl sobre h3 sin verificar, y las pruebas adversarias de QUIC del modelo de amenazas no se han ejecutado |
| Usuarios | Ninguno fuera del autor; la fase 9 de producción sigue pendiente |
map | Solo coincidencia por equals |
error_pages con format = "raw" | Conserva el estado, el Content-Type y el cuerpo; el Date generado sustituye al del fichero |
Date de un origen que no lo manda | Se retransmite tal cual: el proxy solo sella las respuestas que genera él |
Respuesta interina 100 Continue | Sin campos de cabecera |
| Caché | Sin stale-while-revalidate ni stale-if-error |
| Binarios de macOS | No son estáticos; solo los de Linux |
Cómo se genera la evidencia
Dos arneses de Rust, ambos #[ignore] porque necesitan Docker.
Corpus diferencial (23/23). Levanta HAProxy 3.4.6, nginx, el dataplane de ingress-nginx y Envoy estático en contenedores, y compara cada caso contra EQProxy: estado, Location (ruta y consulta), cuerpos declarados y cabeceras declaradas, tras la normalización documentada. No compara tiempos, reutilización de conexiones, parámetros TLS ni bytes de páginas de error.
cargo test -p eqproxy-cli --test differential -- --ignored --nocapture
Matriz de migración (65/65). Cuatro configuraciones de origen escritas a mano y su traducción a eqproxy.toml enrutan caso por caso lo mismo: 13 casos declarados × 5 implementaciones. Los originales corren en contenedores y el binario eqproxy de forma nativa, todos delante de los mismos cinco backends de eco.
cargo test -p eqproxy-cli --test migration -- --ignored --nocapture
Un corpus en verde es la ausencia de un contraejemplo, no una prueba de equivalencia. La matriz de migración son 13 casos declarados, no una prueba para configuraciones arbitrarias: el método y sus límites están publicados junto a la evidencia.