Story: Trade Blotter — the remaining work
Table of Contents
This page documents a story in Sprint 29, carried unfinished from Sprint 28 at close. It captures the goal, current status, acceptance criteria, and the tasks that compose it.
1. Goal
Build the Trade Blotter: the primary front-office screen from which traders, sales, and middle office view, manage, and act on the live book of trades – booking new deals, amending existing ones, and routing trades through their lifecycle (expiry, fixing, delivery, exercise, settlement). See the target-state reference: Trade Blotter (knowledge doc) – multi-panel architecture, deal grid, deal actions, STP panel, Expiry/Fixing Manager, Barrier Management, Delta Jump Screen, Spike Map.
The original design said this story depends on Workspaces: finish the feature,
and that a production import needs a holding location, the Pending
Book. The design task found that the sandbox model replaced both. The
workspace story is abandoned and the Pending Book is retired. A real
deal books into a real book at once and waits in the operational
authorisation queue (see * Decisions).
2. Status
| Field | Value |
|---|---|
| State | DONE |
| Parent sprint | Sprint 29 |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-10-24 |
3. Acceptance
- The design is written and checked against the code. It is in Investigation: the blotter and import design.
- The implementation tasks below are scoped and ordered.
- The trade list and the trade page ship in the web client.
- A real import books into a real book and raises an authorisation request for each new live trade.
- Operations can work the authorisation queue.
4. Tasks
| Task | State | Start | End | Description |
|---|---|---|---|---|
| Build the trade list and the trade page | DONE | 2026-10-24 | 2026-10-25 | Build the trade list and the trade page in the web client from the two prototypes. |
| Build Book a trade | DONE | 2026-10-25 | 2026-10-28 | Build the booking screen from its prototype, with the structure card for a leg. |
| Build the structure page | DONE | 2026-10-31 | 2026-10-31 | Build the structure page from its prototype: members, leg checks, a Price tab and history. |
| Import real deals through the authorisation queue | DONE | 2026-10-31 | 2026-10-31 | Make the ORE import raise authorisation requests, report the rows it cannot book, and prove a second run is safe. |
| Build the authorisation queue screen | DONE | 2026-10-31 | 2026-10-31 | Build the Operations screen that works the operational authorisation queue. |
| Raise an authorisation request when a draft is executed | DONE | 2026-10-31 | 2026-10-31 | A draft that goes live through the Execute transition raises the operational authorisation request, as a booking does. |
| Keep seeded trades out of the authorisation queue | ABANDONED | The synthetic population books actual trades into real books, so each raises an authorisation request. Seeded data must not fill the Operations queue. | ||
| Add a draft reason and a structure hold | DONE | 2026-10-31 | 2026-11-01 | A draft states why it is not live and who must unblock it, and a leg names the structure it waits for. |
| Complete a structure in one unit | DONE | 2026-11-01 | 2026-11-01 | One operation makes the draft legs of a structure live, and writes the structure, members and links, in one unit of work. |
| Grant the Trade Blotter its reads and writes | DONE | 2026-10-25 | 2026-10-25 | Every code each Trade Blotter screen needs is seeded and granted to no human role, so each screen would open dark. Decide which human role owns the blotter, grant it the reads and writes the arc needs, and add the check that would have caught the gap. |
| Analyse how a trade states its size | DONE | 2026-11-01 | 2026-11-01 | A notional column was drawn on the structure screens because the prototype draws one. It states a bond's convention for every family, and an FX trade has no such number at all, so the column read as a fault. This task settles what a screen states as a trade's size, if anything. |
| Give the embedded table a selection contract | DONE | 2026-11-01 | 2026-11-01 | The grouping screen needs a table whose rows can be chosen: a chosen count, a mixed-counterparty guard and a submit that enables with the choice. RecordTable carries no selection, so that screen hand-rolls a table — the copy-paste the standard components exist to prevent. |
| Merge the trades and structures screens | DONE | 2026-10-29 | 2026-10-30 | Analysis: should a structure be a row in the trade blotter rather than a screen beside it, and how does one screen hold the portfolio, counterparty and book perspectives at once? |
| Give the blotter its instrument grouping | DONE | 2026-10-30 | 2026-10-31 | The third perspective the signed-off prototype draws: the same rows read by asset class. The instrument-code catalogue the list already reads states each type's class, so the rail can be built without a schema change. |
| Regenerate the trade summary wire protocol | DONE | 2026-10-31 | 2026-10-31 | structure_id and is_leg reached the trade summary model but never the TypeScript the wire protocol generates from it, so the drift gate reports the client two fields behind its server. |
| Book a generated trade without asking for authorisation | DONE | 2026-10-31 | 2026-10-31 | Seeding must never fill the Operations queue. The trading service already raises a request only for a trade whose booking nature is actual, and the trade summary already reads not_required for the others, so the pathway exists; the population writer declares actual and therefore raises one request per seeded trade. State the booking's nature honestly and pin it with a test. |
5. Permissioning
Every screen of this story reads and writes ores.trading, and the story is where that was discovered: the trade list is the first screen to read trading reference data, and it found that every code it needs is seeded for the handler and held by no human role.
| What the arc needs | Where it stands |
|---|---|
| The list, its identifiers and its books | trading::trade_summaries:read, trading::trade_identifiers:read and refdata::books:read are seeded and held by no human role. The menu entry is therefore hidden rather than opening a screen the route refuses |
| The list's counterparties, the trade page and its tabs | refdata::counterparties:read and trading::trades:read are held by ReportRun; trading::trade_links:read and trading::trade_activities:read by nobody |
| The writes: amend, book, group, raise and work a request | No human role holds a single trading::*:write, and none holds inbox::approval_requests:* |
Grant the Trade Blotter its reads and writes settles the role and grants the arc in one change, because the gap is per component and not per screen. No task in this story is delivered until that lands, since a screen nobody may open is not delivered.
6. Decisions
- Split from Trade Blotter on 2026-10-24 at sprint 28 close. The acceptance above is copied from that story; its done tasks are recorded there.
- A leg is a membership, not a trade. Unlinking removes the membership and leaves the trade booked and groupable, which is what the desk means by unlinking.
- The deal's tree is drawn beside its page and selects the leg being read; the selection is in the address, so it is shareable.
- History is the shared timeline over the record and the parts it holds now. The two-pane compare of
HistoryPanelis the retired shape and is not used on the trading screens. - A history read is gated twice: the service must register a provider for the entity type, and the route must allow it. Both were missing for the trade and its parts.
- A screen's party is named from the login session when the read is party-scoped, rather than reading the parties table the trading roles may not see.
- A trade booked from a deal joins it: the deal and the role travel with the form, and the trade is a leg before the form closes.
- The authorisation queue's class is derived from the trade type in the BFF, and the division belongs on the trade type as configuration. The screen reads it as it stands; Classify a product type as flow or non-flow carries the work.
- The queue states a request by the state the inbox holds it in. A withdrawn, expired or approved-but-unapplied request reads as closed rather than as a denial nobody gave.
- Size is not one fact. A bond states a notional, an FX trade two amounts, a commodity a quantity, and a rate swap a schedule per leg; a composition screen therefore states what is grouped and never a total, and a trade page states its family's own fact or nothing. Analyse how a trade states its size holds the enumeration.
- Valuation is out of this arc. The structure page's Price tab is a valuation of the deal against a market snapshot, and the product has no valuation at all, so the tab says the deal has not been valued and the work is captured as Value a trade against a market snapshot. A tab that waits on a capability is not a screen with a gap to fill later.
7. Result
The arc closed on 2026-11-01 with every task done or abandoned. What it shipped:
| Piece | What it does |
|---|---|
| The trade list and the trade page | the blotter's two screens |
| Book a trade | a deal and its first leg, with the structure card |
| The structure page | the tree, the legs, the history, and a leg that moves for a stated reason |
| The authorisation queue | the Operations screen: the flow and non-flow division, the states the inbox holds, and a decision that always carries a comment |
| The queue's data | a request per live actual trade, raised by the booking and by an execution, one per waiting and never two |
| Import and export | an ORE import that books into a real book and raises a request per new live trade, planned from the document so a second run books nothing twice |
| Complete a structure | one unit that writes the structure, its members and takes every leg live, refusing all of it or none |
| The draft reason | why a draft is not live and the desk that unblocks it, required by the booking and refused on a live trade |
| The size analysis | four shapes of size across the families, and a trade page that states its own family's or nothing |
8. What the arc leaves behind
- Value a trade against a market snapshot — the Price tab's valuation, waiting on a capability the product does not have.
- The structure completion has no caller — the operation that ships without a screen calling it.
- Report the drafts and who is late — the report of aged drafts.
- Page the authorisation queue and count it on the server — the counts the queue's buttons state.
- Finish the authorisation queue's specification — expiry, the operational error flag, the changed fields, the package's legs.
- Classify a product type as flow or non-flow — the division as configuration rather than a constant.
9. Out of scope
- The Positions domain model and the trade-expiry workflow stay in the backlog as separate captures.
- Importing from FpML, CSV or another trading system. Only the ORE import exists. Each other source needs its own story.
- The Expiry, Fixing, Barrier, Delta and Spike screens.