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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
//! Canonical launchd labels for every trusty-* LaunchAgent (#4919).
//!
//! Why: there was no single definition of what a service's launchd label IS.
//! Each daemon crate declared its own `LAUNCHD_LABEL` literal, the installer
//! kept a second hand-maintained mirror of those literals
//! (`trusty-installer::commands::plist_label`, whose own doc admitted it was
//! "verified by grepping each daemon crate"), the per-crate Makefiles named a
//! third family (`com.bobmatnyc.trusty-search`), and the signed-install scripts
//! a fourth. Nothing made them agree, so they drifted — that is #2827
//! (install-mpm-signed printed `com.trusty.trusty-mpm.plist` for a daemon whose
//! plist is `com.trusty.mpm.plist`), #2965 (a docs page with yet another
//! family), and #2938 (a stale `com.trusty.trusty-search.plist` sitting beside
//! the live `com.trusty.search.plist`).
//!
//! What it cost: `trusty-search service install` wrote and bootstrapped
//! `com.trusty.trusty-search` while the unit launchd actually had loaded was
//! `com.trusty.search`. The install therefore booted out nothing, started a
//! second daemon contending for :7878 and the index locks, and left the plist
//! fixes made under #4868 (`ExitTimeOut`) sitting in a file launchd never read.
//! Re-fixing the literals one at a time is what let the defect come back after
//! #2827; this module removes the second copy instead.
//!
//! The convention: `com.trusty.<member with its `trusty-` prefix stripped>`,
//! with sub-units suffixed (`com.trusty.mpm.supervisor`,
//! `com.trusty.search.logrotate`). [`canonical_label`] is that rule as code, and
//! [`SERVICES`] is checked against it by `canonical_consts_match_the_convention`
//! — a table entry that restates a label wrongly fails the test run rather than
//! shipping.
//!
//! How far the survey actually reaches, stated exactly, because overstating a
//! partial survey is how the direction got reversed the first time: **every unit
//! with a live daemon obeys it** — `com.trusty.mpm`, `com.trusty.memory`,
//! `com.trusty.analyze`, `com.trusty.search`, `com.trusty.console`,
//! `com.trusty.agents.slack`, all confirmed from `launchctl list` with a pid.
//! Two do not, and both are being normalised onto it here rather than being
//! counted as support for it: `com.trusty.trusty-search.logrotate` is loaded
//! with no pid and no main unit beside it, and `com.trusty.trusty-review.plist`
//! sits on disk unloaded — and that file is this codebase's own output, so it
//! was never independent evidence of anything. Both are recorded as legacy
//! aliases below.
//!
//! Deliberately NOT `#[cfg(target_os = "macos")]`, unlike `crate::launchd`:
//! the registry is data, and gating it would stop the drift tests from running
//! on Linux CI, which is where a divergent literal most needs to be caught.
//!
//! Not to be confused with codesign identifiers
//! (`trusty-installer::commands::macos_signing::codesign_identifier`), which
//! live in their own namespace, use the full binary name, and must NOT be
//! renamed to match — changing a codesign identifier invalidates the binary's
//! designated requirement and re-triggers macOS TCC prompts (#2558).
//!
//! Test: `canonical_consts_match_the_convention`, `sub_unit_labels_extend_their_base`,
//! `legacy_labels_are_never_canonical`, `every_legacy_label_resolves_to_one_service`,
//! `no_stray_launchd_label_literals_in_workspace_sources`.
//!
//! [`canonical_label`]: crate::launchd_labels::canonical_label
//! [`SERVICES`]: crate::launchd_labels::SERVICES
/// Reverse-DNS domain prefix shared by every trusty-* LaunchAgent.
///
/// Why: the one place the `com.trusty` vendor prefix is written down. The
/// `com.bobmatnyc.*` family the trusty-search Makefile invented is a legacy
/// alias, not a second domain.
pub const DOMAIN: &str = "com.trusty";
/// Build a launchd label from a service stem, and optionally a sub-unit name.
///
/// Why: `concat!` is the only const-evaluable string join available without a
/// new dependency, and it takes literals only. Keeping the join in a macro
/// means [`DOMAIN`]'s value is typed once even though `const` items cannot
/// call a function.
/// What: `agent!("search")` → `"com.trusty.search"`;
/// `agent!("search", "logrotate")` → `"com.trusty.search.logrotate"`.
/// The trusty-mpm daemon (`tm daemon`). Binary is `tm`, member is `trusty-mpm`
/// — the label follows the MEMBER, which is why #4059's binary-vs-member
/// confusion cannot be resolved by looking at the executable name.
pub const MPM: &str = agent!;
/// The optional unattended supervisor that restarts the mpm daemon.
pub const MPM_SUPERVISOR: &str = agent!;
/// The trusty-memory daemon.
pub const MEMORY: &str = agent!;
/// The trusty-analyze daemon.
pub const ANALYZE: &str = agent!;
/// The trusty-search daemon.
///
/// #4919: was `com.trusty.trusty-search` in
/// `trusty-search::commands::service::LAUNCHD_LABEL`, which is not the label
/// launchd has loaded on any host — see this module's header.
pub const SEARCH: &str = agent!;
/// The newsyslog-driver agent that rotates trusty-search's launchd stderr log.
pub const SEARCH_LOGROTATE: &str = agent!;
/// The trusty-console dashboard daemon.
///
/// #4919: was `com.trusty.trusty-console` in code while the loaded unit is
/// `com.trusty.console` — the same divergence as [`SEARCH`], so `console
/// service status` queried a label that does not exist.
pub const CONSOLE: &str = agent!;
/// The trusty-review daemon.
pub const REVIEW: &str = agent!;
/// The trusty-agents Slack gateway (`tagent --slack`).
pub const AGENTS_SLACK: &str = agent!;
/// A launchd-managed service: its member name, canonical label, and the labels
/// earlier installs used for the same service.
///
/// Why: an upgrade has to evict what the PREVIOUS installer left behind, or it
/// starts a second unit beside the first (#2938). Recording the old names beside
/// the new one makes eviction derivable instead of remembered.
/// What: `member` is the workspace member / binary family the service belongs
/// to; `label` is what a fresh install writes and bootstraps; `legacy` is every
/// label a prior install of the SAME service could have registered, newest
/// first. `legacy` is never empty for a service whose label has ever changed.
/// Every launchd service this workspace installs.
///
/// Why: `tctl`, each daemon's own `service` subcommand, the doctor checks, and
/// the drift tests all need the same answer to "which label, and what does an
/// upgrade have to evict". This is that answer.
/// Test: `canonical_consts_match_the_convention` proves no entry restates a
/// label the convention would not produce.
pub const SERVICES: & = &;
/// Derive a member's canonical main-daemon label from the convention.
///
/// Why: the convention has to exist as executable code, or "the convention"
/// degrades into whatever the literals happen to say — which is how
/// `com.trusty.trusty-search` survived four issues.
/// What: strips a leading `trusty-` from `member` and prefixes [`DOMAIN`].
/// A member that is already bare (`"mpm"`) is left alone, so the function is
/// idempotent on stems.
/// Test: `canonical_consts_match_the_convention` runs it over every
/// [`SERVICES`] entry.
/// Derive a sub-unit's label from its base label.
///
/// What: `sub_label("com.trusty.search", "logrotate")` →
/// `"com.trusty.search.logrotate"`.
/// Test: `sub_unit_labels_extend_their_base`.
/// Look up a service by its canonical label.
///
/// What: returns the [`SERVICES`] entry whose `label` matches, or `None`.
/// Test: `every_legacy_label_resolves_to_one_service`.
/// Labels an upgrade must evict before bootstrapping `label`.
///
/// Why: this is what makes an install label-correct across a rename. Without
/// it, `service install` bootstraps the new label and leaves the old unit
/// running — two daemons, one port (#2938).
/// What: the `legacy` list for the service owning `label`, or empty when the
/// label is unknown (an unknown label evicts nothing rather than guessing).
/// Test: `legacy_labels_are_never_canonical`.
/// Whether a string is a CANONICAL launchd label this workspace installs.
///
/// Why: deliberately excludes legacy aliases. A legacy label appearing as a
/// literal in production source is not "a known label", it is the #4919 defect
/// — `trusty-search::commands::service::LAUNCHD_LABEL` was exactly such a
/// literal, and a membership test that accepted it would have passed while the
/// installer bootstrapped a unit launchd does not have.
/// What: true iff some [`SERVICES`] entry's `label` equals `candidate`.
/// Test: `no_stray_launchd_label_literals_in_workspace_sources` calls it to
/// decide whether a Makefile / shell / plist literal is acceptable — those
/// files cannot import a Rust constant, so naming the canonical label is the
/// best they can do, while a legacy or unknown one still fails.