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
//! The contract primitive traits (D60/D61): the API-version marker and the
//! version-local wire body.
//!
//! These are the two traits the bus client is generic over - the ABI floor every
//! contract body and api-version marker implements. The concrete versioned API
//! versions (`phoxal::api`, …) and the `phoxal_api_tree!` macro that
//! generates their `ApiVersion` / `ContractBody` impls live in the `phoxal-api`
//! crate, which re-exports these traits - so they are reachable as
//! `phoxal_api::ApiVersion` / `phoxal_api::ContractBody`. The `phoxal` engine
//! re-exports this bus crate at `phoxal::bus`, so they are also reachable as
//! `phoxal::bus::ApiVersion` / `phoxal::bus::ContractBody`.
/// Marker trait identifying one API version (D60).
///
/// Implemented only by the zero-variant `enum Api {}` that
/// [`phoxal_api_tree!`] generates inside each revision module. The [`ID`] is the
/// dotted wire revision (`"v0.1"`) and is carried in bus metadata as
/// informational provenance, never in the wire body or the topic key (D62).
///
/// [`ID`]: ApiVersion::ID
/// [`phoxal_api_tree!`]: https://docs.rs/phoxal
/// The semantic role a topic plays in its owning service's contract.
///
/// Every topic in a [`phoxal_api_tree!`] declares one of these (D63, plan #00).
/// The role records *intent*, separate from the wire shape: a `Command` and a
/// `State` topic are both pub/sub on the wire, but the owner subscribes a
/// `Command` (it is the service's control input) and publishes a `State` (it is
/// the service's telemetry output). `Query` is the request/response role.
///
/// The role drives the side branding (L1): the api tree's builders read it to pick
/// each leaf's side-branded topic kind (`Publish`/`Subscribe`/`AskQuery`/`ServeQuery`),
/// so taking the wrong side of a topic is a compile error. The role also rides
/// alongside each generated contract body as a `ROLE` const; that const is not yet
/// emitted by `emit-apis` (a later increment of plan #00).
///
/// [`phoxal_api_tree!`]: https://docs.rs/phoxal
/// A version-local wire body: a plain serde type bound to exactly one
/// [`ApiVersion`] and one contract topic (D61/D1).
///
/// Every body declared inside a `phoxal_api_tree!` node gets a generated impl.
/// Each body carries its own [`Api`](ContractBody::Api) version marker and
/// version-qualified [`TOPIC`](ContractBody::TOPIC).
/// Participant `Api` derives record contract bodies field by field, and setup
/// builders require the requested handle body to be declared by that struct.
///
/// The serde encoding of an implementor *is* the wire payload; there is no version
/// envelope (D62).
///
/// **Wire identity is the key, not a hash (D1).** The version is folded into
/// [`TOPIC`](ContractBody::TOPIC), so `v0.1::drive::Target` and a
/// hypothetically re-minted `v0.2::drive::Target` publish on different Zenoh
/// keys and physically cannot collide. There is therefore no `SCHEMA_ID`/`FAMILY`
/// axis: two participants interoperate on a contract iff they use the exact same
/// version-qualified name, which is realized on the wire by the key.
/// A receiver's per-key Zenoh subscription is the
/// whole fast-reject; the bus decode path validates only the codec.