pub fn annotation_body(key: &str, value: impl Serialize) -> ValueExpand description
Compose the merge-patch wire body
{"metadata": {"annotations": {<key>: <value>}}} — the ONE substrate
owner of the single-annotation stamp / strip merge-body shape every
workspace controller reaches for when it needs to publish exactly ONE
operator-visible annotation on the primary resource (or strip one by
stamping Value::Null) through the merge-patch semantics of either
merge or apply.
Pre-lift the wire-shape recurred at THREE hand-authored consumer sites across TWO active workspace crates past the ★★ PRIME-DIRECTIVE ≥ 2 duplication threshold:
tatara-reconciler::signals::ingest— strips thetatara.pleme.io/signalannotation off the Process after ingestion by stampingserde_json::Value::Null(JSON merge patch interpretsnullas “remove key”). Dispatched throughmergeon the primary-resource merge-patch axis.tatara-reconciler::phase_machine::transition_to_releasing— stamps the caller-observedtatara.pleme.io/released-fromannotation with the current phase string on Attested/Failed → Releasing. Dispatched throughapplyon the primary-resource SSA axis (SSAPatch::Applyaccepts the same{"metadata": {"annotations": …}}body shape asPatch::Merge— the top-level slot naming is what this composer owns).tatara-pool-reconciler::controller_allocation(Release arm) — stamps thetatara.pleme.io/return-triggerannotation with the literal"true"on the member Process to nudge the Pool reconciler into taking the return path. Dispatched through the rawApi::patchcall inside the release arm (also withapply_patch_params-composed PatchParams; the wire shape is the same{"metadata": {"annotations": {<one key>: <one value>}}}this composer names).
Post-lift each site reads tatara_process::patch::annotation_body( <key>, <value>) and the merge-body wire-shape composition lives at
ONE substrate owner. A future normalization of the single-annotation
merge-body posture (a canonicalization pass over the key spelling —
a case-fold or a namespace-prefix normalization for a future annotation
naming discipline; a stricter serde-failure return in place of the
silent Value::Null fallback; a by: sibling slot naming the
stamping controller for post-hoc audit; a version-tagged wrap for a
future metadata.v2.annotations migration) lands at THIS ONE function
and every downstream single-annotation writer inherits the upgrade
mechanically. Directly benefits the P3 kenshi-runner library lift
(any Job-based observer that stamps a per-suite annotation on its
owning Process rides through the same composer as the strip / stamp
/ return-trigger family) and the P5 shigoto Dag refactor (every
phase-machine RecordingJob that stamps an annotation on a transition
rides through the same composer).
§Value axis — impl Serialize accepts every pre-lift shape
The value slot is impl Serialize matching the discipline of
[phase_status_with] on the extra-key axis: accepts owned or borrowed
values of any serde-serialisable type without widening the signature.
All three pre-lift consumer sites pass distinct value shapes and this
composer serves each verbatim through serde_json::to_value:
serde_json::Value::Null(signals::ingest strip) — the primitiveserde_json::to_valueround-trips aValue::Nullback toValue::Null, which JSON merge patch interprets as “remove key”.String(phase_machine::transition_to_releasing) — the primitiveserde_json::to_valueserializes aStringto a JSON string verbatim.&'static str(controller_allocation Release arm) — the primitiveserde_json::to_valueserializes a&strto a JSON string verbatim, matching the pre-lift"true"literal.
A serialisation failure resolves to Value::Null, matching the
existing [phase_status_with] primitive’s posture. In practice
serialisation of the shapes this composer accepts (a
serde_json::Value, a String, a &str) never fails; the fallback
is a defensive guard against a future caller passing a T: Serialize
whose Serialize impl signals a runtime error.
§Key axis — &str matches every pre-lift call form
The key slot is &str matching the pre-lift call forms exactly:
crate::annotations::SIGNAL via SIGNAL_ANNOTATION: &str at
signals.rs, crate::annotations::RELEASED_FROM via a pub const: &str at phase_machine.rs, and a "tatara.pleme.io/return-trigger"
literal at controller_allocation.rs. &str accepts both the
pre-existing pub const: &str constants in crate::annotations
and inline &'static str literals at the same signature.
A future caller composing a String key at runtime (a per-fleet
prefix, a runtime-computed annotation name) coerces via &*key
or key.as_str() at the call site — the composer stays borrowed
so the common const-fed path pays no allocation.
§must_use on the return
The primitive exists to be handed to a wire-side write (merge,
apply, or a raw Api::patch call at the pool-reconciler’s
release arm), not to probe the merge-body shape. #[must_use]
keeps a caller from building the body and dropping it un-passed to
a wire dispatcher.
Theory anchor: THEORY.md §VI.1 (generation over composition — the
3-link json!({"metadata": {"annotations": {<key>: <value>}}}) merge-
body composition recurred at 3 hand-authored sites past the ★★
PRIME-DIRECTIVE ≥ 2 duplication trigger, spanning two active
workspace crates, and is lifted onto ONE substrate owner here).
THEORY.md §II.1 invariant 5 (composition preserves proofs — the pin
block below binds the composer at fail-before-pass-after granularity,
so a regression that drifts the top-level metadata slot, the nested
annotations slot, the caller-passed key spelling, or the value-slot
pass-through discipline surfaces HERE rather than as silent
operator-facing annotation-writer skew across the three consumer
sites).