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
137
138
139
140
141
142
143
//! The `HarnessEvent` envelope and its domain-tagged `HarnessPayload` union.
//!
//! Why: Producers stamp events here and trusty-console consumes them there, so
//! the envelope has to be a type both sides link against. Carrying
//! `source`, `session`, `seq` and `at` on the envelope keeps each domain's
//! payload taxonomy free of repeated bookkeeping fields, and lets a
//! subscriber order, correlate and route an event without decoding what is
//! inside it.
//! What: Defines `HarnessPayload` (the domain-tagged inner union) and
//! `HarnessEvent` (the envelope). Types only — the transport that fills
//! `seq` and `at`, and the channel these travel over, belong to whoever
//! owns the bus.
//! Test: `super::tests::harness_event_round_trips`,
//! `super::tests::harness_event_omits_none_session`,
//! `super::tests::harness_event_omits_none_parent_id`,
//! `super::tests::harness_event_parent_id_links_to_the_causing_event`,
//! `super::tests::harness_event_back_compat_missing_fields_deserializes`,
//! `super::tests::harness_event_missing_id_mints_a_fresh_id_each_deserialize`,
//! `super::tests::payload_lifecycle_round_trips`,
//! `super::tests::payload_hook_round_trips`,
//! `super::tests::payload_ping_round_trips`,
//! `super::tests::payload_domain_matches_serde_tag`,
//! `super::tests::harness_payload_action_round_trips`,
//! `super::tests::harness_payload_pre_action_payload_still_deserializes`.
// #6846: `HarnessPayload` and `HarnessEvent` moved here from
// `trusty_agents_common::events::bus`; that module keeps its stderr transport.
// #6847: added `id` (`EventId`, always present) and `parent_id`
// (`Option<EventId>`, the call-graph edge) per DOC-73 §3.1. Both carry
// `#[serde(default)]` so a `HarnessEvent` serialized before this field
// existed still deserializes.
use ;
use ;
use Value;
use ActionEvent;
use EventId;
use ;
/// Domain-tagged inner union carried inside a `HarnessEvent`.
///
/// Why: The "adapt, don't fold" decision (ADR-0005): rather than flattening
/// lifecycle, hook, and keepalive events into one giant enum, we tag by
/// *domain* so each harness can grow its own payload taxonomy
/// independently. Hooks in particular are open-ended (arbitrary
/// tool/event names + JSON data), so they get an untyped `Value` arm
/// instead of being modelled variant-by-variant.
/// What: `serde(tag = "domain", content = "event")` produces
/// `{"domain":"lifecycle","event":{...}}`, `{"domain":"hook","event":
/// {"kind":...,"data":...}}`, `{"domain":"ping"}`, or
/// `{"domain":"action","event":{...}}` (issue #6847, DOC-73 §3.1). An
/// old subscriber that matches on `domain` skips an `action` frame
/// cleanly rather than failing to deserialize. `Ping` is the transport
/// keepalive, kept out of the lifecycle enum.
/// Test: `super::tests::payload_lifecycle_round_trips`,
/// `super::tests::payload_hook_round_trips`,
/// `super::tests::payload_ping_round_trips`,
/// `super::tests::harness_payload_action_round_trips`,
/// `super::tests::harness_payload_pre_action_payload_still_deserializes`.
/// Cross-harness event envelope: metadata plus domain-tagged payload.
///
/// Why: Subscribers order (`seq`), time-stamp (`at`), attribute (`source`) and
/// correlate (`session`) events uniformly, whichever harness produced them
/// and whichever domain the payload belongs to. Holding that metadata on
/// the envelope keeps the payload taxonomies free of repeated bookkeeping
/// fields.
/// What: `source` is the originating harness; `session` is the optional task
/// correlation key (omitted from JSON when `None`); `seq` is a
/// process-monotonic counter assigned by the producer; `at` is the
/// emit-time UTC timestamp; `payload` is the domain-tagged union; `id`
/// is a UUIDv7 minted by the emitting process, globally unique and
/// stable through every relay hop (DOC-73 §3.1); `parent_id` is the
/// call-graph edge — the event that caused this one, `None` for a root.
/// All fields are public so a producer can stamp one by struct
/// literal. `id` and `parent_id` both carry `#[serde(default)]`, so an
/// event serialized before issue #6847 added them still deserializes:
/// a missing `id` mints a fresh one, a missing `parent_id` becomes
/// `None`.
/// Test: `super::tests::harness_event_round_trips`,
/// `super::tests::harness_event_omits_none_session`,
/// `super::tests::harness_event_omits_none_parent_id`,
/// `super::tests::harness_event_parent_id_links_to_the_causing_event`,
/// `super::tests::harness_event_back_compat_missing_fields_deserializes`,
/// `super::tests::harness_event_missing_id_mints_a_fresh_id_each_deserialize`.