Skip to main content

tatara_process/
crd.rs

1//! The `Process` CRD — `tatara.pleme.io/v1alpha1`.
2
3use chrono::{DateTime, Utc};
4use kube::CustomResource;
5use schemars::JsonSchema;
6use serde::{Deserialize, Serialize};
7use tatara_lisp::DeriveTataraDomain;
8
9use crate::attestation::ProcessAttestation;
10use crate::boundary::Boundary;
11use crate::classification::Classification;
12use crate::compliance::ComplianceSpec;
13use crate::encapsulates::EncapsulatesSpec;
14use crate::identity::Identity;
15use crate::intent::Intent;
16use crate::lifetime::Lifetime;
17use crate::phase::ProcessPhase;
18use crate::routing::RoutingSpec;
19use crate::signal::ProcessSignal;
20use crate::spec::{DependsOn, IdentitySpec, SignalPolicy};
21use crate::status::{BoundaryStatus, ComplianceStatus, FluxResourceRef, ProcessCondition};
22
23/// Process — one element of the tatara convergence lattice, reconciled as a Unix process.
24///
25/// ```yaml
26/// apiVersion: tatara.pleme.io/v1alpha1
27/// kind: Process
28/// metadata:
29///   name: observability-stack
30///   namespace: seph
31/// spec:
32///   identity:
33///     parent: seph.1
34///   classification:
35///     pointType: Gate
36///     substrate: Observability
37///   intent:
38///     nix:
39///       flakeRef: github:pleme-io/k8s?dir=shared/infrastructure
40///       attribute: observability
41///   compliance:
42///     baseline: fedramp-moderate
43///     bindings:
44///       - framework: nist-800-53
45///         controlId: SC-7
46///         phase: AtBoundary
47///   dependsOn:
48///     - name: secret-injection
49/// ```
50#[derive(CustomResource, DeriveTataraDomain, Clone, Debug, Deserialize, Serialize, JsonSchema)]
51#[kube(
52    group = "tatara.pleme.io",
53    version = "v1alpha1",
54    kind = "Process",
55    plural = "processes",
56    shortname = "proc",
57    namespaced,
58    status = "ProcessStatus",
59    printcolumn = r#"{"name":"PID","type":"string","jsonPath":".status.pid"}"#,
60    printcolumn = r#"{"name":"Phase","type":"string","jsonPath":".status.phase"}"#,
61    printcolumn = r#"{"name":"Type","type":"string","jsonPath":".spec.classification.pointType"}"#,
62    printcolumn = r#"{"name":"Substrate","type":"string","jsonPath":".spec.classification.substrate"}"#,
63    printcolumn = r#"{"name":"Gen","type":"integer","jsonPath":".status.attestation.generation"}"#,
64    printcolumn = r#"{"name":"Age","type":"date","jsonPath":".metadata.creationTimestamp"}"#
65)]
66#[serde(rename_all = "camelCase")]
67#[tatara(keyword = "defpoint")]
68pub struct ProcessSpec {
69    /// Identity (parent, name override).
70    #[serde(default)]
71    pub identity: IdentitySpec,
72
73    /// Lattice position (6 dimensions).
74    pub classification: Classification,
75
76    /// Where rendered artifacts come from. Exactly one variant must be set.
77    pub intent: Intent,
78
79    /// Boundary predicates (preconditions / postconditions).
80    #[serde(default)]
81    pub boundary: Boundary,
82
83    /// Compliance bindings + baseline.
84    #[serde(default)]
85    pub compliance: ComplianceSpec,
86
87    /// Lattice dependencies — must reach phase before we proceed.
88    #[serde(default)]
89    pub depends_on: Vec<DependsOn>,
90
91    /// Signal policy (grace, SIGHUP strategy, start-suspended).
92    #[serde(default)]
93    pub signals: SignalPolicy,
94
95    /// Lifetime — `Permanent` (default, re-converging) or `Ephemeral`
96    /// (auto-SIGTERM per `teardown_policy` + TTL clock).
97    #[serde(default, skip_serializing_if = "Lifetime::is_default")]
98    pub lifetime: Lifetime,
99
100    /// External edges — DNS + Ingress. When `None`, the Process is
101    /// internal-only (matches today's default). See
102    /// [`crate::routing`] for the full shape.
103    #[serde(default, skip_serializing_if = "Option::is_none")]
104    pub routing: Option<RoutingSpec>,
105
106    /// Pre-existing in-cluster state this Process wraps. When `None`,
107    /// the Process is greenfield (Manage mode implicitly applied to
108    /// nothing pre-existing). See [`crate::encapsulates`] for the
109    /// three modes (Manage / Adopt / Observe).
110    #[serde(default, skip_serializing_if = "Option::is_none")]
111    pub encapsulates: Option<EncapsulatesSpec>,
112
113    /// Soft-suspend marker — reconciler treats as SIGSTOP.
114    /// Same effect as delivering SIGSTOP, but persistent across restarts.
115    #[serde(default)]
116    pub suspended: bool,
117}
118
119// Coordinate primitives — the `(namespace, name)` pair every downstream
120// composer (annotation writers, claim arbiter, boundary evaluator,
121// render owner-metadata seed) pulled by hand from `Process.metadata`
122// pre-lift, each restating the same two `Option<String>`-to-`&str`
123// unwrap incantations with the same two workspace-wide fallback
124// strings sprayed inline. Post-lift the pair lives at ONE substrate
125// primitive on `Process` — a future normalization (case-fold,
126// unicode-safe collation, cross-cluster prefix, a rename of either
127// fallback) lands here and every downstream composer inherits the
128// upgrade mechanically. Peer to `qualified_process_ref` in
129// `tatara-reconciler::ssapply`, whose two `&str` arguments are
130// exactly the pair `Process::coordinates_or_defaults` returns.
131impl Process {
132    /// The K8s canonical default namespace — the fallback every
133    /// consumer of a `Process` whose `metadata.namespace` is `None`
134    /// substitutes. Matches the string K8s itself substitutes on
135    /// namespaced resource writes with no explicit namespace.
136    pub const DEFAULT_NAMESPACE: &'static str = "default";
137
138    /// Workspace-wide fallback for a `Process`'s `metadata.name` when
139    /// it is `None` — the sentinel every annotation writer, claim
140    /// arbiter, and owner-metadata seed substitutes so downstream
141    /// grepping / label-selecting sees a stable spelling rather than
142    /// a per-callsite ad-hoc placeholder (`""`, `"<unnamed>"`, or the
143    /// empty `unwrap_or_default()` fallback). A Process authored
144    /// through the reconciler's fork path always has a name; this
145    /// constant covers the surface where an untyped `Process` value
146    /// (test fixture, dynamic API response, adopted resource pre-
147    /// name-resolution) surfaces without one.
148    pub const UNNAMED_PLACEHOLDER: &'static str = "unnamed";
149
150    /// Namespace slice with the [`Self::DEFAULT_NAMESPACE`] fallback
151    /// applied — the ONE-line collapse of the `metadata.namespace
152    /// .as_deref().unwrap_or("default")` incantation every consumer
153    /// spelled by hand pre-lift.
154    ///
155    /// Peer to [`Self::name_or_placeholder`] on the (metadata slot ×
156    /// fallback shape) axis; both compose through
157    /// [`Self::coordinates_or_defaults`] when a consumer needs the
158    /// pair together (annotation writers, claim-arbiter row builders,
159    /// render owner-metadata seed).
160    pub fn namespace_or_default(&self) -> &str {
161        self.metadata
162            .namespace
163            .as_deref()
164            .unwrap_or(Self::DEFAULT_NAMESPACE)
165    }
166
167    /// Name slice with the [`Self::UNNAMED_PLACEHOLDER`] fallback
168    /// applied — the ONE-line collapse of the `metadata.name.as_deref
169    /// ().unwrap_or("unnamed")` incantation every consumer spelled by
170    /// hand pre-lift.
171    ///
172    /// Peer to [`Self::namespace_or_default`] on the (metadata slot ×
173    /// fallback shape) axis; both compose through
174    /// [`Self::coordinates_or_defaults`] when a consumer needs the
175    /// pair together.
176    pub fn name_or_placeholder(&self) -> &str {
177        self.metadata
178            .name
179            .as_deref()
180            .unwrap_or(Self::UNNAMED_PLACEHOLDER)
181    }
182
183    /// `(namespace, name)` coordinates with the workspace-wide default
184    /// fallbacks applied — the ONE-line collapse of the paired
185    /// `metadata.namespace.as_deref().unwrap_or("default")` +
186    /// `metadata.name.as_deref().unwrap_or("unnamed")` extraction
187    /// every downstream composer restated by hand pre-lift.
188    ///
189    /// Return-tuple order matches the axis order of the substrate's
190    /// paired-composer primitive
191    /// `tatara_reconciler::ssapply::qualified_process_ref(ns, name)`:
192    /// the (namespace, name) pair this method returns feeds that
193    /// primitive positionally without an axis-swap step.
194    pub fn coordinates_or_defaults(&self) -> (&str, &str) {
195        (self.namespace_or_default(), self.name_or_placeholder())
196    }
197
198    /// `(namespace, name)` coordinates as owned `String`s, with the
199    /// namespace half fallback-defaulted to [`Self::DEFAULT_NAMESPACE`]
200    /// but the name half REQUIRED — an [`anyhow::Error`] is returned
201    /// when `metadata.name` is absent, because "unnamed" is a display
202    /// placeholder, not a valid K8s API path segment. Fed straight into
203    /// kube-rs API calls (`Api::patch`, `Api::delete`, `Api::get`) that
204    /// take owned `String` arguments; the [`Self::DEFAULT_NAMESPACE`]
205    /// fallback matches what K8s itself substitutes on namespaced
206    /// resource writes with no explicit namespace, so the surface is
207    /// safe against a `Process` whose `metadata.namespace` slot is
208    /// absent (test fixture, dynamic API response pre-defaulting) but
209    /// refuses to guess a name.
210    ///
211    /// Peer to [`Self::coordinates_or_defaults`] on the (return-form ×
212    /// name gate) axis pair:
213    /// * borrow + name-defaulted → `coordinates_or_defaults` (display,
214    ///   annotation writers, ownership-tag composers — every consumer
215    ///   whose downstream drops `"unnamed"` in place of a missing name
216    ///   without an operator-visible failure);
217    /// * owned + name-required → this method (kube-rs API calls —
218    ///   every consumer whose downstream must NOT silently substitute
219    ///   a placeholder for the API call target, because the caller is
220    ///   about to `patch`/`delete`/`get` at `metadata.name`).
221    ///
222    /// The error wording is pinned by
223    /// [`tests::owned_coordinates_or_err_error_message_matches_pre_lift_reconciler_wording`]
224    /// to match the exact spelling every pre-lift `tatara-reconciler`
225    /// helper produced (`"Process has no metadata.name"`) so log-line
226    /// / test greps that anchored on that wording keep matching post-
227    /// lift, and no operator-visible message drift lands as a side
228    /// effect of the substrate move.
229    pub fn owned_coordinates_or_err(&self) -> anyhow::Result<(String, String)> {
230        let ns = self
231            .metadata
232            .namespace
233            .clone()
234            .unwrap_or_else(|| Self::DEFAULT_NAMESPACE.into());
235        let name = self
236            .metadata
237            .name
238            .clone()
239            .ok_or_else(|| anyhow::anyhow!("Process has no metadata.name"))?;
240        Ok((ns, name))
241    }
242
243    /// `(namespace, name)` coordinates in the BORROW + NAME-REQUIRED
244    /// corner of the primitive family — namespace half falls back to
245    /// [`Self::DEFAULT_NAMESPACE`], but the name half is REQUIRED
246    /// (`None` on a `Process` whose `metadata.name` is absent, so the
247    /// caller stops with an `else { continue; }` / `else { return
248    /// …; }` guard rather than proceeding with the empty-string
249    /// sentinel every pre-lift consumer had to spell inline).
250    ///
251    /// Peer to [`Self::coordinates_or_defaults`] +
252    /// [`Self::owned_coordinates_or_err`] on the (return-form ×
253    /// name-gate) axis pair — closes the corner the family previously
254    /// left open:
255    ///
256    /// * borrow + name-defaulted → [`Self::coordinates_or_defaults`]
257    ///   (annotation writers, render owner-metadata seed — consumers
258    ///   whose downstream tolerates the `"unnamed"` display placeholder
259    ///   without operator-visible failure);
260    /// * borrow + name-required → **this method** (claim-arbiter
261    ///   probes, child-Process delete-fan-out — consumers that need a
262    ///   real API-path leaf and cleanly SKIP the row when the name is
263    ///   absent rather than issuing a K8s call with an empty-string
264    ///   name argument);
265    /// * owned + name-required → [`Self::owned_coordinates_or_err`]
266    ///   (kube-rs API-path calls — consumers whose downstream requires
267    ///   owned `String` arguments and rejects the missing-name corner
268    ///   with a load-bearing error message).
269    ///
270    /// The primitive family's `None`-on-missing-name semantics
271    /// intentionally differs from [`Self::owned_coordinates_or_err`]'s
272    /// error-on-missing-name semantics: the caller sites for this form
273    /// (child-Process fan-out, claim-arbiter row probes) are non-fatal
274    /// SKIPS rather than reportable failures — an `Option::None` at
275    /// the primitive lets the caller thread that "skip" through a
276    /// let-else without stringifying / logging an anyhow chain per
277    /// missing-name occurrence.
278    ///
279    /// The namespace fallback matches [`Self::coordinates_or_defaults`]
280    /// (via [`Self::namespace_or_default`]), so a consumer that
281    /// switches between the two borrow-form primitives based on its
282    /// name-gate need never sees a different namespace-fallback string
283    /// as a side effect.
284    pub fn coordinates_or_none(&self) -> Option<(&str, &str)> {
285        let name = self.metadata.name.as_deref()?;
286        Some((self.namespace_or_default(), name))
287    }
288
289    /// Borrowed lookup of ONE key in `metadata.annotations`, with
290    /// BOTH the missing-`annotations` corner AND the missing-key
291    /// corner collapsed to `None` — the ONE-liner collapse of the
292    /// paired `self.metadata.annotations.as_ref().and_then(|m|
293    /// m.get(key)).map(String::as_str)` incantation every consumer
294    /// restated by hand pre-lift.
295    ///
296    /// Pre-lift the 3-line `.metadata.annotations.as_ref().and_then
297    /// (|m| m.get(KEY))` chain (in three tail variants — `.cloned()`,
298    /// `.cloned().unwrap_or_default()`, `.map(String::as_str)`) was
299    /// hand-authored at THREE sites past the ★★ PRIME-DIRECTIVE ≥ 2
300    /// duplication threshold across the workspace:
301    /// * `tatara-reconciler::signals::ingest` — SIGNAL annotation
302    ///   lookup (pre-lift `.cloned()` for owned parsing).
303    /// * `tatara-reconciler::phase_machine::released_from_annotation`
304    ///   — RELEASED_FROM annotation lookup (pre-lift `.cloned()
305    ///   .unwrap_or_default()` for `match v.as_str()`).
306    /// * `tatara-pool-reconciler::controller_pool::process_belongs_to_pool`
307    ///   — POOL annotation lookup (pre-lift `.map(String::as_str)`
308    ///   for `== Some(pool_name)`).
309    ///
310    /// All THREE sites walked the SAME 3-line chain — read the
311    /// annotations map, gate on presence, index by key — differing
312    /// only in the tail that shaped the result. Post-lift each
313    /// caller routes through the ONE substrate primitive here and
314    /// applies its own tail at its own site (`.map(str::to_string)`
315    /// / bare match / `==`).
316    ///
317    /// Return-form axis: `Option<&str>` mirrors the existing borrow-
318    /// first discipline of the peer metadata primitives
319    /// [`Self::namespace_or_default`], [`Self::name_or_placeholder`],
320    /// [`Self::coordinates_or_none`]. The two corners the chain
321    /// swallowed pre-lift (missing `metadata.annotations` map,
322    /// missing key inside the map) BOTH collapse to `None` so
323    /// `.is_some()` / `if let Some(_)` / `Option::map` behave
324    /// identically on a `Process` whose annotations block is `None`
325    /// and on one whose annotations block is populated but omits the
326    /// key — matching what the pre-lift `.and_then(...)` chain
327    /// produced.
328    ///
329    /// A future normalization step (a key-canonicalization pass,
330    /// a case-fold lookup, a per-key alias table for renamed
331    /// annotations across API versions, a per-namespace override
332    /// substrate) lands at ONE substrate method here and all three
333    /// downstream consumers pick up the upgrade mechanically — no
334    /// per-callsite hand-edit at `ingest` / `released_from_annotation`
335    /// / `process_belongs_to_pool`.
336    ///
337    /// Sibling to the peer metadata primitives
338    /// ([`Self::namespace_or_default`], [`Self::name_or_placeholder`],
339    /// [`Self::coordinates_or_defaults`], [`Self::coordinates_or_none`],
340    /// [`Self::owned_coordinates_or_err`]) on the metadata axis;
341    /// this method opens the borrow-form peer on the ANNOTATION
342    /// axis. Future annotation projections (a paired
343    /// `label(&str) -> Option<&str>` on `metadata.labels`, a
344    /// `has_annotation(&str) -> bool` boolean gate for presence-
345    /// only consumers) land as peer methods on this same axis.
346    ///
347    /// Theory anchor: THEORY.md §VI.1 (generation over composition
348    /// — the 3-line annotation-lookup chain recurred at three
349    /// hand-authored sites past the ★★ PRIME-DIRECTIVE ≥ 2
350    /// duplication trigger, and is lifted to ONE owner here).
351    /// THEORY.md §II.1 invariant 5 (composition preserves proofs —
352    /// the pins bind the missing-`annotations` corner + the
353    /// missing-key corner + the borrow-form `&str` lifetime + the
354    /// byte-identical parity with the pre-lift 3-line chain, so a
355    /// regression that drifted any surface at
356    /// `tests::annotation_*` rather than as silent operator-facing
357    /// skew between the SIGNAL / RELEASED_FROM / POOL annotation
358    /// readers).
359    pub fn annotation(&self, key: &str) -> Option<&str> {
360        self.metadata
361            .annotations
362            .as_ref()
363            .and_then(|m| m.get(key))
364            .map(String::as_str)
365    }
366
367    /// Borrow-form metadata-projection primitive on the `metadata.uid`
368    /// axis: returns the K8s-API-server-assigned uid as a `&str`, with
369    /// the missing-uid corner collapsed to the load-bearing empty-string
370    /// sentinel — the ONE-liner collapse of the paired
371    /// `self.metadata.uid.as_deref().unwrap_or("")` incantation every
372    /// owner-reference-emitting consumer restated by hand pre-lift.
373    ///
374    /// The empty-string fallback is NOT arbitrary — it is the exact
375    /// sentinel value the sibling substrate composer
376    /// [`crate::owner_references_json`] gates on (`if uid.is_empty()
377    /// { vec![] } else { vec![owner_reference_json(name, uid)] }`) to
378    /// stamp `metadata.ownerReferences: []` on a resource whose owning
379    /// Process pre-dates the API server's `metadata.uid` assignment
380    /// (test fixture, mid-Forking snapshot before the first `patch`
381    /// round-trip, dynamic API response pre-uid-resolution). Pre-lift
382    /// each consumer spelled the fallback as `.unwrap_or("")` at its
383    /// callsite; the two literals in two files could drift silently to
384    /// `.unwrap_or_default()`, `.unwrap_or("<unknown>")`, or an
385    /// `if let Some(u) = &process.metadata.uid` gate that returned a
386    /// different owner-refs shape for the missing-uid corner. Post-lift
387    /// the sentinel value is composed at ONE substrate site so the
388    /// empty-uid gate at `owner_references_json` and its per-callsite
389    /// producers share the SAME `""` byte-string, and a rename of the
390    /// sentinel would land at ONE substrate site rather than at every
391    /// downstream `owner_references_json(name, uid)` call.
392    ///
393    /// Peer to [`Self::namespace_or_default`] +
394    /// [`Self::name_or_placeholder`] on the metadata-slot × fallback-
395    /// shape axis: `namespace_or_default` returns the K8s-canonical
396    /// `"default"` fallback (matching what the API server substitutes
397    /// on namespaced writes with no explicit namespace);
398    /// `name_or_placeholder` returns the workspace-wide `"unnamed"`
399    /// sentinel (a display placeholder for downstream grepping /
400    /// label-selecting); this method returns the empty-string sentinel
401    /// (a load-bearing gate value that composes with
402    /// [`crate::owner_references_json`]'s `is_empty` check). The three
403    /// primitives partition the metadata-slot family by whether the
404    /// consumer wants a K8s-canonical fallback (namespace), a display
405    /// placeholder (name), or a gate sentinel (uid).
406    ///
407    /// Pre-lift the `.metadata.uid.as_deref().unwrap_or("")` chain was
408    /// hand-authored at TWO sites past the ★★ PRIME-DIRECTIVE ≥ 2
409    /// duplication threshold in `tatara-reconciler::render`, both
410    /// feeding a downstream owner-reference emitter:
411    /// * `render_routing` — the routing-edge seed that binds
412    ///   `process_uid` into every routing-form `EdgeContext` (Ingress +
413    ///   DNSEndpoint) built inside the fanout loop over
414    ///   `RoutingSpec::hostnames`; each `Edge::render` impl then walks
415    ///   its `EdgeContext` through `build_owner_refs` →
416    ///   [`crate::owner_references_json`] to stamp
417    ///   `metadata.ownerReferences` on the emitted resource.
418    /// * `render_export_jobs` — the ephemeral-export Job builder that
419    ///   passes the same uid slice to `tatara_process::
420    ///   owner_references_json(name, uid)` per rendered Job, stamping
421    ///   the export-Job's `metadata.ownerReferences` back at the
422    ///   owning Process.
423    ///
424    /// Both sites walked the SAME `.as_deref().unwrap_or("")` chain and
425    /// both wanted the `&str` form the primitive returns — as the
426    /// second positional argument to `owner_references_json(name, uid)`
427    /// on the ownership-tag axis. Post-lift each callsite reads
428    /// `let uid = process.uid_or_empty();` and the produced slice feeds
429    /// the same downstream composer unchanged.
430    ///
431    /// Return-form axis: `&str` mirrors the existing borrow-first
432    /// discipline of the peer metadata-fallback primitives
433    /// ([`Self::namespace_or_default`], [`Self::name_or_placeholder`]);
434    /// all three return owned-metadata borrows with a slot-specific
435    /// fallback baked in so downstream consumers compose the slice
436    /// directly into their next call without re-spelling the fallback.
437    ///
438    /// A future normalization step (a canonicalization pass that
439    /// rejects a malformed uid before the owner-ref stamp, a cross-
440    /// cluster uid rewrite for multi-tenant control planes, a stale-
441    /// uid warning annotation for a Process whose uid changed under
442    /// the reconciler mid-generation) lands at ONE substrate method
443    /// here and both downstream `owner_references_json` consumers
444    /// pick up the upgrade mechanically — no per-callsite hand-edit
445    /// at `render_routing` / `render_export_jobs`.
446    ///
447    /// Theory anchor: THEORY.md §VI.1 (generation over composition —
448    /// the `.metadata.uid.as_deref().unwrap_or("")` chain recurred at
449    /// two hand-authored sites past the ★★ PRIME-DIRECTIVE ≥ 2
450    /// duplication trigger, and is lifted to ONE owner here).
451    /// THEORY.md §II.1 invariant 5 (composition preserves proofs —
452    /// the pins bind the missing-uid corner + the empty-string
453    /// sentinel byte-shape + the borrow-form `&str` lifetime + the
454    /// byte-identical parity with the pre-lift chain + the composition
455    /// coherence with [`crate::owner_references_json`]'s `is_empty`
456    /// gate, so a regression that drifted any surface at
457    /// `tests::uid_or_empty_*` rather than as silent operator-facing
458    /// skew between the two owner-reference emitters on the SAME
459    /// Process).
460    pub fn uid_or_empty(&self) -> &str {
461        self.metadata.uid.as_deref().unwrap_or("")
462    }
463
464    /// Borrow-form spec-projection primitive on the declared parent-PID
465    /// axis: returns the hierarchical PID path (e.g. `"seph.1"`) the
466    /// author declared at `spec.identity.parent`, with the empty-slot
467    /// corner collapsed to `None` — the ONE-liner collapse of the
468    /// paired `self.spec.identity.parent.as_deref()` incantation every
469    /// consumer restated by hand pre-lift.
470    ///
471    /// Pre-lift the `.spec.identity.parent.as_deref()` chain was hand-
472    /// authored at TWO sites past the ★★ PRIME-DIRECTIVE ≥ 2
473    /// duplication threshold in `tatara-reconciler::phase_machine`:
474    /// * `handle_forking` — the ALLOCATE-PID composer that threads the
475    ///   declared parent PID into [`pid::allocate_pid`] and also into
476    ///   the status patch payload (`{ "pid": new_pid, "parent":
477    ///   parent_pid }`), so the reconciler-observed
478    ///   [`ProcessStatus::parent`] slot mirrors the author-declared
479    ///   [`IdentitySpec::parent`] at fork time. The `info!` tracing
480    ///   span also reads the same slice as the `parent` field on the
481    ///   PID-assigned log line.
482    /// * `handle_exiting` — the SIGTERM cascade's child-fan-out filter
483    ///   that enumerates every Process cluster-wide and picks children
484    ///   whose `spec.identity.parent` equals this Process's currently-
485    ///   observed PID (`.filter(|c| c.spec.identity.parent.as_deref()
486    ///   == Some(pid))`). The filter runs per candidate child, so the
487    ///   borrow-form projection avoids allocating one `String` clone
488    ///   per non-matching row in the cluster-wide list.
489    ///
490    /// Both sites walked the SAME `.as_deref()` chain and both wanted
491    /// the `Option<&str>` form the primitive returns — the
492    /// `handle_forking` site to feed positionally into
493    /// `pid::allocate_pid(&identity, parent_pid, next_seq)` and the
494    /// tracing span's `parent = ?parent_pid` debug print + the JSON
495    /// payload's `"parent": parent_pid` slot; the `handle_exiting`
496    /// filter to compare directly against `Some(pid)` where `pid:
497    /// &str` came off the borrow-form peer [`Self::observed_pid`].
498    ///
499    /// Return-form axis: `Option<&str>` mirrors the borrow-first
500    /// discipline of every peer primitive on the metadata / status
501    /// slot family ([`Self::namespace_or_default`],
502    /// [`Self::name_or_placeholder`], [`Self::observed_pid`],
503    /// [`Self::annotation`]). The empty-slot corner
504    /// (`spec.identity.parent = None`, matching `init` / PID 1 with
505    /// no parent) collapses to `None` so `.is_some()` / `if let
506    /// Some(_)` / `.map(...)` behave identically on a `Process`
507    /// authored at cluster init (PID 1, parent absent) and on any
508    /// PID-N child (parent present) — matching the pre-lift
509    /// `.as_deref()` chain's `None` byte-identically.
510    ///
511    /// Peer to [`Self::observed_pid`] on the (spec-declared ×
512    /// status-observed) axis pair: `observed_pid` returns the PID
513    /// path this Process currently OWNS (the reconciler-persisted
514    /// child position in the hierarchy), while `declared_parent_pid`
515    /// returns the PID path this Process's parent OWNS (the author-
516    /// declared upstream position). The SIGTERM cascade at
517    /// `handle_exiting` composes both: it reads its own
518    /// [`Self::observed_pid`] and matches each candidate child's
519    /// [`Self::declared_parent_pid`] against that value — the child-
520    /// fan-out relation IS the spec-declared × status-observed axis
521    /// pair collapsed to a single comparator, both sides routed
522    /// through the same borrow-form skeleton.
523    ///
524    /// A future normalization step (a per-slot canonicalization pass
525    /// that rejects malformed hierarchical PIDs, a case-fold lookup
526    /// against a table of renamed identities, a cross-cluster prefix
527    /// stripper, an alias-table lookup that maps a legacy PID to its
528    /// current spelling) lands at ONE substrate method here and both
529    /// downstream consumers pick up the upgrade mechanically — no
530    /// per-callsite hand-edit at `handle_forking` / `handle_exiting`.
531    ///
532    /// Sibling to the peer metadata-projection primitives
533    /// ([`Self::namespace_or_default`], [`Self::name_or_placeholder`],
534    /// [`Self::coordinates_or_defaults`], [`Self::coordinates_or_none`],
535    /// [`Self::owned_coordinates_or_err`], [`Self::annotation`]) on the
536    /// metadata axis; this method opens the borrow-form peer on the
537    /// declared-identity axis. Future identity projections
538    /// (`declared_name_override` on the `spec.identity.name_override`
539    /// axis, a paired `declared_identity` composite that returns both
540    /// halves) land as peer methods on this same axis.
541    ///
542    /// Theory anchor: THEORY.md §VI.1 (generation over composition —
543    /// the `.spec.identity.parent.as_deref()` chain recurred at two
544    /// hand-authored sites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication
545    /// trigger, and is lifted to ONE owner here). THEORY.md §II.1
546    /// invariant 5 (composition preserves proofs — the pins bind the
547    /// empty-slot corner + the borrow-form `&str` lifetime + the
548    /// byte-identical parity with the pre-lift `.as_deref()` chain,
549    /// so a regression that drifted any surface at
550    /// `tests::declared_parent_pid_*` rather than as silent operator-
551    /// facing skew between the ALLOCATE-PID composer and the SIGTERM
552    /// cascade's child-fan-out filter on the SAME parent-child pair).
553    pub fn declared_parent_pid(&self) -> Option<&str> {
554        self.spec.identity.parent.as_deref()
555    }
556
557    /// Borrow-form spec-projection primitive on the declared
558    /// name-override axis: returns the human name the author declared
559    /// at `spec.identity.name_override` (used verbatim instead of the
560    /// content-hash-derived name in [`derive_identity`]), with the
561    /// empty-slot corner collapsed to `None` — the ONE-liner collapse
562    /// of the paired `self.spec.identity.name_override.as_deref()`
563    /// incantation every consumer restated by hand pre-lift.
564    ///
565    /// Pre-lift the `.spec.identity.name_override.as_deref()` chain
566    /// was hand-authored at TWO sites past the ★★ PRIME-DIRECTIVE ≥ 2
567    /// duplication threshold in `tatara-reconciler::phase_machine`,
568    /// both feeding the second positional argument of
569    /// [`derive_identity`]:
570    /// * `handle_pending` — the DECLARE composer that computes the
571    ///   Process's [`Identity`] on entry to the state machine (before
572    ///   `patch::phase_status` writes it into `status.identity`).
573    /// * `handle_forking` — the ALLOCATE-PID composer that recomputes
574    ///   the same [`Identity`] on a rehydration path (status may
575    ///   already carry an identity from a prior reconcile, in which
576    ///   case the `.and_then(|s| s.identity.clone())` short-circuit
577    ///   takes it; otherwise this `.unwrap_or_else` branch fires and
578    ///   recomputes the identity fresh from the spec) so `pid::
579    ///   allocate_pid` sees the SAME [`Identity`] the DECLARE phase
580    ///   produced.
581    ///
582    /// Both sites walked the SAME `.as_deref()` chain and both wanted
583    /// the `Option<&str>` form the primitive returns — as the second
584    /// positional argument to `derive_identity(&self.spec, …)`, which
585    /// internally trims + filters empty strings + dispatches on
586    /// `Some(non_empty)` (verbatim name, `name_override: true`) vs
587    /// `None | Some(empty | whitespace)` (content-hash-derived name,
588    /// `name_override: false`). The primitive itself preserves the
589    /// raw slot byte-identically (the trim happens IN
590    /// `derive_identity`, not at the borrow site), so the two live
591    /// paths compose through the SAME borrow-form skeleton.
592    ///
593    /// Return-form axis: `Option<&str>` mirrors the borrow-first
594    /// discipline of every peer primitive on the metadata / status /
595    /// spec-identity slot family ([`Self::namespace_or_default`],
596    /// [`Self::name_or_placeholder`], [`Self::observed_pid`],
597    /// [`Self::annotation`], [`Self::declared_parent_pid`]). The
598    /// empty-slot corner (`spec.identity.name_override = None`,
599    /// matching a Process authored WITHOUT the human-name-override
600    /// escape hatch — the default; `derive_identity` then computes
601    /// the name from the content hash) collapses to `None` so
602    /// `.is_some()` / `if let Some(_)` / `.map(...)` behave
603    /// identically on the two Process shapes an operator can author.
604    ///
605    /// Peer to [`Self::declared_parent_pid`] on the (parent × name-
606    /// override) sub-axis of the declared-identity axis: both
607    /// primitives project a `Option<String>` slot on `IdentitySpec`
608    /// through the SAME borrow-form skeleton, so a future
609    /// `declared_identity` composite that returns both halves
610    /// together (e.g. as a `(Option<&str>, Option<&str>)` tuple or a
611    /// borrow-form `DeclaredIdentityView<'_>` newtype) lands as ONE
612    /// method that COMPOSES the two peer primitives, not as three
613    /// hand-authored `.as_deref()` chains restated at each callsite.
614    ///
615    /// A future normalization step (a per-slot canonicalization pass
616    /// that rejects malformed names, a case-fold lookup against a
617    /// table of renamed identities, an alias-table lookup that maps
618    /// a legacy name-override to its current spelling, a whitespace-
619    /// trim lift OUT of `derive_identity` INTO the primitive so both
620    /// consumers see the trimmed form) lands at ONE substrate method
621    /// here and both downstream consumers pick up the upgrade
622    /// mechanically — no per-callsite hand-edit at `handle_pending` /
623    /// `handle_forking`.
624    ///
625    /// Sibling to the peer spec-identity projection
626    /// [`Self::declared_parent_pid`] on the declared-identity axis;
627    /// this method opens the borrow-form peer on the name-override
628    /// sub-axis of the same closed set (`IdentitySpec { parent,
629    /// name_override }`). Future identity projections (a paired
630    /// `declared_identity` composite that returns both halves
631    /// together) land as peer methods on this same axis.
632    ///
633    /// Theory anchor: THEORY.md §VI.1 (generation over composition —
634    /// the `.spec.identity.name_override.as_deref()` chain recurred
635    /// at two hand-authored sites past the ★★ PRIME-DIRECTIVE ≥ 2
636    /// duplication trigger, and is lifted to ONE owner here).
637    /// THEORY.md §II.1 invariant 5 (composition preserves proofs —
638    /// the pins bind the empty-slot corner + the borrow-form `&str`
639    /// lifetime + the byte-identical parity with the pre-lift
640    /// `.as_deref()` chain + the invariance under
641    /// [`derive_identity`]'s internal trim/filter step, so a
642    /// regression that drifted any surface at
643    /// `tests::declared_name_override_*` rather than as silent
644    /// operator-facing skew between the DECLARE composer and the
645    /// ALLOCATE-PID rehydration branch on the SAME Process spec).
646    pub fn declared_name_override(&self) -> Option<&str> {
647        self.spec.identity.name_override.as_deref()
648    }
649
650    /// Borrowed slice of the FluxCD resources this Process's status
651    /// currently persists at `status.flux_resources`, with the
652    /// missing-`status` corner collapsed to an empty slice — the ONE-
653    /// line collapse of the paired `self.status.as_ref().map(|s|
654    /// s.flux_resources.clone()).unwrap_or_default()` incantation
655    /// every VERIFY-phase / ATTEST-heartbeat consumer restated by hand
656    /// pre-lift.
657    ///
658    /// Pre-lift the 5-line `.status.as_ref().map(|s| s.flux_resources
659    /// .clone()).unwrap_or_default()` chain was hand-authored at TWO
660    /// sites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication threshold in
661    /// `tatara-reconciler::phase_machine`:
662    /// * `handle_running` — the VERIFY-phase per-ref readiness probe
663    ///   seed that walks every ref through
664    ///   [`crate::status::FluxResourceRef::fetch_coords`] via
665    ///   `ssapply::fetch_flux_ref` and rebuilds an updated
666    ///   `Vec<FluxResourceRef>` with `ready` + `message` + `last_check`
667    ///   observed at reconcile time.
668    /// * `handle_attested` — the ATTEST-heartbeat drift detector that
669    ///   short-circuits on the first non-Ready ref via
670    ///   `ssapply::fetch_flux_ref` + `ssapply::ready_condition`.
671    ///
672    /// Both sites walked the SAME 5-line chain — clone the vector
673    /// eagerly for the length of the reconcile pass, then iterate it
674    /// by reference — even though neither site ever mutates the vector
675    /// nor keeps it alive past the enclosing async fn. Post-lift both
676    /// callers borrow the slice directly from `self.status`; the two
677    /// pre-lift `.clone()` calls disappear because the slice lives for
678    /// the borrow of `&self`, and both call sites' subsequent
679    /// downstream calls (`ssapply::fetch_flux_ref` / the
680    /// `patch::patch_process_status` write) do not touch the borrowed
681    /// `p: &Process`, so the borrow lifetime holds.
682    ///
683    /// Return-form axis: `&[FluxResourceRef]` mirrors the existing
684    /// borrow-first discipline every pre-lift consumer already
685    /// iterated by reference (`for r in &refs`), and the shape of
686    /// [`crate::status::FluxResourceRef::fetch_coords`]'s per-ref
687    /// borrow projection extends mechanically to the slice-level
688    /// projection here. The missing-`status` corner collapses to the
689    /// empty slice `&[]` so `.is_empty()` / `.len()` / iteration all
690    /// behave identically on a `Process` whose status is `None` and
691    /// on one whose status carries an empty `flux_resources` slot —
692    /// matching what the pre-lift `.unwrap_or_default()` produced
693    /// (an empty `Vec`).
694    ///
695    /// A future normalization step (a per-ref canonicalization pass
696    /// that skips duplicated refs, an owner-filter that returns only
697    /// refs stamped with the CURRENT `metadata.generation`, a
698    /// staleness gate that drops refs whose `last_check` predates a
699    /// reconcile deadline) lands at ONE substrate method here and
700    /// both downstream consumers pick up the upgrade mechanically —
701    /// no per-callsite hand-edit at `handle_running` /
702    /// `handle_attested`.
703    ///
704    /// Sibling to the [`Self::coordinates_or_none`] borrow-first
705    /// primitive on the metadata axis; this method opens the
706    /// analogous borrow-first primitive on the status-projection
707    /// axis. Future status projections (`observed_attestation` on
708    /// the attestation-chain axis, `observed_pid` on the PID axis,
709    /// `observed_children` on the child-fan-out axis) land as peer
710    /// methods on this same axis.
711    ///
712    /// Theory anchor: THEORY.md §VI.1 (generation over composition —
713    /// the 5-line status-projection chain recurred at two hand-
714    /// authored sites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication
715    /// trigger, and is lifted to ONE owner here). THEORY.md §II.1
716    /// invariant 5 (composition preserves proofs — the pins bind the
717    /// missing-`status` corner + the slice-lifetime borrow discipline
718    /// + the byte-identical parity with the pre-lift 5-line chain, so
719    /// a regression that drifted any of the three surfaces at
720    /// `tests::observed_flux_resources_*` rather than as silent
721    /// operator-facing skew between the VERIFY-phase and ATTEST-
722    /// heartbeat consumers).
723    pub fn observed_flux_resources(&self) -> &[FluxResourceRef] {
724        self.status
725            .as_ref()
726            .map(|s| s.flux_resources.as_slice())
727            .unwrap_or(&[])
728    }
729
730    /// The borrow-form status-projection primitive on the PID axis:
731    /// returns the hierarchical PID path (e.g. `"seph.1.7"`) the
732    /// reconciler currently persists at `status.pid`, with BOTH the
733    /// missing-`status` corner AND the empty-slot corner collapsed
734    /// to `None` — the ONE-liner collapse of the paired
735    /// `self.status.as_ref().and_then(|s| s.pid.clone())` incantation
736    /// every consumer restated by hand pre-lift.
737    ///
738    /// Pre-lift the 3-line `.status.as_ref().and_then(|s| s.pid
739    /// .clone())` chain was hand-authored at TWO sites past the ★★
740    /// PRIME-DIRECTIVE ≥ 2 duplication threshold in
741    /// `tatara-reconciler::phase_machine`:
742    /// * `handle_forking` — the ALLOCATE-PID gate that short-
743    ///   circuits the PID allocator when the reconciler already
744    ///   assigned a PID on a prior reconcile pass (pre-lift the
745    ///   chain composed with `.is_some()` and threw the clone away
746    ///   without ever reading the string).
747    /// * `handle_exiting` — the SIGTERM cascade that enumerates
748    ///   child Processes and terminates them by matching each
749    ///   child's `spec.identity.parent` against the PID this Process
750    ///   currently owns (pre-lift the chain bound an owned
751    ///   `Option<String>` and threaded `pid.as_str()` into the
752    ///   downstream `.as_deref() == Some(...)` comparator).
753    ///
754    /// Both sites walked the SAME 3-line chain — clone the `String`
755    /// eagerly, then either drop it (the `handle_forking` gate) or
756    /// re-borrow it through `.as_str()` (the `handle_exiting`
757    /// comparator) — even though neither site ever mutates the PID
758    /// nor keeps it alive past the enclosing async fn. Post-lift
759    /// both callers borrow the PID directly from `self.status`; the
760    /// pre-lift `.clone()` at both sites disappears because the
761    /// `&str` lives for the borrow of `&self`, and both call sites'
762    /// subsequent downstream calls (the K8s API list/patch, the
763    /// child-Process comparator) do not touch the borrowed
764    /// `p: &Process`, so the borrow lifetime holds.
765    ///
766    /// Return-form axis: `Option<&str>` mirrors the existing
767    /// borrow-first discipline every pre-lift consumer already
768    /// re-borrowed through `.as_str()` before use, and the shape of
769    /// [`Self::coordinates_or_none`]'s `Option<(&str, &str)>`
770    /// projection extends mechanically to the single-slot
771    /// projection here. The missing-`status` corner AND the
772    /// populated-status-with-`pid=None` corner BOTH collapse to
773    /// `None` so `.is_some()` / `if let Some(_)` / `.map(...)`
774    /// behave identically on a `Process` whose status is `None`
775    /// and on one whose status carries an unpopulated `pid` slot —
776    /// matching what the pre-lift `.and_then(...)` chain produced.
777    ///
778    /// A future normalization step (a per-slot canonicalization
779    /// pass that rejects malformed hierarchical PIDs, a
780    /// generation-filter that returns `None` for a PID stamped
781    /// with a stale `metadata.generation`, a staleness gate that
782    /// drops a PID whose observing `phase_since` predates a
783    /// reconcile deadline) lands at ONE substrate method here and
784    /// both downstream consumers pick up the upgrade mechanically
785    /// — no per-callsite hand-edit at `handle_forking` /
786    /// `handle_exiting`.
787    ///
788    /// Sibling to the peer [`Self::observed_flux_resources`]
789    /// borrow-first primitive on the flux-resources axis; both
790    /// methods compose the same missing-`status` fallback +
791    /// borrow-form return-shape skeleton on distinct
792    /// `ProcessStatus` slots. Future status projections
793    /// (`observed_parent` on the parent-pointer axis,
794    /// `observed_message` on the human-readable-status axis,
795    /// `observed_attestation` on the attestation-chain axis) land
796    /// as peer methods on this same axis.
797    ///
798    /// Theory anchor: THEORY.md §VI.1 (generation over
799    /// composition — the 3-line status-projection chain recurred
800    /// at two hand-authored sites past the ★★ PRIME-DIRECTIVE ≥ 2
801    /// duplication trigger, and is lifted to ONE owner here).
802    /// THEORY.md §II.1 invariant 5 (composition preserves proofs —
803    /// the pins bind the missing-`status` corner + the empty-slot
804    /// corner + the borrow-form `&str` lifetime + the
805    /// byte-identical parity with the pre-lift 3-line chain, so a
806    /// regression that drifted any surface at
807    /// `tests::observed_pid_*` rather than as silent operator-
808    /// facing skew between the ALLOCATE-PID gate and the SIGTERM
809    /// cascade on the SAME `Process`).
810    pub fn observed_pid(&self) -> Option<&str> {
811        self.status.as_ref().and_then(|s| s.pid.as_deref())
812    }
813
814    /// The borrow-form status-projection primitive on the
815    /// attestation-chain axis: returns the last
816    /// [`ProcessAttestation`] the reconciler persisted at
817    /// `status.attestation`, with the missing-`status` corner AND the
818    /// empty-slot corner BOTH collapsed to `None` — the ONE-liner
819    /// collapse of the paired `self.status.as_ref().and_then(|s|
820    /// s.attestation.as_ref())` incantation every consumer restated
821    /// by hand pre-lift.
822    ///
823    /// Pre-lift the 3-line `.status.as_ref().and_then(|s| s
824    /// .attestation.as_ref())` chain was hand-authored at TWO sites
825    /// past the ★★ PRIME-DIRECTIVE ≥ 2 duplication threshold in
826    /// `tatara-reconciler`:
827    /// * `phase_machine::advance_to_attested` — the ATTEST composer
828    ///   that chains `prior.next(pillars)` when a prior attestation
829    ///   is persisted and seeds with `ProcessAttestation::initial`
830    ///   otherwise.
831    /// * `render::render_export_jobs` — the ephemeral-export Job
832    ///   builder that pulls the prior `composed_root` off the last
833    ///   persisted attestation and threads it into every rendered
834    ///   Job's `previousRoot` env var, so the export receipt chains
835    ///   into the Process's BLAKE3 attestation tree at the correct
836    ///   generation boundary.
837    ///
838    /// Both sites walked the SAME 3-line chain — the borrow-form
839    /// `Option<&ProcessAttestation>` shape both consumers wanted
840    /// already — even though neither site ever mutated the
841    /// attestation nor kept it alive past the enclosing async fn.
842    /// Post-lift both callers borrow the attestation directly from
843    /// `self.status`; the pre-lift 3-line chain shrinks to a single
844    /// method call at both sites, and both consumers' subsequent
845    /// downstream calls (`ProcessAttestation::next` for the ATTEST
846    /// composer, `.composed_root.clone()` for the export Job builder)
847    /// do not touch the borrowed `p: &Process`, so the borrow
848    /// lifetime holds.
849    ///
850    /// Return-form axis: `Option<&ProcessAttestation>` mirrors the
851    /// existing borrow-first discipline every pre-lift consumer
852    /// already re-borrowed through `.as_ref()`, and the shape of the
853    /// peer [`Self::observed_pid`] projection extends mechanically
854    /// to the whole-attestation-record projection here. The missing-
855    /// `status` corner AND the populated-status-with-`attestation
856    /// =None` corner BOTH collapse to `None` so `.is_some()` / `if
857    /// let Some(_)` / `.map(...)` behave identically on a `Process`
858    /// whose status is `None` and on one whose status carries an
859    /// unpopulated `attestation` slot — matching what the pre-lift
860    /// `.and_then(...)` chain produced.
861    ///
862    /// A future normalization step (a per-slot canonicalization pass
863    /// that rejects a persisted attestation whose `composed_root`
864    /// fails `verify`, a generation-filter that returns `None` for
865    /// an attestation stamped with a stale `metadata.generation`, a
866    /// staleness gate that drops an attestation whose `attested_at`
867    /// predates a reconcile deadline) lands at ONE substrate method
868    /// here and both downstream consumers pick up the upgrade
869    /// mechanically — no per-callsite hand-edit at
870    /// `advance_to_attested` / `render_export_jobs`.
871    ///
872    /// Sibling to the peer [`Self::observed_pid`] +
873    /// [`Self::observed_flux_resources`] borrow-first primitives on
874    /// the PID + flux-resources axes; all three methods compose the
875    /// same missing-`status` fallback + borrow-form return-shape
876    /// skeleton on distinct `ProcessStatus` slots. Future status
877    /// projections (`observed_parent` on the parent-pointer axis,
878    /// `observed_message` on the human-readable-status axis) land
879    /// as peer methods on this same axis.
880    ///
881    /// Theory anchor: THEORY.md §VI.1 (generation over composition
882    /// — the 3-line status-projection chain recurred at two hand-
883    /// authored sites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication
884    /// trigger, and is lifted to ONE owner here). THEORY.md §II.1
885    /// invariant 5 (composition preserves proofs — the pins bind
886    /// the missing-`status` corner + the empty-slot corner + the
887    /// borrow-form `&ProcessAttestation` lifetime + the byte-
888    /// identical parity with the pre-lift 3-line chain, so a
889    /// regression that drifted any surface at
890    /// `tests::observed_attestation_*` rather than as silent
891    /// operator-facing skew between the ATTEST composer and the
892    /// ephemeral-export receipt chain on the SAME `Process`).
893    pub fn observed_attestation(&self) -> Option<&ProcessAttestation> {
894        self.status.as_ref().and_then(|s| s.attestation.as_ref())
895    }
896
897    /// The borrow-form status-projection primitive on the resolved-
898    /// identity axis: returns the [`Identity`] the reconciler
899    /// currently persists at `status.identity` (name + content hash +
900    /// override flag), with the missing-`status` corner AND the
901    /// empty-slot corner BOTH collapsed to `None` — the ONE-liner
902    /// collapse of the paired `self.status.as_ref().and_then(|s|
903    /// s.identity.as_ref())` incantation every consumer restated by
904    /// hand pre-lift.
905    ///
906    /// Pre-lift the paired `.status.as_ref().and_then(|s|
907    /// s.identity.<clone|as_ref>())` chain was hand-authored at TWO
908    /// sites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication threshold
909    /// in `tatara-reconciler`:
910    /// * `phase_machine::handle_forking` — the FORK-time identity
911    ///   seed that reuses the reconciler-persisted `Identity` if
912    ///   present and falls back to a fresh `derive_identity(&spec,
913    ///   name_override)` otherwise. Pre-lift the site cloned the
914    ///   whole `Identity` off the borrow before threading it through
915    ///   `.unwrap_or_else(...)` even though the fallback path
916    ///   allocates its own owned `Identity` — the pre-lift clone
917    ///   allocated a fresh `Identity` on the happy path just so the
918    ///   `Option`'s shape matched the fallback's `Identity` return
919    ///   type.
920    /// * `ssapply::inject_annotations` — the SSA-time annotation
921    ///   composer that stamps the content-hash annotation onto every
922    ///   owned resource. Pre-lift the site nested the identity
923    ///   borrow-form check inside a manual `if let Some(status) =
924    ///   &process.status { … }` guard alongside sibling `status.pid`
925    ///   and `status.attestation` accesses — three siblings the peer
926    ///   primitives [`Self::observed_pid`] and
927    ///   [`Self::observed_attestation`] already own, so the outer
928    ///   status guard was the last hand-authored `.status.as_ref()`
929    ///   destructure at this composer.
930    ///
931    /// Both sites walked the SAME 3-line chain (one via `.clone()`,
932    /// one via `.as_ref()`) — the borrow-form
933    /// `Option<&Identity>` shape both consumers wanted already, even
934    /// though the FORK-time seed then had to `.clone()` off the
935    /// borrow to compose with the owned-`Identity` fallback. Post-
936    /// lift the seed calls `.observed_identity().cloned()` at the
937    /// exact composition point where the owned value is required
938    /// (the empty-borrow corner clones nothing, since
939    /// `Option::cloned` on `None` is `None`), and the SSA-time
940    /// consumer drops the outer status guard entirely — the
941    /// three-sibling primitive family (pid + identity + attestation)
942    /// now peers through `observed_pid` +
943    /// `observed_identity` + `observed_attestation` at ONE call each
944    /// with no shared status destructure between them.
945    ///
946    /// Return-form axis: `Option<&Identity>` mirrors the
947    /// existing borrow-first discipline every pre-lift consumer
948    /// already re-borrowed through `.as_ref()` / re-cloned through
949    /// `.clone()`, and the shape of the peer
950    /// [`Self::observed_attestation`] projection extends
951    /// mechanically to the whole-`Identity`-record projection here.
952    /// The missing-`status` corner AND the populated-status-with-
953    /// `identity=None` corner BOTH collapse to `None` so
954    /// `.is_some()` / `if let Some(_)` / `.map(...)` behave
955    /// identically on a `Process` whose status is `None` and on one
956    /// whose status carries an unpopulated `identity` slot —
957    /// matching what the pre-lift `.and_then(...)` chain produced.
958    ///
959    /// A future normalization step (a per-slot canonicalization
960    /// pass that rejects an `Identity` whose `content_hash` fails
961    /// re-derivation against the current spec, a generation-filter
962    /// that returns `None` for an identity stamped with a stale
963    /// `metadata.generation`, a staleness gate that drops an
964    /// identity whose observing `phase_since` predates a reconcile
965    /// deadline) lands at ONE substrate method here and both
966    /// downstream consumers pick up the upgrade mechanically — no
967    /// per-callsite hand-edit at `handle_forking` /
968    /// `inject_annotations`.
969    ///
970    /// Sibling to the peer [`Self::observed_pid`] +
971    /// [`Self::observed_attestation`] +
972    /// [`Self::observed_flux_resources`] borrow-first primitives on
973    /// the PID + attestation-chain + flux-resources axes; all four
974    /// methods compose the same missing-`status` fallback +
975    /// borrow-form return-shape skeleton on distinct `ProcessStatus`
976    /// slots. Future status projections (`observed_parent` on the
977    /// parent-pointer axis, `observed_message` on the human-
978    /// readable-status axis) land as peer methods on this same
979    /// axis.
980    ///
981    /// Theory anchor: THEORY.md §VI.1 (generation over composition
982    /// — the 3-line status-projection chain recurred at two hand-
983    /// authored sites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication
984    /// trigger, and is lifted to ONE owner here). THEORY.md §II.1
985    /// invariant 5 (composition preserves proofs — the pins bind
986    /// the missing-`status` corner + the empty-slot corner + the
987    /// borrow-form `&Identity` lifetime + the byte-identical parity
988    /// with the pre-lift 3-line chain, so a regression that drifted
989    /// any surface at `tests::observed_identity_*` rather than as
990    /// silent operator-facing skew between the FORK-time identity
991    /// seed and the SSA-time content-hash annotation stamp on the
992    /// SAME `Process`).
993    pub fn observed_identity(&self) -> Option<&Identity> {
994        self.status.as_ref().and_then(|s| s.identity.as_ref())
995    }
996
997    /// The copy-form status-projection primitive on the phase axis:
998    /// returns the [`ProcessPhase`] the reconciler currently persists
999    /// at `status.phase`, wrapped in an `Option` so the missing-
1000    /// `status` corner collapses to `None` — the ONE-liner collapse
1001    /// of the paired `self.status.as_ref().map(|s| s.phase)`
1002    /// incantation every consumer restated by hand pre-lift.
1003    ///
1004    /// Peer to the borrow-form projections
1005    /// [`Self::observed_pid`] (PID axis, `Option<&str>`),
1006    /// [`Self::observed_flux_resources`] (flux-resources axis,
1007    /// `&[FluxResourceRef]`), and [`Self::observed_attestation`]
1008    /// (attestation-chain axis, `Option<&ProcessAttestation>`); this
1009    /// method opens the copy-form peer for `ProcessPhase` — a
1010    /// `Copy` scalar with a `Default` impl (`Pending`), so the
1011    /// return is `Option<ProcessPhase>` rather than
1012    /// `Option<&ProcessPhase>` (borrow would give the caller
1013    /// nothing over the copy for a 1-byte enum) and neither the
1014    /// missing-`status` corner nor a "empty slot" corner is
1015    /// meaningful — the underlying slot is a bare `ProcessPhase`,
1016    /// not `Option<ProcessPhase>`, so the primitive returns `None`
1017    /// iff `status: None`.
1018    ///
1019    /// Pre-lift the 3-line `.status.as_ref().map(|s| s.phase)`
1020    /// chain was hand-authored at FIVE sites past the ★★
1021    /// PRIME-DIRECTIVE ≥ 2 duplication threshold in
1022    /// `tatara-reconciler`:
1023    /// * `controller::reconcile` — the top-level dispatcher's
1024    ///   `current_phase` seed that feeds the deletion-preempt +
1025    ///   signal-ingestion gates + the per-phase handler dispatch.
1026    ///   Pre-lift `.unwrap_or(ProcessPhase::Pending)`.
1027    /// * `boundary::evaluate_process_phase` — the boundary
1028    ///   evaluator's `ProcessPhase` condition (a peer-Process
1029    ///   `phase`-reached postcondition). Pre-lift
1030    ///   `.unwrap_or(ProcessPhase::Pending)`.
1031    /// * `boundary::check_depends_on` — the `depends_on`
1032    ///   pre-condition audit that stashes the observed phase into
1033    ///   the `UnmetDependency::actual: Option<ProcessPhase>` slot
1034    ///   (keeps the `Option` form). Pre-lift the raw
1035    ///   `.map(|s| s.phase)` shape.
1036    /// * `phase_machine::p_current_phase_str` — the released-from
1037    ///   annotation composer that emits `"Attested"` for every
1038    ///   non-`Failed` phase (SIGSTOP/SIGCONT release gate).
1039    ///   Pre-lift `.unwrap_or(ProcessPhase::Attested)` — the ONE
1040    ///   site whose default is not `Pending`; the primitive
1041    ///   returns the raw `Option` so the caller's `.unwrap_or`
1042    ///   default choice stays local rather than baked in.
1043    /// * `table_controller::stable_name_group_key` — the routing-
1044    ///   groupby seed that pairs the phase with the PID + creation
1045    ///   timestamp when partitioning Processes claiming the same
1046    ///   stable name. Pre-lift `.unwrap_or(ProcessPhase::Pending)`.
1047    ///
1048    /// All FIVE sites walked the SAME 3-line `.status.as_ref()
1049    /// .map(|s| s.phase)` chain — three closed with `unwrap_or
1050    /// (ProcessPhase::Pending)` (the `Default`), one closed with
1051    /// `unwrap_or(ProcessPhase::Attested)`, one kept the raw
1052    /// `Option<ProcessPhase>` — so the ONE substrate accessor
1053    /// returns the raw `Option<ProcessPhase>` and each consumer
1054    /// keeps its `.unwrap_or(...)` default choice at its own site.
1055    ///
1056    /// A future normalization step (a generation-filter that
1057    /// returns `None` for a phase stamped with a stale
1058    /// `metadata.generation`, a staleness gate that drops a phase
1059    /// whose observing `phase_since` predates a reconcile
1060    /// deadline, a canonicalization pass that maps a phase that
1061    /// no longer belongs to the CRD's closed set to `None`) lands
1062    /// at ONE substrate method here and all five consumers pick
1063    /// up the upgrade mechanically — no per-callsite hand-edit at
1064    /// `reconcile` / `evaluate_process_phase` / `check_depends_on`
1065    /// / `p_current_phase_str` / `stable_name_group_key`.
1066    ///
1067    /// Future status projections (`observed_parent` on the
1068    /// parent-pointer axis, `observed_message` on the human-
1069    /// readable-status axis, `observed_children` on the child
1070    /// fan-out axis, `observed_exit_code` on the terminal-exit
1071    /// axis) land as peer methods on this same axis.
1072    ///
1073    /// Theory anchor: THEORY.md §VI.1 (generation over
1074    /// composition — the 3-line status-projection chain recurred
1075    /// at FIVE hand-authored sites past the ★★ PRIME-DIRECTIVE
1076    /// ≥ 2 duplication trigger, and is lifted to ONE owner here).
1077    /// THEORY.md §II.1 invariant 5 (composition preserves proofs
1078    /// — the pins bind the missing-`status` corner + the
1079    /// per-variant enum round-trip + the byte-identical parity
1080    /// with the pre-lift 3-line chain, so a regression that
1081    /// drifted any surface at `tests::observed_phase_*` rather
1082    /// than as silent operator-facing skew between the
1083    /// controller's dispatch seed and the boundary evaluator's
1084    /// depends-on audit on the SAME `Process` within one
1085    /// reconcile pass).
1086    pub fn observed_phase(&self) -> Option<ProcessPhase> {
1087        self.status.as_ref().map(|s| s.phase)
1088    }
1089
1090    /// Copy-form metadata-projection primitive on the deletion-tombstone
1091    /// axis: returns `true` iff the K8s API server has stamped a
1092    /// `metadata.deletionTimestamp` on this Process (the moment the
1093    /// object entered the "being deleted" corner of its lifecycle,
1094    /// after which further mutating writes are refused and finalizers
1095    /// are drained before the object is actually removed) — the ONE-
1096    /// liner collapse of the paired `self.metadata.deletion_timestamp
1097    /// .is_some()` incantation every consumer restated by hand
1098    /// pre-lift.
1099    ///
1100    /// Pre-lift the `.metadata.deletion_timestamp.is_some()` chain
1101    /// was hand-authored at TWO sites past the ★★ PRIME-DIRECTIVE
1102    /// ≥ 2 duplication threshold in `tatara-reconciler`, both
1103    /// projecting the SAME tombstone-presence predicate on a
1104    /// `Process` value:
1105    /// * `controller::reconcile` — the top-level dispatcher's
1106    ///   deletion-preempt gate that forces the SIGTERM cascade
1107    ///   (`→ Exiting`) as soon as the API server stamps the
1108    ///   tombstone, before the phase handler for the current
1109    ///   [`ProcessPhase`] gets a chance to run. Composed with
1110    ///   [`ProcessPhase::is_alive`] so the preempt only fires on a
1111    ///   Process still in an alive phase — a Process already in
1112    ///   `Zombie` / `Reaped` / `Failed` runs its normal handler.
1113    /// * `phase_machine::handle_exiting` — the SIGTERM cascade's
1114    ///   child-fan-out loop that enumerates every child Process and
1115    ///   skips ones the API server has already tombstoned (so the
1116    ///   reconciler does not re-issue a `DELETE` against a child
1117    ///   whose deletion the API server is already draining through
1118    ///   its own finalizer). The skip composes with
1119    ///   [`Self::coordinates_or_none`]'s name-required probe so a
1120    ///   child missing either its tombstone-absent gate or its
1121    ///   `metadata.name` slot is a clean `continue` rather than an
1122    ///   attempted `child_api.delete("")` no-op.
1123    ///
1124    /// Both sites walked the SAME `.metadata.deletion_timestamp
1125    /// .is_some()` chain and both wanted the `bool` form the
1126    /// primitive returns — the `controller::reconcile` site to gate
1127    /// the SIGTERM preempt with `&& current_phase.is_alive()` and
1128    /// the `handle_exiting` site to gate the DELETE-skip with a
1129    /// bare `if child.is_being_deleted() { continue; }`. Post-lift
1130    /// each callsite reads `process.is_being_deleted()` and the
1131    /// produced `bool` feeds the same downstream gate unchanged.
1132    ///
1133    /// Return-form axis: `bool` matches the copy-form discipline of
1134    /// [`Self::observed_phase`] (an `Option<Copy>` scalar) — the
1135    /// underlying slot is a wire-format `Option<Time>` that carries
1136    /// only presence information at this axis (the RFC-3339 timestamp
1137    /// payload itself is not what the two consumers read; both only
1138    /// probe presence to detect the tombstone-stamped state).
1139    /// Returning the raw `Option<&Time>` would push the `.is_some()`
1140    /// probe back to every callsite, restating the pre-lift chain
1141    /// one link shorter without collapsing the primitive.
1142    ///
1143    /// Peer to the metadata-fallback primitives
1144    /// [`Self::namespace_or_default`], [`Self::name_or_placeholder`],
1145    /// [`Self::uid_or_empty`], [`Self::coordinates_or_defaults`],
1146    /// [`Self::coordinates_or_none`], [`Self::owned_coordinates_or_err`],
1147    /// [`Self::annotation`] on the metadata axis; this method opens
1148    /// the copy-form peer for the presence-probe corner. Future
1149    /// metadata-presence projections (an `is_being_finalized`
1150    /// projection on `metadata.finalizers.is_empty()`'s negation,
1151    /// a `has_owner` projection on `metadata.owner_references.is_empty()`'s
1152    /// negation) land as peer methods on this same axis.
1153    ///
1154    /// A future normalization step (a per-tombstone staleness gate
1155    /// that returns `false` for a tombstone older than the reconciler's
1156    /// grace-period budget, a canonicalization pass that treats a
1157    /// tombstone from a paused controller as absent, a cross-cluster
1158    /// tombstone-observation clock skew guard) lands at ONE substrate
1159    /// method here and both downstream consumers pick up the upgrade
1160    /// mechanically — no per-callsite hand-edit at
1161    /// `controller::reconcile` / `phase_machine::handle_exiting`.
1162    ///
1163    /// Theory anchor: THEORY.md §VI.1 (generation over composition —
1164    /// the `.metadata.deletion_timestamp.is_some()` chain recurred at
1165    /// two hand-authored sites past the ★★ PRIME-DIRECTIVE ≥ 2
1166    /// duplication trigger, and is lifted to ONE owner here).
1167    /// THEORY.md §II.1 invariant 5 (composition preserves proofs —
1168    /// the pins bind the missing-tombstone corner + the present-
1169    /// tombstone corner + the copy-form `bool` return + the byte-
1170    /// identical parity with the pre-lift `.is_some()` chain, so a
1171    /// regression that drifted any surface at
1172    /// `tests::is_being_deleted_*` rather than as silent operator-
1173    /// facing skew between the top-level dispatcher's SIGTERM
1174    /// preempt and the SIGTERM cascade's child-fan-out DELETE-skip
1175    /// on the SAME `Process` within one reconcile pass).
1176    pub fn is_being_deleted(&self) -> bool {
1177        self.metadata.deletion_timestamp.is_some()
1178    }
1179
1180    /// Copy-form metadata-projection primitive on the
1181    /// `metadata.creationTimestamp` axis: returns the K8s-API-server-
1182    /// assigned creation moment as a `DateTime<Utc>`, hiding the wire-
1183    /// format `k8s_openapi::apimachinery::pkg::apis::meta::v1::Time`
1184    /// newtype behind an inherent projection — the ONE-liner collapse
1185    /// of the paired `self.metadata.creation_timestamp.as_ref().map(|t|
1186    /// t.0)` incantation every timestamp-driven consumer restated by
1187    /// hand pre-lift.
1188    ///
1189    /// Pre-lift the paired `.metadata.creation_timestamp.as_ref()` +
1190    /// `t.0` unwrap chain was hand-authored at THREE sites past the
1191    /// ★★ PRIME-DIRECTIVE ≥ 2 duplication threshold across the
1192    /// workspace, all projecting the SAME creation-moment `DateTime<Utc>`
1193    /// on a `Process`:
1194    /// * `tatara-process::lifetime_clock::evaluate` — TTL-expiry gate
1195    ///   in the ephemeral-lifetime decision (`elapsed = now
1196    ///   .signed_duration_since(creation.0)`), inside the non-terminal-
1197    ///   phase guard that fires the `AutoTerminate::Now { TtlExpired }`
1198    ///   branch. Pre-lift the site read `if let Some(creation) = process
1199    ///   .metadata.creation_timestamp.as_ref() { ... creation.0 ... }`.
1200    /// * `tatara-process::lifetime_clock::requeue_with_ttl` — sleep-
1201    ///   budget picker for the reconciler's next requeue, choosing the
1202    ///   smaller of HEARTBEAT and TTL-remaining so the reconciler
1203    ///   doesn't oversleep past a TTL boundary. Pre-lift the site read
1204    ///   `let Some(creation) = process.metadata.creation_timestamp
1205    ///   .as_ref() else { return default; };` + `creation.0`.
1206    /// * `tatara-reconciler::table_controller::reconcile_process_table`
1207    ///   — stable-name claim-arbiter row builder, seeding each
1208    ///   candidate row's `created_at` for the tie-break ordering
1209    ///   (oldest wins). Pre-lift the site read `p.metadata
1210    ///   .creation_timestamp.as_ref().map(|t| t.0).unwrap_or_else(Utc
1211    ///   ::now)`.
1212    ///
1213    /// All THREE sites walked the SAME two-link chain — read the
1214    /// `Option<Time>` slot as a borrow, then unwrap the `Time` newtype
1215    /// to its inner `DateTime<Utc>` — differing only in the tail
1216    /// (`if-let-Some` guard, `let-else` short-circuit, `Utc::now`
1217    /// fallback). Post-lift each callsite reads
1218    /// `process.created_at()` and applies its own tail at its own site
1219    /// (`if let Some(creation) = ...`, `let Some(creation) = ... else`,
1220    /// `.unwrap_or_else(Utc::now)`).
1221    ///
1222    /// Return-form axis: `Option<DateTime<Utc>>` matches the copy-form
1223    /// discipline of the sibling status-projection primitive
1224    /// [`Self::observed_phase`] — both return `Option<T>` where `T:
1225    /// Copy` and hide the wire-format wrapper (`ProcessStatus` on the
1226    /// status side; `Time` on the metadata side). Returning the raw
1227    /// `Option<&Time>` would push the `.0` unwrap back to every
1228    /// callsite, restating the pre-lift chain one link shorter without
1229    /// collapsing the primitive; returning owned `Option<Time>` would
1230    /// force a `Time` import at every consumer for a projection every
1231    /// consumer immediately discards past `.0`.
1232    ///
1233    /// Peer to the metadata-fallback + presence-probe primitives
1234    /// [`Self::namespace_or_default`], [`Self::name_or_placeholder`],
1235    /// [`Self::uid_or_empty`], [`Self::coordinates_or_defaults`],
1236    /// [`Self::coordinates_or_none`], [`Self::owned_coordinates_or_err`],
1237    /// [`Self::annotation`], [`Self::is_being_deleted`] on the metadata
1238    /// axis; this method opens the copy-form timestamp corner. Future
1239    /// metadata-timestamp projections (a
1240    /// `deletion_at() -> Option<DateTime<Utc>>` peer on the
1241    /// tombstone-payload axis for staleness gates that need the
1242    /// timestamp value alongside the presence bit) land as peer
1243    /// methods on this same axis.
1244    ///
1245    /// A future normalization step (a per-cluster clock-skew guard
1246    /// that offsets the returned timestamp by the observing controller's
1247    /// measured skew, a canonicalization pass that maps a suspiciously-
1248    /// zero creation moment to `None`, a per-namespace override that
1249    /// substitutes a `spec.identity`-declared creation anchor for the
1250    /// metadata slot on adopted resources) lands at ONE substrate
1251    /// method here and all three downstream consumers pick up the
1252    /// upgrade mechanically — no per-callsite hand-edit at `evaluate`
1253    /// / `requeue_with_ttl` / `reconcile_process_table`.
1254    ///
1255    /// Theory anchor: THEORY.md §VI.1 (generation over composition —
1256    /// the `.metadata.creation_timestamp.as_ref().map(|t| t.0)` chain
1257    /// recurred at three hand-authored sites past the ★★
1258    /// PRIME-DIRECTIVE ≥ 2 duplication trigger, and is lifted to ONE
1259    /// owner here). THEORY.md §II.1 invariant 5 (composition preserves
1260    /// proofs — the pins bind the missing-timestamp corner + the
1261    /// present-timestamp corner + the copy-form `DateTime<Utc>` return
1262    /// + the byte-identical parity with the pre-lift `.as_ref().map(|t|
1263    /// t.0)` chain, so a regression that drifted any surface at
1264    /// `tests::created_at_*` rather than as silent operator-facing
1265    /// skew between the TTL-expiry gate, the requeue-budget picker,
1266    /// and the stable-name claim-arbiter tie-break on the SAME
1267    /// `Process` within one reconcile pass).
1268    pub fn created_at(&self) -> Option<DateTime<Utc>> {
1269        self.metadata.creation_timestamp.as_ref().map(|t| t.0)
1270    }
1271}
1272
1273/// Process status — every field optional until the reconciler writes it.
1274#[derive(Clone, Debug, Default, Deserialize, Serialize, JsonSchema)]
1275#[serde(rename_all = "camelCase")]
1276pub struct ProcessStatus {
1277    /// Hierarchical PID path — e.g., `"seph.1.7"`.
1278    #[serde(default, skip_serializing_if = "Option::is_none")]
1279    pub pid: Option<String>,
1280
1281    /// Parent PID path (mirror of `spec.identity.parent`, resolved at fork).
1282    #[serde(default, skip_serializing_if = "Option::is_none")]
1283    pub parent: Option<String>,
1284
1285    /// Direct children's PID paths.
1286    #[serde(default)]
1287    pub children: Vec<String>,
1288
1289    /// Resolved identity (name + content hash).
1290    #[serde(default, skip_serializing_if = "Option::is_none")]
1291    pub identity: Option<Identity>,
1292
1293    /// Current phase.
1294    #[serde(default)]
1295    pub phase: ProcessPhase,
1296
1297    /// When the process entered the current phase.
1298    #[serde(default, skip_serializing_if = "Option::is_none")]
1299    pub phase_since: Option<DateTime<Utc>>,
1300
1301    /// Three-pillar attestation (written at end of every successful cycle).
1302    #[serde(default, skip_serializing_if = "Option::is_none")]
1303    pub attestation: Option<ProcessAttestation>,
1304
1305    /// FluxCD resources currently owned by this Process.
1306    #[serde(default)]
1307    pub flux_resources: Vec<FluxResourceRef>,
1308
1309    /// Boundary verification state.
1310    #[serde(default)]
1311    pub boundary: BoundaryStatus,
1312
1313    /// Compliance summary at the latest attestation.
1314    #[serde(default)]
1315    pub compliance: ComplianceStatus,
1316
1317    /// Pending signals (delivered, not yet handled).
1318    #[serde(default)]
1319    pub signal_queue: Vec<ProcessSignal>,
1320
1321    /// Standard K8s Conditions.
1322    #[serde(default)]
1323    pub conditions: Vec<ProcessCondition>,
1324
1325    /// Human-readable last status message.
1326    #[serde(default, skip_serializing_if = "Option::is_none")]
1327    pub message: Option<String>,
1328
1329    /// Exit code (only set on Failed / Reaped).
1330    #[serde(default, skip_serializing_if = "Option::is_none")]
1331    pub exit_code: Option<i32>,
1332}
1333
1334#[cfg(test)]
1335mod tests {
1336    use super::*;
1337    use crate::classification::{ConvergencePointType, SubstrateType};
1338    use crate::intent::NixIntent;
1339
1340    #[test]
1341    fn minimal_spec_serializes() {
1342        let spec = ProcessSpec {
1343            identity: IdentitySpec::default(),
1344            classification: Classification {
1345                point_type: ConvergencePointType::Gate,
1346                substrate: SubstrateType::Observability,
1347                horizon: Default::default(),
1348                calm: Default::default(),
1349                data_classification: Default::default(),
1350            },
1351            intent: Intent {
1352                nix: Some(NixIntent {
1353                    flake_ref: "github:pleme-io/k8s".into(),
1354                    attribute: "obs".into(),
1355                    system: None,
1356                    attic_cache: None,
1357                    extra_args: vec![],
1358                    delegate_to_nix_build: false,
1359                }),
1360                ..Intent::default()
1361            },
1362            boundary: Default::default(),
1363            compliance: Default::default(),
1364            depends_on: vec![],
1365            signals: Default::default(),
1366            lifetime: Default::default(),
1367            routing: None,
1368            encapsulates: None,
1369            suspended: false,
1370        };
1371        let yaml = serde_yaml::to_string(&spec).unwrap();
1372        assert!(yaml.contains("pointType: Gate"));
1373        assert!(yaml.contains("substrate: Observability"));
1374        assert!(yaml.contains("flakeRef: github:pleme-io/k8s"));
1375    }
1376
1377    // ─── Process::coordinates_or_defaults substrate pins ────────────────
1378    //
1379    // Pins the (namespace, name) coordinate-primitive family on the
1380    // (metadata slot × fallback shape) axis. Fail-before-pass-after
1381    // granularity: a regression that flipped either fallback string,
1382    // swapped the return-tuple axis order, or dropped the
1383    // `Option::as_deref` unwrap surfaces here rather than as silent
1384    // drift at every downstream annotation writer / claim-arbiter row
1385    // builder / render owner-metadata seed.
1386
1387    fn empty_spec() -> ProcessSpec {
1388        ProcessSpec {
1389            identity: IdentitySpec::default(),
1390            classification: Classification {
1391                point_type: ConvergencePointType::Gate,
1392                substrate: SubstrateType::Compute,
1393                horizon: Default::default(),
1394                calm: Default::default(),
1395                data_classification: Default::default(),
1396            },
1397            intent: Intent::default(),
1398            boundary: Default::default(),
1399            compliance: Default::default(),
1400            depends_on: vec![],
1401            signals: Default::default(),
1402            lifetime: Default::default(),
1403            routing: None,
1404            encapsulates: None,
1405            suspended: false,
1406        }
1407    }
1408
1409    #[test]
1410    fn default_namespace_constant_is_k8s_canonical_default() {
1411        // Pins the load-bearing convention that this primitive's
1412        // namespace fallback matches K8s's own implicit-namespace
1413        // spelling. A regression that renamed this to "kube-system"
1414        // or any other K8s-reserved name would silently misroute
1415        // every downstream namespaced-Api call on a Process without
1416        // a metadata.namespace.
1417        assert_eq!(Process::DEFAULT_NAMESPACE, "default");
1418    }
1419
1420    #[test]
1421    fn unnamed_placeholder_constant_matches_prior_annotation_writer_fallback() {
1422        // Pins the load-bearing convention that this primitive's name
1423        // fallback matches the exact spelling every annotation writer
1424        // (tatara-reconciler::ssapply::inject_annotations,
1425        // tatara-reconciler::render::render, and
1426        // tatara-reconciler::table_controller's claim-row builder)
1427        // was hand-authoring pre-lift ("unnamed", NOT "<unnamed>" or
1428        // ""). A regression that renamed this would break the
1429        // annotation-writer / claim-arbiter grep contract silently.
1430        assert_eq!(Process::UNNAMED_PLACEHOLDER, "unnamed");
1431    }
1432
1433    #[test]
1434    fn namespace_or_default_falls_back_when_metadata_namespace_is_none() {
1435        let mut p = Process::new("some-proc", empty_spec());
1436        p.metadata.namespace = None;
1437        assert_eq!(p.namespace_or_default(), Process::DEFAULT_NAMESPACE);
1438    }
1439
1440    #[test]
1441    fn namespace_or_default_returns_metadata_slice_when_some() {
1442        let mut p = Process::new("some-proc", empty_spec());
1443        p.metadata.namespace = Some("prod-app".into());
1444        assert_eq!(p.namespace_or_default(), "prod-app");
1445    }
1446
1447    #[test]
1448    fn name_or_placeholder_falls_back_when_metadata_name_is_none() {
1449        let mut p = Process::new("real-name", empty_spec());
1450        p.metadata.name = None;
1451        assert_eq!(p.name_or_placeholder(), Process::UNNAMED_PLACEHOLDER);
1452    }
1453
1454    #[test]
1455    fn name_or_placeholder_returns_metadata_slice_when_some() {
1456        let p = Process::new("api-gateway", empty_spec());
1457        assert_eq!(p.name_or_placeholder(), "api-gateway");
1458    }
1459
1460    #[test]
1461    fn coordinates_or_defaults_composes_both_halves() {
1462        // Both slots present — returns metadata slices in
1463        // (namespace, name) axis order.
1464        let mut p = Process::new("api", empty_spec());
1465        p.metadata.namespace = Some("staging".into());
1466        assert_eq!(p.coordinates_or_defaults(), ("staging", "api"));
1467    }
1468
1469    #[test]
1470    fn coordinates_or_defaults_falls_back_on_both_slots() {
1471        // Both slots None — returns (DEFAULT_NAMESPACE,
1472        // UNNAMED_PLACEHOLDER) in axis order.
1473        let mut p = Process::new("scratch", empty_spec());
1474        p.metadata.name = None;
1475        p.metadata.namespace = None;
1476        assert_eq!(
1477            p.coordinates_or_defaults(),
1478            (Process::DEFAULT_NAMESPACE, Process::UNNAMED_PLACEHOLDER)
1479        );
1480    }
1481
1482    #[test]
1483    fn coordinates_or_defaults_mixes_slotted_and_fallback_halves() {
1484        // Namespace set, name missing — the (namespace, name) tuple
1485        // pins each half independently. A regression that returned
1486        // BOTH fallbacks when EITHER metadata slot was None would
1487        // surface here rather than at every downstream reader.
1488        let mut p = Process::new("kept-name", empty_spec());
1489        p.metadata.namespace = Some("prod".into());
1490        assert_eq!(p.coordinates_or_defaults(), ("prod", "kept-name"));
1491
1492        // Name set, namespace missing — the peer corner.
1493        let mut q = Process::new("api", empty_spec());
1494        q.metadata.namespace = None;
1495        assert_eq!(
1496            q.coordinates_or_defaults(),
1497            (Process::DEFAULT_NAMESPACE, "api")
1498        );
1499    }
1500
1501    // ─── Process::owned_coordinates_or_err substrate pins ──────────────
1502    //
1503    // Pins the owned + name-required peer of the coordinate-primitive
1504    // family on the (return-form × name gate) axis pair. Fail-before-
1505    // pass-after granularity: a regression that flipped the namespace
1506    // fallback string, dropped the `Option::clone` unwrap, changed the
1507    // return-tuple axis order, or altered the "Process has no
1508    // metadata.name" error wording surfaces here rather than as silent
1509    // drift at every pre-lift caller (10 sites in
1510    // `tatara-reconciler::phase_machine` + 2 sites in
1511    // `tatara-reconciler::signals` pre-lift).
1512
1513    #[test]
1514    fn owned_coordinates_or_err_returns_owned_strings_when_both_slots_present() {
1515        // Happy path — both slots populated, method returns owned
1516        // Strings in (namespace, name) axis order.
1517        let mut p = Process::new("api-gateway", empty_spec());
1518        p.metadata.namespace = Some("prod-app".into());
1519        let (ns, name) = p.owned_coordinates_or_err().unwrap();
1520        assert_eq!(ns, "prod-app");
1521        assert_eq!(name, "api-gateway");
1522        // Ownership pin: type inference above binds ns/name as
1523        // owned Strings — a regression that returned &str would
1524        // fail to compile at the following .push() call. This
1525        // holds the "owned" half of the primitive's contract.
1526        let mut owned_ns = ns;
1527        owned_ns.push_str("-mutated");
1528        assert_eq!(owned_ns, "prod-app-mutated");
1529    }
1530
1531    #[test]
1532    fn owned_coordinates_or_err_falls_back_on_namespace_but_returns_owned_name() {
1533        // Namespace absent → DEFAULT_NAMESPACE. Name present → owned.
1534        let p = Process::new("api", empty_spec());
1535        // Process::new leaves metadata.namespace = None by default.
1536        let (ns, name) = p.owned_coordinates_or_err().unwrap();
1537        assert_eq!(ns, Process::DEFAULT_NAMESPACE);
1538        assert_eq!(name, "api");
1539    }
1540
1541    #[test]
1542    fn owned_coordinates_or_err_errors_when_metadata_name_absent_regardless_of_namespace() {
1543        // Name absent → Err, REGARDLESS of whether the namespace is
1544        // populated. The name gate is strictly on `metadata.name` and
1545        // does NOT fall back to `Self::UNNAMED_PLACEHOLDER` (that
1546        // fallback is on the peer `coordinates_or_defaults`, which
1547        // exists precisely for consumers that can tolerate a
1548        // display placeholder).
1549        for ns_slot in [None, Some("prod".to_string())] {
1550            let mut p = Process::new("scratch", empty_spec());
1551            p.metadata.name = None;
1552            p.metadata.namespace = ns_slot.clone();
1553            let err = p.owned_coordinates_or_err().unwrap_err();
1554            assert!(
1555                err.to_string().contains("metadata.name"),
1556                "err on missing name (ns={ns_slot:?}) should mention metadata.name; got {err}"
1557            );
1558        }
1559    }
1560
1561    #[test]
1562    fn owned_coordinates_or_err_error_message_matches_pre_lift_reconciler_wording() {
1563        // Load-bearing wording pin — every pre-lift `tatara-reconciler`
1564        // helper (`phase_machine::namespace_and_name`,
1565        // `signals::ingest`, `signals::consume_effect`) errored with
1566        // EXACTLY this wording. Post-lift the substrate owner produces
1567        // the same wording so log-line / test greps that anchored on
1568        // it keep matching, and no operator-visible message drift
1569        // lands as a side effect of the substrate move.
1570        let mut p = Process::new("scratch", empty_spec());
1571        p.metadata.name = None;
1572        let err = p.owned_coordinates_or_err().unwrap_err();
1573        assert_eq!(err.to_string(), "Process has no metadata.name");
1574    }
1575
1576    #[test]
1577    fn owned_coordinates_or_err_namespace_fallback_matches_default_namespace_const() {
1578        // Byte-identity pin between the owned form's namespace
1579        // fallback and the workspace-wide `DEFAULT_NAMESPACE` const.
1580        // A regression that spelled this fallback as any other
1581        // string ("kube-system", "", "default-ns") would silently
1582        // misroute every downstream namespaced-Api call on a
1583        // Process without a metadata.namespace — surfaces here
1584        // rather than at every kube-rs API caller.
1585        let mut p = Process::new("api", empty_spec());
1586        p.metadata.namespace = None;
1587        let (ns, _) = p.owned_coordinates_or_err().unwrap();
1588        assert_eq!(ns, Process::DEFAULT_NAMESPACE);
1589    }
1590
1591    #[test]
1592    fn owned_coordinates_or_err_matches_pre_lift_reconciler_helper_shape() {
1593        // Byte-identical parity pin between the owned + name-required
1594        // primitive here and the pre-lift `tatara-reconciler` helper
1595        // shape — the exact 2-slot unwrap chain each pre-lift caller
1596        // spelled by hand:
1597        //
1598        //   let ns = p.metadata.namespace.clone().unwrap_or_else(|| "default".into());
1599        //   let name = p.metadata.name.clone().ok_or_else(|| anyhow!(...))?;
1600        //   Ok((ns, name))
1601        //
1602        // Sweeps every corner every callsite plausibly encounters
1603        // (both slots present, namespace absent, name absent, both
1604        // absent). A regression that inserted a normalization step
1605        // at the primitive that the pre-lift chain does NOT apply —
1606        // or vice versa — surfaces here rather than as silent drift
1607        // between the 12 pre-lift consumer callsites and the ONE
1608        // substrate owner they now route through.
1609        fn pre_lift(p: &Process) -> anyhow::Result<(String, String)> {
1610            let ns = p
1611                .metadata
1612                .namespace
1613                .clone()
1614                .unwrap_or_else(|| "default".into());
1615            let name = p
1616                .metadata
1617                .name
1618                .clone()
1619                .ok_or_else(|| anyhow::anyhow!("Process has no metadata.name"))?;
1620            Ok((ns, name))
1621        }
1622        // Both present.
1623        let mut p = Process::new("api", empty_spec());
1624        p.metadata.namespace = Some("prod".into());
1625        assert_eq!(p.owned_coordinates_or_err().unwrap(), pre_lift(&p).unwrap());
1626        // Namespace absent.
1627        let p = Process::new("api", empty_spec());
1628        assert_eq!(p.owned_coordinates_or_err().unwrap(), pre_lift(&p).unwrap());
1629        // Name absent → both variants error with the same wording.
1630        let mut p = Process::new("api", empty_spec());
1631        p.metadata.name = None;
1632        p.metadata.namespace = Some("prod".into());
1633        assert_eq!(
1634            p.owned_coordinates_or_err().unwrap_err().to_string(),
1635            pre_lift(&p).unwrap_err().to_string(),
1636        );
1637        // Both absent → still errors on the name gate.
1638        let mut p = Process::new("api", empty_spec());
1639        p.metadata.name = None;
1640        p.metadata.namespace = None;
1641        assert_eq!(
1642            p.owned_coordinates_or_err().unwrap_err().to_string(),
1643            pre_lift(&p).unwrap_err().to_string(),
1644        );
1645    }
1646
1647    #[test]
1648    fn owned_coordinates_or_err_axis_order_matches_coordinates_or_defaults() {
1649        // Cross-primitive coherence pin between the owned + name-
1650        // required form and the borrow + name-defaulted peer:
1651        // (namespace, name) axis order is IDENTICAL across both
1652        // return-forms. A regression that swapped the tuple slots on
1653        // only ONE of the two primitives would silently misroute
1654        // every consumer that picked between the two forms based on
1655        // its callsite's ownership needs. The pin re-reads both
1656        // primitives at test time so the equality holds iff both
1657        // live paths are the current implementation.
1658        let mut p = Process::new("app", empty_spec());
1659        p.metadata.namespace = Some("infra".into());
1660        let (borrow_ns, borrow_name) = p.coordinates_or_defaults();
1661        let (owned_ns, owned_name) = p.owned_coordinates_or_err().unwrap();
1662        assert_eq!(owned_ns, borrow_ns);
1663        assert_eq!(owned_name, borrow_name);
1664        // Explicit slot labels — pins the (namespace, name) axis
1665        // order as opposed to (name, namespace).
1666        assert_eq!(owned_ns, "infra"); // NOT "app"
1667        assert_eq!(owned_name, "app"); // NOT "infra"
1668    }
1669
1670    // ─── Process::coordinates_or_none substrate pins ──────────────────
1671    //
1672    // Pins the borrow + name-required peer of the coordinate-primitive
1673    // family on the (return-form × name-gate) axis pair. Closes the
1674    // corner previously left open (borrow + name-required) so the
1675    // three consumer shapes (child-Process delete-fan-out at
1676    // `phase_machine::handle_exiting`, claim-arbiter probe at
1677    // `phase_machine::process_holds_any_claim`, any future non-fatal
1678    // skip site) route through ONE primitive rather than three hand-
1679    // authored empty-string / `unwrap_or_default()` sentinel chains.
1680    // Fail-before-pass-after granularity: a regression that flipped
1681    // the namespace fallback, swapped the return-tuple axis order,
1682    // returned an owned form, or promoted a missing name to an error
1683    // rather than `None` surfaces here rather than as silent drift at
1684    // every borrow + name-required consumer.
1685
1686    #[test]
1687    fn coordinates_or_none_returns_slices_when_both_slots_present() {
1688        // Happy path — both slots populated, method returns borrowed
1689        // (&str, &str) in (namespace, name) axis order wrapped in
1690        // `Some`.
1691        let mut p = Process::new("api-gateway", empty_spec());
1692        p.metadata.namespace = Some("prod-app".into());
1693        let (ns, name) = p.coordinates_or_none().expect("Some when name set");
1694        assert_eq!(ns, "prod-app");
1695        assert_eq!(name, "api-gateway");
1696    }
1697
1698    #[test]
1699    fn coordinates_or_none_falls_back_on_namespace_but_returns_name_slice() {
1700        // Namespace absent → DEFAULT_NAMESPACE (shared with the peer
1701        // `coordinates_or_defaults` + `namespace_or_default`). Name
1702        // present → the metadata slice, wrapped in `Some`.
1703        let mut p = Process::new("api", empty_spec());
1704        p.metadata.namespace = None;
1705        let (ns, name) = p.coordinates_or_none().expect("Some when name set");
1706        assert_eq!(ns, Process::DEFAULT_NAMESPACE);
1707        assert_eq!(name, "api");
1708    }
1709
1710    #[test]
1711    fn coordinates_or_none_returns_none_when_metadata_name_absent_regardless_of_namespace() {
1712        // Name absent → `None`, REGARDLESS of whether the namespace
1713        // slot is populated. The name gate is strictly on
1714        // `metadata.name` and does NOT fall back to
1715        // `Self::UNNAMED_PLACEHOLDER` (that fallback is on the peer
1716        // `coordinates_or_defaults`, which exists precisely for
1717        // consumers that tolerate a display placeholder). Peer to
1718        // `owned_coordinates_or_err_errors_when_metadata_name_absent_regardless_of_namespace`
1719        // on the sibling primitive; a regression that widened THIS
1720        // form to substitute the placeholder while leaving the owned
1721        // form strict would silently drift the two borrow-form
1722        // primitives out of the coherence the family carries.
1723        for ns_slot in [None, Some("prod".to_string())] {
1724            let mut p = Process::new("scratch", empty_spec());
1725            p.metadata.name = None;
1726            p.metadata.namespace = ns_slot.clone();
1727            assert!(
1728                p.coordinates_or_none().is_none(),
1729                "coordinates_or_none must be None on missing name (ns={ns_slot:?})",
1730            );
1731        }
1732    }
1733
1734    #[test]
1735    fn coordinates_or_none_namespace_fallback_matches_default_namespace_const() {
1736        // Byte-identity pin between the borrow + name-required form's
1737        // namespace fallback and the workspace-wide `DEFAULT_NAMESPACE`
1738        // const. Sibling to
1739        // `owned_coordinates_or_err_namespace_fallback_matches_default_namespace_const`
1740        // on the peer primitive — the two forms MUST substitute the
1741        // same fallback string, else a consumer that switches between
1742        // them based on its ownership need silently observes a
1743        // different namespace-fallback shape as a side effect.
1744        let mut p = Process::new("api", empty_spec());
1745        p.metadata.namespace = None;
1746        let (ns, _) = p.coordinates_or_none().unwrap();
1747        assert_eq!(ns, Process::DEFAULT_NAMESPACE);
1748    }
1749
1750    #[test]
1751    fn coordinates_or_none_axis_order_matches_coordinates_or_defaults_when_name_present() {
1752        // Cross-primitive coherence pin between the two borrow-form
1753        // primitives: when the name is present, the (namespace, name)
1754        // return-tuple axis order is IDENTICAL across the two forms,
1755        // and the returned slices are the SAME `&str` view onto the
1756        // same metadata slots. A regression that swapped the tuple
1757        // slots on ONE form would silently misroute every consumer
1758        // that picked between the two forms based on its name-gate
1759        // need. The pin re-reads both primitives at test time so the
1760        // equality holds iff both live paths are the current
1761        // implementation.
1762        let mut p = Process::new("app", empty_spec());
1763        p.metadata.namespace = Some("infra".into());
1764        let (defaulted_ns, defaulted_name) = p.coordinates_or_defaults();
1765        let (required_ns, required_name) = p.coordinates_or_none().unwrap();
1766        assert_eq!(defaulted_ns, required_ns);
1767        assert_eq!(defaulted_name, required_name);
1768        // Explicit slot labels — pins the (namespace, name) axis order
1769        // as opposed to (name, namespace).
1770        assert_eq!(required_ns, "infra"); // NOT "app"
1771        assert_eq!(required_name, "app"); // NOT "infra"
1772    }
1773
1774    #[test]
1775    fn coordinates_or_none_axis_pair_diverges_from_coordinates_or_defaults_on_missing_name() {
1776        // Divergence pin between the two borrow-form primitives when
1777        // the name gate fires: `coordinates_or_defaults` substitutes
1778        // the display placeholder AND still returns a tuple;
1779        // `coordinates_or_none` returns `None`. A regression that
1780        // collapsed the two behaviors (either by dropping the gate
1781        // from the required form or by adding a `None` corner to the
1782        // defaulted form) would blur the axis pair's whole reason to
1783        // exist as two peer primitives.
1784        let mut p = Process::new("scratch", empty_spec());
1785        p.metadata.name = None;
1786        p.metadata.namespace = Some("prod".into());
1787        // Defaulted form: substitutes placeholder, no gate.
1788        assert_eq!(
1789            p.coordinates_or_defaults(),
1790            ("prod", Process::UNNAMED_PLACEHOLDER)
1791        );
1792        // Required form: gate fires, `None`.
1793        assert!(p.coordinates_or_none().is_none());
1794    }
1795
1796    #[test]
1797    fn coordinates_or_none_matches_pre_lift_reconciler_helper_shape() {
1798        // Byte-identical parity pin between the borrow + name-required
1799        // primitive here and the pre-lift `tatara-reconciler` helper
1800        // shapes — the exact 2-slot unwrap + gate chains each pre-lift
1801        // caller spelled by hand (`phase_machine::process_holds_any_claim`
1802        // spelled it as `unwrap_or("")` + `is_empty` early-return;
1803        // `phase_machine::handle_exiting`'s child-fan-out spelled it
1804        // as `unwrap_or_default()` + implicit no-op delete on the
1805        // empty API-path). Sweeps every corner every callsite plausibly
1806        // encounters (both slots present, namespace absent, name
1807        // absent + ns present, both absent). A regression that
1808        // inserted a normalization step at the primitive the pre-lift
1809        // chain does NOT apply — or vice versa — surfaces here rather
1810        // than as silent drift between the pre-lift consumer sites
1811        // and the ONE substrate owner they now route through.
1812        fn pre_lift_holds_any_claim(p: &Process) -> Option<(&str, &str)> {
1813            let ns = p.metadata.namespace.as_deref().unwrap_or("default");
1814            let name = p.metadata.name.as_deref().unwrap_or("");
1815            if name.is_empty() {
1816                return None;
1817            }
1818            Some((ns, name))
1819        }
1820        // Both present.
1821        let mut p = Process::new("api", empty_spec());
1822        p.metadata.namespace = Some("prod".into());
1823        assert_eq!(p.coordinates_or_none(), pre_lift_holds_any_claim(&p));
1824        // Namespace absent.
1825        let p = Process::new("api", empty_spec());
1826        assert_eq!(p.coordinates_or_none(), pre_lift_holds_any_claim(&p));
1827        // Name absent → both variants return `None` regardless of ns.
1828        let mut p = Process::new("api", empty_spec());
1829        p.metadata.name = None;
1830        p.metadata.namespace = Some("prod".into());
1831        assert_eq!(p.coordinates_or_none(), pre_lift_holds_any_claim(&p));
1832        // Both absent → still `None` on the name gate.
1833        let mut p = Process::new("api", empty_spec());
1834        p.metadata.name = None;
1835        p.metadata.namespace = None;
1836        assert_eq!(p.coordinates_or_none(), pre_lift_holds_any_claim(&p));
1837    }
1838
1839    #[test]
1840    fn coordinates_or_none_axis_order_matches_owned_coordinates_or_err_on_happy_path() {
1841        // Cross-primitive coherence pin at the sibling corner: when
1842        // BOTH slots are present, the borrow + name-required form
1843        // (this method) and the owned + name-required peer
1844        // (`owned_coordinates_or_err`) return the SAME `(ns, name)`
1845        // pair — the axis order is IDENTICAL and neither primitive
1846        // silently applies a normalization the other omits. A
1847        // regression that skewed one form's normalization would
1848        // surface here rather than as silent drift between the two
1849        // name-required corners of the primitive family.
1850        let mut p = Process::new("app", empty_spec());
1851        p.metadata.namespace = Some("infra".into());
1852        let (borrow_ns, borrow_name) = p.coordinates_or_none().unwrap();
1853        let (owned_ns, owned_name) = p.owned_coordinates_or_err().unwrap();
1854        assert_eq!(borrow_ns, owned_ns.as_str());
1855        assert_eq!(borrow_name, owned_name.as_str());
1856    }
1857
1858    #[test]
1859    fn coordinates_or_defaults_axis_order_matches_qualified_process_ref() {
1860        // Pins the load-bearing convention that the return-tuple
1861        // axis order is (namespace, name) — the exact positional
1862        // argument order the substrate's paired-composer primitive
1863        // `tatara_reconciler::ssapply::qualified_process_ref(ns,
1864        // name)` consumes. A regression that swapped the tuple
1865        // slots would silently misroute every annotation writer /
1866        // claim-arbiter row / owner-metadata seed built by feeding
1867        // this pair into the composer — every downstream `<ns>/
1868        // <name>` grep would suddenly see `<name>/<ns>`. The test
1869        // verifies the tuple's first slot is what a hand-authored
1870        // `.metadata.namespace.as_deref()...` produced pre-lift, and
1871        // the second slot is what `.metadata.name.as_deref()...`
1872        // produced.
1873        let mut p = Process::new("app", empty_spec());
1874        p.metadata.namespace = Some("infra".into());
1875        let (ns, name) = p.coordinates_or_defaults();
1876        assert_eq!(ns, "infra"); // NOT "app"
1877        assert_eq!(name, "app"); // NOT "infra"
1878    }
1879
1880    // ─── Process::annotation substrate pins ────────────────────────────
1881    //
1882    // Pins the borrow-form annotation-lookup primitive that owns the
1883    // 3-line `.metadata.annotations.as_ref().and_then(|m| m.get(KEY))`
1884    // chain three hand-authored sites restated by hand pre-lift:
1885    // `tatara-reconciler::signals::ingest` (SIGNAL),
1886    // `tatara-reconciler::phase_machine::released_from_annotation`
1887    // (RELEASED_FROM), and
1888    // `tatara-pool-reconciler::controller_pool::process_belongs_to_pool`
1889    // (POOL). Fail-before-pass-after granularity: a regression that
1890    // widened the missing-`annotations` corner (returning `Some("")`
1891    // instead of `None`), promoted a missing key to an error, dropped
1892    // the borrow-form return, or changed the two swallowed corners'
1893    // shared collapse to `None` surfaces here rather than as silent
1894    // drift at the three consumer sites.
1895    fn process_with_annotation(key: &str, value: &str) -> Process {
1896        let mut p = Process::new("some-proc", empty_spec());
1897        let mut anns = std::collections::BTreeMap::new();
1898        anns.insert(key.to_string(), value.to_string());
1899        p.metadata.annotations = Some(anns);
1900        p
1901    }
1902
1903    #[test]
1904    fn annotation_returns_none_when_metadata_annotations_is_none() {
1905        // Missing-`annotations` corner: a Process with no annotations
1906        // block at all returns `None` for every key. Peer to
1907        // `observed_flux_resources_returns_empty_slice_when_status_is_none`
1908        // on the status-projection axis; both primitives collapse the
1909        // outer `Option` corner rather than requiring each consumer
1910        // to spell the guard by hand.
1911        let mut p = Process::new("scratch", empty_spec());
1912        p.metadata.annotations = None;
1913        assert!(p.annotation("tatara.pleme.io/signal").is_none());
1914        assert!(p.annotation("tatara.pleme.io/pool").is_none());
1915        assert!(p.annotation("").is_none());
1916    }
1917
1918    #[test]
1919    fn annotation_returns_none_when_key_absent_from_populated_map() {
1920        // Missing-key corner: annotations block populated with OTHER
1921        // keys returns `None` for the queried key. Symmetric with the
1922        // missing-`annotations` corner — both corners collapse to the
1923        // same `None`, matching the pre-lift `.and_then(...)`
1924        // behavior every consumer relied on.
1925        let p = process_with_annotation("tatara.pleme.io/other", "value");
1926        assert!(p.annotation("tatara.pleme.io/signal").is_none());
1927        assert!(p.annotation("").is_none());
1928    }
1929
1930    #[test]
1931    fn annotation_returns_borrowed_slice_when_key_present() {
1932        // Happy path: annotations block populated + key present →
1933        // `Some(&str)` borrowed from the underlying `String` in the
1934        // map. A regression that returned an owned `String` (defeating
1935        // the primitive's role as a zero-copy projection) would
1936        // surface at the lifetime of the returned reference — the
1937        // `&str` outlives the borrow of `&p` here.
1938        let p = process_with_annotation("tatara.pleme.io/signal", "SIGHUP");
1939        assert_eq!(p.annotation("tatara.pleme.io/signal"), Some("SIGHUP"));
1940    }
1941
1942    #[test]
1943    fn annotation_returns_borrowed_empty_string_slice_when_value_is_empty() {
1944        // Edge corner between the missing-key `None` and the present-
1945        // key `Some("")` — a Process whose annotation is EXPLICITLY
1946        // set to an empty string returns `Some("")`, NOT `None`. A
1947        // regression that normalized the empty-string value to `None`
1948        // (a plausible "defensive" simplification) would silently
1949        // reshape the corner every callsite pre-lift kept distinct via
1950        // `.cloned().unwrap_or_default()` (which collapses BOTH to
1951        // `""`) or `.map(String::as_str)` (which keeps them distinct
1952        // as `None` vs `Some("")`).
1953        let p = process_with_annotation("tatara.pleme.io/signal", "");
1954        assert_eq!(p.annotation("tatara.pleme.io/signal"), Some(""));
1955    }
1956
1957    #[test]
1958    fn annotation_is_a_pure_projection() {
1959        // Purity pin — repeated calls return equal results and the
1960        // primitive does not mutate `self`. Peer to
1961        // `observed_flux_resources_is_a_pure_projection` on the
1962        // status-projection axis.
1963        let p = process_with_annotation("tatara.pleme.io/released-from", "Attested");
1964        let a = p.annotation("tatara.pleme.io/released-from");
1965        let b = p.annotation("tatara.pleme.io/released-from");
1966        assert_eq!(a, b);
1967        assert_eq!(a, Some("Attested"));
1968    }
1969
1970    #[test]
1971    fn annotation_matches_pre_lift_reconciler_chain_shape() {
1972        // Byte-identical parity pin between the borrow-form primitive
1973        // here and the pre-lift `tatara-reconciler` / `tatara-pool-
1974        // reconciler` chain shape — the exact 3-line
1975        // `.metadata.annotations.as_ref().and_then(|m| m.get(KEY))
1976        // .map(String::as_str)` incantation each pre-lift caller
1977        // spelled by hand (three variants of tail collapsed onto ONE
1978        // borrow-form primitive here; each caller reapplies its own
1979        // tail at its own site). Sweeps every corner (missing
1980        // annotations map, missing key, present key with value,
1981        // present key with empty value) so a regression that inserted
1982        // a normalization at the primitive the pre-lift chain does
1983        // NOT apply — or vice versa — surfaces here rather than as
1984        // silent drift between the ONE substrate owner and the three
1985        // consumer sites.
1986        fn pre_lift<'a>(p: &'a Process, key: &str) -> Option<&'a str> {
1987            p.metadata
1988                .annotations
1989                .as_ref()
1990                .and_then(|m| m.get(key))
1991                .map(String::as_str)
1992        }
1993        // Missing annotations map.
1994        let mut p = Process::new("x", empty_spec());
1995        p.metadata.annotations = None;
1996        assert_eq!(p.annotation("k"), pre_lift(&p, "k"));
1997        // Missing key in populated map.
1998        let p = process_with_annotation("other", "v");
1999        assert_eq!(p.annotation("k"), pre_lift(&p, "k"));
2000        // Present key with non-empty value.
2001        let p = process_with_annotation("k", "v");
2002        assert_eq!(p.annotation("k"), pre_lift(&p, "k"));
2003        // Present key with explicitly-empty value — the corner
2004        // `.cloned().unwrap_or_default()` collapses to `""` post-tail
2005        // but the primitive-level shape stays `Some("")`.
2006        let p = process_with_annotation("k", "");
2007        assert_eq!(p.annotation("k"), pre_lift(&p, "k"));
2008    }
2009
2010    #[test]
2011    fn annotation_composes_owned_tail_matching_pre_lift_signals_ingest() {
2012        // Pins the exact tail shape `tatara-reconciler::signals::
2013        // ingest` composed pre-lift: an `Option<String>` for the
2014        // downstream `let Some(raw) = raw else { ... }` guard.
2015        // Post-lift the callsite composes `.map(str::to_string)` at
2016        // its own site; this test pins the composition matches the
2017        // pre-lift `.cloned()` tail byte-for-byte on both corners the
2018        // consumer's downstream distinguishes (annotation present →
2019        // `Some(String)`; absent → `None`).
2020        let p = process_with_annotation("tatara.pleme.io/signal", "SIGUSR1");
2021        assert_eq!(
2022            p.annotation("tatara.pleme.io/signal").map(str::to_string),
2023            Some("SIGUSR1".to_string())
2024        );
2025        let mut q = Process::new("y", empty_spec());
2026        q.metadata.annotations = None;
2027        assert_eq!(
2028            q.annotation("tatara.pleme.io/signal").map(str::to_string),
2029            None
2030        );
2031    }
2032
2033    #[test]
2034    fn annotation_composes_default_tail_matching_pre_lift_released_from() {
2035        // Pins the exact tail shape
2036        // `tatara-reconciler::phase_machine::released_from_annotation`
2037        // composed pre-lift: a bare `String` via `.cloned()
2038        // .unwrap_or_default()` for the downstream
2039        // `match v.as_str()` dispatch. Post-lift the callsite matches
2040        // directly on `Option<&str>` (Some("Failed") vs _); this test
2041        // pins that the borrow-form primitive plus the `.unwrap_or("")`
2042        // fallback reproduces the pre-lift bare-string shape on both
2043        // corners.
2044        let p = process_with_annotation("tatara.pleme.io/released-from", "Failed");
2045        assert_eq!(
2046            p.annotation("tatara.pleme.io/released-from").unwrap_or(""),
2047            "Failed"
2048        );
2049        let mut q = Process::new("y", empty_spec());
2050        q.metadata.annotations = None;
2051        assert_eq!(
2052            q.annotation("tatara.pleme.io/released-from").unwrap_or(""),
2053            ""
2054        );
2055    }
2056
2057    #[test]
2058    fn annotation_composes_borrow_equality_tail_matching_pre_lift_pool() {
2059        // Pins the exact tail shape `tatara-pool-reconciler::
2060        // controller_pool::process_belongs_to_pool` composed pre-lift:
2061        // an `Option<&str>` compared with `== Some(pool_name)` for the
2062        // membership gate. Post-lift the callsite composes
2063        // `p.annotation(POOL) == Some(pool_name)` verbatim; this test
2064        // pins that the borrow-form primitive returns exactly the
2065        // shape the equality gate expects.
2066        let p = process_with_annotation("tatara.pleme.io/pool", "demo-pool");
2067        assert_eq!(
2068            p.annotation("tatara.pleme.io/pool") == Some("demo-pool"),
2069            true
2070        );
2071        assert_eq!(p.annotation("tatara.pleme.io/pool") == Some("other"), false);
2072    }
2073
2074    // ─── Process::uid_or_empty substrate pins ──────────────────────────
2075    //
2076    // Pins the borrow-form metadata-projection primitive on the
2077    // `metadata.uid` axis that owns the `.metadata.uid.as_deref()
2078    // .unwrap_or("")` chain the two hand-authored
2079    // `tatara-reconciler::render` sites (`render_routing` +
2080    // `render_export_jobs`) restated by hand pre-lift. Peer to the
2081    // sibling `namespace_or_default_*` + `name_or_placeholder_*` pin
2082    // families on the metadata-slot × fallback-shape axis; all three
2083    // primitives return borrows of an owned-metadata slot with a slot-
2084    // specific fallback baked in (`"default"` for namespace, `"unnamed"`
2085    // for name, `""` for uid — the load-bearing gate value for
2086    // `owner_references_json`'s `is_empty` check). Fail-before-pass-
2087    // after granularity: `uid_or_empty` did not exist pre-lift, so any
2088    // test invoking it fails to compile pre-lift and passes post-lift.
2089
2090    #[test]
2091    fn uid_or_empty_returns_empty_string_when_metadata_uid_is_none() {
2092        // Empty-slot corner pin: the primitive collapses the no-uid
2093        // case to `""`, matching the pre-lift `.as_deref().unwrap_or("")`
2094        // chain's `""` byte-identically at both render consumer sites.
2095        // Semantically corresponds to a Process pre-metadata (fixtured
2096        // in tests, or caught mid-Forking before the API server has
2097        // stamped a `uid`); the downstream `owner_references_json`
2098        // composer gates on this exact `""` sentinel to stamp
2099        // `metadata.ownerReferences: []` rather than emit an owner-ref
2100        // pointing at a placeholder uid.
2101        let mut p = Process::new("scratch", empty_spec());
2102        p.metadata.uid = None;
2103        assert_eq!(p.uid_or_empty(), "");
2104    }
2105
2106    #[test]
2107    fn uid_or_empty_returns_borrowed_str_when_slot_is_populated() {
2108        // Happy-path pin: with a populated `metadata.uid` slot, the
2109        // primitive returns a borrowed `&str` whose contents match the
2110        // persisted `String`. A regression that reshaped / normalized
2111        // / cross-cluster-stripped the uid without touching this pin
2112        // would surface here rather than as silent skew at the two
2113        // `owner_references_json(name, uid)` emitters on the SAME
2114        // Process.
2115        let mut p = Process::new("owned-proc", empty_spec());
2116        p.metadata.uid = Some("uid-abc-123".into());
2117        assert_eq!(p.uid_or_empty(), "uid-abc-123");
2118    }
2119
2120    #[test]
2121    fn uid_or_empty_returns_empty_string_when_slot_is_explicitly_empty_string() {
2122        // Corner between the missing-slot `None` and the explicitly-
2123        // empty-string `Some("")` — both collapse to `""` at the
2124        // primitive because the downstream gate at
2125        // `owner_references_json` treats `.is_empty()` uniformly (the
2126        // empty-slot posture is what the whole primitive family
2127        // encodes: "no admissible owner reference, stamp `[]`"). A
2128        // regression that discriminated the two corners (returning a
2129        // sentinel `"<none>"` for the missing slot but `""` for the
2130        // explicit slot) would break the composition with
2131        // `owner_references_json` at the exactly-two-corner gate.
2132        let mut p = Process::new("owned-proc", empty_spec());
2133        p.metadata.uid = Some(String::new());
2134        assert_eq!(p.uid_or_empty(), "");
2135    }
2136
2137    #[test]
2138    fn uid_or_empty_is_a_zero_copy_borrow_projection() {
2139        // Borrow-discipline pin: the returned `&str` borrows the
2140        // persisted `String`'s underlying byte buffer in place — NOT
2141        // a fresh allocation or a clone. A regression that switched
2142        // the projection to an owned `String` (via `.clone()` or a
2143        // `format!` wrap) would defeat the zero-copy contract the
2144        // lift's primary strict-widening delivers, and would surface
2145        // here via pointer-identity comparison.
2146        let mut p = Process::new("owned-proc", empty_spec());
2147        p.metadata.uid = Some("uid-borrow-pin".into());
2148        let slice = p.uid_or_empty();
2149        assert!(std::ptr::eq(
2150            slice.as_ptr(),
2151            p.metadata.uid.as_ref().unwrap().as_ptr()
2152        ));
2153    }
2154
2155    #[test]
2156    fn uid_or_empty_is_a_pure_projection() {
2157        // Purity pin — repeated calls return byte-identical slices
2158        // (same pointer, same length). A regression that introduced
2159        // state (a lazy-cached normalized slot, a first-call
2160        // canonicalization pass) would surface here rather than as
2161        // silent drift between the two render consumer sites on the
2162        // SAME Process within one render pass.
2163        let mut p = Process::new("owned-proc", empty_spec());
2164        p.metadata.uid = Some("uid-pure".into());
2165        let a = p.uid_or_empty();
2166        let b = p.uid_or_empty();
2167        assert!(std::ptr::eq(a.as_ptr(), b.as_ptr()));
2168        assert_eq!(a.len(), b.len());
2169    }
2170
2171    #[test]
2172    fn uid_or_empty_matches_pre_lift_render_chain_shape() {
2173        // Byte-identical parity pin between the borrow-form primitive
2174        // here and the pre-lift `tatara-reconciler::render` chain shape
2175        // — the exact `.metadata.uid.as_deref().unwrap_or("")`
2176        // incantation both `render_routing` (line 514) and
2177        // `render_export_jobs` (line 653) spelled by hand pre-lift.
2178        // Sweeps every corner (missing uid slot, populated uid slot,
2179        // explicitly-empty uid slot) so a regression that inserted a
2180        // normalization the pre-lift chain does NOT apply — or vice
2181        // versa — surfaces here rather than as silent drift between
2182        // the ONE substrate owner and the two consumer sites.
2183        fn pre_lift(p: &Process) -> &str {
2184            p.metadata.uid.as_deref().unwrap_or("")
2185        }
2186        // Missing slot.
2187        let mut p = Process::new("x", empty_spec());
2188        p.metadata.uid = None;
2189        assert_eq!(p.uid_or_empty(), pre_lift(&p));
2190        // Populated slot.
2191        let mut p = Process::new("x", empty_spec());
2192        p.metadata.uid = Some("uid-42".into());
2193        assert_eq!(p.uid_or_empty(), pre_lift(&p));
2194        // Explicitly-empty slot.
2195        let mut p = Process::new("x", empty_spec());
2196        p.metadata.uid = Some(String::new());
2197        assert_eq!(p.uid_or_empty(), pre_lift(&p));
2198    }
2199
2200    #[test]
2201    fn uid_or_empty_composes_with_owner_references_json_empty_gate() {
2202        // Cross-primitive composition pin — the empty-string sentinel
2203        // this primitive returns for the missing-uid corner is EXACTLY
2204        // the sentinel the sibling substrate composer
2205        // `owner_references_json(name, uid)` gates on to stamp
2206        // `metadata.ownerReferences: []`. A regression that changed
2207        // the sentinel at either end (this primitive returning
2208        // `"<none>"`, `owner_references_json` gating on `uid == "0"`
2209        // instead of `uid.is_empty()`) would break the composition
2210        // and surface here rather than as an operator-observed
2211        // orphan resource after apply.
2212        let mut p = Process::new("x", empty_spec());
2213        p.metadata.uid = None;
2214        let refs = crate::owner_references_json("some-name", p.uid_or_empty());
2215        assert!(
2216            refs.is_empty(),
2217            "empty-uid corner must produce empty owner-refs array"
2218        );
2219
2220        p.metadata.uid = Some("real-uid".into());
2221        let refs = crate::owner_references_json("some-name", p.uid_or_empty());
2222        assert_eq!(
2223            refs.len(),
2224            1,
2225            "populated-uid corner must produce one owner-ref entry"
2226        );
2227    }
2228
2229    // ─── Process::declared_parent_pid substrate pins ─────────────────
2230    //
2231    // Pins the borrow-form spec-projection primitive on the declared
2232    // parent-PID axis that owns the `.spec.identity.parent.as_deref()`
2233    // chain the two hand-authored `tatara-reconciler::phase_machine`
2234    // sites (`handle_forking` ALLOCATE-PID composer + `handle_exiting`
2235    // SIGTERM-cascade child-fan-out filter) restated by hand pre-lift.
2236    // Peer to the sibling `observed_pid_*` pin family on the (spec-
2237    // declared × status-observed) axis pair; both compose the same
2238    // borrow-form `Option<&str>` return-shape skeleton on distinct
2239    // slots (`spec.identity.parent` vs. `status.pid`). Fail-before-
2240    // pass-after granularity: `declared_parent_pid` did not exist
2241    // pre-lift, so any test invoking it fails to compile pre-lift and
2242    // passes post-lift.
2243    fn process_with_declared_parent(parent: Option<&str>) -> Process {
2244        let mut spec = empty_spec();
2245        spec.identity.parent = parent.map(str::to_string);
2246        Process::new("child-proc", spec)
2247    }
2248
2249    #[test]
2250    fn declared_parent_pid_returns_none_when_slot_is_none() {
2251        // Empty-slot corner pin: the primitive collapses the no-
2252        // parent case to `None`, matching the pre-lift `.as_deref()`
2253        // chain's `None` byte-identically at both reconciler consumer
2254        // sites. Semantically corresponds to a Process authored at
2255        // cluster init (PID 1) with no upstream parent — the
2256        // ALLOCATE-PID composer feeds `None` into `pid::allocate_pid`
2257        // to signal "no prefix", and the SIGTERM cascade's filter
2258        // never matches such a Process because a child's declared
2259        // parent can never equal `Some(pid)` when the slot is `None`.
2260        let p = process_with_declared_parent(None);
2261        assert!(p.declared_parent_pid().is_none());
2262    }
2263
2264    #[test]
2265    fn declared_parent_pid_returns_borrowed_str_when_slot_is_populated() {
2266        // Happy-path pin: with a populated `spec.identity.parent`
2267        // slot, the primitive returns a borrowed `&str` whose
2268        // contents match the persisted `String`. A regression that
2269        // filtered / reshaped / canonicalized the string would
2270        // surface here rather than as silent skew at the child-fan-
2271        // out filter's `.declared_parent_pid() == Some(pid)`
2272        // equality check on the SAME parent-child pair.
2273        let p = process_with_declared_parent(Some("seph.1"));
2274        assert_eq!(p.declared_parent_pid(), Some("seph.1"));
2275    }
2276
2277    #[test]
2278    fn declared_parent_pid_is_a_zero_copy_borrow_projection() {
2279        // Borrow-discipline pin: the returned `&str` borrows the
2280        // persisted `String`'s underlying byte buffer in place —
2281        // NOT a fresh allocation or a clone. A regression that
2282        // switched the projection to an owned `String` (via
2283        // `.clone()` or `.to_owned()`) would defeat the zero-copy
2284        // contract the lift's primary strict-widening delivers.
2285        // The `handle_exiting` cascade filter runs per candidate
2286        // child across the cluster-wide Process list; a per-row
2287        // `String::clone` would allocate one heap block per non-
2288        // matching row, so the borrow-form primitive is load-
2289        // bearing for large clusters. Peer to the sibling
2290        // `observed_pid_is_a_zero_copy_borrow_projection` pin on
2291        // the status-observed side of the axis pair.
2292        let p = process_with_declared_parent(Some("seph.1"));
2293        let borrowed = p.declared_parent_pid().expect("populated slot");
2294        let persisted = p.spec.identity.parent.as_ref().unwrap();
2295        assert!(std::ptr::eq(borrowed.as_ptr(), persisted.as_ptr()));
2296    }
2297
2298    #[test]
2299    fn declared_parent_pid_is_a_pure_projection() {
2300        // Purity pin: calling the projection twice on the same
2301        // `Process` returns byte-identical `&str`s (same pointer,
2302        // same length). A regression that introduced state — a
2303        // lazy-cached slice materialized on first call, a
2304        // normalization step that ran once and cached — would
2305        // surface here rather than as silent drift between the
2306        // ALLOCATE-PID composer and the SIGTERM cascade's child-
2307        // fan-out filter within one reconcile pass.
2308        let p = process_with_declared_parent(Some("seph.1.3"));
2309        let a = p.declared_parent_pid().expect("populated slot");
2310        let b = p.declared_parent_pid().expect("populated slot");
2311        assert!(std::ptr::eq(a.as_ptr(), b.as_ptr()));
2312        assert_eq!(a.len(), b.len());
2313    }
2314
2315    #[test]
2316    fn declared_parent_pid_matches_pre_lift_reconciler_chain_shape() {
2317        // Byte-identical parity pin between the borrow-form primitive
2318        // here and the pre-lift `tatara-reconciler::phase_machine`
2319        // `.spec.identity.parent.as_deref()` chain shape. Sweeps
2320        // every corner every callsite plausibly encounters (empty
2321        // slot, populated with a hierarchical PID). A regression
2322        // that inserted a normalization step at the primitive the
2323        // pre-lift chain does NOT apply — or vice versa — surfaces
2324        // here rather than as silent drift between the pre-lift
2325        // consumer sites and the ONE substrate owner they now route
2326        // through. Peer to
2327        // `observed_pid_matches_pre_lift_reconciler_chain_shape` on
2328        // the sibling axis's borrow-form primitive.
2329        fn pre_lift(p: &Process) -> Option<&str> {
2330            p.spec.identity.parent.as_deref()
2331        }
2332        // Empty slot.
2333        let p = process_with_declared_parent(None);
2334        assert_eq!(p.declared_parent_pid(), pre_lift(&p));
2335        // Populated with a hierarchical PID.
2336        let p = process_with_declared_parent(Some("seph.1"));
2337        assert_eq!(p.declared_parent_pid(), pre_lift(&p));
2338        // Populated with a deeper hierarchical PID.
2339        let p = process_with_declared_parent(Some("seph.1.7.42"));
2340        assert_eq!(p.declared_parent_pid(), pre_lift(&p));
2341    }
2342
2343    #[test]
2344    fn declared_parent_pid_preserves_hierarchical_pid_format() {
2345        // Format-preservation pin: the hierarchical PID path
2346        // (dotted-segment form `seph.1.7`, matching the ported
2347        // `convergence-controller/src/identity.rs` scheme) reaches
2348        // the caller with segments and separators byte-identical
2349        // to the persisted `String`. A regression that inserted a
2350        // canonicalization pass (a segment-count validator, a
2351        // separator swap `.` → `/`, a leading/trailing whitespace
2352        // trim) would silently misroute the SIGTERM cascade's
2353        // `declared_parent_pid() == Some(pid)` comparator against
2354        // children whose `parent` field was authored in the ported
2355        // scheme's exact form — the SAME children the observed_pid
2356        // primitive is pinned to match on the other side of the
2357        // axis pair.
2358        for parent in ["seph", "seph.1", "seph.1.7", "seph.1.7.42"] {
2359            let p = process_with_declared_parent(Some(parent));
2360            assert_eq!(p.declared_parent_pid(), Some(parent));
2361        }
2362    }
2363
2364    #[test]
2365    fn declared_parent_pid_composes_with_observed_pid_for_child_fanout_filter() {
2366        // Cross-axis coherence pin against the sibling
2367        // [`Self::observed_pid`] on the (spec-declared × status-
2368        // observed) axis pair: a child's `.declared_parent_pid()`
2369        // and its parent's `.observed_pid()` compose through the
2370        // SAME borrow-form `Option<&str>` skeleton so the
2371        // `handle_exiting` cascade filter's equality gate holds
2372        // structurally. A regression that skewed EITHER primitive's
2373        // return-form (return-shape, borrow discipline, empty-slot
2374        // collapse) would silently misroute every SIGTERM cascade
2375        // on the parent-child pair. This pin re-reads both primitives
2376        // at test time so the composition holds iff both live paths
2377        // are the current implementation.
2378        // Parent Process: has an observed PID.
2379        let mut parent = Process::new("parent-proc", empty_spec());
2380        parent.status = Some(ProcessStatus {
2381            pid: Some("seph.1".to_string()),
2382            ..Default::default()
2383        });
2384        // Child Process: declared parent matches parent's observed PID.
2385        let child = process_with_declared_parent(Some("seph.1"));
2386        // The `handle_exiting` filter's equality gate:
2387        // `child.declared_parent_pid() == Some(parent.observed_pid()?)`.
2388        let parent_pid = parent.observed_pid().expect("parent has PID");
2389        assert_eq!(child.declared_parent_pid(), Some(parent_pid));
2390        // Sibling Process with an unrelated declared parent must NOT
2391        // match the same parent — pins that the filter's SKIP branch
2392        // holds on the other side of the axis pair.
2393        let sibling = process_with_declared_parent(Some("seph.2"));
2394        assert_ne!(sibling.declared_parent_pid(), Some(parent_pid));
2395    }
2396
2397    // ─── Process::declared_name_override substrate pins ──────────────
2398    //
2399    // Pins the borrow-form spec-projection primitive on the declared
2400    // name-override sub-axis of the declared-identity axis that owns
2401    // the `.spec.identity.name_override.as_deref()` chain the two
2402    // hand-authored `tatara-reconciler::phase_machine` sites
2403    // (`handle_pending` DECLARE composer + `handle_forking` ALLOCATE-
2404    // PID rehydration branch) restated by hand pre-lift. Peer to the
2405    // sibling `declared_parent_pid_*` pin family on the (parent ×
2406    // name-override) sub-axis pair; both compose the same borrow-form
2407    // `Option<&str>` return-shape skeleton on distinct slots
2408    // (`spec.identity.name_override` vs `spec.identity.parent`).
2409    // Fail-before-pass-after granularity: `declared_name_override`
2410    // did not exist pre-lift, so any test invoking it fails to
2411    // compile pre-lift and passes post-lift.
2412    fn process_with_declared_name_override(name_override: Option<&str>) -> Process {
2413        let mut spec = empty_spec();
2414        spec.identity.name_override = name_override.map(str::to_string);
2415        Process::new("some-proc", spec)
2416    }
2417
2418    #[test]
2419    fn declared_name_override_returns_none_when_slot_is_none() {
2420        // Empty-slot corner pin: the primitive collapses the no-
2421        // override case to `None`, matching the pre-lift `.as_deref()`
2422        // chain's `None` byte-identically at both reconciler consumer
2423        // sites. Semantically corresponds to a Process authored
2424        // WITHOUT the human-name-override escape hatch — the default;
2425        // `derive_identity` then computes the name from the content
2426        // hash and stamps `name_override: false` on the resulting
2427        // [`Identity`].
2428        let p = process_with_declared_name_override(None);
2429        assert!(p.declared_name_override().is_none());
2430    }
2431
2432    #[test]
2433    fn declared_name_override_returns_borrowed_str_when_slot_is_populated() {
2434        // Happy-path pin: with a populated `spec.identity
2435        // .name_override` slot, the primitive returns a borrowed
2436        // `&str` whose contents match the persisted `String`. A
2437        // regression that filtered / reshaped / canonicalized the
2438        // string at the primitive (as opposed to inside
2439        // `derive_identity`, where the trim/empty-filter lives today)
2440        // would surface here rather than as silent skew between the
2441        // DECLARE composer and the ALLOCATE-PID rehydration branch on
2442        // the SAME Process spec.
2443        let p = process_with_declared_name_override(Some("observability-stack"));
2444        assert_eq!(p.declared_name_override(), Some("observability-stack"));
2445    }
2446
2447    #[test]
2448    fn declared_name_override_is_a_zero_copy_borrow_projection() {
2449        // Borrow-discipline pin: the returned `&str` borrows the
2450        // persisted `String`'s underlying byte buffer in place —
2451        // NOT a fresh allocation or a clone. Peer to the sibling
2452        // `declared_parent_pid_is_a_zero_copy_borrow_projection` pin
2453        // on the other side of the (parent × name-override) sub-axis
2454        // pair; the borrow discipline holds structurally on BOTH
2455        // sub-axes so a future `declared_identity` composite that
2456        // returns both halves together can compose them without
2457        // dropping into an owning form.
2458        let p = process_with_declared_name_override(Some("observability-stack"));
2459        let borrowed = p.declared_name_override().expect("populated slot");
2460        let persisted = p.spec.identity.name_override.as_ref().unwrap();
2461        assert!(std::ptr::eq(borrowed.as_ptr(), persisted.as_ptr()));
2462    }
2463
2464    #[test]
2465    fn declared_name_override_is_a_pure_projection() {
2466        // Purity pin: calling the projection twice on the same
2467        // `Process` returns byte-identical `&str`s (same pointer,
2468        // same length). A regression that introduced state — a
2469        // lazy-cached slice materialized on first call, a
2470        // normalization step that ran once and cached — would
2471        // surface here rather than as silent drift between the
2472        // DECLARE composer and the ALLOCATE-PID rehydration branch
2473        // within one reconcile pass.
2474        let p = process_with_declared_name_override(Some("gateway-primary"));
2475        let a = p.declared_name_override().expect("populated slot");
2476        let b = p.declared_name_override().expect("populated slot");
2477        assert!(std::ptr::eq(a.as_ptr(), b.as_ptr()));
2478        assert_eq!(a.len(), b.len());
2479    }
2480
2481    #[test]
2482    fn declared_name_override_matches_pre_lift_reconciler_chain_shape() {
2483        // Byte-identical parity pin between the borrow-form primitive
2484        // here and the pre-lift `tatara-reconciler::phase_machine`
2485        // `.spec.identity.name_override.as_deref()` chain shape.
2486        // Sweeps every corner every callsite plausibly encounters
2487        // (empty slot, populated with a bare name, populated with a
2488        // whitespace-containing name that `derive_identity`'s
2489        // internal trim would collapse, populated with an explicitly
2490        // empty string that `derive_identity`'s internal
2491        // `!s.is_empty()` filter would reject). A regression that
2492        // inserted a normalization step at the primitive the pre-
2493        // lift chain does NOT apply — or vice versa — surfaces here
2494        // rather than as silent drift between the pre-lift consumer
2495        // sites and the ONE substrate owner they now route through.
2496        // Peer to
2497        // `declared_parent_pid_matches_pre_lift_reconciler_chain_shape`
2498        // on the sibling sub-axis's borrow-form primitive.
2499        fn pre_lift(p: &Process) -> Option<&str> {
2500            p.spec.identity.name_override.as_deref()
2501        }
2502        // Empty slot.
2503        let p = process_with_declared_name_override(None);
2504        assert_eq!(p.declared_name_override(), pre_lift(&p));
2505        // Populated with a bare name.
2506        let p = process_with_declared_name_override(Some("observability-stack"));
2507        assert_eq!(p.declared_name_override(), pre_lift(&p));
2508        // Populated with a whitespace-containing name.
2509        let p = process_with_declared_name_override(Some("  observability-stack  "));
2510        assert_eq!(p.declared_name_override(), pre_lift(&p));
2511        // Populated with an explicitly empty string. Distinct from
2512        // the missing-slot `None` corner both at the primitive here
2513        // and at the pre-lift chain (the trim/filter that collapses
2514        // these two into the same `false`-branched
2515        // `Identity { name_override: false, .. }` lives INSIDE
2516        // `derive_identity`, NOT at the borrow site) — the primitive
2517        // MUST preserve the distinction so a future lift of the trim/
2518        // filter OUT of `derive_identity` INTO the primitive is a
2519        // conscious substrate change, not a silent one.
2520        let p = process_with_declared_name_override(Some(""));
2521        assert_eq!(p.declared_name_override(), pre_lift(&p));
2522    }
2523
2524    #[test]
2525    fn declared_name_override_preserves_raw_slot_verbatim() {
2526        // Invariance-under-`derive_identity`-normalization pin: the
2527        // primitive returns the slot's raw byte contents verbatim —
2528        // no trim, no empty-string filter, no case fold, no
2529        // normalization of any kind. `derive_identity` internally
2530        // applies `.map(str::trim).filter(|s| !s.is_empty())` before
2531        // dispatching on `Some(non_empty)` vs `None | Some(empty |
2532        // whitespace)`, but that transform lives IN `derive_identity`,
2533        // NOT at the borrow site. A regression that pulled the trim/
2534        // filter forward INTO the primitive would silently collapse
2535        // three currently-distinct corners at the borrow site (bare
2536        // populated → `Some(name)`; whitespace-only → `Some("   ")`;
2537        // empty → `Some("")`) into two (bare → `Some(name)`; the
2538        // other two → `None`). That collapse might be an intentional
2539        // substrate change some future run wants to make; if so, it
2540        // lands as a conscious edit here (with this pin updated in
2541        // the same commit) rather than as silent behavior drift.
2542        for value in ["bare", "  padded  ", "\ttabs\t", "   ", ""] {
2543            let p = process_with_declared_name_override(Some(value));
2544            assert_eq!(
2545                p.declared_name_override(),
2546                Some(value),
2547                "declared_name_override must preserve raw slot verbatim for value {value:?}"
2548            );
2549        }
2550    }
2551
2552    #[test]
2553    fn declared_name_override_composes_with_derive_identity_call_shape() {
2554        // Cross-primitive coherence pin against the [`derive_identity`]
2555        // consumer: the two live `tatara-reconciler::phase_machine`
2556        // callsites feed `p.declared_name_override()` as the second
2557        // positional argument to `derive_identity(&p.spec, …)`. This
2558        // pin exercises that exact call shape at test time so a
2559        // regression that skewed the primitive's return-form (return-
2560        // shape, borrow discipline, empty-slot collapse) surfaces
2561        // here as a shape mismatch at the [`derive_identity`] call
2562        // site rather than as silent operator-facing skew between the
2563        // DECLARE composer and the ALLOCATE-PID rehydration branch.
2564        // Populated with a bare non-empty name: `derive_identity`
2565        // dispatches on `Some(non_empty)` and stamps
2566        // `name_override: true` on the resulting [`Identity`], with
2567        // the resulting `.name` equal to the raw slot value.
2568        let p = process_with_declared_name_override(Some("gateway-primary"));
2569        let id = crate::identity::derive_identity(&p.spec, p.declared_name_override());
2570        assert!(id.name_override);
2571        assert_eq!(id.name, "gateway-primary");
2572        // Empty slot: `derive_identity` dispatches on `None` and
2573        // stamps `name_override: false` on the resulting [`Identity`],
2574        // with the resulting `.name` derived from the content hash
2575        // (NOT equal to any operator-authored slot value).
2576        let p = process_with_declared_name_override(None);
2577        let id = crate::identity::derive_identity(&p.spec, p.declared_name_override());
2578        assert!(!id.name_override);
2579    }
2580
2581    // ─── Process::observed_flux_resources substrate pins ───────────────
2582    //
2583    // Pins the borrow-form status-projection primitive that owns the
2584    // 5-line `.status.as_ref().map(|s| s.flux_resources.clone())
2585    // .unwrap_or_default()` chain the two hand-authored
2586    // `tatara-reconciler::phase_machine` sites (`handle_running` +
2587    // `handle_attested`) restated by hand pre-lift. Fail-before-pass-
2588    // after granularity: a regression that widened the missing-`status`
2589    // corner, dropped the slot, or drifted the borrow discipline
2590    // surfaces here rather than as silent operator-facing skew between
2591    // the VERIFY-phase readiness probe and the ATTEST-heartbeat drift
2592    // detector.
2593
2594    fn sample_flux_ref(name: &str) -> FluxResourceRef {
2595        // Distinct slot values so a swap between adjacent tuple
2596        // positions surfaces as an equality failure at the assertion
2597        // site — a slot-inversion regression cannot masquerade as
2598        // identity by accident. Peer to the sibling
2599        // `tatara_process::status::tests::sample_flux_ref` discipline
2600        // on the fetch-coords axis.
2601        FluxResourceRef {
2602            api_version: "kustomize.toolkit.fluxcd.io/v1".to_string(),
2603            kind: "Kustomization".to_string(),
2604            name: name.to_string(),
2605            namespace: "flux-system".to_string(),
2606            ready: false,
2607            message: None,
2608            last_check: None,
2609        }
2610    }
2611
2612    fn process_with_flux_resources(refs: Vec<FluxResourceRef>) -> Process {
2613        let mut p = Process::new("api-gateway", empty_spec());
2614        p.metadata.namespace = Some("prod".into());
2615        let mut status = ProcessStatus::default();
2616        status.flux_resources = refs;
2617        p.status = Some(status);
2618        p
2619    }
2620
2621    #[test]
2622    fn observed_flux_resources_returns_empty_slice_when_status_is_none() {
2623        // Missing-`status` corner pin: the primitive collapses the
2624        // no-status case to `&[]` so downstream `.is_empty()` /
2625        // `.len()` / iteration behave identically on a `Process`
2626        // whose status field is `None` and on one whose status
2627        // carries an empty `flux_resources` slot. Matches the
2628        // pre-lift `.unwrap_or_default()`'s empty-`Vec` corner
2629        // byte-identically at every reconciler consumer's downstream
2630        // shape.
2631        let mut p = Process::new("api", empty_spec());
2632        p.status = None;
2633        assert!(p.observed_flux_resources().is_empty());
2634        assert_eq!(p.observed_flux_resources().len(), 0);
2635    }
2636
2637    #[test]
2638    fn observed_flux_resources_returns_empty_slice_when_flux_resources_is_empty() {
2639        // Zero-refs-under-populated-status corner pin: the primitive
2640        // returns an empty slice, matching the missing-`status`
2641        // corner byte-identically. A regression that treated the two
2642        // corners differently (a `None`-vs-empty signal that
2643        // downstream consumers could grep on) would silently promote
2644        // an internal representation detail (whether the reconciler
2645        // has ever written a status subresource) into observable
2646        // behavior.
2647        let p = process_with_flux_resources(vec![]);
2648        assert!(p.observed_flux_resources().is_empty());
2649        assert_eq!(p.observed_flux_resources().len(), 0);
2650    }
2651
2652    #[test]
2653    fn observed_flux_resources_returns_slice_of_persisted_vec() {
2654        // Happy-path pin: with a populated `status.flux_resources`
2655        // slot, the primitive returns a borrowed slice whose length
2656        // and per-element identity match the persisted vector. A
2657        // regression that filtered / reshaped / deduplicated the
2658        // slice would surface here rather than as silent skew at the
2659        // downstream fetch consumers.
2660        let refs = vec![
2661            sample_flux_ref("observability-stack"),
2662            sample_flux_ref("gateway"),
2663        ];
2664        let p = process_with_flux_resources(refs.clone());
2665        let observed = p.observed_flux_resources();
2666        assert_eq!(observed.len(), 2);
2667        assert_eq!(observed[0].name, "observability-stack");
2668        assert_eq!(observed[1].name, "gateway");
2669    }
2670
2671    #[test]
2672    fn observed_flux_resources_is_a_zero_copy_borrow_projection() {
2673        // Borrow-discipline pin: the returned slice borrows the
2674        // persisted `Vec<FluxResourceRef>` in place — NOT a fresh
2675        // allocation or a clone. A regression that switched the
2676        // projection to owned refs (via `.clone()` or `.to_vec()`)
2677        // would defeat the zero-copy contract the lift's primary
2678        // strict-widening delivers (the pre-lift 5-line chain
2679        // eagerly cloned the whole vector per reconcile pass; the
2680        // post-lift primitive borrows). Peer to the sibling
2681        // `flux_resource_ref_fetch_coords_returns_borrows_of_owned_slots`
2682        // pin on the per-ref borrow-projection axis.
2683        let refs = vec![sample_flux_ref("observability-stack")];
2684        let p = process_with_flux_resources(refs);
2685        let observed = p.observed_flux_resources();
2686        let persisted = &p.status.as_ref().unwrap().flux_resources;
2687        assert!(std::ptr::eq(observed.as_ptr(), persisted.as_ptr()));
2688    }
2689
2690    #[test]
2691    fn observed_flux_resources_is_a_pure_projection() {
2692        // Purity pin: calling the projection twice on the same
2693        // `Process` returns byte-identical slices (same pointer,
2694        // same length). A regression that introduced state — a
2695        // lazy-cached slice materialized on first call, a
2696        // normalization step that ran once and cached — would
2697        // surface here rather than as silent drift between the
2698        // VERIFY-phase and ATTEST-heartbeat consumers on the SAME
2699        // `Process` within one reconcile pass.
2700        let refs = vec![sample_flux_ref("observability-stack")];
2701        let p = process_with_flux_resources(refs);
2702        let a = p.observed_flux_resources();
2703        let b = p.observed_flux_resources();
2704        assert!(std::ptr::eq(a.as_ptr(), b.as_ptr()));
2705        assert_eq!(a.len(), b.len());
2706    }
2707
2708    #[test]
2709    fn observed_flux_resources_matches_pre_lift_reconciler_chain_shape() {
2710        // Byte-identical parity pin between the borrow-form primitive
2711        // here and the pre-lift `tatara-reconciler::phase_machine`
2712        // 5-line chain shape. Sweeps every corner every callsite
2713        // plausibly encounters (missing status, empty flux_resources,
2714        // populated flux_resources with one ref, populated with
2715        // multiple refs). A regression that inserted a normalization
2716        // step at the primitive the pre-lift chain does NOT apply —
2717        // or vice versa — surfaces here rather than as silent drift
2718        // between the pre-lift consumer sites and the ONE substrate
2719        // owner they now route through. Peer to
2720        // `coordinates_or_none_matches_pre_lift_reconciler_helper_shape`
2721        // on the metadata axis's borrow-form primitive.
2722        // `FluxResourceRef` does not derive `PartialEq` — the parity
2723        // check walks the per-ref fetch-coords tuple (the same 4-slot
2724        // borrow projection every downstream fetch consumer routes
2725        // through) so a regression that reshaped ANY slot at ANY
2726        // index surfaces here through the sibling
2727        // `FluxResourceRef::fetch_coords` typed projection.
2728        fn pre_lift(p: &Process) -> Vec<FluxResourceRef> {
2729            p.status
2730                .as_ref()
2731                .map(|s| s.flux_resources.clone())
2732                .unwrap_or_default()
2733        }
2734        fn coord_shape(refs: &[FluxResourceRef]) -> Vec<(String, String, String, String)> {
2735            refs.iter()
2736                .map(|r| {
2737                    let (ns, av, kind, name) = r.fetch_coords();
2738                    (
2739                        ns.to_string(),
2740                        av.to_string(),
2741                        kind.to_string(),
2742                        name.to_string(),
2743                    )
2744                })
2745                .collect()
2746        }
2747        // Missing status.
2748        let mut p = Process::new("api", empty_spec());
2749        p.status = None;
2750        assert_eq!(
2751            coord_shape(p.observed_flux_resources()),
2752            coord_shape(&pre_lift(&p))
2753        );
2754        // Populated status, empty slot.
2755        let p = process_with_flux_resources(vec![]);
2756        assert_eq!(
2757            coord_shape(p.observed_flux_resources()),
2758            coord_shape(&pre_lift(&p))
2759        );
2760        // Populated status, one ref.
2761        let p = process_with_flux_resources(vec![sample_flux_ref("obs")]);
2762        assert_eq!(
2763            coord_shape(p.observed_flux_resources()),
2764            coord_shape(&pre_lift(&p))
2765        );
2766        // Populated status, multiple refs.
2767        let p = process_with_flux_resources(vec![
2768            sample_flux_ref("obs"),
2769            sample_flux_ref("gw"),
2770            sample_flux_ref("api"),
2771        ]);
2772        assert_eq!(
2773            coord_shape(p.observed_flux_resources()),
2774            coord_shape(&pre_lift(&p))
2775        );
2776    }
2777
2778    #[test]
2779    fn observed_flux_resources_missing_status_and_empty_slot_collapse_to_the_same_slice_shape() {
2780        // Cross-corner coherence pin: the missing-`status` corner and
2781        // the populated-empty-slot corner return slices whose
2782        // `.is_empty()` / `.len()` observations are IDENTICAL. A
2783        // regression that promoted the missing-`status` corner to
2784        // returning `None` (via a signature change) — or that widened
2785        // the empty-slot corner to a synthetic single-element slice
2786        // — would surface here rather than as silent operator-facing
2787        // divergence between a never-status-written Process and a
2788        // status-emptied Process.
2789        let mut p_no_status = Process::new("api", empty_spec());
2790        p_no_status.status = None;
2791        let p_empty_status = process_with_flux_resources(vec![]);
2792        assert_eq!(
2793            p_no_status.observed_flux_resources().len(),
2794            p_empty_status.observed_flux_resources().len()
2795        );
2796        assert_eq!(
2797            p_no_status.observed_flux_resources().is_empty(),
2798            p_empty_status.observed_flux_resources().is_empty()
2799        );
2800    }
2801
2802    #[test]
2803    fn observed_flux_resources_slice_preserves_persisted_ordering() {
2804        // Ordering-preservation pin: the borrowed slice preserves
2805        // the exact insertion order of the persisted vector — no
2806        // sort, no dedup, no reshape. A regression that inserted a
2807        // sort or reordering would silently misroute per-ref
2808        // observations at the downstream VERIFY-phase / ATTEST-
2809        // heartbeat consumers, both of which walk the slice
2810        // positionally and correlate the position to the observed
2811        // readiness.
2812        let refs = vec![
2813            sample_flux_ref("z-last"),
2814            sample_flux_ref("a-first"),
2815            sample_flux_ref("m-middle"),
2816        ];
2817        let p = process_with_flux_resources(refs);
2818        let observed = p.observed_flux_resources();
2819        assert_eq!(observed[0].name, "z-last");
2820        assert_eq!(observed[1].name, "a-first");
2821        assert_eq!(observed[2].name, "m-middle");
2822    }
2823
2824    // ─── Process::observed_pid substrate pins ─────────────────────────
2825    //
2826    // Pins the borrow-form status-projection primitive on the PID axis
2827    // that owns the 3-line `.status.as_ref().and_then(|s| s.pid.clone())`
2828    // chain the two hand-authored `tatara-reconciler::phase_machine`
2829    // sites (`handle_forking` ALLOCATE-PID gate + `handle_exiting`
2830    // SIGTERM cascade) restated by hand pre-lift. Peer to the sibling
2831    // `observed_flux_resources_*` pin family on the flux-resources
2832    // axis; both compose the missing-`status` fallback + borrow-form
2833    // return-shape skeleton on distinct `ProcessStatus` slots. Fail-
2834    // before-pass-after granularity: `observed_pid` did not exist
2835    // pre-lift, so any test invoking it fails to compile pre-lift and
2836    // passes post-lift.
2837
2838    fn process_with_pid(pid: Option<&str>) -> Process {
2839        let mut p = Process::new("api-gateway", empty_spec());
2840        p.metadata.namespace = Some("prod".into());
2841        let mut status = ProcessStatus::default();
2842        status.pid = pid.map(str::to_string);
2843        p.status = Some(status);
2844        p
2845    }
2846
2847    #[test]
2848    fn observed_pid_returns_none_when_status_is_none() {
2849        // Missing-`status` corner pin: the primitive collapses the
2850        // no-status case to `None` so downstream `.is_some()` /
2851        // `if let Some(_)` / `.map(...)` behave identically on a
2852        // `Process` whose status field is `None` and on one whose
2853        // status carries an unpopulated `pid` slot. Matches the
2854        // pre-lift `.and_then(...)` chain's `None` byte-identically
2855        // at every reconciler consumer's downstream shape.
2856        let mut p = Process::new("api", empty_spec());
2857        p.status = None;
2858        assert!(p.observed_pid().is_none());
2859    }
2860
2861    #[test]
2862    fn observed_pid_returns_none_when_pid_slot_is_none() {
2863        // Empty-slot-under-populated-status corner pin: the
2864        // primitive returns `None`, matching the missing-`status`
2865        // corner byte-identically. A regression that treated the
2866        // two corners differently (a `None`-vs-`Some("")` signal
2867        // that downstream consumers could grep on) would silently
2868        // promote an internal representation detail (whether the
2869        // reconciler has ever written a status subresource) into
2870        // observable behavior at the ALLOCATE-PID gate.
2871        let p = process_with_pid(None);
2872        assert!(p.observed_pid().is_none());
2873    }
2874
2875    #[test]
2876    fn observed_pid_returns_borrowed_str_when_pid_slot_is_populated() {
2877        // Happy-path pin: with a populated `status.pid` slot, the
2878        // primitive returns a borrowed `&str` whose contents match
2879        // the persisted `String`. A regression that filtered /
2880        // reshaped / canonicalized the string would surface here
2881        // rather than as silent skew at the downstream cascade
2882        // comparator's `.as_deref() == Some(...)` equality check.
2883        let p = process_with_pid(Some("seph.1.7"));
2884        assert_eq!(p.observed_pid(), Some("seph.1.7"));
2885    }
2886
2887    #[test]
2888    fn observed_pid_is_a_zero_copy_borrow_projection() {
2889        // Borrow-discipline pin: the returned `&str` borrows the
2890        // persisted `String`'s underlying byte buffer in place —
2891        // NOT a fresh allocation or a clone. A regression that
2892        // switched the projection to an owned `String` (via
2893        // `.clone()` or `.to_owned()`) would defeat the zero-copy
2894        // contract the lift's primary strict-widening delivers
2895        // (the pre-lift 3-line chain eagerly cloned the `String`
2896        // per reconcile pass at BOTH call sites even though the
2897        // ALLOCATE-PID gate immediately dropped the clone and the
2898        // SIGTERM cascade only re-borrowed it via `.as_str()`; the
2899        // post-lift primitive borrows). Peer to the sibling
2900        // `observed_flux_resources_is_a_zero_copy_borrow_projection`
2901        // pin on the flux-resources borrow-projection axis.
2902        let p = process_with_pid(Some("seph.1.7"));
2903        let observed = p.observed_pid().expect("populated slot");
2904        let persisted = p.status.as_ref().unwrap().pid.as_ref().unwrap();
2905        assert!(std::ptr::eq(observed.as_ptr(), persisted.as_ptr()));
2906    }
2907
2908    #[test]
2909    fn observed_pid_is_a_pure_projection() {
2910        // Purity pin: calling the projection twice on the same
2911        // `Process` returns byte-identical `&str`s (same pointer,
2912        // same length). A regression that introduced state — a
2913        // lazy-cached slice materialized on first call, a
2914        // normalization step that ran once and cached — would
2915        // surface here rather than as silent drift between the
2916        // ALLOCATE-PID gate and the SIGTERM cascade on the SAME
2917        // `Process` within one reconcile pass.
2918        let p = process_with_pid(Some("seph.1.7"));
2919        let a = p.observed_pid().expect("populated slot");
2920        let b = p.observed_pid().expect("populated slot");
2921        assert!(std::ptr::eq(a.as_ptr(), b.as_ptr()));
2922        assert_eq!(a.len(), b.len());
2923    }
2924
2925    #[test]
2926    fn observed_pid_matches_pre_lift_reconciler_chain_shape() {
2927        // Byte-identical parity pin between the borrow-form
2928        // primitive here and the pre-lift `tatara-reconciler
2929        // ::phase_machine` 3-line chain shape. Sweeps every corner
2930        // every callsite plausibly encounters (missing status,
2931        // empty pid slot, populated pid slot). A regression that
2932        // inserted a normalization step at the primitive the pre-
2933        // lift chain does NOT apply — or vice versa — surfaces
2934        // here rather than as silent drift between the pre-lift
2935        // consumer sites and the ONE substrate owner they now
2936        // route through. Peer to
2937        // `observed_flux_resources_matches_pre_lift_reconciler_chain_shape`
2938        // on the flux-resources axis's borrow-form primitive.
2939        fn pre_lift(p: &Process) -> Option<String> {
2940            p.status.as_ref().and_then(|s| s.pid.clone())
2941        }
2942        // Missing status.
2943        let mut p = Process::new("api", empty_spec());
2944        p.status = None;
2945        assert_eq!(p.observed_pid().map(str::to_string), pre_lift(&p));
2946        // Populated status, empty pid slot.
2947        let p = process_with_pid(None);
2948        assert_eq!(p.observed_pid().map(str::to_string), pre_lift(&p));
2949        // Populated status, populated pid slot.
2950        let p = process_with_pid(Some("seph.1.7"));
2951        assert_eq!(p.observed_pid().map(str::to_string), pre_lift(&p));
2952    }
2953
2954    #[test]
2955    fn observed_pid_missing_status_and_empty_slot_collapse_to_the_same_option_shape() {
2956        // Cross-corner coherence pin: the missing-`status` corner
2957        // and the populated-empty-slot corner return `Option`s whose
2958        // `.is_none()` observations are IDENTICAL. A regression
2959        // that promoted the missing-`status` corner to returning a
2960        // typed error (via a signature change to `Result<_, _>`) —
2961        // or that widened the empty-slot corner to a synthetic
2962        // `Some("")` — would surface here rather than as silent
2963        // operator-facing divergence between a never-status-
2964        // written Process and a status-emptied Process on the
2965        // ALLOCATE-PID gate.
2966        let mut p_no_status = Process::new("api", empty_spec());
2967        p_no_status.status = None;
2968        let p_empty_slot = process_with_pid(None);
2969        assert_eq!(
2970            p_no_status.observed_pid().is_none(),
2971            p_empty_slot.observed_pid().is_none()
2972        );
2973        assert_eq!(
2974            p_no_status.observed_pid().is_some(),
2975            p_empty_slot.observed_pid().is_some()
2976        );
2977    }
2978
2979    #[test]
2980    fn observed_pid_preserves_hierarchical_pid_format() {
2981        // Format-preservation pin: the hierarchical PID path
2982        // (dotted-segment form `seph.1.7`, matching the ported
2983        // `convergence-controller/src/identity.rs` scheme) reaches
2984        // the caller with segments and separators byte-identical
2985        // to the persisted `String`. A regression that inserted a
2986        // canonicalization pass (a segment-count validator, a
2987        // separator swap `.` → `/`, a leading/trailing whitespace
2988        // trim) would silently misroute the SIGTERM cascade's
2989        // `spec.identity.parent == Some(pid)` comparator against
2990        // children whose `parent` field was authored in the ported
2991        // scheme's exact form.
2992        for pid in ["seph", "seph.1", "seph.1.7", "seph.1.7.42"] {
2993            let p = process_with_pid(Some(pid));
2994            assert_eq!(p.observed_pid(), Some(pid));
2995        }
2996    }
2997
2998    // ─── Process::observed_attestation substrate pins ─────────────────
2999    //
3000    // Pins the borrow-form status-projection primitive on the
3001    // attestation-chain axis that owns the 3-line
3002    // `.status.as_ref().and_then(|s| s.attestation.as_ref())` chain
3003    // the two hand-authored `tatara-reconciler` sites
3004    // (`phase_machine::advance_to_attested` ATTEST composer +
3005    // `render::render_export_jobs` export-Job builder) restated by
3006    // hand pre-lift. Peer to the sibling `observed_pid_*` +
3007    // `observed_flux_resources_*` pin families; all three compose
3008    // the missing-`status` fallback + borrow-form return-shape
3009    // skeleton on distinct `ProcessStatus` slots. Fail-before-pass-
3010    // after granularity: `observed_attestation` did not exist
3011    // pre-lift, so any test invoking it fails to compile pre-lift
3012    // and passes post-lift.
3013
3014    fn sample_attestation(artifact: &str, intent: &str) -> ProcessAttestation {
3015        // Distinct pillar strings so a regression that swapped the
3016        // artifact / intent pillars silently surfaces as an
3017        // equality failure at the composed-root parity pin.
3018        ProcessAttestation::initial(artifact.to_string(), None, intent.to_string())
3019    }
3020
3021    fn process_with_attestation(attestation: Option<ProcessAttestation>) -> Process {
3022        let mut p = Process::new("api-gateway", empty_spec());
3023        p.metadata.namespace = Some("prod".into());
3024        let mut status = ProcessStatus::default();
3025        status.attestation = attestation;
3026        p.status = Some(status);
3027        p
3028    }
3029
3030    #[test]
3031    fn observed_attestation_returns_none_when_status_is_none() {
3032        // Missing-`status` corner pin: the primitive collapses the
3033        // no-status case to `None` so downstream `.is_some()` /
3034        // `if let Some(_)` / `.map(...)` behave identically on a
3035        // `Process` whose status field is `None` and on one whose
3036        // status carries an unpopulated `attestation` slot.
3037        // Matches the pre-lift `.and_then(...)` chain's `None`
3038        // byte-identically at every reconciler consumer's
3039        // downstream shape.
3040        let mut p = Process::new("api", empty_spec());
3041        p.status = None;
3042        assert!(p.observed_attestation().is_none());
3043    }
3044
3045    #[test]
3046    fn observed_attestation_returns_none_when_attestation_slot_is_none() {
3047        // Empty-slot-under-populated-status corner pin: the
3048        // primitive returns `None`, matching the missing-`status`
3049        // corner byte-identically. A regression that treated the
3050        // two corners differently (a `None`-vs-`Some(_)` signal
3051        // that downstream consumers could grep on) would silently
3052        // promote an internal representation detail (whether the
3053        // reconciler has ever written a status subresource) into
3054        // observable behavior at the ATTEST composer's
3055        // seed-vs-chain branch.
3056        let p = process_with_attestation(None);
3057        assert!(p.observed_attestation().is_none());
3058    }
3059
3060    #[test]
3061    fn observed_attestation_returns_borrow_when_slot_is_populated() {
3062        // Happy-path pin: with a populated `status.attestation`
3063        // slot, the primitive returns a borrowed
3064        // `&ProcessAttestation` whose fields match the persisted
3065        // record. A regression that filtered / reshaped /
3066        // canonicalized the record would surface here rather than
3067        // as silent skew at the downstream `prior.next(pillars)`
3068        // chain composer + the ephemeral-export receipt's
3069        // `previous_root` linker.
3070        let att = sample_attestation("art-1", "int-1");
3071        let composed_root = att.composed_root.clone();
3072        let p = process_with_attestation(Some(att));
3073        let observed = p.observed_attestation().expect("populated slot");
3074        assert_eq!(observed.artifact_hash, "art-1");
3075        assert_eq!(observed.intent_hash, "int-1");
3076        assert_eq!(observed.composed_root, composed_root);
3077        assert_eq!(observed.generation, 0);
3078        assert!(observed.previous_root.is_none());
3079    }
3080
3081    #[test]
3082    fn observed_attestation_is_a_zero_copy_borrow_projection() {
3083        // Borrow-discipline pin: the returned reference points at
3084        // the persisted `ProcessAttestation` in place — NOT a fresh
3085        // allocation or a clone. A regression that switched the
3086        // projection to an owned `ProcessAttestation` (via
3087        // `.clone()`) would defeat the zero-copy contract the
3088        // lift's primary strict-widening delivers (the pre-lift
3089        // 3-line chain returned a borrow, but the export-Job
3090        // builder then cloned `composed_root` off it; the post-
3091        // lift primitive preserves the borrow all the way to the
3092        // consumer's own cloning choice). Peer to the sibling
3093        // `observed_pid_is_a_zero_copy_borrow_projection` +
3094        // `observed_flux_resources_is_a_zero_copy_borrow_projection`
3095        // pins on the PID + flux-resources borrow-projection axes.
3096        let att = sample_attestation("art-1", "int-1");
3097        let p = process_with_attestation(Some(att));
3098        let observed = p.observed_attestation().expect("populated slot") as *const _;
3099        let persisted = p.status.as_ref().unwrap().attestation.as_ref().unwrap() as *const _;
3100        assert!(std::ptr::eq(observed, persisted));
3101    }
3102
3103    #[test]
3104    fn observed_attestation_is_a_pure_projection() {
3105        // Purity pin: calling the projection twice on the same
3106        // `Process` returns byte-identical borrows (same pointer).
3107        // A regression that introduced state — a lazy-cached
3108        // reference materialized on first call, a normalization
3109        // step that ran once and cached — would surface here
3110        // rather than as silent drift between the ATTEST composer
3111        // and the ephemeral-export receipt chain on the SAME
3112        // `Process` within one reconcile pass.
3113        let att = sample_attestation("art-1", "int-1");
3114        let p = process_with_attestation(Some(att));
3115        let a = p.observed_attestation().expect("populated slot") as *const _;
3116        let b = p.observed_attestation().expect("populated slot") as *const _;
3117        assert!(std::ptr::eq(a, b));
3118    }
3119
3120    #[test]
3121    fn observed_attestation_matches_pre_lift_reconciler_chain_shape() {
3122        // Byte-identical parity pin between the borrow-form
3123        // primitive here and the pre-lift `tatara-reconciler`
3124        // 3-line chain shape. Sweeps every corner every callsite
3125        // plausibly encounters (missing status, empty attestation
3126        // slot, populated attestation slot). A regression that
3127        // inserted a normalization step at the primitive the pre-
3128        // lift chain does NOT apply — or vice versa — surfaces
3129        // here rather than as silent drift between the pre-lift
3130        // consumer sites and the ONE substrate owner they now
3131        // route through. Peer to
3132        // `observed_pid_matches_pre_lift_reconciler_chain_shape` +
3133        // `observed_flux_resources_matches_pre_lift_reconciler_chain_shape`
3134        // on the PID + flux-resources axes.
3135        // `ProcessAttestation` does not derive `PartialEq` — the
3136        // parity check walks the `composed_root` field (the
3137        // byte-string every downstream consumer keys off) so a
3138        // regression that reshaped the record without touching
3139        // the composed-root observation surfaces here through
3140        // the receipt-chain projection.
3141        fn pre_lift(p: &Process) -> Option<String> {
3142            p.status
3143                .as_ref()
3144                .and_then(|s| s.attestation.as_ref())
3145                .map(|a| a.composed_root.clone())
3146        }
3147        // Missing status.
3148        let mut p = Process::new("api", empty_spec());
3149        p.status = None;
3150        assert_eq!(
3151            p.observed_attestation().map(|a| a.composed_root.clone()),
3152            pre_lift(&p)
3153        );
3154        // Populated status, empty attestation slot.
3155        let p = process_with_attestation(None);
3156        assert_eq!(
3157            p.observed_attestation().map(|a| a.composed_root.clone()),
3158            pre_lift(&p)
3159        );
3160        // Populated status, populated attestation slot.
3161        let p = process_with_attestation(Some(sample_attestation("art-1", "int-1")));
3162        assert_eq!(
3163            p.observed_attestation().map(|a| a.composed_root.clone()),
3164            pre_lift(&p)
3165        );
3166    }
3167
3168    #[test]
3169    fn observed_attestation_missing_status_and_empty_slot_collapse_to_the_same_option_shape() {
3170        // Cross-corner coherence pin: the missing-`status` corner
3171        // and the populated-empty-slot corner return `Option`s
3172        // whose `.is_none()` observations are IDENTICAL. A
3173        // regression that promoted the missing-`status` corner to
3174        // returning a typed error (via a signature change to
3175        // `Result<_, _>`) — or that widened the empty-slot corner
3176        // to a synthetic `Some(default_attestation)` — would
3177        // surface here rather than as silent operator-facing
3178        // divergence between a never-status-written Process and
3179        // an attestation-emptied Process on the ATTEST composer's
3180        // seed-vs-chain branch.
3181        let mut p_no_status = Process::new("api", empty_spec());
3182        p_no_status.status = None;
3183        let p_empty_slot = process_with_attestation(None);
3184        assert_eq!(
3185            p_no_status.observed_attestation().is_none(),
3186            p_empty_slot.observed_attestation().is_none()
3187        );
3188        assert_eq!(
3189            p_no_status.observed_attestation().is_some(),
3190            p_empty_slot.observed_attestation().is_some()
3191        );
3192    }
3193
3194    #[test]
3195    fn observed_attestation_preserves_chain_generation_field() {
3196        // Generation-preservation pin: a chained attestation
3197        // (`prior.next(...)` at generation N ≥ 1 with a
3198        // `previous_root` linked to `prior.composed_root`) reaches
3199        // the caller with its `generation` counter + `previous_root`
3200        // link byte-identical to the persisted record. The pre-lift
3201        // ATTEST composer discriminated exactly on this borrow's
3202        // `Some(prior)` vs `None` arm; a regression that dropped
3203        // the chain's `generation` counter (say, by folding
3204        // `next(...)` into a fresh `initial(...)` on every
3205        // reconcile pass) would silently reset every chain and
3206        // orphan every downstream `previous_root` link, but that
3207        // drift is invisible to a Process CRD reader who only
3208        // observes the LATEST composed_root.
3209        let prior = sample_attestation("art-0", "int-0");
3210        let chained = prior.next("art-1".to_string(), None, "int-1".to_string());
3211        let expected_generation = chained.generation;
3212        let expected_previous = chained.previous_root.clone();
3213        let p = process_with_attestation(Some(chained));
3214        let observed = p.observed_attestation().expect("populated slot");
3215        assert_eq!(observed.generation, expected_generation);
3216        assert_eq!(observed.generation, 1);
3217        assert_eq!(observed.previous_root, expected_previous);
3218        assert_eq!(
3219            observed.previous_root.as_deref(),
3220            Some(prior.composed_root.as_str())
3221        );
3222    }
3223
3224    // ─── Process::observed_identity substrate pins ────────────────────
3225    //
3226    // The borrow-form status-projection primitive on the resolved-
3227    // identity axis. Collapses the paired 3-line `.status.as_ref()
3228    // .and_then(|s| s.identity.<clone|as_ref>())` chain every
3229    // consumer in `tatara-reconciler` restated by hand pre-lift at
3230    // TWO sites (`phase_machine::handle_forking` seed +
3231    // `ssapply::inject_annotations` content-hash annotation
3232    // composer). Peer to the sibling `observed_pid_*` +
3233    // `observed_attestation_*` + `observed_flux_resources_*` pin
3234    // families; all four compose the same missing-`status` fallback
3235    // + borrow-form return-shape skeleton on distinct
3236    // `ProcessStatus` slots. Each pin fails-before-pass-after
3237    // granularity: `observed_identity` did not exist pre-lift, so
3238    // any test invoking it fails to compile pre-lift and passes
3239    // post-lift.
3240
3241    fn sample_identity(name: &str) -> Identity {
3242        // Distinct name + content_hash + override flag so a
3243        // regression that reshaped one slot surfaces at the
3244        // populated-slot pin's field-equality check without
3245        // aliasing the sibling slots.
3246        Identity {
3247            name: name.to_string(),
3248            content_hash: "a".repeat(26),
3249            name_override: true,
3250        }
3251    }
3252
3253    fn process_with_identity(identity: Option<Identity>) -> Process {
3254        let mut p = Process::new("api-gateway", empty_spec());
3255        p.metadata.namespace = Some("prod".into());
3256        let mut status = ProcessStatus::default();
3257        status.identity = identity;
3258        p.status = Some(status);
3259        p
3260    }
3261
3262    #[test]
3263    fn observed_identity_returns_none_when_status_is_none() {
3264        // Missing-`status` corner pin: the primitive collapses the
3265        // no-status case to `None` so downstream `.is_some()` /
3266        // `if let Some(_)` / `.cloned().unwrap_or_else(...)` behave
3267        // identically on a `Process` whose status field is `None`
3268        // and on one whose status carries an unpopulated `identity`
3269        // slot. Matches the pre-lift `.and_then(...)` chain's `None`
3270        // byte-identically at every reconciler consumer's
3271        // downstream shape.
3272        let mut p = Process::new("api", empty_spec());
3273        p.status = None;
3274        assert!(p.observed_identity().is_none());
3275    }
3276
3277    #[test]
3278    fn observed_identity_returns_none_when_identity_slot_is_none() {
3279        // Empty-slot-under-populated-status corner pin: the
3280        // primitive returns `None`, matching the missing-`status`
3281        // corner byte-identically. A regression that treated the
3282        // two corners differently (a `None`-vs-`Some(_)` signal
3283        // that downstream consumers could grep on) would silently
3284        // promote an internal representation detail (whether the
3285        // reconciler has ever written a status subresource) into
3286        // observable behavior at the FORK-time `derive_identity`
3287        // fallback branch.
3288        let p = process_with_identity(None);
3289        assert!(p.observed_identity().is_none());
3290    }
3291
3292    #[test]
3293    fn observed_identity_returns_borrow_when_slot_is_populated() {
3294        // Happy-path pin: with a populated `status.identity` slot,
3295        // the primitive returns a borrowed `&Identity` whose fields
3296        // match the persisted record. A regression that filtered /
3297        // reshaped / canonicalized the record would surface here
3298        // rather than as silent skew at the FORK-time seed's
3299        // `.cloned().unwrap_or_else(derive_identity)` composition
3300        // + the SSA-time content-hash annotation stamp on the SAME
3301        // Process.
3302        let id = sample_identity("seph");
3303        let expected = id.clone();
3304        let p = process_with_identity(Some(id));
3305        let observed = p.observed_identity().expect("populated slot");
3306        assert_eq!(observed, &expected);
3307        assert_eq!(observed.name, "seph");
3308        assert_eq!(observed.content_hash, "a".repeat(26));
3309        assert!(observed.name_override);
3310    }
3311
3312    #[test]
3313    fn observed_identity_is_a_zero_copy_borrow_projection() {
3314        // Borrow-discipline pin: the returned reference points at
3315        // the persisted `Identity` in place — NOT a fresh
3316        // allocation or a clone. A regression that switched the
3317        // projection to an owned `Identity` (via `.clone()`) would
3318        // defeat the zero-copy contract the lift's primary strict-
3319        // widening delivers (the SSA-time consumer never clones the
3320        // whole `Identity`, only the `content_hash` field it stamps
3321        // onto the annotation map, so the borrow-form return
3322        // shape's happy-path allocation count is exactly ZERO).
3323        // Peer to the sibling
3324        // `observed_attestation_is_a_zero_copy_borrow_projection`
3325        // + `observed_pid_is_a_zero_copy_borrow_projection` +
3326        // `observed_flux_resources_is_a_zero_copy_borrow_projection`
3327        // pins on the attestation-chain + PID + flux-resources
3328        // borrow-projection axes.
3329        let id = sample_identity("seph");
3330        let p = process_with_identity(Some(id));
3331        let observed = p.observed_identity().expect("populated slot") as *const _;
3332        let persisted = p.status.as_ref().unwrap().identity.as_ref().unwrap() as *const _;
3333        assert!(std::ptr::eq(observed, persisted));
3334    }
3335
3336    #[test]
3337    fn observed_identity_is_a_pure_projection() {
3338        // Purity pin: calling the projection twice on the same
3339        // `Process` returns byte-identical borrows (same pointer).
3340        // A regression that introduced state — a lazy-cached
3341        // reference materialized on first call, a normalization
3342        // step that ran once and cached — would surface here
3343        // rather than as silent drift between the FORK-time
3344        // identity seed and the SSA-time content-hash annotation
3345        // stamp on the SAME `Process` within one reconcile pass.
3346        let p = process_with_identity(Some(sample_identity("seph")));
3347        let a = p.observed_identity().expect("populated slot") as *const _;
3348        let b = p.observed_identity().expect("populated slot") as *const _;
3349        assert!(std::ptr::eq(a, b));
3350    }
3351
3352    #[test]
3353    fn observed_identity_matches_pre_lift_reconciler_chain_shape() {
3354        // Byte-identical parity pin between the borrow-form
3355        // primitive here and the pre-lift `tatara-reconciler`
3356        // 3-line chain shape. Sweeps every corner every callsite
3357        // plausibly encounters (missing status, empty identity
3358        // slot, populated identity slot). A regression that
3359        // inserted a normalization step at the primitive the pre-
3360        // lift chain does NOT apply — or vice versa — surfaces
3361        // here rather than as silent drift between the pre-lift
3362        // consumer sites and the ONE substrate owner they now
3363        // route through. Peer to
3364        // `observed_attestation_matches_pre_lift_reconciler_chain_shape`
3365        // + `observed_pid_matches_pre_lift_reconciler_chain_shape`
3366        // + `observed_flux_resources_matches_pre_lift_reconciler_chain_shape`
3367        // on the attestation-chain + PID + flux-resources axes.
3368        fn pre_lift(p: &Process) -> Option<Identity> {
3369            p.status.as_ref().and_then(|s| s.identity.clone())
3370        }
3371        // Missing status.
3372        let mut p = Process::new("api", empty_spec());
3373        p.status = None;
3374        assert_eq!(p.observed_identity().cloned(), pre_lift(&p));
3375        // Populated status, empty identity slot.
3376        let p = process_with_identity(None);
3377        assert_eq!(p.observed_identity().cloned(), pre_lift(&p));
3378        // Populated status, populated identity slot.
3379        let p = process_with_identity(Some(sample_identity("seph")));
3380        assert_eq!(p.observed_identity().cloned(), pre_lift(&p));
3381    }
3382
3383    #[test]
3384    fn observed_identity_missing_status_and_empty_slot_collapse_to_the_same_option_shape() {
3385        // Cross-corner coherence pin: the missing-`status` corner
3386        // and the populated-empty-slot corner return `Option`s
3387        // whose `.is_none()` observations are IDENTICAL. A
3388        // regression that promoted the missing-`status` corner to
3389        // returning a typed error (via a signature change to
3390        // `Result<_, _>`) — or that widened the empty-slot corner
3391        // to a synthetic `Some(derive_identity(default_spec))` —
3392        // would surface here rather than as silent operator-facing
3393        // divergence between a never-status-written Process and an
3394        // identity-cleared Process on the FORK-time seed branch.
3395        let mut p_no_status = Process::new("api", empty_spec());
3396        p_no_status.status = None;
3397        let p_empty_slot = process_with_identity(None);
3398        assert_eq!(
3399            p_no_status.observed_identity().is_none(),
3400            p_empty_slot.observed_identity().is_none()
3401        );
3402        assert_eq!(
3403            p_no_status.observed_identity().is_some(),
3404            p_empty_slot.observed_identity().is_some()
3405        );
3406    }
3407
3408    #[test]
3409    fn observed_identity_cloned_composes_with_derive_identity_fallback() {
3410        // Cross-primitive composition pin: the borrow-form
3411        // primitive threaded through `.cloned().unwrap_or_else(||
3412        // derive_identity(...))` reproduces the pre-lift FORK-time
3413        // seed's owned-`Identity` shape at every corner. Binds the
3414        // exact composition the `phase_machine::handle_forking`
3415        // consumer performs: on the populated-slot corner the
3416        // reconciler-persisted `Identity` is returned verbatim (the
3417        // fallback never fires), and on both empty corners
3418        // (missing-status + empty-slot) the fallback fires
3419        // producing a fresh `derive_identity(&spec,
3420        // name_override)`. A regression that (a) swapped the
3421        // fallback direction, (b) made `.cloned()` re-derive
3422        // instead of clone, or (c) made the empty-slot corner
3423        // return a synthetic `Some(default_identity)` collides
3424        // with the fallback surfaces here rather than as silent
3425        // FORK-time PID allocator skew.
3426        let spec = empty_spec();
3427        let fallback_expected = crate::identity::derive_identity(&spec, None);
3428        // Populated-slot corner: the seed returns the persisted
3429        // identity, NOT the derive fallback.
3430        let persisted = sample_identity("seph");
3431        let p = process_with_identity(Some(persisted.clone()));
3432        let seed = p.observed_identity().cloned().unwrap_or_else(|| {
3433            crate::identity::derive_identity(&p.spec, p.declared_name_override())
3434        });
3435        assert_eq!(seed, persisted);
3436        assert_ne!(seed, fallback_expected);
3437        // Empty-slot corner: the seed fires the derive fallback.
3438        let p = process_with_identity(None);
3439        let seed = p.observed_identity().cloned().unwrap_or_else(|| {
3440            crate::identity::derive_identity(&p.spec, p.declared_name_override())
3441        });
3442        assert_eq!(seed, fallback_expected);
3443        // Missing-status corner: the seed fires the derive
3444        // fallback, byte-identical to the empty-slot corner.
3445        let mut p = Process::new("api-gateway", empty_spec());
3446        p.metadata.namespace = Some("prod".into());
3447        p.status = None;
3448        let seed = p.observed_identity().cloned().unwrap_or_else(|| {
3449            crate::identity::derive_identity(&p.spec, p.declared_name_override())
3450        });
3451        assert_eq!(seed, fallback_expected);
3452    }
3453
3454    // ─── Process::observed_phase substrate pins ───────────────────────
3455    //
3456    // The copy-form status-projection primitive on the phase axis.
3457    // Collapses the paired 3-line `.status.as_ref().map(|s| s.phase)`
3458    // chain every consumer in `tatara-reconciler` restated by hand
3459    // pre-lift at FIVE sites. Peer to the borrow-form
3460    // `observed_pid_*` + `observed_flux_resources_*` +
3461    // `observed_attestation_*` pin families; all four compose the
3462    // same missing-`status` fallback skeleton on distinct
3463    // `ProcessStatus` slots, with the phase-axis form returning
3464    // `Option<ProcessPhase>` (copy of a `Copy` scalar) rather than
3465    // `Option<&T>` (borrow) because the underlying slot is a bare
3466    // `ProcessPhase` — no allocation to borrow past, and the enum
3467    // is one byte on the wire. Each pin fails-before-pass-after
3468    // granularity: `observed_phase` did not exist pre-lift, so any
3469    // test invoking it fails to compile pre-lift and passes
3470    // post-lift.
3471
3472    fn process_with_phase(phase: Option<ProcessPhase>) -> Process {
3473        let mut p = Process::new("api-gateway", empty_spec());
3474        p.metadata.namespace = Some("prod".into());
3475        if let Some(ph) = phase {
3476            let mut status = ProcessStatus::default();
3477            status.phase = ph;
3478            p.status = Some(status);
3479        }
3480        p
3481    }
3482
3483    #[test]
3484    fn observed_phase_returns_none_when_status_is_none() {
3485        // Missing-`status` corner pin: the primitive collapses the
3486        // no-status case to `None` so downstream `.unwrap_or(...)`
3487        // at every reconciler consumer chooses the default
3488        // deliberately (`Pending` for the top-level dispatch seed
3489        // + boundary evaluator + routing groupby; `Attested` for
3490        // the released-from annotation composer). Matches the
3491        // pre-lift `.map(|s| s.phase)` chain's `None`
3492        // byte-identically at every consumer's downstream shape.
3493        let mut p = Process::new("api", empty_spec());
3494        p.status = None;
3495        assert!(p.observed_phase().is_none());
3496    }
3497
3498    #[test]
3499    fn observed_phase_returns_some_default_when_status_is_populated_with_default_phase() {
3500        // Populated-status corner pin: the primitive returns
3501        // `Some(ProcessPhase::default())` — a `ProcessStatus`
3502        // constructed via `default()` carries `phase: Pending`
3503        // because the phase field is a bare `ProcessPhase` (not
3504        // `Option<ProcessPhase>`), so there is NO "empty slot"
3505        // corner peer to the borrow-form projections' empty-slot
3506        // pins. A regression that reshaped the return type to
3507        // filter out `Pending` (treating it as "unset") would
3508        // surface here and silently break the top-level
3509        // dispatcher's Pending → Forking transition on a Process
3510        // freshly written by the reconciler.
3511        let p = process_with_phase(Some(ProcessPhase::default()));
3512        assert_eq!(p.observed_phase(), Some(ProcessPhase::Pending));
3513        assert_eq!(p.observed_phase(), Some(ProcessPhase::default()));
3514    }
3515
3516    #[test]
3517    fn observed_phase_returns_persisted_phase_when_status_is_populated() {
3518        // Happy-path pin: with a populated `status.phase` slot,
3519        // the primitive returns the persisted `ProcessPhase`.
3520        // A regression that filtered / reshaped / canonicalized
3521        // the phase would surface here rather than as silent
3522        // skew at the top-level dispatcher's phase handler
3523        // dispatch on the SAME Process.
3524        let p = process_with_phase(Some(ProcessPhase::Running));
3525        assert_eq!(p.observed_phase(), Some(ProcessPhase::Running));
3526    }
3527
3528    #[test]
3529    fn observed_phase_is_a_pure_projection() {
3530        // Purity pin: two consecutive calls return byte-identical
3531        // `Option<ProcessPhase>` values (no lazy materialization,
3532        // no interior mutation of `self`). Peer to the sibling
3533        // `observed_pid_is_a_pure_projection` +
3534        // `observed_flux_resources_is_a_pure_projection` +
3535        // `observed_attestation_is_a_pure_projection` pins; all
3536        // four bind the pure-projection discipline on the ONE
3537        // substrate accessor per status slot.
3538        let p = process_with_phase(Some(ProcessPhase::Attested));
3539        let a = p.observed_phase();
3540        let b = p.observed_phase();
3541        assert_eq!(a, b);
3542        assert_eq!(a, Some(ProcessPhase::Attested));
3543    }
3544
3545    #[test]
3546    fn observed_phase_matches_pre_lift_reconciler_chain_shape() {
3547        // Parity pin: sweeps the two corners every pre-lift
3548        // consumer plausibly encountered (missing status,
3549        // populated status with a particular phase) and compares
3550        // the substrate call against a hand-authored pre-lift
3551        // chain byte-identically. A regression that reshaped ANY
3552        // of the two corners would surface here rather than as
3553        // silent operator-facing skew between the top-level
3554        // dispatcher and any of the four other reconciler
3555        // consumers on the SAME `Process`.
3556        fn pre_lift(p: &Process) -> Option<ProcessPhase> {
3557            p.status.as_ref().map(|s| s.phase)
3558        }
3559        let mut p = Process::new("api", empty_spec());
3560        p.status = None;
3561        assert_eq!(p.observed_phase(), pre_lift(&p));
3562        let p = process_with_phase(Some(ProcessPhase::Running));
3563        assert_eq!(p.observed_phase(), pre_lift(&p));
3564        let p = process_with_phase(Some(ProcessPhase::Attested));
3565        assert_eq!(p.observed_phase(), pre_lift(&p));
3566        let p = process_with_phase(Some(ProcessPhase::Failed));
3567        assert_eq!(p.observed_phase(), pre_lift(&p));
3568    }
3569
3570    #[test]
3571    fn observed_phase_default_unwrap_matches_pre_lift_pending_default() {
3572        // Callsite-shape pin: three of the FIVE pre-lift consumers
3573        // (`controller::reconcile`, `boundary::evaluate_process_phase`,
3574        // `table_controller::stable_name_group_key`) closed the
3575        // 3-line chain with `.unwrap_or(ProcessPhase::Pending)`
3576        // (identical to `.unwrap_or_default()`). This pin binds
3577        // that call-site shape: `observed_phase().unwrap_or
3578        // (Pending)` returns `Pending` on missing status and the
3579        // persisted phase otherwise. A regression that swapped
3580        // the `None` sentinel's downstream default would surface
3581        // here rather than as silent skew at three of the five
3582        // consumer sites.
3583        let mut p = Process::new("api", empty_spec());
3584        p.status = None;
3585        assert_eq!(
3586            p.observed_phase().unwrap_or(ProcessPhase::Pending),
3587            ProcessPhase::Pending
3588        );
3589        let p = process_with_phase(Some(ProcessPhase::Running));
3590        assert_eq!(
3591            p.observed_phase().unwrap_or(ProcessPhase::Pending),
3592            ProcessPhase::Running
3593        );
3594    }
3595
3596    #[test]
3597    fn observed_phase_attested_unwrap_matches_pre_lift_released_from_default() {
3598        // Callsite-shape pin: the ONE pre-lift consumer
3599        // (`phase_machine::p_current_phase_str` — the
3600        // released-from annotation composer) closed the 3-line
3601        // chain with `.unwrap_or(ProcessPhase::Attested)` rather
3602        // than the `Default` (`Pending`). This pin binds that
3603        // call-site shape: `observed_phase().unwrap_or(Attested)`
3604        // returns `Attested` on missing status and the persisted
3605        // phase otherwise. A regression that folded the
3606        // `Attested`-default consumer into the `Pending`-default
3607        // majority would break the SIGSTOP/SIGCONT release gate's
3608        // "which annotation label to emit" branch — the pin binds
3609        // the primitive at the raw `Option<ProcessPhase>` form so
3610        // this default choice stays local at the callsite.
3611        let mut p = Process::new("api", empty_spec());
3612        p.status = None;
3613        assert_eq!(
3614            p.observed_phase().unwrap_or(ProcessPhase::Attested),
3615            ProcessPhase::Attested
3616        );
3617        let p = process_with_phase(Some(ProcessPhase::Failed));
3618        assert_eq!(
3619            p.observed_phase().unwrap_or(ProcessPhase::Attested),
3620            ProcessPhase::Failed
3621        );
3622    }
3623
3624    #[test]
3625    fn observed_phase_preserves_every_process_phase_variant() {
3626        // Round-trip pin: every `ProcessPhase` variant round-
3627        // trips through the primitive unchanged. Peer to the
3628        // sibling `observed_pid_preserves_hierarchical_pid_format`
3629        // pin's dotted-segment sweep; this pin sweeps the closed
3630        // set of `ProcessPhase` variants directly so a
3631        // canonicalization pass that dropped or reshaped one
3632        // (e.g. folded `Reconverging` back into `Execing`, or
3633        // remapped `Zombie` to `Reaped`) surfaces here rather
3634        // than as silent skew at the SIGSTOP/SIGCONT release
3635        // gate's phase-name annotation branch. Covers every
3636        // variant the `ProcessPhase::DeriveClosedSet` enumerates
3637        // so a future variant addition surfaces via the closed-
3638        // set macro rather than at a silent partial sweep.
3639        for phase in [
3640            ProcessPhase::Pending,
3641            ProcessPhase::Forking,
3642            ProcessPhase::Execing,
3643            ProcessPhase::Running,
3644            ProcessPhase::Attested,
3645            ProcessPhase::Reconverging,
3646            ProcessPhase::Releasing,
3647            ProcessPhase::Exiting,
3648            ProcessPhase::Failed,
3649            ProcessPhase::Zombie,
3650            ProcessPhase::Reaped,
3651        ] {
3652            let p = process_with_phase(Some(phase));
3653            assert_eq!(
3654                p.observed_phase(),
3655                Some(phase),
3656                "phase variant {phase:?} did not round-trip"
3657            );
3658        }
3659    }
3660
3661    // ─── Process::is_being_deleted substrate pins ───────────────────────
3662    //
3663    // Pins the copy-form metadata-projection primitive on the
3664    // deletion-tombstone axis. Peer to the borrow-form + copy-form
3665    // metadata-fallback family (`namespace_or_default`,
3666    // `name_or_placeholder`, `uid_or_empty`, `coordinates_or_defaults`,
3667    // `coordinates_or_none`, `owned_coordinates_or_err`, `annotation`);
3668    // this one opens the presence-probe corner for the tombstone slot.
3669    // Fail-before-pass-after granularity: `is_being_deleted` did not
3670    // exist pre-lift, so any test invoking it fails to compile pre-
3671    // lift and passes post-lift.
3672
3673    fn tombstoned_process() -> Process {
3674        let mut p = Process::new("api-gateway", empty_spec());
3675        p.metadata.namespace = Some("prod".into());
3676        p.metadata.deletion_timestamp = Some(k8s_openapi::apimachinery::pkg::apis::meta::v1::Time(
3677            Utc::now(),
3678        ));
3679        p
3680    }
3681
3682    #[test]
3683    fn is_being_deleted_returns_false_when_deletion_timestamp_is_absent() {
3684        // Missing-tombstone corner pin: the primitive collapses the
3685        // no-tombstone case to `false` so the SIGTERM preempt at
3686        // `controller::reconcile` skips the `→ Exiting` forcing
3687        // branch and the DELETE-skip at `handle_exiting`'s child
3688        // fan-out does NOT `continue` past a child that is still
3689        // healthy. Matches the pre-lift `.is_some()` chain's `false`
3690        // byte-identically at every consumer's downstream gate.
3691        let mut p = Process::new("api", empty_spec());
3692        p.metadata.deletion_timestamp = None;
3693        assert!(!p.is_being_deleted());
3694    }
3695
3696    #[test]
3697    fn is_being_deleted_returns_true_when_deletion_timestamp_is_present() {
3698        // Present-tombstone corner pin: the primitive returns
3699        // `true` on any populated `metadata.deletionTimestamp`
3700        // slot regardless of the timestamp payload — the two
3701        // consumers only read the tombstone's PRESENCE, never
3702        // its RFC-3339 timestamp value. A regression that gated
3703        // the `true` return on the timestamp being non-epoch, or
3704        // parsed the timestamp before returning, would surface
3705        // here rather than as silent skew at the SIGTERM preempt
3706        // or child-fan-out DELETE-skip on the SAME `Process`.
3707        let p = tombstoned_process();
3708        assert!(p.is_being_deleted());
3709    }
3710
3711    #[test]
3712    fn is_being_deleted_is_a_pure_projection() {
3713        // Purity pin: two consecutive calls return byte-identical
3714        // `bool` values (no lazy materialization, no interior
3715        // mutation of `self`). Peer to the sibling
3716        // `observed_phase_is_a_pure_projection` +
3717        // `observed_pid_is_a_pure_projection` +
3718        // `observed_flux_resources_is_a_pure_projection` +
3719        // `observed_attestation_is_a_pure_projection` pins; all
3720        // five bind the pure-projection discipline on the ONE
3721        // substrate accessor per metadata / status slot.
3722        let p = tombstoned_process();
3723        let a = p.is_being_deleted();
3724        let b = p.is_being_deleted();
3725        assert_eq!(a, b);
3726        assert!(a);
3727    }
3728
3729    #[test]
3730    fn is_being_deleted_matches_pre_lift_reconciler_chain_shape() {
3731        // Parity pin: sweeps the two corners every pre-lift
3732        // consumer plausibly encountered (missing tombstone,
3733        // present tombstone) and compares the substrate call
3734        // against a hand-authored pre-lift chain byte-identically.
3735        // A regression that reshaped either corner would surface
3736        // here rather than as silent operator-facing skew between
3737        // the top-level dispatcher's SIGTERM preempt and the
3738        // SIGTERM cascade's child-fan-out DELETE-skip on the
3739        // SAME `Process` within one reconcile pass.
3740        fn pre_lift(p: &Process) -> bool {
3741            p.metadata.deletion_timestamp.is_some()
3742        }
3743        let mut p = Process::new("api", empty_spec());
3744        p.metadata.deletion_timestamp = None;
3745        assert_eq!(p.is_being_deleted(), pre_lift(&p));
3746        let p = tombstoned_process();
3747        assert_eq!(p.is_being_deleted(), pre_lift(&p));
3748    }
3749
3750    #[test]
3751    fn is_being_deleted_composes_with_process_phase_is_alive_at_reconcile_preempt() {
3752        // Call-site-shape pin: the `controller::reconcile` SIGTERM
3753        // preempt composes `is_being_deleted() && current_phase
3754        // .is_alive()` — the tombstone-presence probe AND the
3755        // alive-phase gate must BOTH hold to force `→ Exiting`.
3756        // A dead-phase (`Zombie` / `Reaped` / `Failed`) Process
3757        // that carries a tombstone still runs its normal handler,
3758        // not the preempt. This pin binds that composition shape
3759        // at the primitive so a regression that flipped either
3760        // half of the `&&` (or that broadened the tombstone probe
3761        // to include the `is_alive` half implicitly) surfaces
3762        // here rather than as silent skew at the top-level
3763        // dispatch on the SAME `Process`.
3764        let mut p = tombstoned_process();
3765        // Alive + tombstoned → preempt fires.
3766        let mut alive = ProcessStatus::default();
3767        alive.phase = ProcessPhase::Running;
3768        p.status = Some(alive);
3769        assert!(p.is_being_deleted());
3770        assert!(p.observed_phase().unwrap_or_default().is_alive());
3771        // Dead + tombstoned → preempt does NOT fire (composition
3772        // with `is_alive` returns false).
3773        let mut dead = ProcessStatus::default();
3774        dead.phase = ProcessPhase::Reaped;
3775        p.status = Some(dead);
3776        assert!(p.is_being_deleted());
3777        assert!(!p.observed_phase().unwrap_or_default().is_alive());
3778    }
3779
3780    // ─── Process::created_at substrate pins ─────────────────────────
3781    //
3782    // Pins the copy-form metadata-projection primitive on the
3783    // `metadata.creationTimestamp` axis that owns the
3784    // `.metadata.creation_timestamp.as_ref().map(|t| t.0)` chain the
3785    // three hand-authored sites (`lifetime_clock::evaluate`,
3786    // `lifetime_clock::requeue_with_ttl`,
3787    // `tatara-reconciler::table_controller`) restated by hand pre-lift.
3788    // Peer to the sibling `is_being_deleted_*` +
3789    // `observed_phase_*` pin families — all three primitives project a
3790    // wire-format `Option<T>` slot into a `Copy` inner value at ONE
3791    // owner. Fail-before-pass-after granularity: `created_at` did not
3792    // exist pre-lift, so any test invoking it fails to compile pre-lift
3793    // and passes post-lift.
3794
3795    fn creation_stamped_process(t: DateTime<Utc>) -> Process {
3796        let mut p = Process::new("age-anchor", empty_spec());
3797        p.metadata.namespace = Some("prod".into());
3798        p.metadata.creation_timestamp =
3799            Some(k8s_openapi::apimachinery::pkg::apis::meta::v1::Time(t));
3800        p
3801    }
3802
3803    #[test]
3804    fn created_at_returns_none_when_creation_timestamp_is_absent() {
3805        // Missing-slot corner pin: the primitive collapses the
3806        // no-creation-timestamp case to `None` so the TTL-expiry gate
3807        // at `lifetime_clock::evaluate` short-circuits its inner
3808        // `if let Some(...)` branch (no elapsed computation), the
3809        // requeue-budget picker returns its default sleep, and the
3810        // stable-name arbiter's `.unwrap_or_else(Utc::now)` tail
3811        // synthesizes a "just created" anchor at its own site. Matches
3812        // the pre-lift `.as_ref().map(|t| t.0)` chain's `None`
3813        // byte-identically at every consumer's downstream tail.
3814        let mut p = Process::new("api", empty_spec());
3815        p.metadata.creation_timestamp = None;
3816        assert!(p.created_at().is_none());
3817    }
3818
3819    #[test]
3820    fn created_at_returns_some_datetime_when_slot_is_populated() {
3821        // Populated-slot corner pin: with a populated
3822        // `metadata.creationTimestamp` slot, the primitive unwraps the
3823        // wire-format `Time` newtype to its inner `DateTime<Utc>` and
3824        // returns it as `Some(datetime)` — hiding the `.0` field-access
3825        // every pre-lift consumer restated to reach the underlying
3826        // instant.
3827        let anchor = Utc::now() - chrono::Duration::seconds(300);
3828        let p = creation_stamped_process(anchor);
3829        assert_eq!(p.created_at(), Some(anchor));
3830    }
3831
3832    #[test]
3833    fn created_at_is_a_pure_projection() {
3834        // Purity pin: two consecutive calls return byte-identical
3835        // `Option<DateTime<Utc>>` values (no lazy materialization, no
3836        // interior mutation of `self`). Peer to the sibling
3837        // `is_being_deleted_is_a_pure_projection` +
3838        // `observed_phase_is_a_pure_projection` pins; all three bind
3839        // the pure-projection discipline on the ONE substrate accessor
3840        // per metadata / status slot.
3841        let anchor = Utc::now();
3842        let p = creation_stamped_process(anchor);
3843        let a = p.created_at();
3844        let b = p.created_at();
3845        assert_eq!(a, b);
3846        assert_eq!(a, Some(anchor));
3847    }
3848
3849    #[test]
3850    fn created_at_matches_pre_lift_creation_timestamp_chain_shape() {
3851        // Parity pin: sweeps the two corners every pre-lift consumer
3852        // plausibly encountered (missing slot, populated slot) and
3853        // compares the substrate call against a hand-authored pre-lift
3854        // chain byte-identically. A regression that reshaped either
3855        // corner (returning `Some(Utc::now())` on the missing slot,
3856        // returning a rounded / truncated timestamp on the populated
3857        // slot) would surface here rather than as silent operator-
3858        // facing skew between the TTL-expiry gate, the requeue-budget
3859        // picker, and the stable-name claim-arbiter tie-break on the
3860        // SAME `Process` within one reconcile pass.
3861        fn pre_lift(p: &Process) -> Option<DateTime<Utc>> {
3862            p.metadata.creation_timestamp.as_ref().map(|t| t.0)
3863        }
3864        // Missing slot.
3865        let mut p = Process::new("x", empty_spec());
3866        p.metadata.creation_timestamp = None;
3867        assert_eq!(p.created_at(), pre_lift(&p));
3868        // Populated slot.
3869        let anchor = Utc::now() - chrono::Duration::seconds(42);
3870        let p = creation_stamped_process(anchor);
3871        assert_eq!(p.created_at(), pre_lift(&p));
3872    }
3873
3874    #[test]
3875    fn created_at_composes_with_signed_duration_since_at_ttl_gate() {
3876        // Call-site-shape pin: the `lifetime_clock::evaluate` TTL-
3877        // expiry gate composes `now.signed_duration_since(creation)`
3878        // where `creation` is the `DateTime<Utc>` returned by this
3879        // primitive's `Some` corner. A regression that returned a
3880        // per-callsite `Local` timezone (or that stripped the timezone
3881        // marker) would break the arithmetic silently. This pin
3882        // computes the elapsed duration byte-identically against the
3883        // pre-lift `.map(|t| t.0)` chain so a timezone drift surfaces
3884        // here rather than as silent skew at the TTL-expiry decision
3885        // on the SAME `Process` within one reconcile pass.
3886        let now = Utc::now();
3887        let anchor = now - chrono::Duration::seconds(120);
3888        let p = creation_stamped_process(anchor);
3889        let via_primitive = p.created_at().expect("populated slot");
3890        let via_pre_lift = p
3891            .metadata
3892            .creation_timestamp
3893            .as_ref()
3894            .map(|t| t.0)
3895            .expect("populated slot");
3896        assert_eq!(
3897            now.signed_duration_since(via_primitive),
3898            now.signed_duration_since(via_pre_lift)
3899        );
3900    }
3901}