Bilateral attestation and settlement
Two parties who do not trust each other each seal only what their own side observed, and a verifier who trusts neither derives from the two records whether they agree.
1What it is
Bilateral attestation is an exchange in which the requesting party signs what it asked for, the performing party signs what it did about it (performed, declined, or escalated), and each acknowledges the other's record.
Settlement records apply the same idea to a payment: the payer and the payee each seal, under their own key, only what their own system observed, as separate Agent Action Capsule leg records that cite one terms leg.
No record states whether the two sides agree; a verifier derives that from which records are present and whether their bound fields match.
2Design choices
delivery_unconfirmed, counterparty_timeout, countersign_refused) is kept apart from a decline. (bilateral-attestation §6, §8)wrapped_resigned; restating its claims as the leg's own members is also forbidden, though no vector checks for it. (settlement-records §8, rule 3)3What it shows / what it does not
Shows
- That two records sealed under two distinct keys commit to the same payment reference, amount (after the receive fee) and status:
agreed. - Which of
amount,statusandpayment_refdiffer, when both sides are present and joinable. - When only one side sealed:
payer_statedorpayee_stated, labelled as a stated claim. - When a payer-observed and a payee-observed leg share one key:
sealer_conflation, neveragreed. - Delivery separately:
none,stated,matchedormismatchon the delivered content digest. - For a bilateral exchange: that a refusal was made and acknowledged, recorded with the same fidelity as performance.
Does not show
- That either side's observation is true; agreement on a digest attests to the digest, not to what it represents (bilateral-attestation §10.1).
- That a key belongs to the payer or the payee; that is the verifier's own key policy.
- That a missing leg means disagreement; it may not exist yet, may not have been shared, or may never be produced.
- Whether a fee was acceptable;
agreedis about the payment only, and the terms comparison is reported separately asterms_amount. - That delivered content matches a description; with only a
description_digestthat judgment is outside the draft. - Who is right in a disagreement; neither half is preferred, and no dispute mechanism is defined.
A note on counts: the six slots above are the payment states of the settlement-records draft (§9.2). The bilateral-attestation draft defines three verifier states (§10.1), plus the three asymmetry dispositions and the orphan half of §8, and the reduced-assurance indicator of §7.
4Example
The payee's leg from the conformance vector for two Lightning payments: 995 received plus a receive fee of 5 explains the payer's 1000, so the expected state is agreed.
"id": "pos-ln-receive-fee-two-payments",
…
"label": "ln-payee-observed-1",
"capsule": {
"spec_version": "draft-mih-scitt-agent-action-capsule-05",
"format_version": "4",
"canonicalization_id": "jcs",
"action_id": "ln-payee-observed-1",
"action_type": "fyi",
"operator": "payee.example",
…
"settlement": {
"version": "0",
"leg": "payee_observed",
"sealer_role": "payee",
"terms_ref": "7fcbce842a8ac9c67c18c004905d06743709de02ecedd83dc486f9e4ac419005",
"payment_ref": {
"type": "ln.payment_hash",
"value": "6aaa35ab4414eae0f97b9e5c2674aea404c421f8106b476295145ad7e13c6097"
},
"received": {
"value": "995",
"assetCode": "BTC",
"assetScale": 11
},
"status": "settled",
"observed_at": "2026-10-01T12:02:05Z",
"receive_fee": {
"value": "5",
"assetCode": "BTC",
"assetScale": 11
}
},
"references": [
{
"type": "agent-action-capsule",
"digest_alg": "SHA-256",
"digest": "27c08813e6d7640f88d6b5ade05c4310312b47bcb3b47c89900ad411ef722173",
"citation_purpose": "counterparty_half"
}
],
"capsule_id": "63271df109557076918258ed3e7e8586264db676054de716b18535f199a62db5"
},
…
"envelope_kid": "7125e78196a360c3a278d00944a6133f53265c295fe8e1ed7f75a2a65d4681f8"
…
"terms": "ln-terms-1",
"payment_state": "agreed",
"agreed_status": "settled",
"terms_amount": "equal",
"delivery_state": "none"
| Field | Type | Meaning |
|---|---|---|
| settlement.leg | string | Which of the four legs this is; a closed set. |
| settlement.sealer_role | string | payee; must match the leg (payee_observed is sealed by the payee). |
| settlement.terms_ref | string | capsule_id of the terms leg this leg answers; the verifier recomputes and compares it. |
| settlement.payment_ref | object | Typed join key both sides report; here a Lightning payment hash. |
| settlement.received | object | Amount credited to the payee: integer string, asset code, decimal scale. |
| settlement.receive_fee | object | Fee deducted on the receiving side; enters the amount rule. |
| settlement.status | string | What the payee's own system reported: pending, settled, failed or reversed. |
| references[] | array | Cites the payer's leg by capsule_id as counterparty_half: custody, not an observation. |
| envelope_kid | hex | The payee's key; differs from the payer leg's 2cbfe3c8…. |
| payment_state | string | The expected derived state, written by hand from the draft text. |
Source: action-state-group/agent-action-capsule:vectors/settlement/cases.json @ 2ef8aeb49e2334e24c404bd62d3fdb161770873c
5Specs
- Internet-Draft draft-mih-agent-bilateral-attestation-02 — the four-move exchange, refusals, asymmetry dispositions, the three verifier states.
- Internet-Draft draft-mih-agent-settlement-records-00 — the four legs, exact amounts, payment references, derived payment and delivery states.
- Internet-Draft draft-mih-scitt-agent-action-capsule-05 — the record each leg is, its capsule_id and Producer Envelope.
- RFC RFC 8785 — JSON Canonicalization Scheme (JCS), the canonical form under each capsule_id.
- RFC RFC 9052 — COSE; each leg's Producer Envelope is a COSE_Sign1.
- RFC RFC 9943 — SCITT architecture; anchoring makes the record checkable by everyone else.
- Code action-state-group/agent-action-capsule — settlement conformance vectors and their generator.
- Code action-state-group/capsule-emit —
capsule_emit.bilateral, the four-move handshake helpers.