Engineering Lab · Legacy modernisation
Reconstructing business-critical logic without losing the behaviour that matters.
Thirteen COBOL programs from an open-source banking and payroll ledger, reconstructed as one standalone Rust application and compared byte for byte against the running originals: 2,174 exact file comparisons, 185,968 record images, zero failures, zero monetary tolerance.
Thirteen programs, one binary,
every file compared.
Select a program to see what it carries, which Rust module now carries it and what the harness compares afterwards. Roles and retained quirks are taken from the repository's README and conversion report.
Banking · six-node simulation
Payroll · 25 employees
banking programINTEREST.cob
INTEREST
Monthly interest: balance × annual rate ÷ 12, with COMPUTE ROUNDED deciding the last cent.
- Rust
- src-rust/bank.rs + decimal.rs
- Compared
- Rounded interest in every account record and journal line
Every comparison is raw bytes after the step, under a fixed clock, with no normalised or removed fields. verification.json · MIGRATION.md
01 / THE CASE
Why this case matters.
A ledger is where modernisation is least forgiving. Balances carry across days, interest compounds on rounded cents, fees have floors, journals grow, and a payroll batch writes packed-decimal pay stubs that a downstream system reads as bytes. Change the scale of one field or the rounding of one COMPUTE and the error is silent and permanent.
The original, Albert Mendes's COBOL Legacy Ledger, is a teaching system with nine banking programs and a payroll suite. Genyra reconstructed the verified scope as a single Rust binary with no COBOL, Python, database service or network at runtime, and built the harness that proves the two behave identically on the same inputs.
02 / PRESERVED, CHANGED, VERIFIED
What was preserved, what changed, how it was verified.
Preserved: every picture clause's scale, every ROUNDED and truncating assignment, the 70-byte account record and the journal layouts, status codes, the fixed-clock timestamps including the original's six-digit time quirk, the packed pay-stub bytes and the documented defects in the transfer, settlement and batch programs.
Changed: the language, the runtime and the safety. Monetary arithmetic uses integer cents with checked i128 intermediates; overflow is rejected instead of wrapping; malformed records return errors. One read-only usability fix in a report command is documented and kept outside the exact comparison corpus.
Verified: both implementations run 90 simulated days across six nodes, 860 operations and a 25-employee payroll on separate copies of the same inputs. After each applicable step, every account, journal and outbound file is compared as raw bytes.
03 / BOUNDARY
The boundary of the claim.
This is a simulator. The published equivalence shows that the reconstruction reproduces the original's behaviour on the recorded corpus under the recorded compiler and runtime profile. It does not certify the original's business rules, current tax calculations or regulatory compliance, and it is not evidence of z/OS or EBCDIC interoperability. The conversion report lists what a real financial deployment would still have to resolve.
Inspect the evidence.
Each view answers one question: what was shown, how, what Genyra built, the numbers, what has not been established, where the code is and how to run the same check yourself.
Reconstructing business-critical logic without losing the behaviour that matters.
Thirteen COBOL programs from an open-source banking and payroll ledger, reconstructed as one standalone Rust application and compared byte for byte against the running originals.
Original work: Albert Mendes / AKD APP BREWING, MIT, retained. Rust implementation and evidence: Genyra LLC. Status: Verified simulator · Rust 1.0.0.
Both implementations run the same deterministic corpus: 90 simulated banking days across six nodes and a 25-employee payroll batch. After each step every account, journal and outbound file is compared as raw bytes, with no normalised fields and no monetary tolerance.
Standards used on this project
- Exact byte-for-byte comparison
- Functional tests
- CI build success
Recorded test conditions
- Original compiled with cobc (GnuCOBOL) 3.2.0; runtime clock fixed at 2026-03-16 16:40:52.000000000.
- Comparison: byte-for-byte; fixed clock; no normalized or removed fields.
- Payroll binary transport: COB_LS_VALIDATE=N; COB_LS_NULLS=Y, the setting the original needs to write packed bytes.
- Pinned upstream revision 4ec2a1f, source hashes checked before every run.
What Genyra engineered
- A standalone Rust implementation of nine banking programs (accounts, transactions, validation, reports, fees, interest, reconciliation, simulation, settlement) and four payroll programs.
- Checked integer-cent arithmetic with explicit rounding policies: COBOL ROUNDED as nearest-ties-away, everything else truncated toward zero, as the original statements specify.
- A COMP-3 packed-decimal codec with sign nibbles, even-digit padding and malformed-data rejection, tested over 199,999 signed round trips.
- Fixed-width record encoding that preserves the original file layouts, and a reproducible comparison harness that runs both implementations on the same inputs with a fixed clock.
Source passages quoted on this page
- COBOL-BANKING/src/INTEREST.cob · The original rule
- src-rust/decimal.rs · The reconstruction
- src-rust/decimal.rs · Record encoding
Figures are read from the repository's evidence file at build time; every label states which standard produced it. Figures of different standards are never combined.
- A banking and payroll simulator. It is not a deployed production banking system, a certified payroll service or evidence of regulatory compliance.
- Equivalence intentionally preserves documented legacy defects, such as a reused loop index in the transfer path and an unterminated IF in the batch program. Matching the original does not make the original rule correct.
- The preserved Python console and the separate merchant, dispute and risk programs are outside the verified scope.
- Proof is bounded by this corpus and compiler profile: not z/OS execution, not an EBCDIC interoperability certification, not a concurrent-service test.
The full list is in the published report.
- Genyra repository · Legacy Ledger & Payroll, Rust implementation and harness
- Original project · COBOL Legacy Ledger by Albert Mendes / AKD APP BREWING, MIT, retained
- Verification evidence · machine-readable results
- Report · decisions, conditions and limitations
- Upstream revision ·
4ec2a1fd9a56 - GitHub Actions · the same verification on every push
Latest verification run passed · 2026-11-03 · afcae59· run
git clone https://github.com/GenyraLLC/legacy-ledger-rust.git cd legacy-ledger-rust make demo # Rust only make verify # also needs Python 3.10+ and GnuCOBOL 3.2
make verify checks the original source hashes, compiles the 13 originals, runs both implementations on separate copies of the same inputs and compares every file as bytes. GitHub Actions runs the same job. Instructions in the repository.
- Multi-program legacy reconstruction
- COBOL business-rule analysis
- Fixed-width records
- Exact fixed-point calculation
- COMP-3 packed decimal
- Checked arithmetic
- Receiving-field rounding
- Record-format preservation
- Deterministic simulation
- Reconciliation
- Byte-for-byte verification
Questions we are asked.
Short answers in the same terms as the page. Anything specific to your systems is agreed by enquiry.
- Why compare files as bytes rather than compare balances?
- Because a balance can match while a record does not: a different sign convention, a shifted field or a reordered journal would pass a numeric check and still break the next program that reads the file. Byte comparison of the complete file after each step catches all of it, with no judgement about which fields matter.
- How is COBOL ROUNDED reproduced in Rust?
- As nearest, ties away from zero, applied at the receiving field, exactly where the COBOL statement applies it. Non-rounded assignments truncate toward zero. The decimal primitive also implements half-even and prohibited-inexact policies so that a different system's rule can be stated explicitly rather than assumed.
- What happens to a legacy defect during a faithful reconstruction?
- It is preserved and documented. The ledger's transfer path, settlement description and batch program each carry a documented defect; the Rust code reproduces the observable behaviour so that the comparison is honest, and the report names each one so that a real migration can decide, with the business, what to correct.
Discuss legacy modernisation
From an unanswered question
to an engineered possibility.

