← All posts Engineering

One domain spec, two runtimes, one test suite

Telos Engineering 5 min read

Standalone runs Dart. LAN and online run Java. Keeping them byte-identical is not a nice-to-have — it is the thing that makes switching deployment shapes safe.

A single-PC shop should not need a JVM. A ten-station distributor should not run its books through a desktop app. So Telos ships two implementations of the same rules: Dart for standalone, Java for LAN and online.

Two implementations of anything is a liability. Two implementations of money is a liability with a number attached.

The rule

A change to a domain rule ships in three places in the same pull request: the Dart implementation, the Java implementation, and a test vector.

A vector is a JSON file with inputs and the exact expected output. Both runtimes read the same file. CI runs both and fails the build on any mismatch — not "close enough", not "rounding difference". Byte-identical.

What this catches

The interesting failures are never the obvious ones.

  • Rounding. Java BigDecimal with HALF_EVEN, Dart decimal wrapped in our own money type. Two libraries agreeing on 2.5 rounding to 2 is not automatic.
  • FEFO ties. Two batches with the same expiry date. Which goes first? Whatever the vector says — and both runtimes had better say the same.
  • Calendar edges. Solar Hijri leap years do not line up with Gregorian ones. A date that exists in one calendar and not the other is a vector.

What it costs

Every domain change is roughly twice the work, plus a vector. We think that is the right trade for a product where a customer can start on one PC and move to a server without their numbers changing underneath them.