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
//! 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::payload_lifecycle_round_trips`,
//! `super::tests::payload_hook_round_trips`,
//! `super::tests::payload_ping_round_trips`,
//! `super::tests::payload_domain_matches_serde_tag`.
// #6846: `HarnessPayload` and `HarnessEvent` moved here from
// `trusty_agents_common::events::bus`; that module keeps its stderr transport.
use ;
use ;
use Value;
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":...}}`, or `{"domain":"ping"}`. `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`.
/// 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. All
/// fields are public so a producer can stamp one by struct literal.
/// Test: `super::tests::harness_event_round_trips` and
/// `super::tests::harness_event_omits_none_session`.