pub fn namespaced<K>(client: Client, ns: &str) -> Api<K>Expand description
Bind a namespace-scoped typed Api<K> handle from an owned
Client + &str namespace for any K that satisfies the
standard kube::Resource projection with a zero-sized
DynamicType (every derive-generated CRD + every K8s built-in
Rust binding meets this bound).
Sibling to all on the (scope × K) axis pair: all owns the
cluster-scoped Api::all(<client>) shape at any K; this owns the
namespace-scoped Api::namespaced(<client>, <ns>) shape at any K.
Both primitives fix the scope choice structurally at the function
name — a caller writes api::all(client) for the cluster-wide
posture or api::namespaced(client, ns) for the namespace-scoped
posture, and a regression that silently drifted one for the other
(a stray Api::all where a namespace-scoped dependency lookup was
intended, an Api::namespaced where a cluster-wide watch was
intended) fails at the callsite’s scope-word rather than as silent
operator-facing skew.
The K type parameter is inferred from the callsite’s return-
type annotation (or its enclosing -> Api<K> signature). Fixed-K
namespaced binders already open at crate::process_api::namespaced
(K = Process) and crate::configmap::namespaced (K = ConfigMap)
delegate through THIS primitive post-lift, so a future
normalization of the ns-scoped Api posture (a default-injected
tracing span for handle construction, a client-side QPS budget, a
per-namespace retry budget, a fixture-backed client for CI/smoke-
tests, a wired-in PatchParams field manager for status writes)
lands at THIS ONE function and every downstream consumer inherits
the upgrade mechanically.
§Pre-lift call-site history
The Api::namespaced(<client>.clone(), <ns>) chain recurred at
SIX hand-authored production sites past the ★★ PRIME-DIRECTIVE ≥ 2
duplication threshold spanning four crates and five distinct K
bindings — three tatara CRDs and two K8s built-ins:
tatara_pool_reconciler::context::PoolContext::pool_api— the namespace-scopedApi<EphemeralPool>binder every pool-side reconcile handler rides through.tatara_pool_reconciler::context::PoolContext::allocation_api— the namespace-scopedApi<EphemeralAllocation>binder every pool-side reconcile handler rides through.tatara_pool_reconciler::context::PoolContext::process_api— the namespace-scopedApi<Process>binder every pool-side reconcile handler rides through when it patches a bound member’s overlay.tatara_github_watcher::handler::HandlerState::allocation_api— the github-watcher’s per-request namespace-scopedApi<EphemeralAllocation>binder.tatara_reconciler::phase_machine::classify_export_jobs— the namespace-scopedApi<Job>binder for the export-watching Verifying-arm reconcile step.tatara_process::process_api::namespaced+tatara_process::configmap::namespaced— the two fixed-K siblings already lifted (K = Process, K = ConfigMap), which now delegate through THIS primitive rather than restatingApi::namespaced(client, ns)at their own bodies.
Each pre-lift site restated Api::namespaced(self.kube.clone(), ns) verbatim, with the .clone() on the ambient Client field
feeding the primitive’s owned-Client slot. Post-lift each consumer
reads tatara_process::api::namespaced::<K>(client, ns) (or
delegates through a fixed-K sibling that itself routes here) and
the ns-scoped typed-handle binding lives at ONE substrate owner
across every CRD binding.
Theory anchor: THEORY.md §VI.1 (generation over composition — the
1-link Api::namespaced::<K>(<client>, <ns>) chain recurred at 6
hand-authored sites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication
trigger and is lifted onto the ONE workspace-wide substrate owner
here). THEORY.md §II.1 invariant 5 (composition preserves proofs —
the pin block below binds the primitive at fail-before-pass-after
granularity, so a regression that drifted the scope slot from
Api::namespaced to Api::all — silently widening a
namespace-scoped dependency lookup into a cluster-wide sweep —
surfaces at api::tests::* rather than as silent operator-facing
skew across the six consumer sites).