René Cano
Todos los proyectos

Núm. 4Hackatón + hardening de seguridad

AgentBuyer

Compras seguras para agentes de IA · NextWave Hackathon 2026

Mi rol
Co-desarrollador en el hackatón; hardening posterior en solitario
Periodo
Ago – sep 2026
Pantalla «Authorize Saturday» de AgentBuyer: el usuario verifica su identidad paso a paso antes de darle permiso al agente, junto a una tarjeta con la cara del agente.

El problema

Los sistemas de pago asumen que quien presiona "Pagar" es una persona. Cuando un agente de IA compra en nombre de alguien, esa suposición se rompe: el comercio no sabe si confiar, la persona no quiere darle su tarjeta al agente, y después nadie puede probar quién autorizó qué. Ese fue el Reto 01 del NextWave Hackathon 2026, "El comprador que no es humano".

El equipo respondió con un protocolo: mandatos firmados con Ed25519, tokens virtuales acotados en lugar de la tarjeta, un motor de restricciones que falla cerrado, revocación en vivo, escalamiento a la persona y una bitácora encadenada con SHA-256.

Qué construí

En el hackatón (29–30 de agosto de 2026) fui uno de los desarrolladores del equipo: 9 commits, ~15% del código. Hice la API de mandatos y verificación, Mission Control y la pantalla de creación de mandatos. El protocolo base lo diseñó y escribió principalmente Ana Paola Oviedo.

Después del hackatón, del 16 al 18 de septiembre, tomé una copia del proyecto y lo endurecí por mi cuenta:

  • Primero congelé con tests el contrato de la API que consume el frontend, para poder refactorizar sin romperlo.
  • Autenticación por correo con OTP (expiración, uso único, almacenamiento con HMAC y límite de intentos) que emite JWT HS256. La API se niega a arrancar sin un JWT_SECRET de al menos 32 bytes, salvo en modo de desarrollo explícito.
  • 3 roles (usuario, admin y servicio) y verificación de dueño en cada mandato.
  • Encontré que el verificador original aceptaba una firma si no había llave pública, si medía menos de 64 caracteres o ante cualquier excepción. Lo reescribí para que falle cerrado con Ed25519 y lo cubrí con tests de integración.
  • En el frontend reemplacé la biometría y la tokenización simuladas por OTP real (−1,016 líneas) y agregué manejo de sesión expirada.
  • En la rama fase-3-firma-cliente: llavero WebCrypto con llaves Ed25519 no extraíbles, prueba de posesión y JSON canónico compartido entre JavaScript y Python, con 29 casos de Vitest. Todavía no está fusionada.

Arquitectura

Diagrama de arquitectura: la persona inicia sesión con OTP por correo y recibe un JWT; firma un mandato con Ed25519; el agente comprador presenta el mandato a la API FastAPI; un verificador fail-closed revisa firma, restricciones, presupuesto y revocación; si todo pasa emite un token virtual acotado para el comercio; si hay duda escala a la persona; cada paso queda en una bitácora encadenada con SHA-256. Las piezas de mi hardening están marcadas.

Resultados

VersiónTests de pytest
Snapshot del hackatón68
Mi rama principal231
Rama fase-3-firma-cliente292

GitHub Actions corre los tests y el build del frontend en cada push: 19 ejecuciones, 18 exitosas. La única fallida se resolvió en las siguientes y la última de la rama principal está en verde.

Límites conocidos

  • No está desplegado y guarda el estado en memoria.
  • El README heredado afirma latencias que nadie midió. Hay que medirlas o quitarlas.
  • La suite adversarial de 8 ataques la guionizó el equipo; no es un benchmark externo.
  • frontend/.vite/deps está versionado y debería salir del repo.
  • Mi repositorio parte de un snapshot del repo del equipo, así que GitHub muestra como míos commits que no lo son. El repositorio original está enlazado abajo.

Links

  • Paso «Set the limits» de AgentBuyer: formulario para fijar el monto máximo, la categoría, el comercio, el número de compras, la vigencia y la condición de precio del mandato.
  • Mission Control de AgentBuyer: el mandato activo, la búsqueda del agente y el panel de verificación, que deja la compra pendiente de aprobación porque el comercio no está autorizado.