Task: Author the credit family header and its fact tables
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 credit family has a header and one fact table per product, generated from models.
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
- The header's trade_type check lists the six codes the importer writes, and the catalogue routes only those.
- Six fact tables are keyed by the trade and pinned to the header by the generated delete cascade.
- Codegen drift is clean and the generated eventing tests pass.
4. Plan
- The header.
credit_instrumentloses its product columns and keeps the trade key, the party, the type, the reference entity, the two common dates and the description. It is cloned from the rates header: the delete cascade names every table the family writes, and a pinned-key trigger holds the party and type to the anchor trade. The check lists the six codes the importer writes. - Six fact tables. One model per product, cloned from the rates facts: keyed by the trade, tenant isolated, party scoped for writes, with generated eventing tests. A column lands only when a mapper writes it today, so unit 6 adds the rest with their writers.
- The routing. The two codes with no importer leave the catalogue's routing. The six facts join the catalogue's children and the header's digest.
- Generate and wire. Regenerate the trading component, then wire the six entities by hand as the basket child was: the create and drop includes, the permission seeds, the registrars, the history providers and the event mappings.
- The carrier. A
credit_fact_variantholds the product's fact row. The carrier gains it, with the shared strikes and schedules, and the batch, the export service, the import handler and the mapper read and write it. - Prove it. Update the credit mapper tests, recreate the database, and run the suites and every check.
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 | ctest --preset linux-clang-debug-make -R ores.ore.core.tests |
the PR head |
| Trading core suite | all pass, with the generated eventing tests of the seven entities | 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 |
| Build | exit 0 | compass build ores.ore.core.tests ores.trading.core.tests ores.shell.trading.tests |
the PR head |
| SQL hygiene | 2,499 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 | 1,040 codes seeded; resolve | check_handler_permissions.py and check_populate_references.py |
the PR head |
| Documentation checks | all 39 components pass | validate_docs.sh |
the PR head |
6. Notes
- The ctest runs went straight to ctest, because the host build lock was held by other worktrees. The user allowed it.
- The index option's fact row holds the wrapped index swap's credit curve id, and the trade has no row in the index swap's table. The design said two rows; the carrier holds one fact row, so the design now says one.
- The header's dates carry
:common_date:and the common-date view lists the credit header. Unit 7 keeps the probe that proves it. - The generated header eventing test seeds an anchor trade of the header's own type, because the pinned-key trigger refuses a header that disagrees with its anchor. The rates header passes by coincidence: both default to Swap.
- An index option states one strike and its exercise dates in the shared strike and schedule rows. The rest of its option block (long or short, style, premium) waits for unit 6.
- Fact columns without a writer are not in the tables. Unit 6 adds the flags, the upfront fee and date, the participation rate and the protection fee with the code that writes them.
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 |
|---|---|
| #3205 | [ore,trading,sql,shell] Author the credit family header and its fact tables |
9. Review
| # | Comment summary | File | Decision | Notes |
|---|---|---|---|---|
| 1 | The fact tables hold fewer columns than the design lists | the six fact models | accept | The runbook drops a column no mapper writes. Unit 6 adds each with its writer. |
| 2 | The index option has a column the design did not list | index_credit_default_swap_option_instrument | accept | It carries the wrapped swap's curve id, so the carrier needs one fact row. |
| 3 | The header check allows maturity equal to start | credit_instrument model | accept | A risk participation agreement may start and end on one day. |
| 4 | The shared option block is not written for the index option | credit_instrument_mapper.cpp | decline | Unit 6 writes the whole option block with the other dropped elements. |
| 5 | The fact visitor ends in a catch-all else, so a new fact type would take the agreement's path | ore_import_execute_handler.cpp | accept | The agreement has its own branch and the last else is a static_assert. |
| 6 | The NATS call boilerplate repeats in each branch | ore_import_execute_handler.cpp | decline | Every family branch of the handler repeats it; a helper is its own task. |
| 7 | A failed fact write leaves a header with no fact row | ore_import_execute_handler.cpp | decline | A false return is an item error on that trade, and a total failure triggers the saga rollback, as for every family. |
| 8 | Nothing links the strike and schedule rows to the index option | design.org | accept | The design now says the shared tables are keyed by the trade alone and only the option's mapper writes them. |
| 9 | The trading API, trading service, shell application and codegen suites were not rerun | the PR | accept | Run: the three C++ suites pass; the codegen suite passes after merging main. |
10. Result
The credit family has a header and one fact table per product, generated from
models. credit_instrument is the slim header with the common dates and the
delete cascade, and six fact tables hold the credit curve, the issuer, the
recovery rate, the CDO tranche and the wrapped index curve. The catalogue routes
the six importer codes and leaves the two codes with no importer out. The
carrier, the batch, the export service, the import handler and the mapper read
and write the header with its fact row, and the corpus documents come back
through them.
Acceptance met: the header lists the six codes; six fact tables are keyed by the trade and pinned by the generated delete cascade; and codegen drift is clean with the generated eventing tests passing. Unit 6 closes the round trip.