Skip to content

Auditoría pre-canary: 27 hallazgos corregidos (F-01..F-27), venue loopback y documentación fiel al estado real - #9

Open
Adlgr87 wants to merge 2 commits into
mainfrom
arena/01a0ff72-bot-crowdintel
Open

Adlgr87 wants to merge 2 commits into
mainfrom
arena/01a0ff72-bot-crowdintel

Conversation

@Adlgr87

@Adlgr87 Adlgr87 commented Oct 3, 2026 •

Copy link
Copy Markdown
Owner

Qué es esta rama

Dos commits sobre main (f151bc7):

  1. 9e187fa — estado auditado pre-canary: las Fases 1-8 de seguridad en vivo (canal user privado, ledger write-ahead, reconciliación, preflight, heartbeat, metadata) más la auditoría estricta de 2026-10-03 con 27 hallazgos corregidos.
  2. f3e2f27 — limpieza de restos (3 ficheros de documentación que eran redirecciones/créditos sin enlaces entrantes, 7 entradas muertas en .gitignore) y documentación actualizada al estado real, incluido el README.md reescrito en español.

Resultado de la auditoría

Veredicto: apto para preparar el canary; no apto para poner capital todavía. El hueco que queda es verificación contra el venue real (checklist H1–H15), no código.

27 hallazgos corregidos: 1 bloqueante, 2 altos, 12 medios, 12 bajos.

El bloqueante (F-22): crowdintel-preflight nunca llamaba a MarketConfig::finalize_identity, así que signer_identity comparaba la EOA derivada contra cfg.signer en ceros y nunca podía aprobarse → no se escribía token → BOT_ENABLE_LIVE_TRADING=1 quedaba inautorizable → el canary no podía arrancar. Además maker_funder y api_owner pasaban en vacío y los checks de saldo/allowance/posiciones consultaban la dirección cero. Corregido: identidad ligada, wallet=/maker=/api_address= impresos en ambos binarios, un CTest que ejecuta el binario real (preflight_binds_wallet_identity) y la primera cobertura unitaria de preflight::Runner::run.

Otros destacados: BOT_METADATA_MAX_AGE_MS se validaba pero nunca se aplicaba (F-03); BOT_CONFIG_FILE y BOT_REQUIRE_STARTUP_RECONCILIATION eran knobs decorativos (F-02/F-06); el kill switch sólo corría en la rama live (F-04); post_raw/post_order podían sacar una orden firmada saltándose gateway, observer, reserva y gate (F-05); HmacSha256 con midstates sin inicializar provocaba un SEGV real en Release (F-17); latency_bench no medía nada (0/10000 productivos, p50=0, mean=-nan) y la puerta de CI lo daba por PASS (F-25); 62 de 80 claves de entorno no tenían prueba de su cableado ENV→campo (F-26); y la autenticación L1 ClobAuth no tenía vector conocido — ahora coincide byte a byte con el vector publicado por py-clob-client (F-27).

Lista completa, con evidencia, en CHANGELOG.md y docs/LIVE_SAFETY_2026-10-03.md.

Verificación (árboles construidos y ejecutados de verdad)

Configuración Build CTest
Release + red rc=0, 0 warnings, 0 errores 7/7
Release offline rc=0, 0 warnings, 0 errores 6/6
Debug + ASan/UBSan rc=0, 0 warnings, 0 errores 7/7
Debug + TSan rc=0, 0 warnings, 0 errores 7/7

Flags confirmados en flags.make: -O3 -std=c++20 -flto=auto -Wall -Wextra -Wpedantic -Wconversion -Wshadow -fno-plt -fvisibility=hidden.

  • TSan repetido: 100 iteraciones (50 × test_live_safety + 50 × test_local_venue), 0 informes.
  • Cppcheck 2.17.1 sobre core/ y tests/: 0 errores, 0 warnings, 0 performance, 0 portability.
  • Mutation testing: 19 mutaciones deliberadas, 17 detectadas, 2 equivalentes documentadas.
  • Binarios reales: crowdintel-config validate infra/config/production.env.example → keys=65 errors=0 ok=true; crowdintel-preflight sin configuración → exit 2; en paper con clave → wallet=0x26972a79b73e93a0374afabd80302d19638051c9, [PASS] signer_identity, [PASS] api_owner, READY=true; en live sin red → FATAL: cannot verify the chain id over POLYGON_RPC_URL; kill switch activo → apagado en 105 ms frente a 8085 ms sin él; latency_bench → 10000/10000 productivos, p50 pool 0,44 µs / inline 34-38 µs (~33 µs de Keccak+ECDSA).

Lo que NO está verificado (sólo el venue real lo resuelve)

Path y body exactos del heartbeat (/v1/heartbeats vs /heartbeats; null vs ""), cadencia real de cancelación (umbral 10 s confirmado en los dos SDK oficiales, peor caso ~15 s), si el orderID del venue coincide con el digesto EIP-712 local, semántica de fd.e≠1 y unidades de base_fee, latencias y margen de rate limit. Todo está marcado [NO VERIFICADO] con su paso de verificación en docs/CANARY_CHECKLIST.md (H1–H15).

No se ha ejecutado trading real ni se ha observado ninguna orden/fill contra el venue. Nada de esta rama autoriza capital hasta que H1–H15 estén ejecutados y registrados.

Decisiones abiertas (documentadas, no aplicadas)

  • Ligar el token de preflight a la dirección de la wallet (hoy se mitiga imprimiendo wallet= en ambos binarios y comparándola en H2/H3, más la reconciliación autoritativa de arranque).
  • Test de la ruta de éxito de MetadataPipeline; main_hot_path.cpp sólo se ejercita vía el test de integración loopback, el humo del contenedor en CI y corridas manuales.
  • Signature type 3 (ERC-7739) y la migración del market listener a ws_session siguen diferidas, como se decidió.
  • Se mantienen BOT_ALLOW_PROTOCOL_V2=0, BOT_RECON_MAX_PAGES=4 y la ausencia de aprobación automática de allowances.

Nota sobre la historia de commits

La auditoría se desarrolló como 28 commits atómicos en una rama de sesión. El checkout del sandbox fue re-clonado en f151bc7 y esos commits dejaron de ser alcanzables como objetos; el árbol de trabajo conservó el contenido final, que se reverificó desde cero (tabla anterior) y se re-commiteó. CHANGELOG.md es el registro superviviente de qué cambió y por qué.

Aviso de coordinación con el PR #8

El PR #8 (arena/01a0f487-bot-crowdintel, "Hardening P1-P4", abierto, 29 ficheros +5012/-100) toca ficheros que esta rama también modifica: README.md, core/CMakeLists.txt, core/src/main_hot_path.cpp, core/src/market_config.hpp, core/src/execution_engine.hpp, core/src/polymarket_order.hpp, core/src/lightweight_client.hpp, core/src/mock_client.hpp, core/src/bench_engine.hpp. Quien se mergée segundo tendrá que resolver conflictos y re-verificar (builds + ctest + el humo de preflight y del benchmark). Esta rama no toca la estrategia; el PR #8 no toca el preflight, el ledger, la reconciliación ni el venue loopback.


Summary by cubic

Fixes 27 pre-canary audit findings (F-01..F-27), adds a loopback venue for integration tests, and brings documentation in line with the actual state. The blocking fix (F-22) makes crowdintel-preflight call MarketConfig::finalize_identity, so the preflight gate can now pass and BOT_ENABLE_LIVE_TRADING=1 becomes authorisable; previously it never could, and the canary could not start.

  • Preflight now binds identity before reading credentials, prints wallet=/maker=/api_address= in both binaries, and has a CTest that runs the real binary (preflight_binds_wallet_identity).
  • latency_bench was reporting p50=0 over an empty sample set (0/10000 productive, mean=-nan) and CI passed it; it now exits 1 when a loop has no samples, and check_latency.py rejects p50=0.
  • HmacSha256 uninitialised midstates caused a real SEGV in Release; they are now zero-initialised, so a compute-before-set_key fails authentication deterministically.
  • L1 ClobAuth now matches byte-for-byte the published py-clob-client test vector (previously no known vector existed).
  • 62 of 80 environment keys had no proof of ENV→field wiring; a new test binds 52 keys to non-default values and reads each field.
  • New test_live_safety and test_local_venue suites exercise the production ledger, state machine, REST client, user channel, heartbeat and reconciliation over real sockets/threads in offline builds.
  • Removed dead files (docs/PERF_METRICS.md, docs/REMEDIATION_2026-09-22.md, docs/TEAM.md) and rewrote README.md in Spanish to match the real stage of the bot.

No real trading was executed: the remaining gap is venue verification against the live platform (checklist H1–H15), not code.

Written for commit f3e2f27. Summary will update on new commits.

Review in cubic

arena-agent and others added 2 commits October 3, 2026 18:05
…n las 4 configuraciones

NOTA SOBRE LA HISTORIA: este checkout fue re-clonado en f151bc7 y los 28 commits de
la auditoria (35163da..9b5e5ba) dejaron de existir como objetos en este repositorio
(`git cat-file -t 9b5e5ba` no devuelve nada; `git fsck --lost-found` vacio). El
arbol de trabajo si conservo el contenido final, que es lo que se commitea aqui. Se
reverifico por completo antes de commitear, no se da por bueno a ciegas:

  Release + red      build rc=0 warnings=0 errors=0   ctest 7/7
  Release offline    build rc=0 warnings=0 errors=0   ctest 6/6
  Debug + ASan/UBSan build rc=0 warnings=0 errors=0   ctest 7/7
  Debug + TSan       build rc=0 warnings=0 errors=0   ctest 7/7

Mas el humo con binarios reales: `crowdintel-config validate
infra/config/production.env.example` -> keys=65 errors=0 ok=true;
`crowdintel-preflight` sin configuracion -> exit 2; en paper con clave ->
`wallet=0x26972a79b73e93a0374afabd80302d19638051c9`, `[PASS] signer_identity`,
`[PASS] api_owner`, READY=true; `latency_bench` -> 10000/10000 productivos en los
dos bucles y check_latency.py en PASS; corrida paper -> banner con
wallet/maker/api_address, post-mortem `last_reconciliation none recorded` y
`heartbeat_contract chain_active=0 ... id_present=0`, `readiness=BLOCKED`.

Contenido (resumen de los hallazgos; la evidencia detallada iba en cada mensaje de
commit de la serie perdida):

F-22 BLOQUEANTE (B/G) crowdintel-preflight nunca llamaba a finalize_identity:
 signer_identity fallaba siempre (READY imposible, sin token, live inautorizable),
 maker_funder y api_owner pasaban en vacuo sobre ceros y los checks de saldo,
 allowance y posiciones consultaban la direccion cero. Ahora se liga la identidad,
 se imprime wallet/maker/api_address en los dos binarios y hay un ctest que ejecuta
 el binario real (preflight_binds_wallet_identity) + tests unitarios de
 Runner::run (los primeros que existian).
F-01 ALTA (D/F) parse_hex_bytes con longitud 42 sobre buffer de 20 sin inicializar.
F-03 ALTA (C/B/G) BOT_METADATA_MAX_AGE_MS no se aplicaba; guarda de edad real,
 observed_wall_ns en el seqlock, defaults 90000/30000 y re-enable condicionado a
 frescura.
F-02/F-06 (C) BOT_CONFIG_FILE y BOT_REQUIRE_STARTUP_RECONCILIATION eran
 configuracion decorativa: eliminados.
F-04 (B/G) kill switch solo en la rama live + PASS con access() fallando por motivos
 distintos de ENOENT: kill_switch.hpp, UNKNOWN bloquea, hilo en todos los modos.
F-05 (B/G/I) post_raw/post_order podian sacar una orden firmada sin gateway,
 observer, reserva ni gate: cerrojo cold_egress_armed_ cerrado por defecto.
F-07 (C) token_id_from_metadata sin lector y paper heredando el token id fijo de
 replay: procedencia observable (token_id_source), vector restringido a replay.
F-08/F-11/F-16/F-18/F-19 (B) simbolos muertos, UB de shift en u64_to_hex32 (demostrado
 con salida real), asignacion muerta del fee, ternario con ramas identicas y doble
 escritura de F_STATUS_TEXT; last_run_copy/heartbeat_copy/K_AMOY_CHAIN_ID/
 K_VENUE_WORST_CASE_MS pasan a tener funcion operativa (post-mortem y diagnosticos).
F-09/F-10/F-14 (E/D) tests no deterministas, raices /tmp fijas compartidas (24/24
 FAILED) con fopen sin comprobar y SEGV real bajo ASan, y buffers menores que el
 contrato del cliente en el test de cabeceras L2.
F-12/F-13/F-15/F-17 (D/G/F) aritmetica con puntero nulo en keccak256_hash, CSPRNG
 construido por trama dentro de noexcept (std::terminate), higiene de avisos y
 HmacSha256 con midstates sin inicializar (SEGV rc=139 en Release, traza ASan).
F-20/F-21/F-23/F-24 (H/C/B/E) documentacion que permitia assume-cancelled de 15 s
 que el codigo rechaza; cancel_market_orders verificado contra py-clob-client y
 cubierto por test; las tres sondas opcionales del preflight y dos knobs sin
 documentar; la sonda de heartbeat informaba del path supuesto en vez del que
 respondio.
F-25 (D/E/F) latency_bench no media nada (0/10000 productivos, p50=0, mean=-nan, UB
 con vector vacio) y check_latency.py daba PASS: ahora fija su identidad, cuenta
 rechazos por motivo, termina con rc=1 si no hay muestras y el script rechaza p50=0.
F-26 (C/E) cableado ENV->campo sin prueba para 62 de 80 claves: test que fija 52
 claves a valores validos no predeterminados y lee cada campo.
F-27 (G/E) autenticacion L1 sin vector conocido: KAT contra el vector publicado por
 py-clob-client (tests/signing/test_eip712.py), firma identica byte a byte.

Mutation testing de la serie: 19 mutaciones, 17 detectadas, 2 equivalentes
documentadas. TSan: 100 iteraciones (50x test_live_safety + 50x test_local_venue)
sin un solo informe. Cppcheck 2.17.1: 0 errores, 0 warnings, 0 performance.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…anol, etapa del bot)

Peticion del usuario: borrar carpetas innecesarias y basura, verificar que no se rompa
nada y actualizar el README para que refleje el proyecto real (partes y funciones), sin
mercadotecnia, y para que los socios sepan en que etapa esta el bot.

BASURA / RESTOS ELIMINADOS (con la comprobacion de que nada los referencia):
- docs/PERF_METRICS.md y docs/REMEDIATION_2026-09-22.md: eran redirecciones de
  compatibilidad de 5 y 13 lineas ("retained so old links do not break") sin ningun
  enlace entrante en el repositorio. Un grep de *.md/*.yml/*.txt/*.sh devuelve 0
  referencias despues de borrarlos.
- docs/TEAM.md: creditos/vitrina sin enlaces entrantes; la unica informacion util (las
  dependencias y el commit fijado de libsecp256k1) se movio a la seccion "Dependencias"
  del README.
- .gitignore: siete entradas de experimentos locales (`test_keccak`, `test_keccak_bin`,
  `test_keccak_debug`, `test_keccak_verify` y sus .cpp); no existe ningun fichero con
  esos nombres, se mantienen los ignores con sentido (build/, __pycache__, *.o/*.a/*.so,
  secretos, logs, IDE).
- Comprobado ademas que no hay restos de merge, backups, logs, caches de Python,
  directorios de build ni binarios en el arbol (`find` de *.orig/*.rej/*.bak/*~/*.log/
  *.tmp/__pycache__/*.pyc/build/*.o/*.a/*.so = vacio; 1,5 MB en total, sin ficheros
  mayores de 200 KB). alpha/, infra/ y tests/ son codigo y herramientas vivos: cada
  fichero esta referenciado por el build, por CI o por la documentacion operativa.

README REESCRITO (era la parte que mas mintia):
- Decia que "la reconciliacion de fills/ordenes del canal privado y la recuperacion
  automatica de inventario siguen faltando": es falso desde las Fases 1-8.
- Decia que el binario arranca en mock salvo BOT_MODE=mock: el modo por defecto es
  paper y mock esta obsoleto (avisa).
- Su ejemplo de corrida no pasaba ni BOT_MARKET_SLUG ni BOT_TOKEN_ID: con el cambio de
  F-07 eso deja de firmar nada (todos los ticks body_failed), el mismo fallo que hizo
  que el benchmark no midiera nada (F-25).
- Ahora lleva: etapa actual con tabla (auditado, pre-canary, sin trading real jamas),
  que hay verificado y que NO (los [NO VERIFICADO] que solo resuelve el venue), los
  binarios y sus funciones, las partes del bot por funcion con sus ficheros, el modelo
  de seguridad fail-closed, build y pruebas con los comandos verificados en esta sesion,
  las cifras medidas del benchmark con su interpretacion, configuracion, indice de
  documentos, dependencias con versiones fijadas y el trabajo diferido con sus motivos.
- Sin lenguaje de producto: es un bot de uso propio, un proceso, una wallet, un mercado.

DOCUMENTACION ACTUALIZADA AL ESTADO REAL:
- docs/STATUS.md: deja de senalar REMEDIATION_STATUS.md como "authoritative" (es el
  registro historico del pase de 2026-09-22) y anade el resultado de la auditoria, el
  hallazgo bloqueante F-22 explicado, los numeros de verificacion y dos limitaciones que
  no estaban escritas: el token de preflight liga el fingerprint y no la wallet, y ni
  MetadataPipeline ni el cableado de main_hot_path.cpp tienen test propio.
- docs/ARQUITECTURA.es.md: su ultima seccion decia que faltan el canal privado y la
  reconciliacion; ahora describe la etapa real y donde esta el bloqueo (verificacion
  contra el venue, H1-H15).
- docs/REMEDIATION_STATUS.md: cabecera que lo declara registro historico del pase de
  2026-09-22 y estado de la observacion #14 actualizado ("Resolved 2026-10-03
  (Phases 1-8)") en vez de seguir leyendose "Unresolved production blocker".
- docs/BENCHMARKING.md: documenta la identidad fija del bench y los guardas de F-25, y
  sustituye la tabla representativa por la corrida real de 2026-10-03 (min/p50/p90/p99
  de las cuatro metricas, 10000/10000 productivos) con su lectura: ~33 us de los ~37 us
  de la ruta inline son Keccak+ECDSA, el cuello es la firma, no la decision.
- CHANGELOG.md: entrada con los 27 hallazgos de la auditoria agrupados por severidad, la
  verificacion del arbol final, los items abiertos por decision y una nota sobre la
  perdida de la historia de commits y su reverificacion desde cero. Este registro es lo
  que sustituye a los mensajes de los 28 commits que el re-clonado del checkout hizo
  inalcanzables.

No se toco ni una linea de codigo ni de CMake, asi que los builds y los tests del commit
anterior siguen siendo validos: solo cambian .gitignore y ficheros .md. Verificado que
los 0 enlaces relativos de todos los .md del repositorio apuntan a ficheros existentes.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai

coderabbitai Bot commented Oct 3, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 09a3b49e-9160-431f-981c-7e0e6ddd1c03
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant