1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
//! Inbound TSP relationship handling — the **answering arm** of the Rev 3
//! relationship lifecycle, shared by every node that runs a TSP listener
//! (`WebvhTspHandler` on the control plane, `ServerTspHandler` on the edge) so
//! both answer identically.
//!
//! ## Why this exists
//!
//! Under TSP Rev 3 **§7.2.2** a receiver drops any *application* message from a
//! VID it holds no relationship with. A relationship is admitted the moment the
//! receiver *records* an inbound relationship-forming invite, which the
//! messaging-service framework does before it calls
//! [`TspHandler::handle_control`]. What the framework does **not** do is answer
//! it: completing the handshake — sending the accept that moves the peer from
//! `InviteReceived` back to `Bidirectional` and restores *our own* ability to
//! send (`can_send()` is `Bidirectional`-only) — is the application's job. This
//! module is that completion.
//!
//! Without it, `affinidi-tsp` 0.2.1's recovery transition
//! (`Bidirectional + ReceiveInvite → InviteReceived`) is only half a mechanism:
//! a peer that lost its half re-invites, our side transitions to
//! `InviteReceived`, and — with no answer — `can_send()` goes **false**,
//! turning "the peer drops our frames" into "we can no longer send to the peer"
//! (see `docs/tsp-transport.md`). Answering is what makes the re-invite repair
//! the relationship instead of breaking it further.
//!
//! ## Why we accept from any framework-authenticated sender
//!
//! Forming a relationship grants **no authorization**; it only lets us decrypt
//! a peer's frames. Every trust task the peer then sends is still authorized at
//! the *task* layer (`trust_tasks::dispatch_*`, keyed on the framework-
//! authenticated sender VID), which refuses an unauthorized op with a named
//! `trust-task-error` the peer's application can read.
//!
//! Gating the *invite* on the ACL instead would be redundant *and* actively
//! harmful: §3.6 lets a peer send its invite and its first application message
//! together, so refusing the invite makes §7.2.2 silently drop that payload —
//! and the refusal (an `XRFD` control message) is never surfaced to the peer's
//! application. The gate would manufacture exactly the silence it was meant to
//! prevent. So authorization stays at the layer that can answer with a named
//! error; relationship acceptance does not.
use HandlerContext;
use ;
use ;
/// What an inbound control message asks of us. Split out from the effectful
/// [`answer_inbound_control`] so the routing rule — *an invite is the only
/// control message we answer* — is a pure function the tests can pin without a
/// live mediator.
/// Answer an inbound TSP control message: accept a relationship-forming invite
/// from any framework-authenticated sender, and no-op the rest. Call this from
/// a [`affinidi_messaging_didcomm_service::TspHandler::handle_control`] impl.
///
/// Never returns an error: a failed accept is logged and swallowed, because
/// `handle_control` has no reply channel (the framework already recorded the
/// relationship) and the peer's next re-invite, or our own connect-time
/// re-invite, is the retry.
pub async