Task: Model netting agreements and netting sets
Table of Contents
This page documents a task in the Model netting agreements, netting sets and CSAs story. It captures the goal, current status, acceptance, and any notes or results.
1. Goal
Give every netting set an identity of its own and tie it to the legal agreement that makes netting enforceable.
2. Status
| Field | Value |
|---|---|
| State | DONE |
| Parent story | Model netting agreements, netting sets and CSAs |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-10-03 |
3. Acceptance
- netting_agreement and netting_set are generated in ores.refdata across every layer the codegen covers.
- A netting set with an agreement has that agreement's counterparty and legal entity, enforced by a pinned key.
- A set without an agreement is allowed and records that its trades do not net.
4. Plan
- Two models in
projects/ores.refdata/modeling, on theuuid-identified-lookupprofile (tenant-scoped, no workspace, since the trade shape design removes workspaces). netting_agreement: agreement number (natural key), the firm's legal entity and the counterparty (both required, fixed for the agreement's life), agreement type checked against ISDA, AFB, FBF and OTHER, and governing law.netting_set: code (ORE's netting set id, natural key), the agreement, the counterparty and the legal entity, call type, initial margin type and risk weight. The agreement and the two parties are optional, because an ORE document names a set by code alone. A check requires both parties when the set has an agreement, so the pinned key to the agreement is never skipped by a null.- Generate every layer with
compass codegen entity generate, then wire by hand what no generator owns: the SQL create and drop lists, the permission seeds, the core registrar, the shell menu and the CMake file lists. - The credit limit the note names as part of a set's identity has no entity yet, so it is left out.
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 |
|---|---|---|---|
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 |
|---|---|
| #2537 | [refdata] Model netting agreements and netting sets |
9. Review
| # | Comment summary | File | Decision | Notes |
|---|---|---|---|---|
| 1 | The agreement's parties can change in a new version | netting_agreement | Fix | New codegen column property :fixed:; the agreement's two parties are fixed, so a version that changes either is refused. |
| 2 | An agreement can close while sets reference it | netting_agreement | Document | Every soft foreign key in the schema behaves this way; the model note says so. |
| 3 | A set's parties are not re-checked on update | netting_set | No change | Each new version of a set is an insert and runs the pin again; with fixed agreement parties the copy cannot go stale. |
| 4 | Call type and IM type unchecked; negative risk weight | netting_set | Partly fix | Risk weight checked non-negative. ORE types the two as plain strings and no example uses them, so they stay free text; the model says why. |
| 5 | Credit limit left out | — | Capture | Filed as Key netting sets by their credit limit. |
| 6 | (CI) RLS warnings fail the ER check | refdata RLS layer | Fix | Tenant and party isolation policies added for both tables. |
| 7 | (CI) Shell recipe inventory stale | shell.org | Fix | Regenerated. |
10. Result
netting_agreementandnetting_setare generated inores.refdata: SQL schema and notify triggers, domain types, repository, service, protocol, handlers, history providers, eventing, generators, shell commands and TypeScript wire types.- Wired by hand: the refdata SQL create and drop lists, the permission seeds, the refdata core registrar, the shell refdata menu and the CMake file lists of the four components touched.
- A netting set with an agreement must carry both parties, by a check, and they must be the agreement's, by a pinned key. A set without an agreement is accepted.
- In Postgres, in a transaction that rolled back, with stub counterparties inserted with their own triggers off: an unknown agreement type was refused by its check (23514); a set naming another counterparty than its agreement's was refused by the pin (23503); a set with an agreement and no parties was refused by the check (23514); a set without an agreement and a matching set were accepted.
- After review: an amendment that kept the agreement's parties was accepted; one that changed the counterparty was refused (23514, fixed column); a negative risk weight was refused (23514).
- Row-level security: tenant isolation on both tables, and party isolation on reads; a set without a legal entity stays visible across its tenant.
- Build: linux-clang-debug-make clean. ctest: 89 of 89 binaries passed on a database recreated from this branch, including the two generated eventing integration tests and 38 generated shell command cases.