René Cano
All projects

No. 4Hackathon + security hardening

AgentBuyer

Safe purchasing for AI agents · NextWave Hackathon 2026

My role
Co-developer at the hackathon; solo hardening afterwards
Period
Aug – Sep 2026
AgentBuyer “Authorize Saturday” screen: the user verifies their identity step by step before granting the agent permission, next to a card showing the agent’s face.

The problem

Payment systems assume that whoever presses "Pay" is a person. When an AI agent buys on someone's behalf, that assumption breaks: the merchant doesn't know whether to trust it, the person doesn't want to hand the agent their card, and afterwards nobody can prove who authorized what. That was Challenge 01 at the NextWave Hackathon 2026, "The buyer that isn't human".

The team answered with a protocol: Ed25519-signed mandates, scoped virtual tokens instead of the card, a fail-closed constraint engine, live revocation, escalation to the person and a SHA-256 hash-chained log.

What I built

At the hackathon (August 29–30, 2026) I was one of the team's developers: 9 commits, ~15% of the code. I built the mandate and verification API, Mission Control and the mandate creation screen. The core protocol was designed and written mainly by Ana Paola Oviedo.

After the hackathon, from September 16 to 18, I took a copy of the project and hardened it on my own:

  • First I froze the API contract the frontend relies on with tests, so I could refactor without breaking it.
  • Email authentication with OTP (expiry, single use, HMAC storage and rate limiting) that issues HS256 JWTs. The API refuses to start without a JWT_SECRET of at least 32 bytes unless dev mode is explicitly on.
  • 3 roles (user, admin and service) and an ownership check on every mandate.
  • I found that the original verifier accepted a signature when there was no public key, when it was shorter than 64 characters, or on any exception. I rewrote it to fail closed with Ed25519 and covered it with integration tests.
  • On the frontend I replaced the simulated biometrics and tokenization with real OTP (−1,016 lines) and added expired-session handling.
  • On the fase-3-firma-cliente branch: a WebCrypto keystore with non-extractable Ed25519 keys, proof of possession and canonical JSON shared between JavaScript and Python, with 29 Vitest cases. It isn't merged yet.

Architecture

Architecture diagram: the person signs in with an email OTP and gets a JWT; they sign a mandate with Ed25519; the buying agent presents the mandate to the FastAPI API; a fail-closed verifier checks the signature, constraints, budget and revocation; if everything passes it issues a scoped virtual token to the merchant; if in doubt it escalates to the person; every step is written to a SHA-256 hash-chained log. The parts of my hardening are marked.

Results

Versionpytest tests
Hackathon snapshot68
My main branch231
fase-3-firma-cliente branch292

GitHub Actions runs the tests and the frontend build on every push: 19 runs, 18 successful. The only failure was fixed in the following runs and the latest run on main is green.

Known limits

  • It isn't deployed and keeps state in memory.
  • The inherited README claims latencies nobody measured. They need to be measured or removed.
  • The 8-attack adversarial suite was scripted by the team; it isn't an external benchmark.
  • frontend/.vite/deps is committed and should be removed from the repo.
  • My repository starts from a snapshot of the team repo, so GitHub shows commits as mine that aren't. The original repository is linked below.

Links

  • AgentBuyer “Set the limits” step: a form to set the mandate’s maximum amount, category, merchant, number of purchases, expiry and price condition.
  • AgentBuyer Mission Control: the active mandate, the agent’s search and the verification panel, which holds the purchase for approval because the merchant isn’t authorized.