Implementation Plan: YU03-in-memory-risk-gateway
Goalβ
Add a two-tier pre-trade risk admission gate to the LMAX BLP; an in-process Gateway replica that screens without any synchronous lookup, and an authoritative single-writer BLP decision that checks and reserves exact aggregate exposure in global sequence order; so every acceptance and rejection is journaled and replays deterministically, without changing the inherited ring topology, journal gate, matching policy, or NATS subjects.
Workstreamsβ
- Risk core (
risk/)RiskReason,RiskMetrics,RiskRejectedException,RiskRejectionBodyported;BlpRiskStateandGatewayReplicaStoreadapted to the YU02 base;ReservationHolderandReplicaBootstrapnew.
- BLP integration (
lmax/)- Decide-and-reserve before book entry, consume on fill, release on cancel, market-trade decisions with correlation acks, and control-event handlers.
InputEventtype-discriminated payload slots,OutputEventreject/trade-decision kinds,RestingOrderreservation,SnapshotStorev3, and marshaller/read-model plumbing.
- Edge + control plane
OrderMatcherServicescreening, rejection surface, and metrics;RiskControlControllerandRiskExceptionHandler;risk.*config; journaled startup bootstrap.
- Observability
- Bounded Micrometer metric set on both tiers and a provisioned Grafana risk-gateway dashboard.
- State registration
- Spec pack, generation hook + render script, catalog entry, runtime harness registration.
- Validation
- Unit tests for the decision pipeline, reservation lifecycle, edge screening, and replay determinism; allocation-gate and p99 latency CI gates over the risk path.
Key decisions (see ADRs + spec.md)β
- Two-tier Gateway + authoritative BLP decision (ADR-018); control events in the global journal (ADR-020); replica bootstrap is journal-sequenced (ADR-019).
- No journal/replication wire-format change: new data rides type-discriminated payload slots unused by each event type, so pre-state journals replay unchanged and the 64-byte record is shared by the journal and the NATS replication stream.
- Reservations ride the pooled order entry (
ReservationHolderonRestingOrder) rather than dense orderRef-indexed arrays, since orderRef is monotonic/unbounded here; aggregates rebuild from open orders at snapshot restore. - SymbolTable stays the security-id authority (
symbols.tabpersists ids across restarts); the replica aligns to it at startup. - Snapshot format v3 extends the single
snapshot.dat; v1/v2 snapshots still load. - Market trades become synchronous (
POST /tradesblocks for the sequenced decision); the optionalclientOrderIdfield is the only other admission API delta.
Exit Criteriaβ
- Spec and tasks are complete and reviewed.
- Generation hook produces expected artifacts and exits successfully.
- Unit test suites pass:
BlpRiskStateTest,GatewayReplicaStoreTest,RiskReplayDeterminismTest, the allocation gate with risk gating on, and the p99 latency gates on both tiers. - Generated shared files retain every ancestor state's content alongside this state's additions.
- State can be published to
code/generated-state-YU03-in-memory-risk-gateway.
Validation statusβ
- Unit + integration suite green (48 tests: 47 pass, 1 skipped), including replay-determinism and snapshot-v3-tail parity, which prove ADR-020 / NFR-IMRG03.
- Perf acceptance: the allocation gate runs the real
BlpRiskStateon every ORDER_NEW under Epsilon-GC with zero steady-state allocation, and the p99 latency gate holds on both the BLPdecideAndReserveand edgescreen()paths (seeAllocationGateTest,GatewayReplicaStoreTest). - Live verification ran in an isolated
traderx-yu03-stagingnamespace (seegeneration/implementation-status.md); full multi-scenario container smoke is tracked intasks.mdunder "Still open".