Task: Join trades with typed links

Table of Contents

This page documents a task in the Record trade activities and trade links story. It captures the goal, current status, acceptance, and any notes or results.

1. Goal

Every relation between two trades that a process did not create is a typed, directed link, and it holds nothing.

2. Status

Field Value
State DONE
Parent story Record trade activities and trade links
Now Nothing.
Waiting on Nothing. A link holds nothing and needs no run.
Next Nothing.
Last touched 2026-10-08

3. Acceptance

  • trade_link joins two trades with enforced foreign keys and a type from trade_link_type, and records the trade activity stamp that made it.
  • trade_link_type names the from and to roles and the economic effect, seeded from the link catalogue (novation, exercise, roll and the rest).
  • Nothing in the tree carries a successor trade id.

4. Plan

(Implementation strategy. Written when work starts; key decisions are distilled into the parent story's * Decisions at close, but the plan itself stays — it is the historical record of what we did.)

5. Measurements

Every number this task claims about a tree, with the command that produced it and the commit it was measured at. A number without both is not a measurement, because a clean-up record describes a tree and trunk moves under a branch: a consumer count, a gate's component count and a suite's size all change with no code changing, and the reader of a bare number cannot tell which tree it came from. Where the raw output matters, put it in an evidence/ file beside the task and name that file in the Command column.

What Value Command Commit
pgTAP, the trade links, under the test DDL role 8 of 8 pg_prove test/trading_trade_links_test.sql b7dba42f59
pgTAP, every trading file, under the test DDL role 8 files, 94 tests, pass pg_prove test/trading_*_test.sql b7dba42f59
create files unreachable from the schema roots 0 (was 4) reachability probe over \\ir and \\i from the top-level .sql files 7d98c723ea
constraints on ores_trading_trade_links_tbl 4: both ends, the activity, and the anchor party pin \\d 017bb3dc48
link type rows the populate writes 12 select count(*) from ores_trading_trade_link_types_tbl ae49575dda

6. Notes

7. Test Scenarios

Manual QA scenarios (scaffolded via compass add test_scenario) that verify this task. Link new ones here as they're created; the scenario doc itself links back via its "Verifies task" field.

Scenario State Notes
     

8. PRs

PR Title
#2820 [trading] Unbreak main after the link work
#2807 [doc] Close the trade activities and trade links story
#2806 [trading] Join trades with typed links

9. Review

Comment summary File Decision Notes
       

10. Result

trade_link joins two trades under a type from trade_link_type, with both ends enforced, the type validated against the seeded catalogue, and the activity that made it recorded. The link holds no amount, no state and no cash flow, and the tree still carries no successor trade id.

Three defects surfaced only when the database was rebuilt, and none of them was visible from the C++. The two link tables had generated create files that no aggregator listed, so the tables had never existed. The link copied its party from the from trade and pinned it to nothing, so the copy could drift from its source. And the link had no party isolation policy, so a session restricted to a set of parties read every link in its tenant. All three are fixed here.

The tables are wired into the schema, the party is pinned to the from trade's key, the party isolation policy matches the sibling trade tables, and a link may not join a trade to itself.

Emacs 29.3 (Org mode 9.6.15)