Estado: ⚠️ Aceptada con limitación documentada Fecha: 2026-05-29 Bloque: Z1e (estructura Argon2id; RFC vector match pendiente) Bump on-disk: VERSION 29 → 30

🧭 Contexto

Z1d (ADR-0058) entregó la primitiva Blake2b validada contra RFC 7693 §A — foundation crypto sobre la cual Argon2id se construye. Z1e arrancó con la ambición de cerrar Argon2id completo: H’ variable-length, G compression con BlaMka, memory matrix con indexing híbrido data-dependent/independent, pass loop, parallelism p>1, y match con el test vector oficial RFC 9106 §A.3.

Honestidad técnica: implementé la estructura completa (~450 LOC) pero el output no matchea el test vector RFC §A.3. El primer byte diverge (0xa6 vs esperado 0x0a), indicando un bug que afecta el output desde temprano — probablemente en el column phase del compress, el cálculo de W para el indexing, o el manejo de start_pos en pass > 0. Sin un reference implementation paso-a-paso para contrastar, debug ciego es impráctico.

Decisión Z1e: shippear la estructura como código pub fn argon2id(...) disponible para experimentación + debug, pero NO cambiar el default de password hashing (sigue siendo scrypt Z1c). El vector match queda como Z1f dedicado para debugging con una reference implementation a mano.

Esta partición es honesta:

💡 Decisión

1. Implementación estructural completa

pub fn argon2id(password, salt, secret, ad, m_kib, t, p, dk_len) -> Vec<u8>:

2. Funciones auxiliares

3. PASSWORD_SCHEME_ARGON2ID = 3 sigue rechazado

exec_set_session_auth dispatch retorna [GBY-4137] con mensaje informativo:

SET SESSION AUTHORIZATION '...': scheme Argon2id (3) structural
implementation disponible en Z1e pero pendiente de matchear RFC 9106
§A.3 test vector — debug en Z1f. Default sigue siendo scrypt (Z1c).

exec_create_user y exec_alter_user_password siguen persistiendo con scheme = PASSWORD_SCHEME_SCRYPT = 2. Sin regresión de seguridad.

4. Bump VERSION 29 → 30

Aunque el on-disk format no cambia, bumpeamos para señalizar el corte: el binario Z1e tiene la struct Argon2id disponible (aunque no usada por default). Binarios pre-Z1e no la tienen.

📁 Archivos tocados

⛔ Lo que no entra en Z1e (defer Z1f)

Ítem Razón del defer
RFC 9106 §A.3 vector match Bug en algún sitio del pipeline (compress / indexing / start_pos / W). Requiere debug paso-a-paso contra una reference implementation.
Cambio de default a scheme=3 Bloqueado por el vector match — no podemos shippear “Argon2id” sin matchear el RFC.
Argon2d / Argon2i variants Sólo Argon2id en scope; los otros dos variants tienen indexing distinto.
Migración silenciosa scheme=2 → scheme=3 Sin Argon2id production-ready no hay a dónde migrar.
Wire-up al server HTTP Mismo defer histórico.

🧪 Validación

🔗 Referencias

📜 Reflexión

Z1e es un caso interesante de honestidad técnica vs ambición de scope. La opción “shippear Argon2id-inspired sin RFC match” sería deshonesta — usuarios esperarían interoperabilidad con otras implementaciones. La opción “no shippear nada” desperdicia el trabajo ya hecho. La opción elegida — shippear estructura + flagear claramente la limitación + defer del vector match a Z1f — preserva el progreso, mantiene la integridad del label “Argon2id”, y deja una pista clara de qué falta.

El default de scrypt sigue cubriendo el objetivo memory-hard, así que la seguridad efectiva no se degrada.