hub v0.112.0: a floor carries a declared MinAgent past the golden (R-472)
gates / gates (push) Successful in 18s
gates / gates (push) Successful in 18s
Operator ruling 2026-09-13. Above the vouched golden, a floor saved with a declared MinAgent is served under the same agent comparison; an undeclared one is still held beyond the golden. The declaration is stored beside each floor as FLOOR=MINAGENT so it never carries to a later floor. Both floor forms require min_agent above the golden (flash floor_needs_min_agent, nothing stored). The Hosts page and the API log name the source. Vouch path and R-120 gate untouched. Scenarios A-E tested; red-proofs A and C in documentation/audits/rulings-r472-r475-2026-09-13/.
This commit is contained in:
@@ -117,6 +117,19 @@ reconciles only on change and reports which generation it has converged to).
|
||||
**Geo is *not* in the agent's desired state** — it's customer→hub→Cloudflare (§7); the agent never
|
||||
touches WAF.
|
||||
|
||||
**The controller floor and its agent requirement (hub v0.112.0, R-472).** The managed controller floor
|
||||
rides the report ACK. `store.ResolveManagedFloor` decides per box whether to serve it, from three
|
||||
inputs: the floor in force (per-customer override, else global), the vouched Day-0 manifest (golden
|
||||
version + MinAgent), and a **declared MinAgent** stored beside the floor
|
||||
(`hub_settings.min_controller_version_declared_min_agent` for the global floor,
|
||||
`customer_configs.min_controller_declared_min_agent` for an override, each as `FLOOR=MINAGENT` so it
|
||||
binds only to the floor it was saved with). Inside the golden the manifest's MinAgent governs. Above
|
||||
the golden the declared one does; with no declaration the floor is **held beyond the golden**, as since
|
||||
R-216. Either way the box's reported agent must meet the chosen MinAgent, else the floor is held with
|
||||
`agent <v> < MinAgent <w>`. The decision carries `MinAgentSource` (`manifest` / `declared`), shown on
|
||||
the Hosts page and logged once per change as `managed floor SERVED`. The rules the operator follows:
|
||||
`runbooks/publish-train-rules.md` rule 1.
|
||||
|
||||
## 6. Authorization — signed-op queue + editing flow
|
||||
|
||||
Implements Part 4's gate on the hub side. The hub holds **no signing key**.
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
MUTATION in internal/store/store.go:
|
||||
- if beyondGolden && d.DeclaredMinAgent != "" {
|
||||
d.MinAgent, d.MinAgentSource = d.DeclaredMinAgent, MinAgentSourceDeclared
|
||||
}
|
||||
+ _ = MinAgentSourceDeclared
|
||||
|
||||
=== RUN TestDeclaredMinAgent_A_AboveGoldenServedWhenAgentMeetsIt
|
||||
declared_floor_test.go:33: a declared floor above the golden must be SERVED: {Floor: Held:true AgentVersion:0.129.0 RequestedFloor:0.239.0 MinAgent:0.129.0 GoldenVersion:0.236.0 HeldBeyondGolden:true DeclaredMinAgent:0.129.0 MinAgentSource:manifest} (reason "held: floor 0.239.0 is ABOVE the vouched golden 0.236.0, so its agent requirement is unknown — vouch a golden carrying the floor's controller (publish-train rule 1)")
|
||||
--- FAIL: TestDeclaredMinAgent_A_AboveGoldenServedWhenAgentMeetsIt (0.02s)
|
||||
FAIL
|
||||
FAIL gitea.dooplex.hu/admin/felhom-hub/internal/store 0.027s
|
||||
FAIL
|
||||
exit=1
|
||||
@@ -0,0 +1,11 @@
|
||||
MUTATION in internal/store/store.go:
|
||||
- if beyondGolden && d.MinAgentSource != MinAgentSourceDeclared {
|
||||
+ if false && beyondGolden && d.MinAgentSource != MinAgentSourceDeclared {
|
||||
|
||||
=== RUN TestDeclaredMinAgent_C_UndeclaredAboveGoldenIsHeldExactlyAsBefore
|
||||
declared_floor_test.go:64: an UNDECLARED floor above the golden must stay held beyond the golden: {Floor:0.239.0 Held:false AgentVersion:0.130.0 RequestedFloor:0.239.0 MinAgent:0.129.0 GoldenVersion:0.236.0 HeldBeyondGolden:false DeclaredMinAgent: MinAgentSource:manifest}
|
||||
--- FAIL: TestDeclaredMinAgent_C_UndeclaredAboveGoldenIsHeldExactlyAsBefore (0.02s)
|
||||
FAIL
|
||||
FAIL gitea.dooplex.hu/admin/felhom-hub/internal/store 0.031s
|
||||
FAIL
|
||||
exit=1
|
||||
@@ -98,6 +98,18 @@ the manifest vouches the target FIRST; any MinAgent must be satisfied fleet-wide
|
||||
boxes below it automatically, and flags them); **save the floor LAST** — the DB row acts immediately
|
||||
on every box below it, on their next report.
|
||||
|
||||
**Raise the floor to a release with no golden (hub v0.112.0+, R-472).** Between bakes this is the
|
||||
normal route — do not hand-deploy.
|
||||
|
||||
1. Build and push the controller image (above). Do not install it on any box.
|
||||
2. Read the MinAgent from the release's header: `grep -m1 -A3 '^## v<VER>' CHANGELOG.md` shows
|
||||
`**MinAgent: X.Y.Z**`. `controller_gates.py --fast` refuses a release whose newest header lacks it.
|
||||
3. Hub → Configuration → Managed updates: type `<VER>` in the floor field **and** that value in
|
||||
`min_agent`. Save. Without `min_agent` the form refuses with *"This floor is above the vouched
|
||||
golden — declare its MinAgent"* and stores nothing.
|
||||
4. Verify: `sudo kubectl -n felhom-system logs deploy/hub | grep 'managed floor SERVED'` shows
|
||||
`from "declared"`, and each box logs `SetFloor: floor "…" → "<VER>"` within about a minute.
|
||||
|
||||
## 4. Golden image (fresh Day-0 installs)
|
||||
|
||||
The golden is a pre-baked controller-era guest image built in the **drill VM** on 180
|
||||
@@ -211,9 +223,9 @@ The full 0.188.0 run, with the observables: `documentation/audits/tester-gate-go
|
||||
because `golden_currency_gate.py` trips on every release by design and the only honest ways past it
|
||||
were a bake or a declared `--no-verify` (thirteen of those by 2026-09-01 — R-404/R-417). **The
|
||||
ruling:** bake on a cadence. The ruling assumed every release would still raise the FLOOR (§4.1 step
|
||||
5) and reach both demo boxes in ~20 s, with only the golden moving to a cadence. **⚠ CORRECTED THE SAME DAY (R-472): between bakes the floor does NOT carry a release — the hub holds any floor above the vouched golden (publish-train rule 1), so releases between bakes reach the demo boxes only by hand-deploy.** A
|
||||
release between bakes is hand-deployed per the `felhom-build-deploy` skill, and the floor is left at
|
||||
the vouched golden.
|
||||
5) and reach both demo boxes in ~20 s, with only the golden moving to a cadence. **⚠ CORRECTED THE SAME DAY (R-472): the hub held any floor above the vouched golden (publish-train rule 1), so releases between bakes reached the demo boxes only by hand-deploy.** **RESOLVED in hub v0.112.0:** a floor above the golden is served when it carries a
|
||||
declared MinAgent (§3 "Raise the floor to a release with no golden"). A release between bakes rides
|
||||
the floor again; only an undeclared floor is still held.
|
||||
|
||||
**The cadence, and it is a step in a routine, not a memory:**
|
||||
|
||||
|
||||
@@ -10,6 +10,24 @@ Publish and vouch the artifacts in the Day-0 manifest **before** any floor movem
|
||||
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.)
|
||||
|
||||
**Since hub v0.112.0 (operator ruling 2026-09-13, R-472): the manifest leads the floor inside the
|
||||
golden; above it, the release's own declared MinAgent does.** A controller image is pulled by tag from
|
||||
the registry, so a floor above the golden does not need a golden to be delivered — it needs to know
|
||||
which agent the release requires. The operator declares that with the floor, in the `min_agent` field
|
||||
next to it, read from the release's controller `CHANGELOG.md` header (`**MinAgent: X.Y.Z**`, pinned by
|
||||
`controller/scripts/minagent_header_gate.py`).
|
||||
|
||||
- **At or below the vouched golden:** the manifest's MinAgent governs, exactly as before. A declared
|
||||
value is recorded and not used.
|
||||
- **Above the golden, declared:** the hub compares each box's agent against the declared MinAgent
|
||||
(rule 3's comparison, same hold text). Hub log: `managed floor SERVED … from declared`. The Hosts
|
||||
page marks the box `floor: declared MinAgent`.
|
||||
- **Above the golden, undeclared:** still **HELD beyond the golden**, unchanged (R-216). Both floor
|
||||
forms refuse to save such a floor (`floor_needs_min_agent`), so the hold is now a sentence at save
|
||||
time instead of a silent fleet-wide stop.
|
||||
- A declaration belongs to the exact floor it was saved with (`FLOOR=MINAGENT`). Moving the floor
|
||||
without a new declaration never carries the old one forward.
|
||||
|
||||
## 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
|
||||
|
||||
Reference in New Issue
Block a user