1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
//! Substrate primitive for the `Api::namespaced::<Process>` binding
//! every workspace consumer of the tatara `Process` CRD reaches for
//! when it needs a namespace-scoped typed handle from a bare
//! [`Client`] + `&str` namespace pair (no per-crate reconciler
//! context in scope).
//!
//! Owns the 1-link chain
//!
//! ```text
//! let api: Api<Process> = Api::namespaced(<client>, <ns>);
//! ```
//!
//! that every below-controller-layer + boundary-layer Process-handle
//! consumer hand-authored pre-lift at each namespace-scoped bind site.
//!
//! Sibling to the ns-scoped K8s-typed-handle family already lifted at:
//! - [`crate::configmap::namespaced`] — the K8s built-in ConfigMap
//! ns-scoped handle binder, opened for the same
//! `tatara-export-worker` + `tatara-closed-loop-probe` consumers
//! that could not thread through a shared reconciler context.
//! - `tatara_reconciler::context::Context::process_api` — the
//! reconciler's per-request Process-typed handle binder (kept as a
//! forwarder that delegates through THIS substrate primitive
//! post-lift, so a future normalization at the substrate owner
//! reaches BOTH the reconciler-side handler sprawl AND every
//! below-controller boundary/export-worker consumer through ONE
//! owner).
//! - `tatara_pool_reconciler::context::PoolContext::{pool_api,
//! allocation_api,pools_all_api,allocations_all_api}` — the
//! pool-reconciler's tatara-CRD-typed handle binders.
//! - `tatara_github_watcher::handler::HandlerState::allocation_api`
//! — the github-watcher's per-request allocation-typed handle
//! binder.
//!
//! All sibling lifts closed the `Api::namespaced(<client>.clone(),
//! <ns>)` shape at either a controller-owned context struct (per-CRD
//! binder) or a workspace-wide substrate module (per-K8s-built-in
//! binder). This primitive closes the SAME shape at the tatara
//! `Process` CRD for the THREE consumer sites that neither own a
//! reconciler context nor thread through a shared per-request
//! state:
//! - `tatara_reconciler::boundary::evaluate_process_phase` — the
//! `ConditionKind::ProcessPhase` boundary evaluator. Called with
//! a bare `Client` moved in from `check_conditions` (no `Context`
//! in scope; the evaluator sits below the reconciler layer so it
//! can be reused by the `tatara-check` binary).
//! - `tatara_reconciler::boundary::check_depends_on` — the
//! `spec.dependsOn` evaluator. Iterates every dep with a
//! `client.clone()` per row; also called from the boundary layer
//! without a `Context`.
//! - `tatara_export_worker::main::read_artifact` — the export
//! worker's `ProcessSnapshotSource` reader. `tatara-export-worker`
//! is a below-controller-layer binary that DOES NOT depend on
//! `tatara-reconciler` (would introduce a cycle) so it cannot
//! reach the reconciler's `Context::process_api`.
//!
//! Pre-lift the 1-link `let api: Api<Process> = Api::namespaced(
//! <client>, <ns>)` chain recurred at THESE THREE hand-authored
//! consumer sites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication
//! threshold. Post-lift each consumer reads
//! `tatara_process::process_api::namespaced(client, ns)` and the
//! ns-scoped Process handle binding lives at ONE substrate owner.
//!
//! ### Naming
//!
//! The module is named [`process_api`] — the tatara-process crate
//! already owns a top-level `crd` module carrying the `Process`
//! type itself, so a bare `process` submodule would collide with
//! the crate's own name and read as an accidental self-reference
//! (`tatara_process::process::namespaced`). `process_api` names the
//! axis it closes ("build a typed `Api` for the tatara `Process`
//! CRD") explicitly, mirrors the reconciler's own `process_api`
//! method on `Context`, and reads unambiguously at every callsite.
//!
//! Fixing the concrete `K = Process` at the primitive lands three
//! guarantees the pre-lift 3-site sprawl could not offer:
//! - the two `use tatara_process::crd::Process;` /
//! `use tatara_process::prelude::*;` imports at the callsite
//! crates are the ONE typed edge to the Process CRD; any future
//! rename or module-path shift lands at ONE substrate primitive
//! rather than at every consumer;
//! - a regression that swapped `Api::namespaced` for `Api::all` at
//! ONE callsite is now structurally impossible — the scope choice
//! is owned by the primitive's name (peer `Api::all` cluster-wide
//! Process consumers route through
//! `tatara_reconciler::context::Context::processes_all_api` on
//! the reconciler side; a future workspace-wide cluster-scoped
//! peer composes as `process_api::all` on this module);
//! - a future migration to `Api::namespaced_with(client, ns, &ar)`
//! (for the same ns-scoped posture through the dynamic-object
//! channel, mirroring `tatara-reconciler::ssapply`'s DynamicObject
//! consumer) lands at ONE point — every downstream consumer
//! inherits the shift mechanically.
use ;
use crateProcess;
/// Bind a namespace-scoped typed [`Api<Process>`] handle for
/// [`Client`] + `ns`.
///
/// Owns the 1-link chain `Api::namespaced(<client>, <ns>)` for the
/// tatara `Process` CRD at ONE substrate owner across every
/// workspace consumer that reads or writes a Process through a
/// typed handle without a shared per-request context in scope.
/// Sibling to the K8s-built-in ns-scoped handle binder
/// [`crate::configmap::namespaced`] and to the reconciler's
/// per-request `Context::process_api` forwarder.
///
/// A future normalization of the Process-handle posture (a
/// default-injected `PatchParams` field manager for status writes,
/// a wired-in tracing span for handle construction, a per-namespace
/// retry budget, a fixture-backed client for CI/smoke-tests) lands
/// at THIS ONE function and every downstream consumer inherits the
/// upgrade mechanically — no per-site edit at any of the three
/// listed callers or at future consumers (a future boundary-layer
/// evaluator for a new `ConditionKind`, a future below-controller
/// binary that reads a Process by name, a future workspace-side
/// audit walker).
///
/// The returned `Api<Process>` matches `Api::namespaced` verbatim
/// — every current consumer chains through `.get_opt(...)` (both
/// boundary-layer evaluators) or `.get(...)` (the export-worker
/// snapshot reader) at its own callsite, so no wire-side posture
/// is baked in at the primitive.
///
/// Theory anchor: THEORY.md §VI.1 (generation over composition —
/// the 1-link `Api::namespaced::<Process>(<client>, <ns>)` chain
/// recurred at 3 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 swapped the fixed `K = Process` type parameter for a
/// different CRD (`EphemeralPool`, `EphemeralAllocation`, `ProcessTable`)
/// or drifted the scope slot away from `Api::namespaced` — a stray
/// `Api::all` cluster-wide read where a namespace-scoped
/// dependency lookup was intended — surfaces at
/// `process_api::tests::*` rather than as silent operator-facing
/// skew across the three consumer sites).