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
- 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.
- The leg group.
swap_legsgets a nullableleg_group, closed to premium, independent, contingent, default, recovery and underlying. - The basket child. A new
credit_basket_constituentmodel, 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. - The carrier.
credit_instrument_dataholds 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. - 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.
- The binding.
nameData.Notionalis a money leaf, so the basket keeps its digits. - 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
100000to100000.0. The source document writes100000.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.