ADR-003: Business date and system time separation
Status
Accepted
Context
Financial systems operate with more than one meaningful time dimension. OpenTRMS needs to distinguish:
- the operator-controlled business date used for EOD and daily processing
- the wall-clock timestamp when the platform observed or wrote something
- the trade execution timestamp supplied by an upstream caller
Collapsing those into a single now() value breaks late booking, historical
replay, and bitemporal reasoning.
Decision
OpenTRMS uses BusinessClock as the application boundary for time-sensitive
logic. The platform keeps three separate concepts:
business_datefromBusinessClock.businessDate()system_timestamp()fromBusinessClock.systemTimestamp()trade_timestampsupplied by the caller and stored as received
Application code should not call LocalDate.now(), Instant.now(), or other
direct system clock APIs for business behavior.
Consequences
This decision makes EOD sequencing and historical replay reproducible. It also forces developers to be explicit about which notion of time they are using.
In practice:
business_datedrives workflow and daily eligibilitysystem_timestamp()drivesrecorded_at,booked_at, and similar audit factstrade_timestampstays distinct from both, withtrade_datederived from it
Projection and audit tables that participate in bitemporal reads may therefore
carry both as_of_date and recorded_at, because those fields answer different
questions.