Extensions

Bilateral Attestation

When two organizations act together across a trust boundary, one record — owned by one side, deniable by the other — isn't evidence. Bilateral attestation gives each organization proof of the other's commitment, verifiable by a third party who trusts neither.

The problem it solves

Each side keeps its own log. A dispute reduces to my log versus your log. Neither log carries the other party's agreement; either side can later claim the terms were different. The record exists, but it proves nothing a relying party can check independently.

Bilateral attestation replaces that with a four-move exchange that produces a record both parties have signed, each party holds proof of the other's signature, and the combined record can be anchored so a third party who trusts neither organization can verify it end-to-end.

The four moves

1

Request attestation

The requesting party signs a statement over the action and its material terms, naming the intended performer. The requester is now bound: it cannot later deny having asked, or having asked on these terms.

2

Constraint evaluation

The performing party verifies the requester's organizational identity and evaluates the request against deterministic constraints at the boundary where the action takes effect — not at the transport edge. No verified request attestation, no consequential action.

3

Action attestation

The performing party signs a statement referencing the request by digest, recording the constraint results and the disposition — executed, blocked, denied, escalated, timed out. Every outcome is a first-class record; refusals carry the same fidelity as performance.

4

Acknowledgment

Each party acknowledges the other's attestation. When both acknowledge, each is bound to its part and holds proof of the other's. The record is complete.

The two capsules are joined by a shared action_digest — SHA-256 of the canonicalized action — so a third party who receives both can confirm they describe the same action without either org having to reveal the action's content.

Refusals are first-class

A declined request is a completed exchange, not a failed one. The action attestation records that the request was declined and on what constraint basis. The requester's acknowledgment is verifiable evidence contradicting any later claim that the request was never answered.

For the performing party, a bilaterally-acknowledged refusal is stronger evidence than a unilateral one — the counterparty that was refused has signed the record. For the requesting party, a pattern of acknowledged refusals is now provable by its counterparties.

Graceful degradation

Counterparties will be of mixed capability. A performing party whose counterpart cannot produce request attestations may proceed under policy, producing its own action attestation unilaterally and recording a reduced-assurance indicator in place of the missing attestations. The record format is the same; the assurance marking differs. A fully-bilateral record and a degraded record are never confusable.

What it composes with

LayerRelationship
Agent Action CapsuleCarries the attestations. The disposition vocabulary — executed, blocked, denied, timeout, errored, deferred, escalated — is reused verbatim.
Delegation receiptsA request attestation may reference a delegation receipt authorizing the requesting agent.
SCITT transparency logAnchoring both capsules makes the record verifiable by parties who trust neither organization.
Remote attestation (RATS)RATS attests platform state; bilateral attestation attests actions. Orthogonal layers that compose.

The Internet-Draft

The bilateral attestation exchange is specified as a companion Internet-Draft to the Agent Action Capsule profile:

draft-mih-agent-bilateral-attestation-00 ↗

The draft fixes the exchange, the binding obligations, and the disposition semantics. Wire encodings are TBD for a future revision; the current draft specifies that JCS (RFC 8785) will be used for deterministic canonicalization when wire formats are defined.

Open-source implementation

A reference implementation is available in two packages:

  • capsule-emitcapsule_emit.bilateral: BilateralHandshake state machine, canonical payload functions, and seal_request / seal_action / seal_bilateral capsule helpers.
  • agent-action-capsuleagent_action_capsule.bilateral: verify_pair(capsule_a, capsule_b) — checks individual Class-1 verify, shared action digest, and chain linkage.
# Run the four-move demo (HMAC-SHA256 demo signer)
pip install capsule-emit agent-action-capsule
git clone https://github.com/action-state-group/capsule-emit
python examples/bilateral/demo.py --no-anchor

# Verify the capsule pair
from agent_action_capsule.bilateral import verify_pair
pvr = verify_pair(capsule_a, capsule_b)
assert pvr.ok
assert pvr.shared_digest == action_digest
The demo uses HMAC-SHA256 with symmetric keys for simplicity. Production deployments should use asymmetric signatures (Ed25519 or equivalent) with keys bound to verifiable organizational identity.