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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//! Send-correlation telemetry for the Telegram surface (#1085 P1a).
//!
//! Duplicate-send and chatty-agent investigations need to attribute every
//! message that LANDS in a chat to its origin. The twin audits
//! (2026-08-17) found exactly one fully-logged send site out of ~57 groups:
//! success paths were log-invisible almost everywhere.
//!
//! P1a policy (grill round 1, decisions Q2/Q3; review F3/F7/F9): log
//! METADATA only — `{chat_id, thread_id, message_id, kind, path, origin,
//! origin_detail, session, len, hash8}` — never message content. The hash
//! lets an investigation correlate "same text sent twice" without the log
//! ever carrying the text itself. Success lines are `info!`: production
//! daemons run at INFO, and an invisible attribution line defeats the
//! purpose.
//!
//! `origin` is a closed vocabulary, `turn | tool | cron | system`; free
//! text goes in `origin_detail` at the call site, never here.
use ;
/// First 8 hex chars of the SHA-256 of `content`.
///
/// 32 bits of hash is ample to correlate duplicates within a day's log
/// (collision odds are irrelevant at log volumes); sha2 is already a
/// direct dependency, so no new crate rides along.
pub
/// Log a message that landed in a chat. One grep shape for every send
/// site on the surface: `grep "Telegram send ok:"`.
///
/// `info!` (not debug): production daemons run at INFO, and an
/// attribution line that is invisible by default defeats the audit's
/// whole purpose (review F7). `origin_detail` carries the job/arm name
/// (Q3), `session` the originating session id or "-" where the call
/// site genuinely cannot know it (review F9).
// correlation fields per the #1085 P1a schema
pub
/// Log a send that failed on every path it tried. The `error` string is
/// the transport error (never message content).
// correlation fields per the #1085 P1a schema
pub
/// One line describing an outbound REQUEST (#721, E1).
///
/// The send telemetry above answers "what reached the chat"; this answers
/// "what did we put ON THE WIRE". A request that fails is still a request, so
/// the line is emitted BEFORE the API call and its presence says nothing
/// about the outcome. Without it, typing / delete / reaction traffic is
/// invisible to the log, and a per-minute rate over the surface cannot be
/// computed at all — which is why most residual 429 refusals show "no
/// predecessor".
///
/// The prefix is distinct (`Telegram request:`) so a grep for landings never
/// picks up requests and vice versa. `origin` / `detail` / `session` / `kind`
/// / `path` / `chat` / `thread` reuse the send schema's correlation fields
/// verbatim; `len` / `hash8` are DROPPED, because they describe a message
/// BODY and a request has none.
///
/// `msg` is the TARGET message id where the request addresses one (delete,
/// reaction) and the create-shaped `-` where it cannot (a chat action targets
/// no message) — the same convention #676 established for rich creates, so
/// every line carries every field and a reader never guesses a shape.
///
/// `info!` and not `debug!`, and the reason is the READER: `oc-log-search`
/// stages `grep -E ' (INFO|WARN|ERROR) '` by default, so a debug line would
/// be invisible to the ordinary read and E1 would swap one blind spot for
/// another.
// correlation fields per the #721 request schema
pub
/// Emit [`request_line`] at INFO. Same arguments; one source of truth for the
/// shape, so a change to the contract cannot drift between the two.
// correlation fields per the #721 request schema
pub