package stacks import ( "strings" "testing" "time" ) // R-679 (v0.270.0): an Update pressed on an app already at the catalog head is refused BEFORE anything // moves — no backup, no pull, no restart — with its own reason and a sentence in the household's // language. A re-tested digest for the same tag is NOT current and still updates. // // COMPANION RED-PROOF (REPORT.md): drop the UpdateOrderCurrent check from UpdatePreflight → "an app at // the head was allowed to update". func TestR679_CurrentAppIsRefused(t *testing.T) { m, _, _, _ := newSlice4Manager(t) st := m.stacks["nextcloud"] st.AppConfig.InstalledImages = map[string]InstalledImage{"web": oi("nextcloud:31.0.14-apache")} st.CatalogImages = map[string]string{"web": "nextcloud:31.0.14-apache"} ref := m.UpdatePreflight("nextcloud") if ref == nil { t.Fatal("an app at the head was allowed to update") } if ref.Reason != "already_current" || ref.Cause == nil || !strings.Contains(ref.Message, "legfrissebb") { t.Fatalf("refusal = %q %q (cause %v) — want already_current, a key-bearing Cause, the Hungarian sentence", ref.Reason, ref.Message, ref.Cause) } } func TestR679_BehindAndRetestedDigestStillUpdate(t *testing.T) { m, _, _, _ := newSlice4Manager(t) st := m.stacks["nextcloud"] st.AppConfig.InstalledImages = map[string]InstalledImage{"web": oi("nextcloud:31.0.13-apache")} st.CatalogImages = map[string]string{"web": "nextcloud:31.0.14-apache"} if ref := m.UpdatePreflight("nextcloud"); ref != nil { t.Fatalf("a behind app was refused: %q", ref.Reason) } // same tag, a newer TESTED digest than the install → behind, not current inst := oi("redis:7-alpine") inst.Digest = "sha256:" + strings.Repeat("a", 64) inst.At = time.Now().Add(-48 * time.Hour).UTC().Format(time.RFC3339) st.AppConfig.InstalledImages = map[string]InstalledImage{"web": inst} st.CatalogImages = map[string]string{"web": "redis:7-alpine"} st.CatalogDigests = map[string]string{"web": "sha256:" + strings.Repeat("b", 64)} st.CatalogTestedAt = time.Now() if ref := m.UpdatePreflight("nextcloud"); ref != nil { t.Fatalf("a re-tested digest was refused as current: %q", ref.Reason) } }