movingparticle@caja-negra ~/reto-2/LOG ← volver al demo --:--:--

movingparticle@caja-negra:~$ cat ./LOG.txt

FRONTIER Bogotá 2026 · Reto 2 · bitácora de sondas.
Un sistema opaco solo se entiende preguntándole. Este log registra cada pregunta, por qué la hicimos, qué respondió y qué decidimos después. Nada se afirma sin un id de experimentos.jsonl.

01 // método

Probing guiado por hipótesis: cada sonda busca falsar una hipótesis rival, no acumular ejemplos.

02 // evidencia

40 registros reales: 20 del baseline público, 14 de probing en vivo, 6 de fuzzing adversarial.

03 // resultado

Regla real: ISO 7064 Mod 97-10 y precedencia E303>E304>E401>E506>E507.

40/40 citados sin filas "por ejecutar" hipótesis → resultado → decisión anti-overfitting
cómo leer

Resumen

Cada línea de experimentos.jsonl es una sonda real. Este log las reproduce en orden de ejecución y las agrupa por origen.

40
registros
20
baseline
14
probes viva
6
adversarial fuzz
grupoidsfuentepregunta que responde
A · Baseline1–20pruebas/ejemplos.jsonl (público, mañana)¿Cuál es el contrato mínimo observable?
B · Probes en vivo21–34probing guiado por hipótesis¿Cuáles son los bordes y la precedencia real?
C · Adversarial fuzz35–40fuzzing dirigido a límites¿Dónde se rompe el modelo y dónde está el tope?
Columnas de la rúbrica. # | Probe | Razón | Resultado | Hipótesis antes | Hipótesis después | Decisión. #N = id:N en experimentos.jsonl. Hipótesis antes = lo que creíamos antes del probe; después = el estado del modelo tras observarlo (confirmada / falsada / ampliada).
evolución

Hipótesis

La investigación no empezó por la fórmula del control: empezó por el dominio. Cada hipótesis se mantuvo hasta que un probe la falsó o la confirmó.

idhipótesisestadoevidenciacómo murió / se confirmó
H-01El dominio es bancario y los mensajes son posicionales CMD;arg;…;Q con 6 verbos.confirmada#1, #3–#8, #13, #34#34 (RETIRO) falsó verbos extra: el set se cierra en 6.
H-02El último campo Q es un valor de verificación determinista que se valida antes de ejecutar el comando (E201/E202).confirmada#2, #17, #20, #29, #30, #31#2 y #17 prueban que validar Q precede a todo efecto; #29/#30 cierran el parser.
H-03El algoritmo de Q es ISO 7064 Mod 97-10 alfanumérico 1-based (A=1…Z=26 sin padding, CD = 98 − (N·100) mod 97, rango 2..98).confirmada#3–#6, #10, #39#31 descarta el padding de ceros; #39 confirma (rem·3) mod 97 == 1 ⇒ Q=97, no 0.
H-04La validación sigue un orden determinista con precedencia E303 > E304 > E401 > E506 > E507.confirmada#26, #27, #28, #9, #16#26 (E303>E304), #27 (E304>E506), #28 (E401>E506); #16 cierra con E507.

Hipótesis rivales descartadas

rivalpredicciónprobe discriminanteresultadoveredicto
Control = Luhn / Módulo 10Q de 1–2 dígitos con paridad#3, #5no reproduce la seriefalsada
Control = suma ponderada de caracteresmonótona por longitud#11coincide con ISO 7064, no con sumafalsada
Control = CRC/hash truncadosin estructura módulo 97#3997 válido ⇒ residuo mod 97falsada
El control admite relleno 03 ≈ 3comparación numérica laxa#31400 E202falsada
E506 antes que existencia de cuentalímite primero#28404 E401falsada
E304 antes que el montocuentas iguales primero#26400 E303falsada
H-01 dominio bancario, 6 verbos posicionales        ✓ #1 #3–#8 #13 #34
H-02 el último campo Q se valida antes de ejecutar   ✓ #2 #17 #20 #29 #30 #31
H-03 Q = ISO 7064 Mod 97-10 alfanumérico 1-based      ✓ #3–#6 #10 #39  (16/16)
H-04 precedencia E303>E304>E401>E506>E507          ✓ #26 #27 #28 #9 #16
rivales: Luhn ✗ · suma ✗ · CRC ✗ · padding-03 ✗ · E506-primero ✗ · E304-primero ✗
grupo A · ids 1–20

Baseline

pruebas/ejemplos.jsonl ejecutado tras POST /__reset. Fija la paridad observable. Los saldos dependen del orden de la secuencia.

#proberazónresultadohipótesis anteshipótesis despuésdecisión
#1PING;64Comando sin argumentos, sin estado200 {"pong":true}PING responde pong independiente del estadoconfirmadaImplementar PING → {pong:true} (aridad 0)
#2ALTA;Lucia;83Aislar el campo de control400 E202 control inválidocontrol erróneo ⇒ E202 (H-02)H-02 confirmada: se valida antes de ejecutarValidar Q antes de cualquier efecto
#3ALTA;Lucia;82Creación y numeración de cuentas201 {"cuentaId":"AC-0001"}ALTA crea cuenta secuencial (H-01)H-01 confirmada; saldo inicial 0Contador AC- desde 1 con padding 4
#4ALTA;Mateo;3Secuencia y control de 1 dígito201 {"cuentaId":"AC-0002"}el contador avanza; Q de 1 dígito es válidoconfirmada; sin relleno de cerosAceptar Q sin padding; incrementar secuencia
#5CONSULTA;AC-0001;14Saldo de cuenta recién creada200 {"cuenta_id":"AC-0001","saldo":0}CONSULTA devuelve cuenta_id + saldo numéricoconfirmadaCONSULTA de solo lectura
#6DEPOSITO;AC-0001;250000;86Acreditación y operacionId200 {"status":"recieved","operacionId":"OP-0001"}DEPOSITO acredita y genera OP-confirmada; typo recievedReplicar recieved literal; contador OP-
#7TRANSFER;AC-0001;AC-0002;40000;86Movimiento entre cuentas200 {"status":"recieved","operacionId":"OP-0002"}TRANSFER debita origen y acredita destinoconfirmadaImplementar débito/crédito + OP-
#8CONSULTA;AC-0002;11Destino refleja fondos200 {"cuenta_id":"AC-0002","saldo":40000}saldo acumulativoconfirmadaEstado persistente entre requests
#9TRANSFER;AC-0001;AC-0002;120000;55Tope de transferencia422 E506 límite excedidoexiste tope, se evalúa antes del saldoconfirmada: supera tope ⇒ E506Tope 100000 → 422 E506
#10TRANSFER;AC-0001;AC-0002;100000;12Borde del tope200 {"operacionId":"OP-0003"}el límite es inclusivoconfirmadaComparación monto > 100000
#11CONSULTa;AC-0001;14Sensibilidad a mayúsculas del comando200 {"saldo":110000}comando case-insensitiveconfirmada; mismo Q=14Normalizar comando a mayúsculas
#12SALDOS;AC-0001;38Comando inexistente400 E301 "comando desconocido "comando desconocido ⇒ E301confirmada; espacio final literalReplicar mensaje exacto (espacio final)
#13ANULA;OP-0003;66Reversión de operación200 {"ok":true,"anulada":"OP-0003"}ANULA revierte la operación previaconfirmadaImplementar reversión de saldos
#14ANULA;OP-0003;66Idempotencia de ANULA200 {"ok":false,"motivo":"ya anulada"}repetir no falla con 4xxconfirmadaMarcar anulada; 2ª vez ok:false
#15CONSULTA;AC-0009;87Cuenta inexistente404 E401 cuenta inexistentecuenta no registrada ⇒ E401confirmadaCONSULTA inexistente → 404 E401
#16TRANSFER;AC-0002;AC-0001;50000;23Fondos insuficientes422 E507 saldo insuficientesaldo < monto ⇒ E507 (tras anular OP-0003)confirmadaComprobar saldo → 422 E507
#17DEPOSITO;AC-0002;700;5XControl no numérico400 E201 control mal formadoQ no numérico ⇒ E201 antes del algoritmoconfirmadaValidar formato de Q primero
#18DEPOSITO;AC-0002;700;35Control correcto200 {"operacionId":"OP-0004"}Q numérico válido se ejecutaconfirmadaAcreditar saldo; emitir OP-
#19CONSULTA;AC-0002;11Nuevo saldo tras depósito200 {"saldo":40700}saldo refleja el último depósitoconfirmadaEstado acumulativo (40700)
#20ALTA;Lucia;Gomez;11Aridad incorrecta400 E302 aridad inválidanº de args ≠ aridad ⇒ E302 (tras control)confirmadaValidar aridad después del control
grupo B · ids 21–34

Probes

Probing guiado por hipótesis en vivo contra el oráculo. Aquí se descubren los bordes, la precedencia y el algoritmo de control.

#proberazónresultadohipótesis anteshipótesis despuésdecisión
#21ANULA;OP-9999;62Operación inexistente404 E402 operación inexistenteoperación desconocida ⇒ E402confirmadaAñadir E402 al catálogo
#22TRANSFER;AC-0001;AC-0001;500;49Origen = destino400 E304 origen y destino igualesorigen≠destino es regla duraconfirmadaComparación de IDs → E304
#23ANULA;OP-0001;46Revertir un DEPOSITO200 {"ok":true,"anulada":"OP-0001"}ANULA aplica a depósitos y transferenciasconfirmadaReversión genérica (no solo TRANSFER)
#24DEPOSITO;AC-0001;0;49Monto cero400 E303 monto inválidomonto estrictamente positivoconfirmada: 0 ⇒ E303Validar monto > 0
#25DEPOSITO;AC-0001;abc;47Monto no numérico400 E303 monto inválidomonto no numérico ⇒ E303confirmadaValidar formato entero
#26TRANSFER;AC-0001;AC-0001;0;94Monto inválido + cuentas iguales400 E303 monto inválido¿qué error gana?resuelta: E303 > E304Orden: monto antes de igualdad
#27TRANSFER;AC-0001;AC-0001;150000;80Cuentas iguales + límite400 E304 origen y destino iguales¿gana el límite?resuelta: E304 > E506Igualdad antes de límite
#28TRANSFER;AC-9999;AC-8888;150000;22Cuenta inexistente + límite404 E401 cuenta inexistente¿gana el límite?resuelta: E401 > E506Existencia antes de límite
#29PING (sin ;)Falta el campo de control400 E103 falta controlmensaje sin delimitador ⇒ E103confirmadaParser exige ; antes de validar Q
#30;64Segmento vacío400 E104 segmento vacíosegmento nulo ⇒ E104confirmadaRechazar cualquier segmento vacío
#31ALTA;Mateo;03Ceros a la izquierda400 E202 control inválido03 podría igualar a 3falsada: comparación estricta de stringNo normalizar ceros; rechazar 03
#32CONSULTA;ac-0001;14IDs de cuenta en minúsculas404 E401 cuenta inexistente¿el case-insensitive aplica a IDs?falsada: solo el comando es case-insensitiveNormalizar comando, no los IDs
#33ANULA;OP-0001;46Revertir con saldo negativo200 {"ok":true,"anulada":"OP-0001"}la anulación podría bloquear negativosfalsada: se permite saldo negativoNo bloquear anulación por saldo
#34RETIRO;AC-0001;71Verbos bancarios alternativos400 E301 comando desconocidopodría existir RETIRO/otrosconfirmada la negación: set = 6 comandosNo implementar verbos extra
grupo C · ids 35–40

Fuzz

Fuzzing dirigido a los bordes: tamaño de transporte, formato de monto y el caso 97 del control.

#proberazónresultadohipótesis anteshipótesis despuésdecisión
#35PING;[8193 bytes];10Exceder el cuerpo HTTP413 E101 cuerpo demasiado grandehay tope de cuerpo ⇒ error estableconfirmada: umbral exacto 8.192 BLímite 8 KiB → 413 E101
#36DEPOSITO;AC-0001;0100;79Ceros a la izquierda en monto400 E303 monto inválidomonto con 0 inicial ⇒ E303confirmadaMonto ^[1-9]\d{0,9}$
#37DEPOSITO;AC-0001;10000000000;22Monto de 11 dígitos400 E303 monto inválidoexiste tope de dígitosconfirmada: máx 10 dígitosValidar longitud del monto
#38DEPOSITO;AC-0001;9999999999;62Monto de 10 dígitos200 {"operacionId":"OP-0009"}10 dígitos admitidos sin overflowconfirmadaEnteros seguros hasta 10 dígitos
#39DEPOSITO;AC-0002;2147483647;97Q=97 en ISO 7064200 {"operacionId":"OP-0006"}Q puede valer 97confirmada: rango 2..98; (rem·3) mod 97 == 1 ⇒ 97, no 0Implementar la fórmula exacta, no mod ingenuo
#40ruta no mapeada ({})Ruta/método fuera del contrato404 E404 ruta desconocidael router responde antes de authconfirmadaDespachar E404 previo al middleware
código · cierre

Decisiones

Cada sonda derivó en una regla concreta. Estas son las que viven en el código.

decisiónevidenciaimplementación
Control = ISO 7064 Mod 97-10 (A=1…Z=26 sin padding; CD = 98 − (N·100) mod 97)H-03 · #3–#6, #10, #39src/checksum.mjs
Orden de validación E303 > E304 > E401 > E506 > E507H-04 · #26, #27, #28, #9, #16src/engine.mjs
Monto ^[1-9]\d{0,9}$ (positivo, sin ceros iniciales, ≤ 10 dígitos)#24, #25, #36, #37, #38src/engine.mjs
Transporte: cuerpo ≤ 8.192 B → 413 E101; ruta desconocida → 404 E404 antes de auth#35, #40src/security.mjs, src/worker.mjs
Comando case-insensitive; IDs de cuenta case-sensitive#11, #32src/engine.mjs
ANULA genérica e idempotente; permite saldo negativo#13, #14, #23, #33src/engine.mjs
Replicar literales con defectos históricos ("recieved", "comando desconocido ")#6, #12src/engine.mjs
Límites de este log. El baseline (#1–#20) es una secuencia con estado: reproducirlo exige POST /__reset primero. #35 registra un payload simbólico ([8193 bytes]): mide el umbral, no el contenido. El incidente de las 15:30 puede invalidar cualquiera de estas filas; el baseline congelado y su re-test viven en INCIDENT.md.
movingparticle@caja-negra:~$ ./probe --verify
40/40 registros citados · 20 baseline · 14 probes · 6 fuzz · 0 pendientes
Hypothesis H-01 → H-04 : CONFIRMED
checksum              : ISO 7064 Mod 97-10
precedence            : E303 > E304 > E401 > E506 > E507
teclas 123 456 saltan sección