ToIP Trust Spanning Protocol (TSP) transport binding for the Trust Tasks framework.
Wraps affinidi-tsp so a Trust Task
document can ride as the authenticated, encrypted payload of a TSP message —
sealed with HPKE authenticated encryption and signed from the producer's
Verifiable Identifier (VID) to the recipient's VID. On unwrap, the
authenticated sender VID becomes the framework's transport-authenticated
sender for SPEC §4.8.1 precedence.
Binding URI
https://trusttasks.org/binding/tsp/0.1
Wire shape
The TSP message payload (the plaintext TSP seals) is the JSON serialisation of the binding envelope object:
Unlike the DIDComm binding — which normalises a sender_kid to its bare DID —
a TSP VID is the framework VID, so no transformation is applied: the
authenticated VID_sndr is surfaced verbatim as the transport-authenticated
issuer. TSP has no anonymous/unauthenticated sender mode, so every envelope
this binding accepts carries a verified sender.
The producer can ship a plain Direct message ([pack_trust_task], sealed
straight to the consumer) or relay it through intermediaries (SPEC binding §5):
a Nested envelope sealed to a single intermediary for metadata privacy
([pack_trust_task_nested]), or a Routed envelope relayed through one or more
hops ([pack_trust_task_routed]). Routed/Nested relaying — where the messaging
mediator unwraps its outer layer and forwards the sealed inner — is the mediator's
job on the wire; the consumer always opens the innermost Direct message, which
[unpack_trust_task] handles regardless of how it was carried.
The guarded inbound path
[unpack_trust_task] opens the seal and stops there. The consumer
obligations of SPEC §7.2 still have to run over the document it returns,
and two of them are stateful: item 11's duplicate-execution record and the
freshness bound that lets that record be dropped.
[TspConsumer] is that path with both wired, on by default. Binding §7
records that TSP data messages "do not inherently prevent replay", and
under §5's routed and nested carriage an intermediary may re-send the
sealed inner message — so an ordinary re-forward, with no attacker
involved, executes a consequential task twice unless the consumer keeps the
record. The record is keyed on the document id and never on the envelope,
which is resealed with fresh material on every send.
Sketch
use PrivateVid;
use ;
// alice (producer) seals a document for bob:
let wire = pack_trust_task?;
// bob (consumer) opens it (alice's VID resolved for verification):
let = ?;
Versioning
This crate exposes trust-tasks-rs types in its own public API, so a
breaking change there breaks this crate's callers even when nothing here
changes. cargo-semver-checks cannot catch that: it compares each crate's
rustdoc against that crate's own published baseline, and does not track
type identity across dependency versions. The crates that share
trust-tasks-rs in their public API are therefore released as one
compatibility unit with a single shared version — see version_group in
release-plz.toml.