Inspiration

AI agents are starting to propose payments. A CFO can't sign off on an agent that pays a vendor whose bank account changed yesterday, or pays the same invoice twice. We wanted a firewall between "the agent proposed it" and "the money moved", plus a month-end proof that the books haven't been touched since.

What it does

  • Takes in invoices (all synthetic) and turns each into a payment proposal.
  • A deterministic firewall decides on every proposal and attaches reason codes:
    • GHOST_TRIPWIRE / GHOST_UNKNOWN_VENDOR / GHOST_DOMAIN_MISMATCH: unknown vendors, lookalike domains and tripwire patterns.
    • ZOMBIE_DUPLICATE / ZOMBIE_SUSPECTED: exact and fuzzy duplicate invoices.
    • POSSESSED_BANK_CHANGE / POSSESSED_VENDOR_HELD: a vendor's bank details changed recently, or the vendor is on hold.
  • Approval tiers: up to $5,000 pays automatically, up to $25,000 goes to controller review, and anything above is blocked for the CFO.
  • Approved payments are posted to a double-entry ledger, with every entry SHA-256 hash-chained to the one before it.
  • The month-end séance checks hash-chain integrity, trial balance and completeness, and returns CLEAN or HAUNTED. If you edit one row in the database, the séance turns HAUNTED and names the entry that was changed.

How we built it (with Kiro)

  • Steering (.kiro/steering/): product, tech and structure docs that kept Kiro on Decimal money, synthetic data only and a strict module layout.
  • Spec-driven development (.kiro/specs/ap-firewall-core/): requirements → design → 19 implementation tasks. Kiro carried out the tasks in the Kiro CLI over several sessions, and the session logs are in docs/kiro-sessions/.
  • Hooks (.kiro/hooks/): run tests on save, a ledger-invariant guard and a synthetic-data guard. They are defined in the repo, but we have not verified that they fired during the headless CLI sessions.
  • Frankenstein: we stitched together an AP rules engine, a blockchain-style hash chain, classic double-entry accounting and an HTMX UI with no build step, all in one small app.
  • 94 automated tests pass, including red-team scenarios.

Challenges we ran into

  • Keeping money exact: we used Decimal everywhere and set tier boundaries at exactly $5,000.00 and $5,000.01.
  • Making tamper detection precise enough to point at the exact entry, not just say "something is wrong".
  • Rate limits during the headless Kiro sessions meant splitting the build into several sessions, with the spec's task list carrying the state between them.

Accomplishments that we're proud of

  • An end-to-end flow from invoice to firewall to ledger to close proof, with an audit trail.
  • Tampering with a single row is caught right away at close.
  • The spec, steering and session logs are all public, so judges can see how Kiro built it.

What we learned

  • Spec-driven development works well for finance software. Writing the requirements and design first kept the generated code consistent across sessions.
  • Steering files are an easy way to hold an agent to the rules that matter, like Decimal money and never using real data.

What's next for Haunted Ledger

  • Connectors for real AP systems and bank feeds, plus an LLM proposer behind the same deterministic firewall.
  • Multi-entity close and role-based approvals for the controller and the CFO.
  • Cubiczan plans to offer it to finance teams that are adopting AI agents (Best Startup).

Built With

Share this project:

Updates

Submission history