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
//! The pure core of an extension: the [`Protocol`] trait authors implement, its typed
//! step algebra ([`Transition`]), and the decode boundary ([`Wire`] → `Event`).
//!
//! An extension owns **its own** effect algebra (`Protocol::Effect`) — the core defines
//! no global `Effect` enum. Effects are interpreted by the extension's own
//! [`Interpret`](super::Interpret) shell, which is handed a namespace-scoped capability
//! ([`Scope`](super::Scope)) — `send`/`inject` confined to its own namespace. This is what
//! keeps the effect set from becoming a global command bus: a new extension brings its own
//! effects and its own interpreter without ever touching the core.
use Bytes;
use Did;
/// The raw boundary input handed to [`Protocol::decode`]: an inbound message's authenticated
/// sender, this node's own did, and the opaque payload bytes. `decode` turns this into the
/// protocol's typed `Event` (or rejects it).
///
/// `from == me` marks a **self re-injected** message (a local command or an effect's result
/// fed back into the router); any other `from` is a network message from an authenticated
/// peer (a peer cannot forge `from`).
/// The explicit result of a failed [`Protocol::decode`]: the input is malformed or not for
/// this protocol. The router drops it (a defined no-op) instead of the pure step silently
/// returning an unchanged state — so "valid no-op" and "undecodable input" are
/// distinguishable.
;
/// Read-only state carrier passed *into* a step: the protocol's current state `S` plus
/// read-only node facts. The state is borrowed; a step returns the next state in its
/// [`Transition`] rather than mutating in place.
/// A locally re-injected message: the output of an effect fed back into the router as a
/// fresh inbound, re-decoded by the target namespace's protocol. `Inbound ≅ (Namespace,
/// from, payload)` — the same shape the router takes from the wire, so re-injection and
/// inbound delivery share one path.
///
/// The fields are `pub(crate)`: only the router constructs an `Inbound` (from an interpreter's
/// scoped re-inject, with the namespace and `from` it controls), so an extension shell cannot
/// fabricate one with an arbitrary namespace or a forged remote `from`.
pub
/// The output of a step: the next state and the protocol's own effects to run.
/// `Transition (S, E) ≅ (S, [E])` — the Writer-over-State pair, now parameterized by the
/// protocol's private effect type `E`. `PartialEq`/`Eq` are derived (when `S`/`E` are) so
/// tests can compare whole transitions.
/// A protocol: a `namespace`, an initial state, a **decode boundary**, and a state
/// transition that is pure **by contract**.
///
/// ```text
/// init : → S
/// decode : Wire ⇀ Event (partial: may Reject)
/// step : (Ctx S, Event) → Transition (S, Effect)
/// ```
///
/// `decode` is the single place raw bytes become a typed `Event`; a malformed/foreign
/// message is an explicit [`Reject`], not a silent no-op in `step`. `step` is then total
/// over well-typed events and pure: no IO, no clocks, no globals. All side effects are
/// described as values of the protocol's **own** `Effect` type and performed by the
/// extension's [`Interpret`](super::Interpret) shell.