Task: Write the credit legs and the basket

Table of Contents

This page documents a task in the Rework the credit instruments to the instrument table rule story. It captures the goal, current status, acceptance, and any notes or results.

1. Goal

The legs and the basket of the credit documents are rows, and the reverse mapping reads them.

2. Status

Field Value
State DONE
Parent story Rework the credit instruments to the instrument table rule
Now Nothing.
Waiting on Nothing.
Next Nothing.
Last touched 2026-10-11

3. Acceptance

  • swap_legs has a nullable leg_group, and a credit leg carries its group.
  • credit_basket_constituents holds the names of an index swap or a CDO basket.
  • The four payment groups of a credit linked swap are all written, not the first contingent leg only.
  • The corpus documents' legs come back as the same rows.

4. Plan

  1. Order. The legs land before the header. The header unit drops the wide columns, and a leg read from a column that is gone would lose data. The design and the story carry the swap.
  2. The leg group. swap_legs gets a nullable leg_group, closed to premium, independent, contingent, default, recovery and underlying.
  3. The basket child. A new credit_basket_constituent model, cloned from the commodity constituent: keyed by trade and sequence number, with the issuer, qualifier, curve, notional, weight and currency. The notional is an exact decimal and the weight is continuous.
  4. The carrier. credit_instrument_data holds the instrument, the legs, the amounts, the rates and the constituents. It replaces the bare instrument in the wire variant, the batch, the batch mapper, the export service, the exporter and the import handler.
  5. The mapper. The credit mapper reads and rebuilds legs through the rates mapper's leg functions, made public as the shared seam. A credit linked swap writes its four payment groups. An index swap, an option and a CDO write their basket.
  6. The binding. nameData.Notional is a money leaf, so the basket keeps its digits.
  7. Prove it. Update the tests that used the bare instrument, add the leg and basket tests, regenerate the one golden whose digits change, and run the suites.

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
ORE core suite all pass, with the bespoke basket golden regenerated ctest --preset linux-clang-debug-make -R ores.ore.core.tests the PR head
Trading core suite all pass ctest --preset linux-clang-debug-make -R ores.trading.core.tests the PR head
Shell trading suite all pass ctest --preset linux-clang-debug-make -R ores.shell.trading.tests the PR head
Telemetry database suite 14 cases, all pass ctest --preset linux-clang-debug-make -R ores.telemetry.database.tests the PR head
Build exit 0 compass build ores.ore.core.tests ores.trading.core.tests ores.shell.trading.tests the PR head
SQL hygiene 2,363 files, 0 problems check_sql_hygiene.py the PR head
cmake sources up to date regenerate_cmake_component_files.py --all --check the PR head
Handler permissions and populate references seeded; resolve check_handler_permissions.py and check_populate_references.py the PR head

6. Notes

  • The ctest runs went straight to ctest, not through compass test run, because the host-wide build lock was held by other worktrees for over an hour. The user allowed it for these runs.
  • The telemetry roster test was broken on main: it reported three instances on one host, and the roster keeps only the newest instance per host. The fix gives the fresh instance another host. It rides in this task to save a PR.
  • The drift run regenerated four create scripts this task does not model: the compute apps, app versions and platforms, and the IAM tenants. Their delete rules were missing the own-tenant limit that the templates now state. Main carried that drift, so the regenerated files ride in this commit.
  • The digest components section of the catalogue covers neither the swap legs nor the constituents. The gap is older than this task and is left as it is.
  • The basket keeps six columns: issuer, qualifier, curve, notional, weight and currency. Recovery rate, prior notional and weight, and the auction and default dates wait for unit 6.
  • The commodity constituent model says the weight is exact, but its column is a double. The credit child uses a double on purpose, because a weight is continuous.
  • Risk participation agreements have no legs yet. Their underlying legs belong to unit 6.
  • The bespoke basket golden changed from 100000 to 100000.0. The source document writes 100000.0, so the old golden had lost the digits.

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
#3179 [ore,trading,sql,shell] Write the credit legs and the basket as rows

9. Review

# Comment summary File Decision Notes
1 The import handler writes the credit legs with the same field set as the rates branch ore_import_execute_handler.cpp accept Checked against the swap branch; the fields match, plus leg_group.
2 A misspell scan of the whole tree exits 1 the tree decline A copy of every file this branch changes scans clean, so the hit is in a file this branch does not touch.
3 The catalogue digest does not cover legs or constituents trade_type_catalogue.org decline An older gap, shared with the commodity constituents; noted for a later task.
4 The telemetry roster test fix is unrelated to the credit work telemetry_repository_tests.cpp accept Kept in this branch to save a PR, and recorded in the Notes.
5 Re-import leaves stale child rows ore_import_execute_handler.cpp decline The planner stamps a fresh trade id on every import, so no import rewrites an earlier trade. The rates and commodity branches write children the same way.
6 A failed child write leaves a header without its children ore_import_execute_handler.cpp decline A false return is recorded as an item error on that trade, and a total failure triggers the saga rollback. The commodity branch has the same shape.
7 The weight goes through a float credit_instrument_mapper.cpp decline The ORE binding types the weight as xs:float and the weight is continuous, so a float is its exact form.
8 Only the first premium leg is exported credit_instrument_mapper.cpp decline The importer writes one leg per premium group for these products. Unit 5 states the one-leg rule on the fact tables.
9 parse_currency_code may throw on a bad constituent currency credit_instrument_mapper.cpp decline The importer writes the code from the ORE currency enum, so only a hand-edited row can be bad.
10 leg_group allows underlying with no writer swap_leg model decline Unit 6 writes the risk participation agreement's underlying legs into that group.
11 The cascade function is security definer with no comment credit_instrument model decline The SQL is generated, and every family's cascade function is the same.
12 Header includes out of order in trade_export_service.cpp trade_export_service.cpp accept Fixed.
13 The new handler and service have no test beyond the shell commands credit_basket_constituent decline The generated eventing and service tests run in the trading core suite, which passes.

10. Result

The credit swap family now writes its legs and its basket as rows. A premium leg and the four payment groups of a credit linked swap are rows of the shared leg tables, told apart by leg_group. The names of a basket are rows of the new credit_basket_constituents table. The import, the export and the reverse mapping all read them through the credit_instrument_data carrier.

Acceptance met: swap_legs has a nullable leg_group and a credit leg carries its group; the basket has its table; the credit linked swap writes all four groups; and the corpus documents come back with the same legs and basket names. The header and the six fact tables follow in unit 5.

Emacs 29.3 (Org mode 9.6.15)