7d64038f02
gates / gates (push) Successful in 6m45s
Hub: the R-120 golden guard judges only a CHANGED golden selection; offsite_snapshots_vanished / _unexplained (operator-only, hub-origin) on the 07:10 listing; internal/accesslog writes path-only lines to /data/access-log, 90 days. Installer: --rotate-recovery-only runs step 4b alone (rides the next installer tag). 03: the orphan check runs after a failed backup (agent 6545ccc). 02: the allow-list is empty, appdata_folders (controller v0.329.0). All red-proofed.
83 lines
3.7 KiB
Go
83 lines
3.7 KiB
Go
package web
|
||
|
||
import (
|
||
"net/http"
|
||
"net/http/httptest"
|
||
"net/url"
|
||
"strings"
|
||
"testing"
|
||
|
||
"gitea.dooplex.hu/admin/felhom-hub/internal/store"
|
||
)
|
||
|
||
// Agent-only vouch (`09` §3 decision 250 items 3–4, hub v0.158.0). The golden is baked weekly while the floor carries
|
||
// controller releases, so mid-week the vouched golden is behind the fleet. The R-120 gate guards a golden SELECTION:
|
||
// an unchanged golden (same version, same sha) is not a selection and must not block an agent-only save; a changed
|
||
// golden is judged exactly as before. Both tests drive handleSetArtifacts — the only UI writer of the manifest.
|
||
|
||
func postArtifacts(t *testing.T, s *Server, form url.Values) *httptest.ResponseRecorder {
|
||
t.Helper()
|
||
r := httptest.NewRequest(http.MethodPost, "/configuration/artifacts", strings.NewReader(form.Encode()))
|
||
r.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||
w := httptest.NewRecorder()
|
||
s.handleSetArtifacts(w, r)
|
||
return w
|
||
}
|
||
|
||
// The mid-week situation: golden 0.330.0 vouched on Sunday, the floor has since carried the fleet to 0.335.0, and the
|
||
// operator vouches a new agent. RED-PROOF (REPORT, 2026-10-17 night): with the `!goldenUnchanged` condition removed
|
||
// from the gate, this fails: `agent-only vouch refused: Location="/configuration?flash=golden_behind_fleet"`.
|
||
func TestVouchAgentOnlyWithStaleGoldenIsSaved(t *testing.T) {
|
||
s, st := newTestServer(t)
|
||
seedReport(t, st, "demo", "0.335.0")
|
||
golden := strings.Repeat("b", 64)
|
||
if err := st.SetArtifactManifest(store.ArtifactManifest{
|
||
AgentVersion: "0.159.0", AgentSHA256: strings.Repeat("a", 64),
|
||
GoldenVersion: "0.330.0", GoldenSHA256: golden, MinAgent: "0.150.0",
|
||
}); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
w := postArtifacts(t, s, url.Values{
|
||
"agent_version": {"0.160.0"}, "agent_sha256": {strings.Repeat("c", 64)},
|
||
"golden_version": {"0.330.0"}, "golden_sha256": {golden}, "min_agent": {"0.150.0"},
|
||
})
|
||
if loc := w.Header().Get("Location"); !strings.Contains(loc, "flash=artifacts_set") {
|
||
t.Fatalf("agent-only vouch refused: Location=%q, want flash=artifacts_set", loc)
|
||
}
|
||
m := st.GetArtifactManifest()
|
||
if m.AgentVersion != "0.160.0" || m.AgentSHA256 != strings.Repeat("c", 64) {
|
||
t.Fatalf("agent not saved: agent=%s sha=%s…", m.AgentVersion, m.AgentSHA256[:4])
|
||
}
|
||
if m.GoldenVersion != "0.330.0" || m.GoldenSHA256 != golden || m.MinAgent != "0.150.0" {
|
||
t.Fatalf("golden/MinAgent moved on an agent-only save: %+v", m)
|
||
}
|
||
}
|
||
|
||
// A golden CHANGED to an older one is still refused, even though the agent changes in the same save — and nothing is
|
||
// written. Also the same version under a different sha (a re-push) is a changed golden.
|
||
func TestVouchGoldenChangedToOlderIsStillRefused(t *testing.T) {
|
||
s, st := newTestServer(t)
|
||
seedReport(t, st, "demo", "0.335.0")
|
||
cur := store.ArtifactManifest{
|
||
AgentVersion: "0.159.0", AgentSHA256: strings.Repeat("a", 64),
|
||
GoldenVersion: "0.330.0", GoldenSHA256: strings.Repeat("b", 64),
|
||
}
|
||
if err := st.SetArtifactManifest(cur); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
for name, form := range map[string]url.Values{
|
||
"older version": {"agent_version": {"0.160.0"}, "agent_sha256": {strings.Repeat("c", 64)},
|
||
"golden_version": {"0.329.0"}, "golden_sha256": {strings.Repeat("d", 64)}},
|
||
"same version, other sha": {"agent_version": {"0.160.0"}, "agent_sha256": {strings.Repeat("c", 64)},
|
||
"golden_version": {"0.330.0"}, "golden_sha256": {strings.Repeat("e", 64)}},
|
||
} {
|
||
w := postArtifacts(t, s, form)
|
||
if loc := w.Header().Get("Location"); !strings.Contains(loc, "golden_behind_fleet") {
|
||
t.Errorf("%s: Location=%q, want the golden_behind_fleet refusal", name, loc)
|
||
}
|
||
if m := st.GetArtifactManifest(); m != cur {
|
||
t.Errorf("%s: refused but the manifest changed: %+v", name, m)
|
||
}
|
||
}
|
||
}
|