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 K8s wire-form literal for this variant — exact-case ASCII,
146    /// safe to write directly into a `metav1.Condition.status` slot
147    /// without further normalization. Byte-identical to the pre-lift
148    /// hand-authored `"True"` / `"False"` / `"Unknown"` literals every
149    /// writer + reader restated inline.
150    #[must_use = "a K8s ConditionStatus wire-form projection that isn't bound swallows the composition"]
151    pub const fn as_wire_str(self) -> &'static str {
152        match self {
153            Self::True => "True",
154            Self::False => "False",
155            Self::Unknown => "Unknown",
156        }
157    }
158
159    /// Parse a K8s wire-form ConditionStatus literal into its typed
160    /// variant. Returns `None` for any input outside the closed set
161    /// — case-drift (`"true"`), whitespace-wrapped variants (`" True"`),
162    /// unrelated literals (`""`, `"Ready"`), all reject silently and
163    /// the caller falls through to its own `_ => ...` arm.
164    ///
165    /// Invertible with [`Self::as_wire_str`]: a round-trip through
166    /// `from_wire_str(v.as_wire_str())` yields `Some(v)` for every
167    /// variant. Pinned at
168    /// [`tests::wire_form_round_trip_holds_for_every_variant`].
169    #[must_use = "a K8s ConditionStatus parse result that isn't bound swallows the classification"]
170    pub fn from_wire_str(s: &str) -> Option<Self> {
171        match s {
172            "True" => Some(Self::True),
173            "False" => Some(Self::False),
174            "Unknown" => Some(Self::Unknown),
175            _ => None,
176        }
177    }
178}
179
180impl fmt::Display for K8sConditionStatus {
181    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
182        f.write_str(self.as_wire_str())
183    }
184}
185
186#[cfg(test)]
187mod tests {
188    use super::K8sConditionStatus;
189
190    /// Fail-before-pass-after: the substrate's `as_wire_str`
191    /// projection produces byte-identical output to the pre-lift
192    /// hand-authored `"True"` / `"False"` / `"Unknown"` literals
193    /// every writer + reader restated inline. A regression that
194    /// lower-cased one variant, added a whitespace prefix, or a
195    /// future `#[derive(Serialize)]` `serde(rename)` drift on this
196    /// type would surface HERE, not as silent operator-facing wire-
197    /// form skew across every K8s `status.conditions[]` writer +
198    /// reader in the workspace.
199    #[test]
200    fn as_wire_str_matches_pre_lift_literals_bytewise() {
201        assert_eq!(K8sConditionStatus::True.as_wire_str(), "True");
202        assert_eq!(K8sConditionStatus::False.as_wire_str(), "False");
203        assert_eq!(K8sConditionStatus::Unknown.as_wire_str(), "Unknown");
204    }
205
206    /// Round-trip through `from_wire_str(v.as_wire_str())` yields
207    /// `Some(v)` for every variant. Pins the invariant that the
208    /// writer + reader compose invertibly at the closed-set boundary
209    /// — a writer's `as_wire_str` output is always accepted by the
210    /// reader's `from_wire_str` on the SAME variant.
211    #[test]
212    fn wire_form_round_trip_holds_for_every_variant() {
213        for v in [
214            K8sConditionStatus::True,
215            K8sConditionStatus::False,
216            K8sConditionStatus::Unknown,
217        ] {
218            assert_eq!(K8sConditionStatus::from_wire_str(v.as_wire_str()), Some(v));
219        }
220    }
221
222    /// Inputs outside the closed set — case-drift, whitespace-
223    /// wrapped variants, empty string, unrelated K8s wire-form
224    /// literals — all reject with `None`. Pins the closed-set
225    /// nature: `from_wire_str` is a total function over the K8s
226    /// wire-form alphabet, not a permissive parser that accepts
227    /// synonyms.
228    #[test]
229    fn from_wire_str_rejects_case_drift_and_unknown() {
230        for bad in [
231            "", "true", "false", "unknown", " True", "True ", "Ready", "Attested", "yes", "1",
232        ] {
233            assert_eq!(
234                K8sConditionStatus::from_wire_str(bad),
235                None,
236                "expected `{bad:?}` outside the K8s ConditionStatus closed set, but from_wire_str accepted it",
237            );
238        }
239    }
240
241    /// `Display` composes through `as_wire_str` — the two
242    /// projections are byte-identical so `format!("{v}")` and
243    /// `v.as_wire_str()` are interchangeable at every consumer.
244    /// Pins the invariant that a caller who reaches for the
245    /// stdlib `Display` conversion path (via `.to_string()`,
246    /// `format!("{v}")`, a `write!` macro) gets the same wire-
247    /// form bytes as a direct `.as_wire_str()` call.
248    #[test]
249    fn display_composes_through_as_wire_str_bytewise() {
250        for v in [
251            K8sConditionStatus::True,
252            K8sConditionStatus::False,
253            K8sConditionStatus::Unknown,
254        ] {
255            assert_eq!(v.to_string(), v.as_wire_str());
256            assert_eq!(format!("{v}"), v.as_wire_str());
257        }
258    }
259
260    /// Closed-set completeness: the three variants exhaust the K8s
261    /// ConditionStatus alphabet. A future K8s revision that added a
262    /// fourth wire-form literal would land as one new variant here,
263    /// and every consumer that pattern-matched exhaustively against
264    /// the closed set gets a compile-time error until it handles the
265    /// new arm — the fifth invariant of the Rust+Lisp pattern.
266    /// Compiler-verified below with an exhaustive match; a regression
267    /// that added a `#[non_exhaustive]` or a private constructor arm
268    /// would break the exhaustiveness proof at this test.
269    #[test]
270    fn closed_set_exhausts_the_k8s_condition_status_alphabet() {
271        fn describe(v: K8sConditionStatus) -> &'static str {
272            match v {
273                K8sConditionStatus::True => "True",
274                K8sConditionStatus::False => "False",
275                K8sConditionStatus::Unknown => "Unknown",
276            }
277        }
278        assert_eq!(describe(K8sConditionStatus::True), "True");
279        assert_eq!(describe(K8sConditionStatus::False), "False");
280        assert_eq!(describe(K8sConditionStatus::Unknown), "Unknown");
281    }
282
283    /// `Copy` + `Clone` + `Eq` + `Hash` — pins the trait derives at
284    /// compile time so a regression that dropped one (a future
285    /// `#[derive(Serialize, Deserialize)]` addition that reshaped
286    /// the enum, a manual `impl Clone` that dropped `Copy`) surfaces
287    /// here rather than at a downstream consumer that stored the
288    /// value in a `HashMap` key or copied it across an `if` arm.
289    #[test]
290    fn value_semantics_hold_at_compile_time() {
291        fn assert_copy<T: Copy>() {}
292        fn assert_hash<T: std::hash::Hash>() {}
293        fn assert_eq<T: Eq>() {}
294        assert_copy::<K8sConditionStatus>();
295        assert_hash::<K8sConditionStatus>();
296        assert_eq::<K8sConditionStatus>();
297    }
298}