Story: Teach the code generator the trade shape

Table of Contents

This page documents a story in Sprint 26. It captures the goal, current status, acceptance criteria, and the tasks that compose it.

1. Goal

Give the code generator the capabilities the netting-set and trade-split stories need first, so they generate their entities rather than hand-write them. Each later capability is built in the story that first consumes it.

2. Status

Field Value
State DONE
Parent sprint Sprint 26
Now Nothing.
Waiting on Nothing.
Next Nothing.
Last touched 2026-10-03

3. Acceptance

  • An entity can be declared immutable (non-temporal), and other entities reference it with real foreign keys.
  • A model can pin a copied fact with a composite foreign key to its source.
  • The rule that limits reflected structs is measured and recorded where the design reads it.

Moved on 2026-10-03, to the story that first consumes each: the catalogue-driven trade-type checks and routing to Split the trade into an anchor and its components; the derived authorisation status to Model operational authorisation and the client-facing agreement; the blotter's common-date view to the rates instrument story, the first family reworked.

4. Tasks

Task State Start End Description
Let a model declare an immutable entity DONE 2026-10-03 2026-10-03 Add an immutable flag to current-state entities: the table rejects updates and deletes, and the generated service writes rows once and never changes them.
Generate real foreign keys into immutable entities DONE 2026-10-03 2026-10-03 Let a foreign key whose target is an immutable entity be declared as a real REFERENCES constraint instead of a trigger check.
Pin copied facts with composite keys DONE 2026-10-03 2026-10-03 Let a model declare a unique key over several columns and a composite foreign key onto it, enforced as a constraint for an immutable target and as a trigger check for a temporal one.
Guard every reflected struct against the C1202 limit ABANDONED 2026-10-03 2026-10-03 Count the effective fields of every generated reflected struct and fail the codegen checks when one exceeds nine.

5. Decisions

  • An immutable entity keeps its generated C++ remove methods. The store refuses the delete, and :read_only: keeps delete verbs off the wire.
  • An enforced foreign key is opt-in per key with :enforce: true. The generator refuses it for a temporal target, because a REFERENCES constraint would accept a closed version as current.
  • Composite keys are pinned keys in their own SQL table rather than entries in * Foreign keys, which C++ consumers read one column at a time. Named unique keys reuse the ** Indexes table.
  • The C1202 guard was abandoned before it was built. A nine-member cap on generated structs would flag 220 models that compile and miss the struct that fails, a hand-written carrier written as a tagged variant.

6. Out of scope

7. Result

The generator can now express the first trade shape tables. Three tasks shipped and one was abandoned on evidence.

  • A model can declare an immutable entity. The store refuses every update, delete and truncate, and the repository inserts rather than upserts (PR 2526).
  • A foreign key into an immutable entity can be a real constraint, matching the row's tenant (PR 2529).
  • A pinned key holds a copied fact to its source: a constraint against an immutable source, a trigger check against a temporal one (PR 2531).
  • Each capability was tested against PostgreSQL in transactions that rolled back.
  • The C1202 guard was abandoned. Its nine-member rule does not hold, and the measured rule is now in the Data-Oriented Design note. The Windows build that fails on main today is filed as a capture.

Emacs 29.3 (Org mode 9.6.15)