Every time you tap your card at a terminal, your payment travels through a binary protocol written in 1987.
It's called ISO-8583. Banks run it on IBM mainframes using a character encoding called EBCDIC — invented in 1964. Together, these two technologies process over $10 trillion in daily payment volume. And almost no modern developer can read them.
Today I want to show you how I built AuraGate — a tool that decodes these ancient binary packets and automatically synthesizes a production-ready OpenAPI 3.1 specification and TypeScript SDK from them. And how Kiro made it possible to build something this technically deep in a single hackathon.
🔗 Live app: https://auragate-i1on.vercel.app/
🔗 GitHub: https://github.com/poowa-gg/auragate
The Problem Nobody Talks About
Here is what an ISO-8583 card authorization packet looks like in the wild:
303230301038000000c08000303030303030303135303030343832393130313433303235313130345445524d303030314d45524348414e5430303030303120383430
That is a real payment message. Field 4 is the transaction amount. Field 41 is the terminal ID. Field 49 is the currency code. But you would never know that by looking at it.
Banks pay COBOL consultants $125,000–$197,000 a year just to read and map these fields. The average COBOL developer is now above 55 years old. Fewer than 1% of computer science graduates study COBOL today. The skills cliff is accelerating at 10% per year.
Every fintech that wants to integrate with a bank, every payment processor building modern infrastructure, every developer trying to understand what their legacy system is actually sending — they all hit the same wall.
I wanted to demolish that wall.
What AuraGate Does
Drop in a raw hex payload. AuraGate gives you back:
- Decoded JSON — every field named and typed:
json { "mti": "0200", "fields": { "4": "000000015000", "11": "482910", "41": "TERM0001", "49": "840" }, "presentFields": [4, 11, 41, 49] } 2. A valid OpenAPI 3.1 specification — ready for Postman, Swagger UI, or AWS API Gateway: { "openapi": "3.1.0", "info": { "title": "PaymentSwitchV1", "version": "1.0.0" }, "paths": { "/api/v1/transactions/process": { ... } }, "components": { "schemas": { "TransactionPayload": { "properties": { "amount": { "type": "number", "example": 150.00 }, "terminalId": { "type": "string", "example": "TERM0001" } } } } } } 3. A TypeScript interface — ready to paste into your microservice: export interface TransactionPayload { mti: '0200'; amount?: number; stan?: number; terminalId?: string; currencyCode?: number; } _What would take a COBOL consultant 3–6 months to document just happened in under a second._ **How I Built It With Kiro** This is where it gets interesting. I didn't just use Kiro as a code autocomplete tool. I used it the way it was designed to be used — spec-first, with steering, hooks, and MCP. 1. Spec-Driven Development Before writing a single line of code, I opened Kiro and created a spec. 2. Requirements.md I defined 7 requirement groups — codecs, error handling, PBT invariants, synthesis engine, MCP server. Then tasks.md organized them into a 5-wave dependency graph: { "waves": [ { "id": 1, "description": "Environment setup", "tasks": ["1"] }, { "id": 2, "description": "Binary codecs", "tasks": ["2", "4"] }, { "id": 3, "description": "Property-based tests", "tasks": ["3", "5"] }, { "id": 4, "description": "OpenAPI synthesizer", "tasks": ["6"] }, { "id": 5, "description": "MCP server", "tasks": ["7"] } ] } Kiro read the spec and implemented each wave in the correct dependency order — without me micromanaging sequencing. The codecs came out correct on the first pass because the spec forced the right design constraints upfront. This is the single biggest shift in how I code now. Writing requirements before code forces clarity that prevents entire classes of bugs. 3. Steering Docs as Architecture Guardrails I created architecture.md with hard rules A) Zero-copy byte parsing only — Buffer.subarray, never string slicing. B) Every decoder returns Result<T, ParseError> — never throws. C No any types anywhere. D) PBT required for every codec module. Kiro respected these rules across every file it generated. I never had to say "don't use string slicing" in chat — it was already in the steering doc. This is the difference between vibe coding and disciplined AI-assisted engineering. 4. MCP — The Feature That Changed Everything I built an MCP server that extends Kiro's own agent with three tools: // Callable directly from Kiro chat: inspect_iso8583_stream({ payload: "303230301038..." }) inspect_ebcdic_stream({ payload: "c1e4d9c1c7..." }) synthesize_microservice({ payload: "303230301038...", serviceName: "CardAuthV2" }) inspect_iso8583_stream, and see the decoded fields inline in my IDE — no browser, no terminal switch, no context break. This collapsed the test-and-verify loop from minutes to seconds. MCP turns AuraGate from a standalone tool into a permanent fixture in an AI-assisted developer workflow. That's the real modernization story. 5. Hooks — Automated Verification on Every Save I added a PostFileSave hook in test-on-save.json that automatically runs the full property-based test suite whenever any .ts file is saved. Every codec edit is instantly verified against 7,000 test assertions without any manual npm test. When you're working on byte-level parsing, this kind of continuous safety net is not a nice-to-have — it is essential. 6. The Vibe Coding That Started It All The architecture emerged from a single Kiro chat conversation. I described the problem domain — "I need to parse ISO-8583 binary packets and generate OpenAPI specs". Kiro proposed: The Result<T, ParseError> discriminated union pattern The 5-wave task dependency graph fast-check for property-based testing Zero-copy Buffer.subarray parsing A blank repo became a complete, typed architecture plan in under 10 minutes. Then the spec locked it in. Then the steering docs enforced it. Then Kiro implemented it. **The Technical Core** _Zero-Copy Binary Parsing_ Every byte range is operated on via typed views: // Never do this: const field = buffer.toString('utf-8').slice(offset, offset + length) // AuraGate does this: const field = buffer.subarray(offset, offset + length).toString('utf-8') The difference: zero intermediate string allocations. For a tool that handles real payment packets, memory efficiency is not optional. The Result Type — Never Throw Every decoder returns a discriminated union: export type Result<T, E = ParseError> = | { success: true; value: T } | { success: false; error: E } In a payments context, an uncaught exception means a failed transaction. The Result type makes failure a first-class typed value that every caller must handle at compile time — not a runtime surprise. **Property-Based Testing** Example-based tests would never find all the edge cases in a 128-bit bitmap parser. fast-check generates 1,000 random inputs per invariant: // Round-trip invariant: decode(encode(M)) === M fc.assert( fc.property(fc.integer({ min: -9999999, max: 9999999 }), (val) => { const packed = encodeComp3(val, 4, 0) const unpacked = decodeComp3(packed, 0) assert.equal(unpacked.success, true) if (unpacked.success) assert.equal(unpacked.value, val) }), { numRuns: 1000 } ) 10 tests. 10 passing. 0 failing. 7,000 total assertions. Try It Yourself The fastest way to see AuraGate work: Open https://auragate-i1on.vercel.app/ The ISO-8583 tab pre-loads a real 0200 authorization packet Click Unpack Fields — see every field decoded Click OpenAPI Synthesizer → paste the same hex → click Synthesize Watch a valid OpenAPI 3.1 spec appear from raw binary Or hit the API directly: curl -X POST https://auragate.vercel.app/api/v1/bridge/synthesize \ -H "Content-Type: application/json" \ -d '{ "payload": "303230301038000000c08000303030303030303135303030343832393130313433303235313130345445524d303030314d45524348414e5430303030303120383430", "serviceName": "CardAuthV2" }' What's Next SWIFT MT + ISO-20022 support — bridging the ISO-8583 to ISO-20022 migration gap Hosted SaaS — team dashboards, saved decode history, CI/CD plugin GitHub Actions step — fail a build if your wire format changed unexpectedly NACHA ACH decoder — $80 trillion/year in US ACH transactions, still flat COBOL files **The mainframe modernisation market is $8 billion today, growing to $18.42 billion by 2034. COBOL developers are disappearing. AuraGate's value increases every single year.** Final Thought Kiro did not just help me write code faster. It changed how I build things. Spec-driven development with steering docs and property-based testing is a fundamentally more reliable way to produce correct software — especially for something as unforgiving as binary protocol parsing. If you work anywhere near legacy financial systems, AuraGate was built for you. Drop in a packet. Walk out with an API. 🔗 Live: https://auragate-i1on.vercel.app/ 🔗 Code: https://github.com/poowa-gg/auragate Built for Kiroween 2026 — Resurrection Category — with Kiro #KiroweenHackathon26 