Skip to main content

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}