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
Top comments (0)