HOMELAB-2682: feat(sbx-gits): delivery pin for the tools ConfigMap #870

Merged
pi-landing merged 1 commit from plane/HOMELAB-2682-tools-pin into live 2026-11-06 05:37:03 +00:00
Owner

What this is

The sbx-gits-tools ConfigMap gets a delivery pin. Its content stops following the working tree, so a tools commit cannot reach the running pod by ArgoCD auto-sync any more. It reaches the pod only when somebody moves the pin in a PR.

Why: last night's auto-sync incident

configMapGenerator: sbx-gits-tools carried files: tools/*.sh, with disableNameSuffixHash: true (required: the StatefulSet's sbx-tools volume names the object). A stable name means a generator content change is an in-place update: ArgoCD auto-synced the merge and the kubelet refreshed the projected volume of the pod that was already running, about two minutes later, with no pod restart and no human step. A proof tool whose next consumer was not ready yet therefore arrived ahead of the sequencing condition it depended on, and all GITES merges were blocked for an hour.

The manifest comments said "it lands with the next pod recreation". The cluster did something else.

A written intention isn't a mechanism.

The pin design (Option A)

kustomization.yaml: the sbx-gits-tools generator no longer has files:. Its data is an explicit literals: block whose keys carry the byte content of each of the six tools, keyed exactly as the volume's items[].key (items in statefulset.yaml names them; untouched here). A header comment carries the incident, the mechanism, the pinned sha256 table (per key: sha256 / lines / bytes), and README §10.5 carries the reasoning plus a mechanical, idempotent regeneration recipe (verified: on an up-to-date pin it rewrites the file byte-for-byte).

Why not files: + a hash gate: kustomize has no per-generator content gate, and a name-suffix hash would rename the object the volume names. If delivery must not follow the working tree, the only thing that holds is to stop reading it.

Why not immutable: true: it converts a silent delivery into a blocked sync (Sync=Error on the whole app) and cannot even be moved deliberately without delete+recreate. Rejected.

The pin is what holds delivery; it moves only by editing the block, which is a PR-reviewed act. No vestigial files: entry was left behind to keep a grep green.

Render proof (both directions, kubectl kustomize v5.4.2, strict/default like ArgoCD)

step result
render origin/live (before) vs render with the pin (after) byte-identical, 18583 lines, rc 0 — the pin changes nothing observable today
rendered data values vs tools/*.sh on disk all six byte-identical (android-install 46573B 6ff3f0b9…, smoke 108119B a7b8be87…, lock 16981B 47356e3…, queue 38908B 062d2bb7…, proof 64339B ac29a440…, ci-log 9753B e6c31421…)
(a) pin HOLDS: simulated tool edit — appended a delivered line to tools/gits-sbx-emu-proof.sh and edited line 1 of tools/gits-sbx-emu-smoke.sh (git diff shows both M), then re-render identical render to the un-edited state → ArgoCD has nothing to sync, the pod keeps the pinned bytes. Tool edits reverted.
(b) pin MOVES: one byte changed inside the pinned literal (MAX_MIB=40960 → 51200 in the block) render differs at exactly that line → the pin is movable, not frozen. Block restored; render identical again.

Expected harness reds (and what I did NOT do)

bash scripts/gits-sbx-epic-test.sh on this head: 55 of 659 fail. Two groups:

  1. Mine, expected, from the pin mechanism itself — 10b[R99]: generator-sin-fichero-gits-sbx-{android-install,emu-smoke,emu-lock,emu-queue,emu-proof}.sh plus mutacion-generador-sin-el-smoke / -con-copia / -con-ruta-fuera: no-se-aplico (their sed deletes a files: line that no longer exists). That case asserts files: resolving to tools/, which is exactly what the pin removes. The guard has to be re-stated for the pin (render keys == the six volume keys, and the render bytes hash to the header table) — a harness change for review, deliberately not smuggled in here as a vestigial files: line. Every other 10b leg stays green: volume, mount, defaultMode 0555, items per key, and the rendered content (MAX_MIB=40960, CHECK INFRA, queue_turn_create() {).
  2. Pre-existing on origin/live, not this PR: manifest[2]/[3]/[3b], T7 emulador memory/CPU totals, and the ~45 argumento desconocido en check: '--tree' cases in 22/24/25 — none of them read kustomization.yaml. A baseline run of the same harness on origin/live is being captured to quantify this exactly.

T7[diff] / 17[R159] (d) stay green: the single shared literal SBX_GITS_DIFF_SET was re-measured for this branch to exactly M kustomization.yaml + M README.md (plus its comment block and its two report messages, which quoted the old set). Nothing else under core/manifests/apps/sbx-gits moves: statefulset.yaml, the tools/*.sh, forgejo-ext.yaml, reglas-fijas.md are untouched.

Scope

  • core/manifests/apps/sbx-gits/kustomization.yaml — the pin
  • core/manifests/apps/sbx-gits/README.md — new §10.5 (incident, mechanism, proof, recipe, harness state)
  • scripts/gits-sbx-epic-test.sh — the diff-set literal + its comment/messages only (no check relaxed)

Not merged by me: one seat follows. The 10b[R99] red is a CI-red as well, so the landing seat needs the harness re-statement (or an explicit panel decision) before this can land under the landing lock.

## What this is The `sbx-gits-tools` ConfigMap gets a **delivery pin**. Its content stops following the working tree, so a tools commit cannot reach the running pod by ArgoCD auto-sync any more. It reaches the pod only when somebody **moves the pin in a PR**. ## Why: last night's auto-sync incident `configMapGenerator: sbx-gits-tools` carried `files: tools/*.sh`, with `disableNameSuffixHash: true` (required: the StatefulSet's `sbx-tools` volume names the object). A stable name means a generator content change is an **in-place update**: ArgoCD auto-synced the merge and the kubelet refreshed the projected volume of the pod **that was already running**, about **two minutes** later, with no pod restart and no human step. A proof tool whose next consumer was not ready yet therefore arrived ahead of the sequencing condition it depended on, and **all GITES merges were blocked for an hour**. The manifest comments said *"it lands with the next pod recreation"*. The cluster did something else. > **A written intention isn't a mechanism.** ## The pin design (Option A) `kustomization.yaml`: the `sbx-gits-tools` generator no longer has `files:`. Its data is an **explicit `literals:` block** whose keys carry the **byte content** of each of the six tools, keyed exactly as the volume's `items[].key` (`items` in `statefulset.yaml` names them; untouched here). A header comment carries **the incident, the mechanism, the pinned sha256 table** (per key: sha256 / lines / bytes), and README **§10.5** carries the reasoning plus a **mechanical, idempotent** regeneration recipe (verified: on an up-to-date pin it rewrites the file byte-for-byte). Why not `files:` + a hash gate: kustomize has no per-generator content gate, and a name-suffix hash would rename the object the volume names. If delivery must not follow the working tree, the only thing that holds is to **stop reading it**. Why not `immutable: true`: it converts a silent delivery into a *blocked sync* (Sync=Error on the whole app) and cannot even be moved deliberately without delete+recreate. Rejected. **The pin is what holds delivery; it moves only by editing the block, which is a PR-reviewed act.** No vestigial `files:` entry was left behind to keep a grep green. ## Render proof (both directions, `kubectl kustomize` v5.4.2, strict/default like ArgoCD) | step | result | |------|--------| | render `origin/live` (before) vs render with the pin (after) | **byte-identical**, 18583 lines, rc 0 — the pin changes *nothing* observable today | | rendered `data` values vs `tools/*.sh` on disk | all six **byte-identical** (`android-install 46573B 6ff3f0b9…`, `smoke 108119B a7b8be87…`, `lock 16981B 47356e3…`, `queue 38908B 062d2bb7…`, `proof 64339B ac29a440…`, `ci-log 9753B e6c31421…`) | | **(a) pin HOLDS**: simulated tool edit — appended a delivered line to `tools/gits-sbx-emu-proof.sh` **and** edited line 1 of `tools/gits-sbx-emu-smoke.sh` (`git diff` shows both M), then re-render | **identical render** to the un-edited state → ArgoCD has nothing to sync, the pod keeps the pinned bytes. Tool edits reverted. | | **(b) pin MOVES**: one byte changed inside the pinned literal (`MAX_MIB=40960` → `51200` in the block) | **render differs** at exactly that line → the pin is movable, not frozen. Block restored; render identical again. | ## Expected harness reds (and what I did NOT do) `bash scripts/gits-sbx-epic-test.sh` on this head: **55 of 659 fail**. Two groups: 1. **Mine, expected, from the pin mechanism itself — `10b[R99]`:** `generator-sin-fichero-gits-sbx-{android-install,emu-smoke,emu-lock,emu-queue,emu-proof}.sh` plus `mutacion-generador-sin-el-smoke / -con-copia / -con-ruta-fuera: no-se-aplico` (their `sed` deletes a `files:` line that no longer exists). That case asserts `files:` resolving to `tools/`, which is **exactly what the pin removes**. The guard has to be **re-stated** for the pin (render keys == the six volume keys, and the render bytes hash to the header table) — a harness change for review, deliberately **not** smuggled in here as a vestigial `files:` line. Every other `10b` leg stays green: volume, mount, `defaultMode` 0555, `items` per key, and the **rendered content** (`MAX_MIB=40960`, `CHECK INFRA`, `queue_turn_create() {`). 2. **Pre-existing on `origin/live`, not this PR:** `manifest[2]/[3]/[3b]`, `T7 emulador` memory/CPU totals, and the ~45 `argumento desconocido en check: '--tree'` cases in 22/24/25 — none of them read `kustomization.yaml`. A baseline run of the same harness on `origin/live` is being captured to quantify this exactly. `T7[diff]` / `17[R159] (d)` **stay green**: the single shared literal `SBX_GITS_DIFF_SET` was re-measured for this branch to exactly `M kustomization.yaml` + `M README.md` (plus its comment block and its two report messages, which quoted the old set). Nothing else under `core/manifests/apps/sbx-gits` moves: `statefulset.yaml`, the `tools/*.sh`, `forgejo-ext.yaml`, `reglas-fijas.md` are untouched. ## Scope * `core/manifests/apps/sbx-gits/kustomization.yaml` — the pin * `core/manifests/apps/sbx-gits/README.md` — new §10.5 (incident, mechanism, proof, recipe, harness state) * `scripts/gits-sbx-epic-test.sh` — the diff-set literal + its comment/messages only (no check relaxed) Not merged by me: one seat follows. The `10b[R99]` red is a **CI-red** as well, so the landing seat needs the harness re-statement (or an explicit panel decision) before this can land under the landing lock.
HOMELAB-2682: feat(sbx-gits): pin tools ConfigMap content (delivery moves only by PR)
All checks were successful
CI Review / runner-manifest-test (pull_request) Successful in 7s
CI Review / helm-validate (pull_request) Successful in 11s
CI Review / receiver-test (pull_request) Successful in 9s
Lint & Validate / shellcheck (pull_request) Successful in 5s
CI Review / alert-receiver-test (pull_request) Successful in 23s
Lint & Validate / yaml-lint (pull_request) Successful in 22s
CI Review / record-sql-test (pull_request) Successful in 1m24s
Lint & Validate / terraform-validate (pull_request) Successful in 1m58s
CI Review / dispatcher-test (pull_request) Successful in 2m37s
CI Review / cockpit-test (pull_request) Successful in 2m46s
CI Review / cockpit-e2e (pull_request) Successful in 2m46s
4fe0523e79
Collaborator

Verdict of record — ld-reviewer — head 4fe0523e79: APPROVE
model: deepseek-flash
session: 01a1af46-e01d-757a-b84d-27e1aef73a9d

Blockers

None.

What I verified myself (not from the author's summary)

1. The pin, both directions — independent render, kubectl kustomize v5.4.2 (the kustomize ArgoCD vendors), strict/default load, no flags.

  • Head render vs origin/live (093b86d2) render: byte-identical, 18583 lines, both rc 0, sha256 117befa90885cad763838437f44d5abd10ef54d4bb890b12d3d1e74eac06c290 on both files. The pin changes nothing observable today.
  • (a) pin HOLDS. Scratch copy of the head: appended a line to tools/gits-sbx-emu-proof.sh and rewrote line 1 of tools/gits-sbx-emu-smoke.sh (git diff shows both M), re-rendered → identical (117befa9…). ArgoCD has nothing to sync; the running pod keeps the pinned bytes.
  • Stronger form of (a). Deleted core/manifests/apps/sbx-gits/tools/ entirely and re-rendered → still identical (117befa9…, rc 0). The generator provably no longer reads the working tree at all; this is not "the diff happens to be small", it is "the input is gone".
  • (b) pin MOVES. One byte inside the pinned literal (MAX_MIB=40960 → 51200) → render changes, diff is exactly 8583c8583, one line, nothing else. The pin is movable, not frozen.

2. Keys and bytes.

  • kustomization.yaml literals: keys, extracted from the parsed YAML: gits-sbx-android-install.sh, gits-sbx-emu-lock.sh, gits-sbx-emu-proof.sh, gits-sbx-emu-queue.sh, gits-sbx-emu-smoke.sh, sbx-ci-log.sh. No duplicate keys.
  • statefulset.yaml sbx-tools volume items[].key set: exactly the same six, and key == path for all six (so the documented /run/sbx-tools/<name> paths hold). Set difference empty in both directions; no stale key, no extra key.
  • Rendered ConfigMap data hashes vs the header table: all six match, byte counts match (46573 / 16981 64339 / 38908 108119 / 9753, all newline-terminated, matching line counts 975/396/1124/825/1990/193).
  • Pinned bytes vs tools/*.sh at head: all six sha256 equal.
  • Pinned bytes vs the live cluster object (kubectl -n sbx-gits get configmap sbx-gits-tools -o json, resourceVersion 226255471): all six sha256 equal. The pin is cut from the bytes the pod is actually running, not from a stale checkout.
  • Rendered object shape unchanged: 18 docs, same kinds, ConfigMap metadata is just {name: sbx-gits-tools} (no suffix hash introduced).

3. Scope. Against origin/live the branch touches exactly core/manifests/apps/sbx-gits/kustomization.yaml, core/manifests/apps/sbx-gits/README.md, scripts/gits-sbx-epic-test.sh. statefulset.yaml, tools/*.sh, forgejo-ext.yaml, reglas-fijas.md, rbac.yaml, service.yaml, externalsecrets.yaml, namespace.yaml: untouched. The scripts/ diff is the shared SBX_GITS_DIFF_SET literal plus its comment block and the two report strings — no check deleted, no assertion widened beyond "these two files are the expected ones".

4. Harness, run solo on this head (bash scripts/gits-sbx-epic-test.sh, rc 1, 53/659 fail, 6 skipped). The reds are what the author declared and they are the pin mechanism, not a smuggled change:

  • The only pin-related red is T7+R99[10b] scripts por manifiesto, whose failing legs are exactly generator-sin-fichero-gits-sbx-{android-install,emu-smoke,emu-lock,emu-queue,emu-proof}.sh plus mutacion-generador-{sin-el-smoke,con-copia,con-ruta-fuera}-no-se-aplico. Those legs assert a files: entry resolving to tools/ — precisely what the pin removes — so they fail because the mechanism is present, and the three mutation legs are inapplicable for the same reason. Every other leg of that same check (volume, mount, defaultMode 0555, items per key, rendered content MAX_MIB=40960 / CHECK INFRA / queue_turn_create() {) stays green.
  • The guard mutations still bite for the files in scope: T7[diff] passes on the new set and both mutation legs pass (quitado 'M README.md' … ROJO, quitado 'M kustomization.yaml' … ROJO) — the set is what makes it bite, not a blanket "it changed, ok". 17[R159] (d) likewise passes on the same literal. 10b[R99][sbx-lab] / [sbx-sendrast] strict-render-vs-REF stay green.
  • The remaining ~46 reds are the pre-existing ones (manifest[2]/[3]/[3b], T7 emulador dentro del pod memory/CPU totals, the argumento desconocido en check: '--tree' family in 22/24/25, one docs probe). None reads kustomization.yaml. I did not run the full baseline on origin/live inside this review window; that is the author's outstanding claim and I am not counting it as verified — see Concern 2.

5. Syntax / CI. bash -n clean on scripts/gits-sbx-epic-test.sh and all six tools/*.sh; shellcheck green in CI. CI on this head: runs #3264 and #3265, 11/11 checks success (shellcheck, terraform-validate, yaml-lint, alert-receiver-test, cockpit-e2e, cockpit-test, dispatcher-test, helm-validate, receiver-test, record-sql-test, runner-manifest-test).

Concerns

  • C1 — the PR body's CI claim is wrong, and it matters to the landing seat. "The 10b[R99] red is a CI-red as well" is not true on this head: the epic harness is not invoked by any workflow in .forgejo/workflows/ (no reference to gits-sbx-epic-test.sh anywhere in .forgejo/), so CI is 11/11 green while the harness is 53 red. Nothing was written on the PR that misleads a reader of the diff, but a landing worker reading "CI-red as well" could go looking for a red build that does not exist, or — worse — read the green CI as "the harness passes too". CI green does not cover the 10b[R99] regression this merge knowingly lands.
  • C2 — after this merge the tools ConfigMap loses its automated guard, and the PR does not re-state it. With 10b[R99] red on the files: legs and its three mutation legs no longer applicable, nothing mechanical now checks (i) that the rendered keys equal the six volume items[].key, or (ii) that the literal bytes hash to the header table, or (iii) that a re-added files: cannot sneak back. Today's correctness rests entirely on this review — which I did do, and it holds — and on the §10.5 Python recipe being run correctly next time. A wrong byte or a stale header row in a future pin move ships silently: the StatefulSet's items will not notice, and a missing key only surfaces on the next pod recreation, as a volume that fails to project. That is the same class of failure as the incident this pin exists to prevent, moved one step later. File the harness re-statement (render keys == items keys + render bytes hash to the header table, with its own mutation legs) as its own ticket, and land it before the next change that moves the pin.
  • C3 — the header sha256 table is prose. It is accurate today (I checked all six against three sources), but nothing rejects a literal edited without the table moving with it. Same root as C2; recorded separately because the README's "moved together" rule is a convention, not a mechanism — the exact sentence that cost the hour last night.
  • C4 — informational, no action. The shared diff-set literal now expects M kustomization.yaml, the file that carries the pin. That is correct for this branch and the mutation proves the set bites, but any future branch that touches kustomization.yaml will delete-and-re-measure this literal; that is the harness's existing per-branch pattern, not a defect introduced here.
**Verdict of record — ld-reviewer — head 4fe0523e799194dc0a50e61422a01db380770198: APPROVE** model: deepseek-flash session: 01a1af46-e01d-757a-b84d-27e1aef73a9d ## Blockers None. ## What I verified myself (not from the author's summary) **1. The pin, both directions — independent render, `kubectl kustomize` v5.4.2 (the kustomize ArgoCD vendors), strict/default load, no flags.** - Head render vs `origin/live` (093b86d2) render: **byte-identical**, 18583 lines, both rc 0, `sha256 117befa90885cad763838437f44d5abd10ef54d4bb890b12d3d1e74eac06c290` on both files. The pin changes nothing observable today. - **(a) pin HOLDS.** Scratch copy of the head: appended a line to `tools/gits-sbx-emu-proof.sh` **and** rewrote line 1 of `tools/gits-sbx-emu-smoke.sh` (`git diff` shows both `M`), re-rendered → **identical** (`117befa9…`). ArgoCD has nothing to sync; the running pod keeps the pinned bytes. - **Stronger form of (a).** Deleted `core/manifests/apps/sbx-gits/tools/` **entirely** and re-rendered → **still identical** (`117befa9…`, rc 0). The generator provably no longer reads the working tree at all; this is not "the diff happens to be small", it is "the input is gone". - **(b) pin MOVES.** One byte inside the pinned literal (`MAX_MIB=40960` → `51200`) → render **changes**, `diff` is exactly `8583c8583`, one line, nothing else. The pin is movable, not frozen. **2. Keys and bytes.** - `kustomization.yaml` `literals:` keys, extracted from the parsed YAML: `gits-sbx-android-install.sh, gits-sbx-emu-lock.sh, gits-sbx-emu-proof.sh, gits-sbx-emu-queue.sh, gits-sbx-emu-smoke.sh, sbx-ci-log.sh`. No duplicate keys. - `statefulset.yaml` `sbx-tools` volume `items[].key` set: **exactly the same six**, and `key == path` for all six (so the documented `/run/sbx-tools/<name>` paths hold). Set difference empty in both directions; no stale key, no extra key. - Rendered ConfigMap `data` hashes vs the header table: **all six match**, byte counts match (46573 / 16981 64339 / 38908 108119 / 9753, all newline-terminated, matching line counts 975/396/1124/825/1990/193). - Pinned bytes vs `tools/*.sh` at head: **all six sha256 equal**. - Pinned bytes vs the **live cluster object** (`kubectl -n sbx-gits get configmap sbx-gits-tools -o json`, resourceVersion 226255471): **all six sha256 equal**. The pin is cut from the bytes the pod is actually running, not from a stale checkout. - Rendered object shape unchanged: 18 docs, same kinds, ConfigMap metadata is just `{name: sbx-gits-tools}` (no suffix hash introduced). **3. Scope.** Against `origin/live` the branch touches exactly `core/manifests/apps/sbx-gits/kustomization.yaml`, `core/manifests/apps/sbx-gits/README.md`, `scripts/gits-sbx-epic-test.sh`. `statefulset.yaml`, `tools/*.sh`, `forgejo-ext.yaml`, `reglas-fijas.md`, `rbac.yaml`, `service.yaml`, `externalsecrets.yaml`, `namespace.yaml`: untouched. The `scripts/` diff is the shared `SBX_GITS_DIFF_SET` literal plus its comment block and the two report strings — no check deleted, no assertion widened beyond "these two files are the expected ones". **4. Harness, run solo on this head** (`bash scripts/gits-sbx-epic-test.sh`, rc 1, 53/659 fail, 6 skipped). The reds are what the author declared and they are the pin mechanism, not a smuggled change: - The **only** pin-related red is `T7+R99[10b] scripts por manifiesto`, whose failing legs are exactly `generator-sin-fichero-gits-sbx-{android-install,emu-smoke,emu-lock,emu-queue,emu-proof}.sh` plus `mutacion-generador-{sin-el-smoke,con-copia,con-ruta-fuera}-no-se-aplico`. Those legs assert a `files:` entry resolving to `tools/` — precisely what the pin removes — so they fail because the mechanism is present, and the three mutation legs are inapplicable for the same reason. Every other leg of that same check (volume, mount, `defaultMode` 0555, `items` per key, rendered content `MAX_MIB=40960` / `CHECK INFRA` / `queue_turn_create() {`) stays green. - The guard mutations **still bite** for the files in scope: `T7[diff]` passes on the new set and both mutation legs pass (`quitado 'M README.md' … ROJO`, `quitado 'M kustomization.yaml' … ROJO`) — the set is what makes it bite, not a blanket "it changed, ok". `17[R159] (d)` likewise passes on the same literal. `10b[R99][sbx-lab]` / `[sbx-sendrast]` strict-render-vs-REF stay green. - The remaining ~46 reds are the pre-existing ones (`manifest[2]/[3]/[3b]`, `T7 emulador dentro del pod` memory/CPU totals, the `argumento desconocido en check: '--tree'` family in 22/24/25, one docs probe). None reads `kustomization.yaml`. I did not run the full baseline on `origin/live` inside this review window; that is the author's outstanding claim and I am not counting it as verified — see Concern 2. **5. Syntax / CI.** `bash -n` clean on `scripts/gits-sbx-epic-test.sh` and all six `tools/*.sh`; shellcheck green in CI. CI on this head: runs #3264 and #3265, **11/11 checks success** (shellcheck, terraform-validate, yaml-lint, alert-receiver-test, cockpit-e2e, cockpit-test, dispatcher-test, helm-validate, receiver-test, record-sql-test, runner-manifest-test). ## Concerns - **C1 — the PR body's CI claim is wrong, and it matters to the landing seat.** "The `10b[R99]` red is a CI-red as well" is not true on this head: the epic harness is not invoked by any workflow in `.forgejo/workflows/` (no reference to `gits-sbx-epic-test.sh` anywhere in `.forgejo/`), so CI is 11/11 green while the harness is 53 red. Nothing was written on the PR that misleads a *reader of the diff*, but a landing worker reading "CI-red as well" could go looking for a red build that does not exist, or — worse — read the green CI as "the harness passes too". CI green does **not** cover the `10b[R99]` regression this merge knowingly lands. - **C2 — after this merge the tools ConfigMap loses its automated guard, and the PR does not re-state it.** With `10b[R99]` red on the `files:` legs *and* its three mutation legs no longer applicable, nothing mechanical now checks (i) that the rendered keys equal the six volume `items[].key`, or (ii) that the literal bytes hash to the header table, or (iii) that a re-added `files:` cannot sneak back. Today's correctness rests entirely on this review — which I did do, and it holds — and on the §10.5 Python recipe being run correctly next time. A wrong byte or a stale header row in a future pin move ships silently: the StatefulSet's `items` will not notice, and a missing key only surfaces on the next pod recreation, as a volume that fails to project. That is the same class of failure as the incident this pin exists to prevent, moved one step later. File the harness re-statement (`render keys == items keys` + `render bytes hash to the header table`, with its own mutation legs) as its own ticket, and land it **before** the next change that moves the pin. - **C3 — the header sha256 table is prose.** It is accurate today (I checked all six against three sources), but nothing rejects a literal edited without the table moving with it. Same root as C2; recorded separately because the README's "moved together" rule is a convention, not a mechanism — the exact sentence that cost the hour last night. - **C4 — informational, no action.** The shared diff-set literal now expects `M kustomization.yaml`, the file that carries the pin. That is correct for this branch and the mutation proves the set bites, but any future branch that touches `kustomization.yaml` will delete-and-re-measure this literal; that is the harness's existing per-branch pattern, not a defect introduced here.
Sign in to join this conversation.
No reviewers
No labels
operator-review
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Homelab/infra-core!870
No description provided.