Files
felhom.eu/documentation/runbooks/publish-train-rules.md
T
admin 4eaabb21d4 docs: publish-train rules — coupled-release gates codified (option-2)
manifest-before-floor; floor field LAST (hub_settings DB row overrides env, acts
immediately — the 0.81/0.113 9-minute skew incident); MinAgent fleet gate
(controller CHANGELOG header convention from ctrl v0.114.0); the controller
capability gate as box-level backstop.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-11 13:55:37 +02:00

48 lines
2.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Publish-train rules — coupled controller/agent releases
Standing gates for every artifact publish train (agent binary + controller golden + Day-0 manifest +
floor). Each rule cites the incident that created it. The box-level backstop (rule 4) exists because
rules 13 are operator discipline and discipline fails; the rules stay the primary control.
## 1. Manifest before floor (the GL-1 rule, restated)
Publish and vouch the artifacts in the Day-0 manifest **before** any floor movement. A floor that
points at an unvouched (or unpublished) version bricks self-updates: boxes are told to move to a
version they cannot verify. (GL-1 supply-chain arc; see the go-live package records.)
## 2. The manifest screen carries the LIVE DB floor — save the floor field LAST
The hub's Day-0 manifest UI also persists the global floor as a DB row
(`hub_settings.min_controller_version``hub/internal/store/store.go`,
`GetGlobalMinControllerVersion`). **The DB row overrides the env floor and acts immediately on the
next report cycle** — it is not staged by the manifest vouch.
**Incident:** publish train 0.81/0.113 (2026-07-11,
`documentation/pilot/RUNBOOK-publish-0.81-0.113-2026-07-11.md`): the operator saved the manifest
screen with the floor field filled; the floor acted at once and controller 0.113.0 reached Peti's
box ~9 minutes **before** agent 0.81.0 — the exact forbidden skew, benign only because the box had
zero NAS shares.
**Rule:** fill the floor field **last**, in a separate save, only after rule 3's fleet check passes.
## 3. MinAgent fleet gate
A controller release that depends on coupled agent behavior declares `MinAgent: X.Y.Z` in its
CHANGELOG entry header line (felhom-controller convention, since v0.114.0; retroactively, 0.113.0's
effective MinAgent was 0.81.0 for the NAS add). **The floor may not rise past a controller version
whose MinAgent is not yet met fleet-wide:** check the hub dashboard — every reporting box must show
agent ≥ MinAgent before the floor save. Manual at the current fleet size; hub-enforced per-box
gating is the deferred option-3.
## 4. Box-level backstop: the controller's capability gate
Since controller v0.114.0, a coupled feature entry point probes the agent's capability
(`controller/internal/agentapi/features.go` — route probe: 2xx ⇒ supported, 404 ⇒ older agent,
transport/5xx ⇒ indeterminate, never "too old") and refuses up front with an honest Hungarian
message instead of failing mid-pipeline. This turns a violated ordering into a graceful refusal —
it does **not** license sloppy trains: rules 13 remain the primary control.
Convention for new coupled features: add a row to the `featureProbes` table + a `Supports` gate
call at the feature's entry point, and declare MinAgent per rule 3. When the agent someday reports
an explicit version in its envelope, `Supports` should prefer the version comparison (roadmap).