CSA (/org/[orgId]/csa)
Purpose: view and act on the Credit Support Annex — post collateral, withdraw excess, dispute marks, resolve disputes.
Who uses it: counterparties (post / withdraw / dispute), operator (resolve).
MARS analog: the MARS collateral / margin module — same ladder layout, same dispute workflow, fully on-chain. See SWPM / MARS parity.
Source: app/src/features/csa/.
See CSA Model for the underlying signed-CSB convention.

CSA proposals
When there is at least one open Csa.Proposal:CsaProposal involving the active party, a CSA PROPOSALS section renders above the active-CSA list. Columns: direction, counterparty, MTA, threshold A/B, rounding. Per-direction actions:
| Direction | Visible actions | Choice fired |
|---|---|---|
In (you are counterparty) | Accept / Reject | CsaProposalAccept / CsaProposalReject |
Out (you are proposer) | Withdraw | CsaProposalWithdraw |
Observer | — | — |
The New CSA proposal button lives on this trader-side /csa page (next to the page header), gated !isOperator. Operators don't propose CSAs — the resulting Csa would have partyA = Operator which is structurally invalid since operator can't be a trading party. Counterparties see the proposed row mirrored here as In direction and accept/reject from the same table.
Operator does not see the New CSA proposal button, but can still see incoming proposals routed to the operator queue when directionForMe resolves (which it doesn't for operator — they are always Observer, so the actions cell is empty).
Accepting creates a live Csa contract with identical terms (threshold, mta, rounding, eligible, valuationCcy, csb = empty, state = Active). It appears in the list below immediately.
List
One row per Csa contract visible to the active party. Columns:
| Column | Meaning |
|---|---|
| Counterparties | partyA ↔ partyB |
| Reporting ccy | valuationCcy |
| Signed CSB | Per-currency, signed (positive = A pledged) |
| MTM | Latest mark |
| Call | Outstanding call amount |
| State | Active / MarginCallOutstanding / MarkDisputed / Terminated |
| Mark sparkline | History from MarkSnapshot |
Clicking a row opens the drawer.
Drawer

Shows full CSA params (thresholds, MTA, rounding, eligible collateral) plus action buttons by role/state:
Funding actions (csa-funding-actions.tsx)
| Button | Choice | When | Who |
|---|---|---|---|
| Post Collateral | PostCollateral | always (open) | poster (A or B) |
| Withdraw Excess | WithdrawExcess | when over-collateralised | either party |
Clicking opens the amount modal:

Pick currency from eligibleCollateral, enter amount, submit.
Dispute modal (csa-dispute-modal.tsx)

| Field | Meaning |
|---|---|
| Counter mark | Your proposed mark value |
| Reason | Free-text justification |
Submitting exercises Dispute, transitions CSA to MarkDisputed. While disputed, no new marks publish.
Operator actions (csa-operator-actions.tsx)
Visible only when activeParty == operator.
| Button | Choice | Effect |
|---|---|---|
| Resolve dispute | AcknowledgeDispute | Returns CSA to Active; either accepts the disputed mark or substitutes operator's resolution |

Mark sparkline
Hover for tooltip with timestamp + mark value. Source: MarkSnapshot ACS query merged with live WebSocket. Disputed marks shown in amber.

Contract id rotation
Every choice rotates the Csa contract id (Daml templates are immutable). The frontend resolves CSAs by stable pair key (partyA + partyB) via makeCsaPairResolver, and mutating actions retry on CONTRACT_NOT_FOUND via exerciseCsaWithRetry. Users never see the rotation.
Configurable via yaml
| yaml key | UI effect |
|---|---|
csa.threshold.{DirA,DirB} | Drives the "uncollateralised tolerance" displayed in the drawer |
csa.mta | "Min Transfer Amount" cell |
csa.rounding | "Call rounding" cell |
csa.valuationCcy | Reporting currency |
csa.eligibleCollateral | Currency dropdown in the amount modal |
demo.csa.initialFunding | Opening signed CSB at boot (demo only) |