tatara_process/k8s_condition.rs
1//! Substrate primitive over the K8s `metav1.Condition.status` wire-
2//! form axis — the workspace-wide ONE substrate owner of the
3//! exact-case ASCII `"True"` / `"False"` / `"Unknown"` closed set
4//! every writer AND reader hand-authored on opposite sides of the
5//! `status.conditions[]` wire.
6//!
7//! ## Why the substrate lives here
8//!
9//! Pre-lift the same three-literal set was hand-authored at FIVE
10//! production sites across two crates past the ★★ PRIME-DIRECTIVE
11//! ≥ 2 duplication threshold — each pair of writer + reader sites
12//! silently coupled by exact-case ASCII agreement:
13//!
14//! * `tatara-process::status::ProcessCondition::ready` — writer,
15//! `status: "True".into()` on the `Ready` type row.
16//! * `tatara-process::status::ProcessCondition::not_ready` — writer,
17//! `status: "False".into()` on the `Ready` type row.
18//! * `tatara-process::status::ProcessCondition::attested` — writer,
19//! `status: "True".into()` on the `Attested` type row.
20//! * `tatara-reconciler::ssapply::ready_condition_value` — reader,
21//! `Some("True") => ReadyState::Ready` at the Deployment /
22//! HelmRelease / Kustomization / StatefulSet condition classifier.
23//! * `tatara-reconciler::ssapply::ready_condition_value` — reader,
24//! `Some("False") => ReadyState::NotReady(...)` at the same
25//! classifier.
26//!
27//! Every site restated the SAME `&'static str` byte-literal (`"True"`,
28//! `"False"`) — three writer sites and two reader sites. A copy-paste
29//! that lower-cased one letter (`"true"` — silently invalid; the K8s
30//! API server rejects it as non-conformant), swapped the pair
31//! semantics (writer emits `"False"` where semantic is `"True"`), or
32//! introduced an alternate spelling drifts the wire-form at ONE end
33//! and leaves the other end unable to classify the condition — the
34//! reader falls through to `ReadyState::Unknown` and every Flux /
35//! Deployment readiness gate silently reports "not observed" for the
36//! remainder of the resource's life. Post-lift each writer composes
37//! with `K8sConditionStatus::<V>.as_wire_str()` and each reader binds
38//! through `K8sConditionStatus::from_wire_str(...)`; the wire-form
39//! literal lives at ONE substrate owner and a drift at either end
40//! becomes unrepresentable at the closed-set level.
41//!
42//! ## Closed-set completeness
43//!
44//! The K8s API defines exactly three ConditionStatus values —
45//! [`ConditionStatus`][cs] — corresponding to the three enum variants
46//! here. A future K8s revision that added a fourth wire-form literal
47//! would land as one new variant at this ONE substrate owner, and
48//! every consumer (writer + reader) that pattern-matched exhaustively
49//! against the closed set gets a compile-time error until it handles
50//! the new arm — the fifth invariant of the pattern (composition
51//! preserves proofs) plays out mechanically at the exhaustiveness
52//! check.
53//!
54//! [cs]: https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#ConditionStatus
55//!
56//! ## Byte-shape parity
57//!
58//! `as_wire_str` returns the EXACT-CASE ASCII the K8s API server
59//! accepts — the same literal every pre-lift site restated. Pinned
60//! bytewise at [`tests::as_wire_str_matches_pre_lift_literals_bytewise`]
61//! against a hand-authored fixture-table of the pre-lift strings. A
62//! regression that lower-cased a variant (a `"true"` spelling, an
63//! accidental `to_lowercase` pass, a `serde(rename = "…")` drift at a
64//! future `#[derive(Serialize)]` impl on this type) surfaces at the
65//! pin rather than as silent operator-facing wire-form skew.
66//!
67//! `from_wire_str` is the invertible partner — a round-trip through
68//! `from_wire_str(v.as_wire_str())` yields `Some(v)` for every
69//! variant, pinned at
70//! [`tests::wire_form_round_trip_holds_for_every_variant`]. Any input
71//! outside the closed set (case-drift, whitespace, empty string,
72//! unrelated literals) returns `None`; the closed-set nature is
73//! pinned at [`tests::from_wire_str_rejects_case_drift_and_unknown`].
74//!
75//! ## Naming — `as_wire_str`, not `as_str`
76//!
77//! Same discipline as the [`crate::k8s_builtin_resource::K8sBuiltinResource`]
78//! and [`crate::phase::ProcessPhase::as_str`] siblings — the method
79//! signals that the returned `&'static str` is the K8s WIRE FORM (the
80//! exact byte-shape the API server accepts on the `status` slot of a
81//! `metav1.Condition`), not a debug-print or `Display` projection. A
82//! caller that reads `.as_wire_str()` immediately understands the
83//! return value is safe to write into a JSON payload without any
84//! further normalization; a call spelled `.as_str()` reads as a
85//! generic string projection and invites callers to reach for
86//! `.to_lowercase()` / `.trim()` normalizations that would break the
87//! wire form.
88//!
89//! ## `#[must_use]` on `as_wire_str`
90//!
91//! Every consumer feeds the returned `&'static str` into either a
92//! `String::from(...)` composition (writer side, going into
93//! `ProcessCondition.status`) or a pattern-match arm (reader side).
94//! Dropping the return means the wire-form projection was computed
95//! for no observable reason — the attribute surfaces that as a
96//! warning at every consumer site.
97//!
98//! Theory anchor: THEORY.md §II.1 invariant 5 (composition preserves
99//! proofs — the wire-form literal at ONE substrate owner means the
100//! writer + reader sides of the K8s `status.conditions[]` wire agree
101//! bytewise by construction; a drift at either end becomes
102//! unrepresentable at the closed-set level, not "detected at runtime
103//! by a mismatched log line"). THEORY.md §III (typescape — the K8s
104//! ConditionStatus closed set is a first-class Rust enum, not a
105//! stringly-typed wire-form). THEORY.md §VI.1 (generation over
106//! composition — the three-literal closed set recurred at FIVE hand-
107//! authored sites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication trigger,
108//! and is lifted to ONE substrate owner here on the K8s-Condition
109//! wire-form axis).
110
111use std::fmt;
112
113/// The K8s API's `metav1.Condition.status` closed set — the three
114/// values that live in every `status.conditions[].status` field on
115/// every K8s object (built-in + CRD), per
116/// [ConditionStatus][cs]. Wire-form is the exact-case ASCII literal
117/// (`"True"`, `"False"`, `"Unknown"`); the K8s API server rejects any
118/// other casing.
119///
120/// Substrate primitive over the wire-form literal every writer AND
121/// reader hand-authors on opposite sides of `status.conditions[]`.
122/// See the [module docs][crate::k8s_condition] for the pre-lift lift
123/// audit + closed-set completeness argument.
124///
125/// [cs]: https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#ConditionStatus
126#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
127pub enum K8sConditionStatus {
128 /// The condition holds (`"True"` on the wire).
129 True,
130 /// The condition does not hold (`"False"` on the wire).
131 False,
132 /// The condition's state cannot be determined (`"Unknown"` on the
133 /// wire). This variant is NOT emitted by any writer in the
134 /// workspace today — pre-lift the writer sites only ever emitted
135 /// `"True"` / `"False"` — but it IS part of the K8s closed set,
136 /// and the reader side falls through to it (`_ => ReadyState::
137 /// Unknown` arm) when the wire-form does not match either `True`
138 /// or `False`. Included here so the exhaustive-match discipline
139 /// downstream compilers can enforce holds against the full K8s
140 /// closed set, not a two-arm subset.
141 Unknown,
142}
143
144impl K8sConditionStatus {
145 /// The closed set of `metav1.Condition.status` values every K8s
146 /// `status.conditions[].status` field carries — single source of
147 /// truth that drives every variant-sweep consumer (round-trip
148 /// tests, Display parity tests, the sibling-axis disjointness pin
149 /// at [`crate::condition_type::ProcessConditionType`]'s tests,
150 /// and any future consumer that needs to iterate the closed set
151 /// exhaustively — a K8s ConditionStatus dashboard column, a
152 /// tatara-check status-classifier enumeration, a typed-completion
153 /// surface for reconciler probes).
154 ///
155 /// The K8s API defines exactly three ConditionStatus values (see
156 /// [`ConditionStatus`][cs]); a future K8s revision that added a
157 /// fourth wire-form literal would land as ONE `ALL` entry + ONE
158 /// `as_wire_str` arm + ONE `from_wire_str` arm — exhaustively
159 /// checked by the compiler (the `[Self; 3]` array literal forces
160 /// the arity, and the exhaustive-match on the projection pair
161 /// covers the rest).
162 ///
163 /// Pre-lift the three-variant array literal was hand-authored at
164 /// THREE test sites across two modules past the ★★ PRIME-DIRECTIVE
165 /// ≥ 2 duplication threshold — the round-trip test + the Display
166 /// parity test in this module, and the sibling-axis disjointness
167 /// test in [`crate::condition_type::tests::from_wire_str_rejects_sibling_axis_wire_forms`].
168 /// Post-lift each iterates `Self::ALL` and the closed-set
169 /// enumeration lives at ONE substrate owner here.
170 ///
171 /// Sibling closed-set `ALL` slices across the crate's typescape:
172 /// [`crate::condition_type::ProcessConditionType::ALL`] (the sibling
173 /// on the K8s-Condition wire-form axis-family — type-slot closed
174 /// set, this owns the status-slot closed set);
175 /// [`crate::boundary::ConditionKind::ALL`],
176 /// [`crate::phase::ProcessPhase::ALL`], [`crate::signal::ProcessSignal::ALL`],
177 /// [`crate::intent::IntentKind::ALL`], [`crate::receipt::ReceiptKind::ALL`].
178 ///
179 /// [cs]: https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#ConditionStatus
180 pub const ALL: [Self; 3] = [Self::True, Self::False, Self::Unknown];
181
182 /// The K8s wire-form literal for this variant — exact-case ASCII,
183 /// safe to write directly into a `metav1.Condition.status` slot
184 /// without further normalization. Byte-identical to the pre-lift
185 /// hand-authored `"True"` / `"False"` / `"Unknown"` literals every
186 /// writer + reader restated inline.
187 #[must_use = "a K8s ConditionStatus wire-form projection that isn't bound swallows the composition"]
188 pub const fn as_wire_str(self) -> &'static str {
189 match self {
190 Self::True => "True",
191 Self::False => "False",
192 Self::Unknown => "Unknown",
193 }
194 }
195
196 /// Parse a K8s wire-form ConditionStatus literal into its typed
197 /// variant. Returns `None` for any input outside the closed set
198 /// — case-drift (`"true"`), whitespace-wrapped variants (`" True"`),
199 /// unrelated literals (`""`, `"Ready"`), all reject silently and
200 /// the caller falls through to its own `_ => ...` arm.
201 ///
202 /// Invertible with [`Self::as_wire_str`]: a round-trip through
203 /// `from_wire_str(v.as_wire_str())` yields `Some(v)` for every
204 /// variant. Pinned at
205 /// [`tests::wire_form_round_trip_holds_for_every_variant`].
206 #[must_use = "a K8s ConditionStatus parse result that isn't bound swallows the classification"]
207 pub fn from_wire_str(s: &str) -> Option<Self> {
208 match s {
209 "True" => Some(Self::True),
210 "False" => Some(Self::False),
211 "Unknown" => Some(Self::Unknown),
212 _ => None,
213 }
214 }
215}
216
217impl fmt::Display for K8sConditionStatus {
218 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
219 f.write_str(self.as_wire_str())
220 }
221}
222
223#[cfg(test)]
224mod tests {
225 use super::K8sConditionStatus;
226
227 /// Fail-before-pass-after: the substrate's `as_wire_str`
228 /// projection produces byte-identical output to the pre-lift
229 /// hand-authored `"True"` / `"False"` / `"Unknown"` literals
230 /// every writer + reader restated inline. A regression that
231 /// lower-cased one variant, added a whitespace prefix, or a
232 /// future `#[derive(Serialize)]` `serde(rename)` drift on this
233 /// type would surface HERE, not as silent operator-facing wire-
234 /// form skew across every K8s `status.conditions[]` writer +
235 /// reader in the workspace.
236 #[test]
237 fn as_wire_str_matches_pre_lift_literals_bytewise() {
238 assert_eq!(K8sConditionStatus::True.as_wire_str(), "True");
239 assert_eq!(K8sConditionStatus::False.as_wire_str(), "False");
240 assert_eq!(K8sConditionStatus::Unknown.as_wire_str(), "Unknown");
241 }
242
243 /// Round-trip through `from_wire_str(v.as_wire_str())` yields
244 /// `Some(v)` for every variant. Pins the invariant that the
245 /// writer + reader compose invertibly at the closed-set boundary
246 /// — a writer's `as_wire_str` output is always accepted by the
247 /// reader's `from_wire_str` on the SAME variant.
248 #[test]
249 fn wire_form_round_trip_holds_for_every_variant() {
250 for v in K8sConditionStatus::ALL {
251 assert_eq!(K8sConditionStatus::from_wire_str(v.as_wire_str()), Some(v));
252 }
253 }
254
255 /// Inputs outside the closed set — case-drift, whitespace-
256 /// wrapped variants, empty string, unrelated K8s wire-form
257 /// literals — all reject with `None`. Pins the closed-set
258 /// nature: `from_wire_str` is a total function over the K8s
259 /// wire-form alphabet, not a permissive parser that accepts
260 /// synonyms.
261 #[test]
262 fn from_wire_str_rejects_case_drift_and_unknown() {
263 for bad in [
264 "", "true", "false", "unknown", " True", "True ", "Ready", "Attested", "yes", "1",
265 ] {
266 assert_eq!(
267 K8sConditionStatus::from_wire_str(bad),
268 None,
269 "expected `{bad:?}` outside the K8s ConditionStatus closed set, but from_wire_str accepted it",
270 );
271 }
272 }
273
274 /// `Display` composes through `as_wire_str` — the two
275 /// projections are byte-identical so `format!("{v}")` and
276 /// `v.as_wire_str()` are interchangeable at every consumer.
277 /// Pins the invariant that a caller who reaches for the
278 /// stdlib `Display` conversion path (via `.to_string()`,
279 /// `format!("{v}")`, a `write!` macro) gets the same wire-
280 /// form bytes as a direct `.as_wire_str()` call.
281 #[test]
282 fn display_composes_through_as_wire_str_bytewise() {
283 for v in K8sConditionStatus::ALL {
284 assert_eq!(v.to_string(), v.as_wire_str());
285 assert_eq!(format!("{v}"), v.as_wire_str());
286 }
287 }
288
289 /// Closed-set completeness: the three variants exhaust the K8s
290 /// ConditionStatus alphabet. A future K8s revision that added a
291 /// fourth wire-form literal would land as one new variant here,
292 /// and every consumer that pattern-matched exhaustively against
293 /// the closed set gets a compile-time error until it handles the
294 /// new arm — the fifth invariant of the Rust+Lisp pattern.
295 /// Compiler-verified below with an exhaustive match; a regression
296 /// that added a `#[non_exhaustive]` or a private constructor arm
297 /// would break the exhaustiveness proof at this test.
298 #[test]
299 fn closed_set_exhausts_the_k8s_condition_status_alphabet() {
300 fn describe(v: K8sConditionStatus) -> &'static str {
301 match v {
302 K8sConditionStatus::True => "True",
303 K8sConditionStatus::False => "False",
304 K8sConditionStatus::Unknown => "Unknown",
305 }
306 }
307 assert_eq!(describe(K8sConditionStatus::True), "True");
308 assert_eq!(describe(K8sConditionStatus::False), "False");
309 assert_eq!(describe(K8sConditionStatus::Unknown), "Unknown");
310 }
311
312 /// `Copy` + `Clone` + `Eq` + `Hash` — pins the trait derives at
313 /// compile time so a regression that dropped one (a future
314 /// `#[derive(Serialize, Deserialize)]` addition that reshaped
315 /// the enum, a manual `impl Clone` that dropped `Copy`) surfaces
316 /// here rather than at a downstream consumer that stored the
317 /// value in a `HashMap` key or copied it across an `if` arm.
318 #[test]
319 fn value_semantics_hold_at_compile_time() {
320 fn assert_copy<T: Copy>() {}
321 fn assert_hash<T: std::hash::Hash>() {}
322 fn assert_eq<T: Eq>() {}
323 assert_copy::<K8sConditionStatus>();
324 assert_hash::<K8sConditionStatus>();
325 assert_eq::<K8sConditionStatus>();
326 }
327
328 /// Fail-before-pass-after: the `ALL` sweep MUST enumerate every
329 /// variant of the K8s ConditionStatus closed set exactly once, with
330 /// no duplicates and no omissions. Pinned three ways so any drift
331 /// surfaces at ONE substrate pin rather than as silent skew at every
332 /// consumer that iterates the sweep:
333 ///
334 /// 1. **Arity** — the array's length equals the variant count.
335 /// The `[Self; 3]` type-level arity already forces this at the
336 /// substrate; the test restates it as a runtime witness so a
337 /// regression that widened the type to `&[Self]` (a slice
338 /// literal) or a `Vec<Self>` builder would surface at the
339 /// substrate pin rather than as silent shape drift.
340 /// 2. **No duplicates** — the collected set of iterated variants
341 /// has cardinality equal to the sweep's length. A regression
342 /// that stamped `[Self::True, Self::True, Self::Unknown]` (a
343 /// copy-paste at the sweep) or `[Self::True, Self::False,
344 /// Self::False]` surfaces at the collected-set cardinality
345 /// check.
346 /// 3. **Cover** — an exhaustive match on each iterated variant
347 /// proves the compiler sees every arm at least once through the
348 /// sweep, so a future variant addition that landed at
349 /// `as_wire_str` + `from_wire_str` but was forgotten at `ALL`
350 /// surfaces at the sweep's compile-time exhaustive-match check.
351 ///
352 /// The K8s API guarantees these three variants (`True` / `False` /
353 /// `Unknown`) as the total ConditionStatus alphabet, so the sweep
354 /// stays stable at three unless K8s itself widens the alphabet —
355 /// at which point the array literal's type-level arity forces a
356 /// deliberate substrate-side update.
357 #[test]
358 fn all_covers_the_k8s_condition_status_closed_set_exhaustively() {
359 assert_eq!(
360 K8sConditionStatus::ALL.len(),
361 3,
362 "ALL must enumerate every variant of the K8s ConditionStatus closed set — \
363 a regression that added a variant at `as_wire_str` but forgot to extend \
364 `ALL` surfaces here",
365 );
366
367 let seen: std::collections::HashSet<K8sConditionStatus> =
368 K8sConditionStatus::ALL.iter().copied().collect();
369 assert_eq!(
370 seen.len(),
371 K8sConditionStatus::ALL.len(),
372 "ALL must not stamp any variant twice — a copy-paste at the sweep surfaces here",
373 );
374
375 for v in K8sConditionStatus::ALL {
376 let _cover: &'static str = match v {
377 K8sConditionStatus::True => "True",
378 K8sConditionStatus::False => "False",
379 K8sConditionStatus::Unknown => "Unknown",
380 };
381 }
382 }
383}