Skip to main content

tatara_process/
time.rs

1//! Wall-clock time primitives — the small typed layer over the
2//! `chrono::DateTime<Utc>` → `std::time::Duration` bridge every timed
3//! decision in the workspace passes through, plus the K8s wire-form
4//! composers ([`tombstone_now`], [`tombstone_at`]) that lift a
5//! `DateTime<Utc>` anchor into the `Option<Time>` shape
6//! `ObjectMeta::deletion_timestamp` (and its metadata-Time peers)
7//! carry.
8//!
9//! Kubernetes exposes wall-clock anchors on the wire as
10//! `k8s_openapi::apimachinery::pkg::apis::meta::v1::Time`
11//! (`DateTime<Utc>` after `.0`) — `metadata.creationTimestamp`,
12//! `metadata.deletionTimestamp`, `status.phaseSince`,
13//! `PoolMember.enteredStateAt`, etc. Every timed decision (TTL
14//! expiry, sleep-budget picker, staleness gate) then projects
15//! `(now, anchor)` onto an `Option<std::time::Duration>` so it can
16//! be compared to a `humantime`-parsed budget (also
17//! `std::time::Duration`). This module owns the one-line chain that
18//! projection reduces to on the READ side, and — via [`tombstone_now`]
19//! and [`tombstone_at`] — the 5-token `Some(Time(<anchor>))` wire
20//! wrap every WRITE-side fixture that seeds a tombstone-present
21//! corner stamps on the metadata slot.
22
23use chrono::{DateTime, FixedOffset, Utc};
24use k8s_openapi::apimachinery::pkg::apis::meta::v1::Time;
25use std::time::Duration;
26
27/// Elapsed wall-clock time between `anchor` and `now`, or `None` if
28/// `anchor` is in `now`'s future (a clock rewind or a mis-sequenced
29/// anchor). The one-line `now.signed_duration_since(anchor).to_std()
30/// .ok()` chain lifted to ONE typed owner past the ★★ PRIME-DIRECTIVE
31/// ≥ 2 duplication threshold, and the peer of every timed-decision
32/// gate that compares an anchor to a `humantime`-parsed budget.
33///
34/// Pre-lift the SAME chain was hand-authored at THREE workspace-wide
35/// consumer sites, each projecting a `(now, anchor)` pair onto an
36/// `Option<std::time::Duration>` for comparison against a
37/// `humantime`-parsed TTL/free-TTL:
38///
39/// * [`crate::lifetime_clock::evaluate`] — the ephemeral-lifetime
40///   TTL-expiry gate. Reads
41///   `now.signed_duration_since(creation).to_std().ok()` inside the
42///   non-terminal-phase guard, fires `AutoTerminate::Now { TtlExpired }`
43///   iff the elapsed duration is `>= ttl`.
44/// * [`crate::lifetime_clock::requeue_with_ttl`] — the sleep-budget
45///   picker for the reconciler's next requeue, choosing the smaller
46///   of HEARTBEAT and TTL-remaining so the controller doesn't oversleep
47///   past a TTL boundary. Reads the SAME two-link chain via a `match`
48///   that maps the `Err` arm onto the caller's `default` fallback.
49/// * `tatara-pool-reconciler::pool_decide::decide_pool_reconcile` —
50///   the Free-member staleness gate. Reads
51///   `now.signed_duration_since(m.entered_state_at).to_std().ok()` per
52///   `MemberState::Free` row and pushes the member's process-name onto
53///   the stale-Free list iff the elapsed duration exceeds the pool's
54///   `free_ttl`.
55///
56/// All THREE sites walked the SAME two-link chain — take the signed
57/// chrono delta, then discard the negative-anchor arm — differing
58/// only in the tail (`if let Some(elapsed)` guard, `match` with a
59/// per-fn `default` fallback, `if let Some` composed with a per-member
60/// push). Post-lift each callsite reads `elapsed_since(now, anchor)`
61/// and applies its own tail at its own site.
62///
63/// Return-form axis: `Option<std::time::Duration>` matches the
64/// downstream comparator's type. `humantime::parse_duration` returns
65/// `Result<std::time::Duration, _>`, so the elapsed-side projection
66/// yielding the SAME `std::time::Duration` puts both operands of the
67/// comparator on the same axis without a per-consumer conversion.
68///
69/// The `None` arm is the "clock ran backwards or the anchor is in the
70/// future" corner — a Kubelet clock skew, a `Time` slot stamped with
71/// `.0 == Utc::now() + Δ`, or a test that fixes `now` before the
72/// anchor to prove the timed decision short-circuits. Every consumer
73/// interprets the corner as "no elapsed data → don't fire the timed
74/// action"; the pins below bind that shape.
75///
76/// A future normalization (a monotonic-clock cross-check, a
77/// millisecond-precision truncation for cross-node determinism, a
78/// per-fleet skew tolerance that bumps a small `Δ` past a negative
79/// signed delta before the `to_std().ok()` cast) lands at THIS ONE
80/// substrate primitive and every downstream timed-decision consumer
81/// inherits the upgrade mechanically — no per-site edit at any of
82/// the THREE listed callers or at future consumers (an
83/// allocation-TTL expiry gate, a stable-name claim-arbiter age
84/// tie-break, a pool member's Allocated-state max-age reap probe).
85#[must_use]
86pub fn elapsed_since(now: DateTime<Utc>, anchor: DateTime<Utc>) -> Option<Duration> {
87    now.signed_duration_since(anchor).to_std().ok()
88}
89
90/// A wall-clock anchor `secs` seconds before the current instant — the
91/// one-line `Utc::now() - chrono::Duration::seconds(secs)` chain lifted
92/// to ONE typed owner past the ★★ PRIME-DIRECTIVE ≥ 2 duplication
93/// threshold, and the composition partner of every timed-decision test
94/// (or production caller) that needs a "recently-past" anchor to feed
95/// [`elapsed_since`] or a `humantime`-parsed budget comparator.
96///
97/// Pre-lift the SAME chain was hand-authored at 21 workspace-wide
98/// consumer sites across 6 files, each restating `Utc::now() -
99/// chrono::Duration::seconds(<N>)` verbatim to seed a
100/// `DateTime<Utc>` `N` seconds in the past:
101///
102/// * `tatara-process` — 15 sites across `crd.rs` + `lib.rs` +
103///   `lifetime_clock.rs` seeding TTL-expiry, staleness-gate, and
104///   observed-anchor tests.
105/// * `tatara-reconciler::claim` — 4 sites in the stable-name claim
106///   arbiter's pure decision tests, each seeding a `granted_at` or
107///   `created_at` anchor for tie-break arithmetic.
108/// * `tatara-pool-reconciler` — 2 sites in `pool_decide` +
109///   `desired.rs` seeding per-member `entered_state_at` /
110///   `created_at` for pool-convergence dwell-time decisions.
111///
112/// All 21 sites walked the SAME two-link chain — read the wall clock,
113/// then subtract a whole-second `chrono::Duration` — differing only in
114/// the second-count `N` (`age_secs` parameter, `500`, `720`, `42`,
115/// etc.). Post-lift each callsite reads `seconds_ago(N)` and the
116/// wall-clock read + subtraction sink lives at ONE substrate owner.
117///
118/// Return-form axis: `DateTime<Utc>` — the copy-form anchor every
119/// consumer's downstream `signed_duration_since` / `[`elapsed_since`]`
120/// / `Time(anchor)` composer takes as its second operand. The `i64`
121/// `secs` parameter matches `chrono::Duration::seconds`'s own signature
122/// so a negative value (rare but permitted) yields a future anchor,
123/// mirroring the pre-lift semantics.
124///
125/// Sibling to [`elapsed_since`] on the same `(now, anchor) → Δ` axis —
126/// `elapsed_since` reads the delta between two given anchors,
127/// `seconds_ago` produces the anchor `N` seconds before now that the
128/// delta consumer needs.
129///
130/// A future normalization (a monotonic-clock cross-check, an injectable
131/// `time_source: impl Fn() -> DateTime<Utc>` for deterministic tests,
132/// a per-fleet skew Δ that clamps the wall-clock read past a known-bad
133/// range) lands at THIS ONE substrate primitive and every downstream
134/// consumer (production callers, test helpers, future timed-decision
135/// gates) inherits the upgrade mechanically — no per-site edit at any
136/// of the 21 listed callers or at future consumers.
137#[must_use]
138pub fn seconds_ago(secs: i64) -> DateTime<Utc> {
139    Utc::now() - chrono::Duration::seconds(secs)
140}
141
142/// A tombstone stamp for a K8s [`metadata.deletionTimestamp`][kdel]
143/// slot at the current wall-clock instant — the wire shape K8s
144/// stamps once the API server has received a DELETE request but the
145/// finalizer chain has not yet released the object for GC. The
146/// `Option<Time>` return form matches the slot's own type
147/// (`ObjectMeta::deletion_timestamp: Option<Time>`) so the tombstone
148/// composes directly into the metadata without a per-caller `Some(...)`
149/// wrap or a per-caller `Time(...)` wrap of the `Utc::now()` read.
150///
151/// Pre-lift the SAME
152/// `Some(k8s_openapi::apimachinery::pkg::apis::meta::v1::Time(Utc::now()))`
153/// / `Some(Time(chrono::Utc::now()))` 5-token wire shape was hand-
154/// authored at 11 workspace-wide fixture sites across four files,
155/// each stamping the tombstone slot on one of the three tatara-owned
156/// CRDs to seed a deletion-in-progress fixture:
157///
158/// * [`crate::crd`] `crd::deletion_tombstoned_tests::tombstoned_process`
159///   — the shared `Process` fixture the [`crate::crd::Process::is_being_deleted`]
160///   inherent-forwarder pin family (7 test cases at `crd.rs` line 4956)
161///   destructures for its tombstone-present corner.
162/// * [`crate::pool`] `pool::deletion_tombstoned_tests::tombstoned_pool`
163///   — the peer `EphemeralPool` fixture the sibling
164///   [`crate::pool::EphemeralPool::is_being_deleted`] inherent-forwarder
165///   pin family destructures (at `pool.rs` line 2768).
166/// * `tatara-pool-reconciler::allocation_decide::tests::
167///   deletion_timestamp_releases_assigned_process` — the allocation
168///   reconciler's tombstone-releases-bind pin (at `allocation_decide.rs`
169///   line 609).
170/// * `tatara-pool-reconciler::pool_decide::tests::
171///   deletion_stamp_triggers_drain` — the pool reconciler's
172///   tombstone-triggers-Drain pin (at `pool_decide.rs` line 343).
173/// * [`crate::deletion_tombstoned_tests`] — 7 pins in `lib.rs` (lines
174///   1588, 1595, 1602, 1621, 1649, 1663, 1688, 1701) covering the
175///   trait's blanket-impl behavior across all three CRDs plus the
176///   two inherent-forwarder coherence pins.
177///
178/// Every callsite walked the SAME 5-token chain — take the wall-clock
179/// instant, wrap it in the K8s Time newtype, wrap that in `Some` — and
180/// wanted the `Option<Time>` form for direct assignment to the
181/// `metadata.deletion_timestamp` slot. Post-lift each callsite reads
182/// `tombstone_now()` and the wall-clock read + K8s Time wrap + Option
183/// wrap sinks live at ONE substrate owner.
184///
185/// Return-form axis: `Option<Time>` — the exact type
186/// `ObjectMeta::deletion_timestamp` carries. A caller wanting the bare
187/// [`Time`] (e.g. seeding a `LastTransitionTime` on a `Condition`,
188/// where the field is `Time` and not `Option<Time>`) unwraps via
189/// `tombstone_now().unwrap()` at the callsite — but this primitive's
190/// contract is the `Option<Time>` slot, matching the pre-lift shape
191/// every one of the 11 hand-authored callsites walked. The peer
192/// [`tombstone_at`] takes an explicit anchor for callers that need a
193/// past-anchored tombstone (e.g. a "stamped an hour ago" fixture for
194/// a stale-tombstone garbage-collection probe).
195///
196/// Peer to [`crate::DeletionTombstoned`] on the (WRITE, READ) axis:
197/// [`crate::DeletionTombstoned::is_being_deleted`] is the READ probe
198/// (the trait's blanket impl reads `.metadata.deletion_timestamp.
199/// is_some()` on any tatara CRD); [`tombstone_now`] is the WRITE
200/// composer (the substrate owner for the 5-token wire shape every
201/// fixture that seeds a tombstone-present corner stamps). The two
202/// primitives partition the deletion-timestamp surface at the (read,
203/// write) axis and cover it end-to-end at the substrate.
204///
205/// A future normalization (a monotonic-clock cross-check on the wall
206/// read, a per-fleet skew Δ that biases the tombstone anchor past a
207/// known-bad range, a widening of the K8s Time wire form under a
208/// future k8s-openapi crate bump, a debug-build assertion that the
209/// caller has admission privileges to stamp a tombstone at all) lands
210/// at THIS ONE substrate primitive and every downstream fixture / seed
211/// / stamp callsite inherits the upgrade mechanically — no per-site
212/// edit at any of the 11 listed callers or at future consumers (a
213/// stable-name claim-arbiter's tombstoned-generation seed, a
214/// tatara-testing helper that stamps a tombstone on a mock-server
215/// object, an admission-webhook fixture that fires the tombstone
216/// stamp itself).
217///
218/// [kdel]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#objectmeta-v1-meta
219#[must_use]
220pub fn tombstone_now() -> Option<Time> {
221    Some(Time(Utc::now()))
222}
223
224/// A tombstone stamp for a K8s [`metadata.deletionTimestamp`][kdel]
225/// slot at the operator-supplied `when` anchor — the peer of
226/// [`tombstone_now`] on the anchor-explicit axis. Composes directly
227/// with [`seconds_ago`] so a callsite needing a "stamped `N` seconds
228/// ago" tombstone (e.g. a stale-tombstone garbage-collection probe, a
229/// fixture that seeds a tombstone predating the reconciler's `now` by
230/// enough to trip a `deletion_grace_period_seconds` cutoff) reads
231/// `tombstone_at(seconds_ago(N))` and routes through ONE substrate
232/// owner for both the anchor construction and the wire-form wrap.
233///
234/// Pre-lift the SAME `Some(Time(<anchor>))` wire shape was hand-
235/// authored at 1 workspace-wide site — the tombstone-present corner
236/// of [`crate::deletion_tombstoned_tests::is_being_deleted_matches_pre_lift_deletion_timestamp_is_some_chain_on_ephemeral_allocation`],
237/// which sweeps three corners of the (absent, present-at-now,
238/// present-at-past) input matrix and stamps `Some(Time(seconds_ago(3600)))`
239/// on the present-at-past corner. Together with [`tombstone_now`]'s
240/// 11 callsites, the pair covers the 12-site `Some(Time(<anchor>))`
241/// family the substrate opens ownership over.
242///
243/// The `DateTime<Utc>` parameter form encodes the invariant "the caller
244/// has already chosen the anchor" at the type level — a caller wanting
245/// the current-instant tombstone routes through [`tombstone_now`]
246/// instead of `tombstone_at(Utc::now())`, keeping the wall-clock read
247/// at ONE substrate owner and avoiding the "did the caller mean the
248/// clock at the seed-instant or the clock at the assertion-instant"
249/// ambiguity a `DateTime<Utc>::default()` form would open.
250///
251/// A future normalization at the wire form (see the doc-comment on
252/// [`tombstone_now`] for the full rationale) lands at THIS primitive
253/// alongside [`tombstone_now`] so both anchor shapes inherit the
254/// upgrade mechanically at the same substrate site.
255///
256/// [kdel]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#objectmeta-v1-meta
257#[must_use]
258pub fn tombstone_at(when: DateTime<Utc>) -> Option<Time> {
259    Some(Time(when))
260}
261
262/// Parse an `Option<&str>` as an RFC-3339 wall-clock stamp, discarding
263/// the `ParseError` arm on the parseable-input axis. The one-line
264/// `<opt>.and_then(|s| chrono::DateTime::parse_from_rfc3339(s).ok())`
265/// chain lifted to ONE typed owner past the ★★ PRIME-DIRECTIVE ≥ 2
266/// duplication threshold, and the sibling of every timed-decision
267/// assertion / API-input parser that reads an RFC-3339 stamp out of a
268/// JSON slot, an HTTP query param, or a K8s `status`-subresource value.
269///
270/// Pre-lift the SAME chain was hand-authored at 7 workspace-wide sites
271/// across `tatara-reconciler::patch` — the wire-body substrate tests
272/// pinning the `phase_status_base` / `phase_status_msg` /
273/// `phase_status_with` sibling family's `phaseSince` slot at
274/// fail-before-pass-after granularity:
275///
276/// * 3 sites walk `.and_then(Value::as_str).and_then(|s|
277///   chrono::DateTime::parse_from_rfc3339(s).ok())` to lift the parsed
278///   `DateTime<FixedOffset>` for a `[before, after]` bracket check that
279///   proves the primitive stamped at call time.
280/// * 4 sites walk `.and_then(Value::as_str).is_some_and(|s|
281///   chrono::DateTime::parse_from_rfc3339(s).is_ok())` inside an
282///   `assert!` that pins the slot's shape as "present + parses as
283///   RFC-3339". The `bool` derives from `parse_rfc3339_opt(<opt>)
284///   .is_some()`.
285///
286/// All 7 sites walked the SAME two-link chain — take an `Option<&str>`
287/// (typically from a `serde_json::Value::as_str` cast), then parse the
288/// inner `&str` as RFC-3339 and discard the `Err` arm. Post-lift each
289/// callsite reads `parse_rfc3339_opt(<opt>)` (with `.is_some()` at the
290/// 4 predicate sites) and the parser + `Result::ok()` discard sinks
291/// live at ONE substrate owner.
292///
293/// Return-form axis: `Option<DateTime<FixedOffset>>` matches
294/// `chrono::DateTime::parse_from_rfc3339`'s own return type — every
295/// consumer that wants a `DateTime<Utc>` composes `.map(|dt| dt
296/// .with_timezone(&chrono::Utc))` at its own site (the shape the
297/// production `list_events` handlers at `tatara-api::rest::list_events`
298/// + `tatara-testing::server::list_events` already walk), keeping the
299/// timezone-normalization axis at the caller rather than baking a
300/// specific `Utc` cast into the primitive.
301///
302/// A future normalization (a relaxed RFC-3339 profile that accepts a
303/// `space`-separated date/time separator, a per-fleet clock-skew Δ
304/// that rejects stamps too far in the future, a debug-build assertion
305/// that the caller has already trimmed surrounding whitespace) lands
306/// at THIS ONE substrate primitive and every downstream consumer
307/// inherits the upgrade mechanically — no per-site edit at any of the
308/// 7 listed callers or at future consumers (a `/proc`-table READ-side
309/// timestamp reader, a compliance-binding freshness gate, a probe-
310/// receipt `verified_at` field parser).
311#[must_use]
312pub fn parse_rfc3339_opt(s: Option<&str>) -> Option<DateTime<FixedOffset>> {
313    s.and_then(|s| DateTime::parse_from_rfc3339(s).ok())
314}
315
316/// A `DateTime<Utc>` anchor at the whole-second Unix epoch offset
317/// `secs` — the one-line `DateTime::<Utc>::from_timestamp(secs, 0)
318/// .expect("valid epoch second")` chain lifted to ONE typed owner past
319/// the ★★ PRIME-DIRECTIVE ≥ 2 duplication threshold, and the
320/// deterministic-anchor peer of the wall-clock-reading composers
321/// [`seconds_ago`] / [`tombstone_now`] on the same `→ DateTime<Utc>`
322/// axis.
323///
324/// Pre-lift the SAME chain was hand-authored at 10 workspace-wide
325/// fixture / helper sites within `tatara-process`, each restating the
326/// whole-second `DateTime::<Utc>::from_timestamp(<secs>, 0)
327/// .unwrap()` / `.expect(...)` shape to seed a deterministic anchor
328/// that a fanout / composition / preservation pin can compare
329/// verbatim (differing only in the whole-second `secs` argument and
330/// in the `.unwrap()` vs `.expect("valid epoch second")` failure
331/// arm):
332///
333/// * `tatara-process::time::tests::t` — the private test helper
334///   `fn t(secs: i64) -> DateTime<Utc>` inside this module's own
335///   tests, called out of every `elapsed_since` composition pin;
336///   swept the `secs = 100 / 160 / 200 / 500` corners.
337/// * `tatara-process::pool::tests::member` — the 3rd-arg
338///   `entered_state_at` seed for the `PoolMember::unallocated` test
339///   helper feeding the `state_count_fanout` / `process_names_set`
340///   pin family; pinned at `secs = 0`.
341/// * `tatara-process::pool::tests::named_member` — the peer
342///   `named_member(process_name, state)` helper feeding the
343///   `process_names_set` deduplication pins; pinned at `secs = 0`.
344/// * `tatara-process::pool::tests::pool_status_observed_composes_
345///   pre_lift_status_seed_verbatim` — the `now` anchor for the
346///   `PoolStatus::observed` composition pin; pinned at `secs =
347///   1_700_000_000` (a mid-2023 wall-clock timestamp).
348/// * `tatara-process::pool::tests::pool_status_observed_moves_
349///   members_by_value_without_extra_clone` — the `now` anchor for
350///   the ownership pin; pinned at `secs = 0`.
351/// * `tatara-process::pool::tests::pool_member_unallocated_fills_
352///   every_slot_verbatim` — the positional-axis pin anchor; pinned
353///   at `secs = 1_700_000_000`.
354/// * `tatara-process::pool::tests::pool_member_unallocated_accepts_
355///   owned_string_and_str_at_the_same_signature` — the `impl
356///   Into<String>` axis pin anchor; pinned at `secs = 0`.
357/// * `tatara-process::pool::tests::pool_member_unallocated_matches_
358///   pre_lift_struct_literal_bytewise` — the byte-shape parity pin
359///   anchor swept across every `MemberState` variant; pinned at
360///   `secs = 1_700_000_000`.
361/// * `tatara-process::pool::tests::pool_member_unallocated_
362///   preserves_caller_clock_anchor` — TWO anchors on the
363///   epoch-vs-future axis, pinned at `secs = 0` and `secs =
364///   2_000_000_000` (a mid-2033 wall-clock timestamp).
365///
366/// All 10 sites walked the SAME two-link chain — build a UTC
367/// `DateTime` from a whole-second Unix epoch offset, then discard
368/// the `None` arm via `.unwrap()` / `.expect(...)` — differing only
369/// in the second-count `secs` and in the failure-arm phrasing.
370/// Post-lift each callsite reads `at_epoch_second(N)` and the
371/// `chrono::DateTime::<Utc>::from_timestamp` construction + `None`-
372/// arm discard sinks live at ONE substrate owner.
373///
374/// Return-form axis: `DateTime<Utc>` — the copy-form anchor every
375/// consumer's downstream `signed_duration_since` / [`elapsed_since`]
376/// / [`tombstone_at`] / `PoolMember::unallocated(<name>, <state>,
377/// <anchor>)` composer takes as its `DateTime<Utc>`-typed operand.
378/// The `i64` `secs` parameter matches `chrono::DateTime::<Utc>::
379/// from_timestamp`'s own signature so a negative value (rare but
380/// permitted for pre-epoch anchors) or a value past `i64::MAX / 2`
381/// (also rare) yields whatever chrono itself yields, preserving the
382/// pre-lift semantics verbatim on every corner every caller cared
383/// about.
384///
385/// Failure-arm axis: `.expect("valid epoch second")` — matches the
386/// module-internal helper's phrasing (which every existing
387/// `elapsed_since` composition pin already routed through) rather
388/// than pool.rs's `.unwrap()` phrasing. The composer is
389/// `#[must_use]` and consumers write `at_epoch_second(N)` inline; a
390/// caller that specifically needed the `.unwrap()` message can still
391/// panic via the primitive because `chrono::DateTime::<Utc>::
392/// from_timestamp` returns `Option<Self>` on the exact SAME
393/// out-of-range corner — the `.expect(...)` phrasing sharpens the
394/// panic message without changing the panic condition.
395///
396/// Sibling to [`seconds_ago`] on the `→ DateTime<Utc>` axis:
397/// `seconds_ago` reads the wall clock at call time and returns an
398/// anchor `N` seconds before it (a production timed-decision seed),
399/// `at_epoch_second` reads a caller-supplied whole-second Unix epoch
400/// offset and returns the anchor deterministically (a test-fixture /
401/// deterministic-composition seed). The two composers partition the
402/// `→ DateTime<Utc>` axis at the (wall-clock, deterministic) split
403/// and cover it end-to-end at the substrate.
404///
405/// A future normalization (a per-fleet millisecond-precision
406/// truncation on the anchor, a debug-build assertion that `secs` is
407/// in a permitted window, a swap of the underlying
408/// `chrono::DateTime::<Utc>::from_timestamp` for a
409/// `TryFrom<UnixEpochSeconds>` typed alternative that pushes the
410/// out-of-range corner into the type system) lands at THIS ONE
411/// substrate primitive and every downstream consumer inherits the
412/// upgrade mechanically — no per-site edit at any of the 10 listed
413/// callers or at future consumers (a stable-name claim-arbiter's
414/// deterministic-anchor fixture, a compliance-binding freshness-gate
415/// test seed, a probe-receipt `verified_at` field's deterministic
416/// fixture).
417#[must_use]
418pub fn at_epoch_second(secs: i64) -> DateTime<Utc> {
419    DateTime::<Utc>::from_timestamp(secs, 0).expect("valid epoch second")
420}
421
422#[cfg(test)]
423mod tests {
424    use super::*;
425
426    fn t(secs: i64) -> DateTime<Utc> {
427        // The whole-second epoch anchor rides through the ONE
428        // substrate owner `at_epoch_second` (peer of the 10 workspace-
429        // wide restatements of the SAME
430        // `DateTime::<Utc>::from_timestamp(<secs>, 0).expect(...)` /
431        // `.unwrap()` fixture chain that pre-lift lived at every
432        // deterministic-anchor test helper in this crate — this
433        // module's own tests + `pool::tests::{member, named_member,
434        // pool_status_observed_composes_pre_lift_status_seed_verbatim,
435        // pool_status_observed_moves_members_by_value_without_extra_
436        // clone, pool_member_unallocated_*}`).
437        at_epoch_second(secs)
438    }
439
440    #[test]
441    fn anchor_before_now_returns_positive_delta() {
442        // The canonical shape every consumer rides through — `anchor`
443        // stamped in the past, `now` fixed later, the elapsed duration
444        // available for comparison against a `humantime`-parsed budget.
445        // Pin: the returned duration is exactly the second-count delta
446        // between the two anchors, in `std::time::Duration` so the
447        // downstream `elapsed >= ttl` / `elapsed > free_ttl` comparator
448        // works without a per-consumer conversion.
449        let anchor = t(100);
450        let now = t(160);
451        assert_eq!(elapsed_since(now, anchor), Some(Duration::from_secs(60)));
452    }
453
454    #[test]
455    fn anchor_equals_now_returns_zero_duration() {
456        // Boundary corner: `now == anchor` yields `Some(Duration::ZERO)`
457        // rather than `None`. Every consumer needs the "just-stamped"
458        // moment to count as elapsed=0 (not as "no elapsed data"): the
459        // TTL-expiry gate at `evaluate` fires iff `elapsed >= ttl`, so
460        // a zero-ttl ephemeral must expire on its own creation instant
461        // — swapping this arm to `None` would silently keep every
462        // zero-TTL Process alive.
463        let same = t(500);
464        assert_eq!(elapsed_since(same, same), Some(Duration::ZERO));
465    }
466
467    #[test]
468    fn anchor_after_now_returns_none() {
469        // The clock-skew / mis-sequenced-anchor corner: `anchor > now`
470        // yields `None`. Every consumer interprets `None` as "don't
471        // fire the timed action this tick" — the TTL-expiry gate skips
472        // the `AutoTerminate::Now` branch, the sleep-budget picker
473        // returns the caller's `default`, the pool staleness gate
474        // leaves the member off the stale-Free list. A regression that
475        // returned a saturating `Duration::ZERO` for this corner would
476        // silently fire a zero-TTL ephemeral's expiry the moment its
477        // creation timestamp landed one Kubelet clock-skew millisecond
478        // ahead of the reconciler's `now`.
479        let anchor = t(200);
480        let now = t(100);
481        assert_eq!(elapsed_since(now, anchor), None);
482    }
483
484    #[test]
485    fn subsecond_precision_survives_the_to_std_cast() {
486        // The `chrono::Duration → std::time::Duration` cast preserves
487        // subsecond precision — a regression that silently truncated
488        // to whole seconds would compare an "elapsed = 500ms" against
489        // a `humantime::parse_duration("1s")` budget as "0s < 1s"
490        // rather than "500ms < 1s" and misfire on any decision whose
491        // budget straddles a second boundary. Pin the cast at the
492        // primitive so a future normalization can't silently drop the
493        // subsecond bits.
494        let anchor = DateTime::<Utc>::from_timestamp(100, 0).expect("valid epoch second");
495        let now = DateTime::<Utc>::from_timestamp(100, 500_000_000).expect("valid epoch nanos");
496        assert_eq!(elapsed_since(now, anchor), Some(Duration::from_millis(500)));
497    }
498
499    #[test]
500    fn one_nanosecond_backwards_returns_none() {
501        // The `.to_std().ok()` cast rejects negative chrono deltas by
502        // returning `Err` — one nanosecond of backwards skew is enough
503        // to reach the `None` arm. Pin the boundary at exactly the
504        // point the wire-shape flips so a future normalization that
505        // widens the tolerance (a per-fleet skew Δ, a monotonic-clock
506        // cross-check) has to move THIS pin rather than silently
507        // trampling every consumer's negative-anchor short-circuit.
508        let anchor = DateTime::<Utc>::from_timestamp(100, 1).expect("valid epoch nano");
509        let now = DateTime::<Utc>::from_timestamp(100, 0).expect("valid epoch second");
510        assert_eq!(elapsed_since(now, anchor), None);
511    }
512
513    // ─── seconds_ago substrate pins ────────────────────────────────────
514    //
515    // Bind [`seconds_ago`] at fail-before-pass-after granularity so a
516    // regression that flipped the sign (`+` instead of `-`), swapped
517    // the unit (`minutes` instead of `seconds`), dropped the wall-clock
518    // read to a stale module-load constant, or reshaped the return
519    // form surfaces HERE rather than as silent operator-visible drift
520    // at the 21 downstream consumers.
521
522    #[test]
523    fn seconds_ago_returns_anchor_in_the_past() {
524        // Primary shape asserted end-to-end: the returned anchor lies
525        // between `before` and `after`, offset back by exactly `secs`.
526        // A regression that flipped the sign to `+` would land the
527        // anchor in the future and this window check would fail; a
528        // regression that swapped the unit (minutes / hours) would
529        // land the anchor far outside the sub-second window.
530        let secs = 42_i64;
531        let before = Utc::now();
532        let anchor = seconds_ago(secs);
533        let after = Utc::now();
534        assert!(
535            anchor <= before - chrono::Duration::seconds(secs) + chrono::Duration::milliseconds(50),
536            "anchor {anchor} must be ≤ before − {secs}s (within 50ms scheduler jitter)"
537        );
538        assert!(
539            anchor >= after - chrono::Duration::seconds(secs) - chrono::Duration::milliseconds(50),
540            "anchor {anchor} must be ≥ after − {secs}s (within 50ms scheduler jitter)"
541        );
542    }
543
544    #[test]
545    fn seconds_ago_composes_with_elapsed_since_at_ttl_gate_shape() {
546        // The canonical downstream composition: a consumer seeds an
547        // anchor with `seconds_ago(N)` and immediately feeds it to
548        // `elapsed_since(Utc::now(), anchor)`, expecting the returned
549        // duration to be ~N seconds. A regression that reshaped either
550        // primitive so the two no longer round-trip would surface HERE
551        // rather than as silent skew at the TTL-expiry gate, the pool
552        // staleness gate, or the requeue-budget picker downstream.
553        let secs = 30_i64;
554        let anchor = seconds_ago(secs);
555        let elapsed = elapsed_since(Utc::now(), anchor).expect("elapsed is Some for past anchor");
556        assert!(
557            elapsed >= Duration::from_secs(secs as u64),
558            "elapsed {elapsed:?} must be ≥ {secs}s — the anchor was stamped {secs}s ago"
559        );
560        assert!(
561            elapsed <= Duration::from_secs(secs as u64) + Duration::from_millis(500),
562            "elapsed {elapsed:?} must be within 500ms of {secs}s — a wider drift means the primitive is no longer wall-clock reading"
563        );
564    }
565
566    #[test]
567    fn seconds_ago_matches_hand_authored_pre_lift_chain_shape() {
568        // Byte-identical parity with the pre-lift `Utc::now() -
569        // chrono::Duration::seconds(N)` block that all 21 hand-
570        // authored callsites restated verbatim, swept across the four
571        // representative second-counts every pre-lift consumer used
572        // (small: 5s, medium: 42s, large: 500s, hour-scale: 3600s).
573        // Both blocks read the wall clock at DIFFERENT instants so the
574        // two anchors CAN differ by the wall-clock delta between
575        // calls — bound the divergence at 100ms scheduler jitter.
576        for secs in [5_i64, 42, 500, 3_600] {
577            let composed = seconds_ago(secs);
578            let hand_authored = Utc::now() - chrono::Duration::seconds(secs);
579            let delta = (hand_authored - composed).abs();
580            assert!(
581                delta <= chrono::Duration::milliseconds(100),
582                "composed {composed} and hand-authored {hand_authored} must agree within 100ms scheduler jitter for secs={secs}"
583            );
584        }
585    }
586
587    #[test]
588    fn seconds_ago_zero_returns_anchor_at_current_instant() {
589        // Boundary corner: `secs = 0` yields the current wall-clock
590        // instant — the "just-created" moment. A regression that
591        // synthesized a small offset (`Duration::from_secs(1)` for
592        // clock skew, a per-fleet Δ) would land the anchor 1 second
593        // in the past and every zero-age test seed would be off by
594        // that offset. Pin the identity so a future normalization
595        // has to explicitly move this pin.
596        let before = Utc::now();
597        let anchor = seconds_ago(0);
598        let after = Utc::now();
599        assert!(anchor >= before && anchor <= after);
600    }
601
602    #[test]
603    fn seconds_ago_negative_returns_anchor_in_the_future() {
604        // Corner: a negative `secs` yields a future anchor. Matches
605        // `chrono::Duration::seconds`'s own signed semantics — a
606        // consumer that wants a future-offset anchor (rare, but the
607        // few tests that stamp `Utc::now() + chrono::Duration::
608        // seconds(...)` for `fallback` construction can route through
609        // this primitive with a negative argument). A regression that
610        // clamped the negative arm to `Utc::now()` (or panicked) would
611        // silently break future callers.
612        let anchor = seconds_ago(-10);
613        let now = Utc::now();
614        assert!(
615            anchor >= now,
616            "negative secs must yield a future anchor: anchor {anchor} vs now {now}"
617        );
618        assert!(
619            anchor <= now + chrono::Duration::seconds(11),
620            "anchor {anchor} must be within (10s + jitter) after now {now}"
621        );
622    }
623
624    // ─── tombstone_now + tombstone_at substrate pins ──────────────────
625    //
626    // Bind the two K8s-wire tombstone composers at fail-before-pass-
627    // after granularity so a regression that dropped the `Some` wrap
628    // (yielding `Option<Time>` = `None`, which would silently un-
629    // tombstone every fixture), swapped the `Time` newtype for a raw
630    // `DateTime<Utc>` (breaking the `metadata.deletion_timestamp: Option<Time>`
631    // slot's shape), or diverged the two composers on the anchor axis
632    // (a `tombstone_at(when)` that ignored `when` and read the wall
633    // clock, an anchor-invariant that clamped a future anchor into
634    // the past) surfaces HERE rather than as silent operator-facing
635    // skew at the 12 downstream fixture consumers.
636    //
637    // Each pin is fail-before-pass-after: the primitives did not exist
638    // pre-lift, so any test that invokes them fails to compile pre-
639    // lift and passes post-lift; the byte-identity pins below then
640    // bind the specific shape choice.
641
642    #[test]
643    fn tombstone_now_returns_some_time_at_current_instant() {
644        // Primary shape asserted end-to-end: the returned option is
645        // `Some(Time(anchor))` with the anchor bracketed by two
646        // wall-clock reads taken immediately before + after the call.
647        // A regression that dropped the `Some` wrap would fail the
648        // outer `is_some()` probe; a regression that stamped a
649        // constant (module-load `Utc::now()`, a `DateTime::<Utc>::
650        // default()` = epoch) would fail the bracket check.
651        let before = Utc::now();
652        let stamp = tombstone_now();
653        let after = Utc::now();
654        let stamped = stamp.expect("tombstone_now must return Some(Time(...))");
655        assert!(
656            stamped.0 >= before && stamped.0 <= after,
657            "tombstone anchor {} must fall in [{before}, {after}]",
658            stamped.0,
659        );
660    }
661
662    #[test]
663    fn tombstone_now_matches_hand_authored_pre_lift_chain_shape() {
664        // Byte-identical parity with the pre-lift
665        // `Some(k8s_openapi::apimachinery::pkg::apis::meta::v1::Time(
666        // Utc::now()))` block that all 11 hand-authored fixture sites
667        // restated verbatim (differing only in `chrono::Utc` vs `Utc`
668        // module-path prefix). Both blocks read the wall clock at
669        // DIFFERENT instants so the two anchors CAN differ by the
670        // wall-clock delta between calls — bound the divergence at
671        // 100ms scheduler jitter, matching the peer
672        // `seconds_ago_matches_hand_authored_pre_lift_chain_shape`
673        // pin's tolerance.
674        let composed = tombstone_now().expect("tombstone_now returns Some");
675        let hand_authored = Some(Time(Utc::now())).expect("hand-authored fixture");
676        let delta = (hand_authored.0 - composed.0).abs();
677        assert!(
678            delta <= chrono::Duration::milliseconds(100),
679            "composed {} and hand-authored {} must agree within 100ms scheduler jitter",
680            composed.0,
681            hand_authored.0,
682        );
683    }
684
685    #[test]
686    fn tombstone_at_returns_some_time_preserving_the_operator_anchor() {
687        // Primary shape for the anchor-explicit peer: the returned
688        // option is `Some(Time(when))` and the anchor is exactly the
689        // `when` argument — no wall-clock read, no normalization, no
690        // clamp. A regression that fell through to the current instant
691        // (`tombstone_at` ignoring `when` and re-reading the wall
692        // clock) would fail the identity check.
693        let epoch = DateTime::<Utc>::from_timestamp(1_700_000_000, 0).expect("valid epoch second");
694        let stamp = tombstone_at(epoch).expect("tombstone_at returns Some");
695        assert_eq!(stamp.0, epoch, "anchor must be preserved verbatim");
696    }
697
698    #[test]
699    fn tombstone_at_composes_with_seconds_ago_at_stale_fixture_shape() {
700        // The canonical downstream composition: a fixture that needs a
701        // "stamped N seconds ago" tombstone composes `tombstone_at(
702        // seconds_ago(N))` and expects the returned anchor to be ~N
703        // seconds in the past. Matches the single pre-lift site at
704        // `lib.rs::deletion_tombstoned_tests::is_being_deleted_matches_pre_lift_deletion_timestamp_is_some_chain_on_ephemeral_allocation`
705        // which stamps `Some(Time(crate::time::seconds_ago(3600)))`.
706        // A regression that reshaped either primitive so the two no
707        // longer round-trip would surface HERE rather than as silent
708        // skew at the stale-tombstone fixture family.
709        let secs = 3_600_i64;
710        let anchor = seconds_ago(secs);
711        let stamp = tombstone_at(anchor).expect("tombstone_at returns Some");
712        assert_eq!(
713            stamp.0, anchor,
714            "tombstone_at must preserve the seconds_ago-produced anchor verbatim",
715        );
716        // And the anchor is ~N seconds in the past — this is the
717        // downstream property every fixture using the composition
718        // relies on.
719        let elapsed = elapsed_since(Utc::now(), stamp.0).expect("elapsed is Some for past anchor");
720        assert!(
721            elapsed >= Duration::from_secs(secs as u64),
722            "elapsed {elapsed:?} must be ≥ {secs}s — the anchor was stamped {secs}s ago",
723        );
724    }
725
726    #[test]
727    fn tombstone_now_and_tombstone_at_agree_at_the_current_instant() {
728        // Cross-composer coherence pin: `tombstone_now()` and
729        // `tombstone_at(Utc::now())` produce the SAME shape (`Some(
730        // Time(...))`) with anchors that agree within scheduler jitter.
731        // A future refactor that consolidated one composer onto the
732        // other (or split them further) cannot land any anchor-axis
733        // drift because this pin binds them at the current-instant
734        // corner where both callsites converge.
735        let a = tombstone_now().expect("tombstone_now returns Some");
736        let b = tombstone_at(Utc::now()).expect("tombstone_at returns Some");
737        let delta = (b.0 - a.0).abs();
738        assert!(
739            delta <= chrono::Duration::milliseconds(100),
740            "tombstone_now anchor {} and tombstone_at(Utc::now()) anchor {} must agree within 100ms scheduler jitter",
741            a.0,
742            b.0,
743        );
744    }
745
746    // ─── parse_rfc3339_opt substrate pins ───────────────────────────
747    //
748    // Bind [`parse_rfc3339_opt`] at fail-before-pass-after granularity
749    // so a regression that swallowed the `Some(_)` arm (yielding
750    // `None` on a well-formed stamp), swapped the parser for a
751    // rfc2822/naive/ISO-8601-only variant (silently rejecting the
752    // `+00:00` offset every K8s `metadata.Time.0` serialiser emits),
753    // or flipped the `.ok()` discard for a `.unwrap()` (panicking on
754    // malformed input rather than short-circuiting at the caller's
755    // `.expect(...)`) surfaces HERE rather than as silent operator-
756    // facing drift at the 7 downstream `phaseSince`-slot pins.
757    //
758    // Each pin is fail-before-pass-after: the primitive did not exist
759    // pre-lift, so any test that invokes it fails to compile pre-lift
760    // and passes post-lift; the byte-identity pins below then bind
761    // the specific shape choice.
762
763    #[test]
764    fn parse_rfc3339_opt_returns_some_datetime_on_well_formed_utc_stamp() {
765        // Primary shape asserted end-to-end: a well-formed `+00:00`
766        // stamp (the exact wire form every K8s `metadata.Time`
767        // serialiser emits, and every `phaseSince`-stamped
768        // `Utc::now()` produces once serialised via `serde_json` into
769        // a `Value`) parses to `Some(dt)` with the anchor preserved
770        // verbatim.
771        let stamp = "2026-05-01T12:34:56+00:00";
772        let parsed = parse_rfc3339_opt(Some(stamp)).expect("well-formed RFC-3339 stamp");
773        let expected =
774            DateTime::parse_from_rfc3339(stamp).expect("hand-authored fixture is well-formed");
775        assert_eq!(parsed, expected);
776    }
777
778    #[test]
779    fn parse_rfc3339_opt_passes_none_through_verbatim() {
780        // The `Option::and_then` short-circuit: a `None` input flows
781        // straight to `None` output without touching the parser. A
782        // regression that expected `Some(_)` unconditionally
783        // (`unwrap_or_default` on the input, an early `.unwrap()`)
784        // would panic HERE rather than at the caller's `.expect(...)`.
785        assert_eq!(parse_rfc3339_opt(None), None);
786    }
787
788    #[test]
789    fn parse_rfc3339_opt_discards_the_err_arm_on_malformed_input() {
790        // The `.ok()` discard arm: a `Some(&str)` that isn't RFC-3339
791        // flows to `None` — the caller's `.is_some()` predicate then
792        // returns `false` for the "present-but-malformed" corner. A
793        // regression that panicked (`unwrap`) or bubbled the
794        // `ParseError` (a `Result` return form) would break every
795        // predicate-site assertion that reads the return as a bool.
796        assert_eq!(parse_rfc3339_opt(Some("not-a-timestamp")), None);
797        assert_eq!(parse_rfc3339_opt(Some("")), None);
798        // A naive-only shape (no offset) — RFC-3339 requires the
799        // offset, so this must land on the `None` arm.
800        assert_eq!(parse_rfc3339_opt(Some("2026-05-01T12:34:56")), None);
801    }
802
803    #[test]
804    fn parse_rfc3339_opt_matches_hand_authored_pre_lift_chain_shape() {
805        // Byte-identical parity with the pre-lift `<opt>.and_then(|s|
806        // chrono::DateTime::parse_from_rfc3339(s).ok())` block all 7
807        // hand-authored callsites restated verbatim, swept across the
808        // four representative corners: a well-formed `Some(&str)`, a
809        // `None`, a `Some("")`, and a `Some(<malformed>)`. Both blocks
810        // must project the SAME `Option<DateTime<FixedOffset>>` on
811        // every corner so the collapse is observationally invisible.
812        for (opt, name) in [
813            (Some("2026-05-01T12:34:56+00:00"), "well-formed +00:00"),
814            (Some("2026-05-01T12:34:56.789012345+00:00"), "sub-second"),
815            (Some("2026-05-01T12:34:56-05:00"), "non-UTC offset"),
816            (Some("2026-05-01T12:34:56Z"), "Z-form UTC"),
817            (Some(""), "empty string"),
818            (Some("not-a-timestamp"), "malformed"),
819            (None, "none input"),
820        ] {
821            let composed = parse_rfc3339_opt(opt);
822            let hand_authored = opt.and_then(|s| DateTime::parse_from_rfc3339(s).ok());
823            assert_eq!(
824                composed, hand_authored,
825                "corner `{name}` must round-trip through both shapes",
826            );
827        }
828    }
829
830    #[test]
831    fn parse_rfc3339_opt_is_some_derives_the_predicate_shape() {
832        // The `.is_some()` composition on the primitive's return is
833        // the byte-identical replacement for the pre-lift `<opt>
834        // .is_some_and(|s| chrono::DateTime::parse_from_rfc3339(s)
835        // .is_ok())` chain the 4 predicate-site pins walked. Sweep
836        // the four representative corners: present-and-well-formed,
837        // present-but-malformed, present-but-empty, absent. A
838        // regression that flipped the primitive's `None`-on-malformed
839        // arm to `Some(default)` would silently pass the malformed
840        // corner past every predicate-site assertion.
841        for (opt, expected, name) in [
842            (Some("2026-05-01T12:34:56+00:00"), true, "well-formed"),
843            (Some("not-a-timestamp"), false, "malformed"),
844            (Some(""), false, "empty string"),
845            (None, false, "none input"),
846        ] {
847            assert_eq!(
848                parse_rfc3339_opt(opt).is_some(),
849                expected,
850                "corner `{name}` must project to `{expected}` through the predicate shape",
851            );
852        }
853    }
854
855    #[test]
856    fn parse_rfc3339_opt_round_trips_a_freshly_stamped_utc_now() {
857        // The canonical downstream composition: a `Utc::now()` stamp
858        // serialised via `chrono::DateTime::to_rfc3339` — the shape
859        // every `phaseSince` slot the reconciler stamps writes onto
860        // the wire — parses back through this primitive to a
861        // `DateTime<FixedOffset>` whose UTC-normalised anchor agrees
862        // with the source stamp bytewise. Pin the round-trip identity
863        // so a future normalization (a millisecond-precision
864        // truncation, a per-fleet skew Δ) cannot silently drift the
865        // reader off the writer at the reconciler's own `phaseSince`
866        // wire.
867        let source = Utc::now();
868        let wire = source.to_rfc3339();
869        let parsed = parse_rfc3339_opt(Some(&wire)).expect("Utc::now → to_rfc3339 must round-trip");
870        assert_eq!(parsed.with_timezone(&Utc), source);
871    }
872
873    #[test]
874    fn tombstone_at_preserves_a_future_anchor_without_clamping() {
875        // Corner: `tombstone_at` accepts a future anchor verbatim —
876        // matches the pre-lift `Some(Time(<future>))` shape a caller
877        // wanting a future-offset tombstone would hand-author. Pin the
878        // identity so a future normalization that clamps the anchor
879        // into the past (a "no tombstone can be in the future" policy)
880        // has to explicitly move this pin rather than silently
881        // trampling future callers.
882        let future = Utc::now() + chrono::Duration::seconds(3_600);
883        let stamp = tombstone_at(future).expect("tombstone_at returns Some");
884        assert_eq!(stamp.0, future);
885    }
886
887    // ─── at_epoch_second substrate pins ───────────────────────────────
888    //
889    // Bind [`at_epoch_second`] at fail-before-pass-after granularity so
890    // a regression that drifted the nanosecond slot off the whole-
891    // second axis (a `from_timestamp(secs, 1)` typo that stamps a
892    // 1-ns offset into every deterministic fixture), swapped the
893    // `.expect(...)` for a saturating fallback (yielding
894    // `DateTime::<Utc>::default()` = epoch on the out-of-range corner
895    // rather than panicking), or reshaped the return form off
896    // `DateTime<Utc>` (e.g., to `DateTime<FixedOffset>`) surfaces HERE
897    // rather than as silent operator-invisible drift at the 10
898    // downstream fixture consumers.
899    //
900    // Each pin is fail-before-pass-after: the primitive did not exist
901    // pre-lift, so any test that invokes it fails to compile pre-lift
902    // and passes post-lift; the byte-identity pins below then bind the
903    // specific shape choice.
904
905    #[test]
906    fn at_epoch_second_returns_utc_datetime_at_whole_second_offset() {
907        // Primary shape asserted end-to-end: the returned anchor is
908        // exactly `secs` whole seconds past the Unix epoch, with no
909        // nanosecond component. A regression that stamped a stray
910        // nanosecond slot (a `from_timestamp(secs, 1)` typo, a
911        // per-fleet skew Δ added below the composer) would surface
912        // here as a non-zero `.timestamp_subsec_nanos()`.
913        let anchor = at_epoch_second(1_700_000_000);
914        assert_eq!(anchor.timestamp(), 1_700_000_000);
915        assert_eq!(anchor.timestamp_subsec_nanos(), 0);
916    }
917
918    #[test]
919    fn at_epoch_second_matches_hand_authored_pre_lift_chain_shape() {
920        // Byte-identical parity with the pre-lift `DateTime::<Utc>::
921        // from_timestamp(<secs>, 0).unwrap()` / `.expect(...)` block
922        // that all 10 hand-authored callsites restated verbatim,
923        // swept across the four representative second-counts every
924        // pre-lift consumer used: `0` (the epoch anchor), `100` (the
925        // `elapsed_since` composition pin anchor), `1_700_000_000`
926        // (the mid-2023 wall-clock anchor), and `2_000_000_000` (the
927        // mid-2033 future anchor). Both blocks must project the SAME
928        // `DateTime<Utc>` on every corner so the collapse is
929        // observationally invisible.
930        for secs in [0_i64, 100, 1_700_000_000, 2_000_000_000] {
931            let composed = at_epoch_second(secs);
932            let hand_authored = DateTime::<Utc>::from_timestamp(secs, 0)
933                .expect("hand-authored fixture is well-formed");
934            assert_eq!(
935                composed, hand_authored,
936                "corner `secs={secs}` must round-trip through both shapes",
937            );
938        }
939    }
940
941    #[test]
942    fn at_epoch_second_is_deterministic_across_repeated_calls() {
943        // Determinism pin: `at_epoch_second` does NOT read the wall
944        // clock — every call with the SAME `secs` produces byte-
945        // identical anchors, in contrast to the sibling
946        // [`seconds_ago`] / [`tombstone_now`] wall-clock-reading
947        // peers. A regression that started stamping the composer's
948        // own `Utc::now()` (a fallback default, a per-call skew) would
949        // silently defeat every fanout / composition / preservation
950        // pin that relies on the anchor being replayable.
951        let first = at_epoch_second(500);
952        let second = at_epoch_second(500);
953        assert_eq!(
954            first, second,
955            "at_epoch_second must be deterministic — no wall-clock read",
956        );
957    }
958
959    #[test]
960    fn at_epoch_second_partitions_the_datetime_axis_against_seconds_ago() {
961        // Cross-composer partition pin: `at_epoch_second` and
962        // [`seconds_ago`] both produce `DateTime<Utc>` but partition
963        // the axis at the (deterministic, wall-clock-reading) split —
964        // `at_epoch_second(0)` is byte-identical across two calls,
965        // `seconds_ago(0)` drifts by the scheduler jitter between two
966        // calls. A regression that merged either primitive onto the
967        // other (a `seconds_ago` that started reading a module-load
968        // constant, an `at_epoch_second` that started subtracting from
969        // `Utc::now`) would collapse the partition and surface here.
970        let a = at_epoch_second(0);
971        let b = at_epoch_second(0);
972        assert_eq!(a, b, "at_epoch_second is deterministic");
973        let live_1 = seconds_ago(0);
974        // Do not compare `live_1` to `a` bytewise — the two live at
975        // different points on the `DateTime<Utc>` axis by design.
976        // Instead, pin that the deterministic anchor equals the epoch
977        // (a live wall-clock read is unambiguously past the epoch on
978        // any post-2020 system clock).
979        assert_eq!(a.timestamp(), 0, "at_epoch_second(0) is the Unix epoch");
980        assert!(
981            live_1.timestamp() > 0,
982            "seconds_ago(0) reads the wall clock, which is unambiguously past the epoch",
983        );
984    }
985
986    #[test]
987    fn at_epoch_second_composes_with_tombstone_at_at_deterministic_fixture_shape() {
988        // The canonical downstream composition: a fixture that needs a
989        // deterministic tombstone at a fixed epoch offset composes
990        // `tombstone_at(at_epoch_second(N))` and expects the returned
991        // anchor to be exactly `N` seconds past the Unix epoch. A
992        // regression that reshaped either primitive so the two no
993        // longer round-trip would surface HERE rather than as silent
994        // skew at the deterministic-tombstone fixture family.
995        let anchor = at_epoch_second(1_700_000_000);
996        let stamp = tombstone_at(anchor).expect("tombstone_at returns Some");
997        assert_eq!(
998            stamp.0, anchor,
999            "tombstone_at must preserve the at_epoch_second-produced anchor verbatim",
1000        );
1001        assert_eq!(stamp.0.timestamp(), 1_700_000_000);
1002        assert_eq!(stamp.0.timestamp_subsec_nanos(), 0);
1003    }
1004}