tatara_process/routing_edge_resource.rs
1//! Closed-set of routing-edge K8s resource kinds emitted by the
2//! tatara reconciler's `render_routing` pipeline + typed projections
3//! for their `(apiVersion, kind)` pair — the substrate primitive that
4//! owns the workspace-wide (variant → wire-form identity) mapping
5//! every routing-edge site would otherwise restate by hand.
6//!
7//! Pre-lift the `(apiVersion, kind)` pairing was hand-authored across
8//! SIX production sites in `tatara-reconciler::edges` past the ★★
9//! PRIME-DIRECTIVE ≥ 2 duplication threshold, split across two edge
10//! variants:
11//!
12//! * `Ingress` — three production sites:
13//! * `IngressEdge::kind()` — the `Edge` trait method returns the
14//! bare `"Ingress"` PascalCase identifier for per-edge logging
15//! + label composition.
16//! * `IngressEdge::render` — the emitted
17//! `json!({"apiVersion": "networking.k8s.io/v1",
18//! "kind": "Ingress", ...})` block's `apiVersion` slot.
19//! * `IngressEdge::render` — the same block's `kind` slot,
20//! byte-identical to the trait method's return.
21//! * `DnsEndpoint` — three production sites:
22//! * `DnsEndpointEdge::kind()` — the `Edge` trait method returns
23//! the bare `"DNSEndpoint"` PascalCase identifier.
24//! * `DnsEndpointEdge::render` — the emitted
25//! `json!({"apiVersion": "externaldns.k8s.io/v1alpha1",
26//! "kind": "DNSEndpoint", ...})` block's `apiVersion` slot.
27//! * `DnsEndpointEdge::render` — the same block's `kind` slot,
28//! byte-identical to the trait method's return.
29//!
30//! Every pre-lift site restated the axis-typed `&'static str` slot
31//! byte-identically; a regression that renamed the K8s Kind at ONE
32//! callsite (say the trait method's return but not the emitted JSON
33//! slot) would silently bifurcate the wire-form identity operators
34//! grep for against the K8s API server — a `HTTPRoute` migration
35//! that reached the trait but not the emitter (or vice versa) is a
36//! 404 at wire time. Post-lift every axis binds at ONE closed-set
37//! owner and rustc enforces every consumer reads the pair from the
38//! SAME variant.
39//!
40//! Sibling to the same-shape [`crate::flux_resource::FluxResource`]
41//! closed set on the FluxCD wire-form axis: both project a closed set
42//! of variant → wire-form identity slots through named per-variant
43//! methods; `FluxResource` covers the Flux controllers' emitted CRs
44//! (Kustomization, HelmRelease, OCIRepository) while
45//! `RoutingEdgeResource` covers the routing edges the reconciler
46//! renders (Ingress, DNSEndpoint). Both share the same `const fn`
47//! per-variant projection idiom + `ALL` sweep-enumerable seed +
48//! injectivity + const-reachability pins.
49//!
50//! Extension: a future edge variant (a Gateway API `HTTPRoute` /
51//! `Gateway`, a `NetworkPolicy` edge, a Cloudflare API CR, a
52//! `TCPRoute` for L4 routing) lands as ONE variant + ONE
53//! `api_version` arm + ONE `kind` arm + ONE `ALL` entry, all four
54//! exhaustively enforced by rustc's match coverage. Every downstream
55//! routing-edge consumer (the trait method, the emitted JSON, any
56//! future coherence sweep) inherits the extension mechanically
57//! through the same `RoutingEdgeResource::X.api_version()` / `.kind()`
58//! dispatch pair.
59//!
60//! Theory grounding: THEORY.md §VI.1 (generation over composition —
61//! the (apiVersion, kind) pairing recurred at six hand-authored sites
62//! past the PRIME-DIRECTIVE ≥ 2 duplication trigger, and is lifted to
63//! ONE closed-set owner per axis here). THEORY.md §II.1 invariant 5
64//! (composition preserves proofs — the two per-axis mappings live at
65//! ONE typed algebra projection apiece; a regression that drifted the
66//! apiVersion at ONE consumer would fail-loudly at this module's byte-
67//! shape pins rather than as silent trait-vs-emit skew at the
68//! reconciler wire).
69
70/// Closed set of K8s resource kinds the tatara reconciler emits as
71/// external routing edges. The two variants partition the current
72/// routing-edge surface:
73///
74/// * `Ingress` — `networking.k8s.io/v1` Ingress, backed by a Service,
75/// matched by the operator's ingress controller (nginx / Contour /
76/// HAProxy). Emitted by `IngressEdge` in
77/// `tatara-reconciler::edges`.
78/// * `DnsEndpoint` — `externaldns.k8s.io/v1alpha1` DNSEndpoint,
79/// picked up by external-dns and written to the operator's
80/// configured DNS provider (Cloudflare / Route53 / etc.). Emitted
81/// by `DnsEndpointEdge` in `tatara-reconciler::edges`.
82///
83/// Every variant carries a stable `(api_version, kind)` pair through
84/// its typed projections; both projections are `const fn` so the
85/// pair reduces to a `&'static str` slot at every callsite with no
86/// runtime overhead.
87#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
88pub enum RoutingEdgeResource {
89 Ingress,
90 DnsEndpoint,
91}
92
93impl RoutingEdgeResource {
94 /// The closed set of routing-edge resource variants this
95 /// substrate binds. Enumerable so a sweep-test (or a future
96 /// coherence check) can walk every variant without a hand-
97 /// maintained list on the caller side. A future third variant
98 /// (a Gateway API `HTTPRoute`, a `NetworkPolicy` edge) added
99 /// without an `ALL` entry surfaces at the
100 /// `all_enumerates_every_variant_exactly_once` pin.
101 pub const ALL: [Self; 2] = [Self::Ingress, Self::DnsEndpoint];
102
103 /// K8s wire-form `apiVersion` string for this routing-edge
104 /// resource variant. Matches the canonical group+version pair the
105 /// K8s / external-dns controllers expose today:
106 ///
107 /// * `Ingress` → `networking.k8s.io/v1`
108 /// * `DnsEndpoint` → `externaldns.k8s.io/v1alpha1`
109 ///
110 /// A future controller upgrade that bumps a group's version
111 /// lands at ONE arm here; every downstream emit or fetch site
112 /// inherits the upgrade mechanically through the same
113 /// `.api_version()` call.
114 pub const fn api_version(self) -> &'static str {
115 match self {
116 Self::Ingress => "networking.k8s.io/v1",
117 Self::DnsEndpoint => "externaldns.k8s.io/v1alpha1",
118 }
119 }
120
121 /// K8s wire-form `kind` string for this routing-edge resource
122 /// variant — the PascalCase identifier the K8s API server matches
123 /// against the resource's `kind:` slot. The trait method
124 /// `Edge::kind` at each downstream impl delegates to this
125 /// projection so the diagnostic label and the emitted JSON slot
126 /// cannot drift.
127 ///
128 /// A regression that misspelled either PascalCase identifier
129 /// would silently mis-route SSA-fetch against SSA-apply (an
130 /// `Ingess` emit against an `Ingress` fetch is a 404 at wire
131 /// time); post-lift a rename lands at ONE arm here rather than
132 /// at every emit or trait-method site.
133 pub const fn kind(self) -> &'static str {
134 match self {
135 Self::Ingress => "Ingress",
136 Self::DnsEndpoint => "DNSEndpoint",
137 }
138 }
139
140 /// Project this variant onto the typed
141 /// [`crate::k8s_wire_identity::K8sWireIdentity`] pair — the
142 /// substrate primitive that owns the workspace-wide
143 /// `(apiVersion, kind)` pairing every emit or fetch site
144 /// composes against. Pre-lift the reconciler's two
145 /// `IngressEdge::render` / `DnsEndpointEdge::render` emit sites
146 /// hand-authored the pair as two adjacent `json!` slots
147 /// (`"apiVersion": RoutingEdgeResource::X.api_version(), "kind":
148 /// RoutingEdgeResource::X.kind()`) mentioning the same variant
149 /// twice; post-lift the emit site names the variant ONCE via
150 /// `.wire_identity().resource_json(json!({...}))` and the pair
151 /// binds structurally at the closed-set owner.
152 ///
153 /// `const fn` so a caller can bind the pair into a `const` slot
154 /// — sibling to [`crate::flux_resource::FluxResource::wire_identity`]
155 /// on the FluxCD wire-form axis; both project through the same
156 /// closed-set → typed-pair idiom.
157 pub const fn wire_identity(self) -> crate::k8s_wire_identity::K8sWireIdentity {
158 crate::k8s_wire_identity::K8sWireIdentity::new(self.api_version(), self.kind())
159 }
160}
161
162#[cfg(test)]
163mod tests {
164 use super::*;
165
166 #[test]
167 fn all_enumerates_every_variant_exactly_once() {
168 // A future 3rd variant added without an `ALL` entry (or a
169 // duplicate entry that skewed the sweep) surfaces here.
170 assert_eq!(RoutingEdgeResource::ALL.len(), 2);
171 // Every variant appears exactly once — no duplicates, no gaps.
172 let mut seen = std::collections::HashSet::new();
173 for v in RoutingEdgeResource::ALL {
174 assert!(seen.insert(v), "duplicate variant in ALL: {v:?}");
175 }
176 }
177
178 #[test]
179 fn ingress_api_version_is_networking_k8s_io_v1() {
180 // Byte-identity pin: the exact wire-form string every pre-lift
181 // callsite hand-authored (both `IngressEdge::render` at the
182 // json! slot and any downstream selector matching against
183 // this apiVersion). A drift that renamed the group or bumped
184 // the version at ONE site would silently mis-route the
185 // fetch-vs-apply pairing.
186 assert_eq!(
187 RoutingEdgeResource::Ingress.api_version(),
188 "networking.k8s.io/v1"
189 );
190 }
191
192 #[test]
193 fn dns_endpoint_api_version_is_externaldns_k8s_io_v1alpha1() {
194 assert_eq!(
195 RoutingEdgeResource::DnsEndpoint.api_version(),
196 "externaldns.k8s.io/v1alpha1"
197 );
198 }
199
200 #[test]
201 fn ingress_kind_is_pascalcase_ingress() {
202 assert_eq!(RoutingEdgeResource::Ingress.kind(), "Ingress");
203 }
204
205 #[test]
206 fn dns_endpoint_kind_is_pascalcase_dns_endpoint() {
207 assert_eq!(RoutingEdgeResource::DnsEndpoint.kind(), "DNSEndpoint");
208 }
209
210 #[test]
211 fn every_variants_api_version_and_kind_are_distinct_across_the_closed_set() {
212 // Cross-variant coherence pin: no two variants may share an
213 // `api_version` or a `kind`. A future extension that added a
214 // variant duplicating an existing wire-form pair (e.g. a
215 // hypothetical `IngressRoute` variant that reused the
216 // `networking.k8s.io/v1` apiVersion in a copy-paste) would
217 // surface here.
218 let mut api_versions = std::collections::HashSet::new();
219 let mut kinds = std::collections::HashSet::new();
220 for v in RoutingEdgeResource::ALL {
221 assert!(
222 api_versions.insert(v.api_version()),
223 "duplicate api_version at {v:?}: {}",
224 v.api_version()
225 );
226 assert!(
227 kinds.insert(v.kind()),
228 "duplicate kind at {v:?}: {}",
229 v.kind()
230 );
231 }
232 }
233
234 #[test]
235 fn api_version_and_kind_are_const_fn_reachable() {
236 // Compile-time reachability pin: every variant's projections
237 // are `const fn`, so a caller can bind them into a `const`
238 // slot. A regression that dropped the `const` qualifier
239 // would fail-loudly here rather than as a wrong-slot runtime
240 // dispatch at every callsite.
241 const I_AV: &str = RoutingEdgeResource::Ingress.api_version();
242 const I_K: &str = RoutingEdgeResource::Ingress.kind();
243 const D_AV: &str = RoutingEdgeResource::DnsEndpoint.api_version();
244 const D_K: &str = RoutingEdgeResource::DnsEndpoint.kind();
245 assert_eq!(I_AV, "networking.k8s.io/v1");
246 assert_eq!(I_K, "Ingress");
247 assert_eq!(D_AV, "externaldns.k8s.io/v1alpha1");
248 assert_eq!(D_K, "DNSEndpoint");
249 }
250
251 #[test]
252 fn wire_identity_pairs_api_version_and_kind_per_variant() {
253 // Projection pin: every variant's `wire_identity()` binds
254 // the SAME closed-set variant's `api_version` and `kind`
255 // into a typed pair. Peer to the sibling `FluxResource`
256 // pin — both closed sets project through the same shape,
257 // and a regression that skewed the pair at one variant
258 // (say the `DnsEndpoint` projection accidentally returned
259 // `Ingress.kind()`) would surface here rather than at the
260 // reconciler wire.
261 for v in RoutingEdgeResource::ALL {
262 let id = v.wire_identity();
263 assert_eq!(id.api_version, v.api_version());
264 assert_eq!(id.kind, v.kind());
265 }
266 }
267
268 #[test]
269 fn wire_identity_is_const_reachable() {
270 // Compile-time reachability pin: `wire_identity` is `const
271 // fn` so a caller (any emit site or future coherence sweep)
272 // can bind the pair into a `const` slot. A regression that
273 // dropped the `const` qualifier would fail-loudly here.
274 const I: crate::k8s_wire_identity::K8sWireIdentity =
275 RoutingEdgeResource::Ingress.wire_identity();
276 const D: crate::k8s_wire_identity::K8sWireIdentity =
277 RoutingEdgeResource::DnsEndpoint.wire_identity();
278 assert_eq!(I.api_version, "networking.k8s.io/v1");
279 assert_eq!(I.kind, "Ingress");
280 assert_eq!(D.api_version, "externaldns.k8s.io/v1alpha1");
281 assert_eq!(D.kind, "DNSEndpoint");
282 }
283
284 #[test]
285 fn projections_are_pure_functions_of_the_variant() {
286 // Purity pin: calling the projections repeatedly on the same
287 // variant returns byte-identical `&'static str`s. Guards
288 // against an implementation that lazily materialized an
289 // interned key per-call and hashed against runtime state.
290 for v in RoutingEdgeResource::ALL {
291 assert_eq!(v.api_version(), v.api_version());
292 assert_eq!(v.kind(), v.kind());
293 }
294 }
295}