Task: Repair the swap leg children's insert trigger and isolation
Table of Contents
This page documents a task in the Rework the rates instruments to the instrument table rule story. It captures the goal, current status, acceptance, and any notes or results.
1. Goal
ores_trading_swap_leg_amounts_tbl and ores_trading_swap_leg_rates_tbl
accept a row again, and are isolated to their tenant. The two tables bind a
profile that describes a single-row instrument, so their generated insert
trigger stamps a party_id column their flattened shape does not have, and
every insert fails. Their siblings carry the tenant isolation policy they are
missing.
2. Status
| Field | Value |
|---|---|
| State | DONE |
| Parent story | Rework the rates instruments to the instrument table rule |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-10-08 |
3. Acceptance
- Neither generated create file stamps a column its table does not declare.
- Both tables enable row level security and carry a tenant isolation policy,
as
ores_trading_bond_leg_amounts_tbldoes. - Both drop files drop that policy, and the drop aggregator reaches all four drop files.
- The tables' column shape is unchanged, so no data migration is implied.
4. Plan
- The root cause is the
:profile: trading-instrumentbinding. The loader resolves the profile into two features,has_tenant_idandparty_id_from_session, and the second emits the party stamp. The profile describes a flat ORE instrument sub-type with an identity group that carriesparty_id; a leg's notional row is not an instrument sub-type and has no such column. - Replace the binding with the one feature the tables actually need,
:has_tenant_id: true, which is exactly what the working siblingores.trading.bond_leg_amountdeclares. The stamp disappears and nothing else about the trigger changes. - Add
:rls_tenant_isolation: trueto both models' SQL Flags, which generates the enable and the tenant policy into each create file and the policy drop into each drop file. - Wire the four drop files into
drop_trading.sql, children before the leg they belong to, because the drop aggregator never reached them. - Regenerate the component and confirm the trigger change is the only difference to the tables.
5. Measurements
| What | Value | Command | Commit |
|---|---|---|---|
| Tables whose trigger stamped a column the table lacks | 2 | grep NEW.party_id across create/trading | worktree |
| Warnings for the swap leg children after the fix | 0 | plantuml_er_parse_sql.py –warn –strict | worktree |
| Schema warnings before the fix, by code | 3 RLS_001, 2 RLS_002, 1 TENANT_002, 16 WIRE_001 | same | worktree |
| Schema warnings after the fix, by code | 1 RLS_001, 2 RLS_002, 1 TENANT_002, 12 WIRE_001 | same | worktree |
| Codegen drift, trading | no drift | check_component_drift.py –component trading-cpp –dry-run | worktree |
| clang-format on the changed C++ | clean | clang-format –dry-run –Werror | worktree |
The warnings that remain belong to other families: ores_trading_structures_tbl
(one RLS_001 and one RLS_002), ores_marketdata_market_series_identity_tbl (one
RLS_002 and one TENANT_002), and the unwired drop files of the structures and
trade link families.
6. Notes
- The defect was latent: no test writes a swap leg amount or rate row yet, so the round trip passed while the table could not accept one.
swap_legs, the parent, has aparty_idcolumn and a hand-written policy intrading_rls_policies_create.sql, which is why it was unaffected. Its children have neither.- The regeneration also refreshed
structure_service.cpp, whose committed copy the outcome-catalogue template had outrun. It is generated output, so the gate requires the regenerated form.
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 |
|---|---|
| #2855 | [trading] Repair the swap leg children's insert trigger and isolation |
9. Review
| Comment summary | File | Decision | Notes |
|---|---|---|---|
10. Result
Both tables accept a row and are tenant-isolated. The profile binding that described a single-row instrument is gone from two child tables that are not instruments, the tenant isolation policy matches the bond family's children, and the drop aggregator reaches the four drop files. The table shape is unchanged.