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++
removemethods. 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 aREFERENCESconstraint 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** Indexestable. - 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.