package release import ( "context" "encoding/json" "errors" "os" "strings" "testing" "time" ) func testSystemRelease(v string) SystemRelease { return SystemRelease{ Version: v, Artifacts: map[string]SystemArtifact{ "linux-arm64": {Key: SystemArtifactKey(v, "linux-arm64"), SHA256: strings.Repeat("ab", 32)}, }, Source: "release:" + v, ReleasedAt: time.Date(2026, 9, 6, 8, 0, 0, 0, time.UTC), } } func TestSystemPointerRoundTrip(t *testing.T) { priv, pub := testKeys(t) s := NewDirStore(t.TempDir()) ctx := context.Background() if _, _, err := GetSystemPointer(ctx, s, pub, SystemComponentRouter, "stable"); !errors.Is(err, os.ErrNotExist) { t.Fatalf("missing pointer: err = %v, want ErrNotExist", err) } p, err := PromoteSystem(ctx, s, RootSigner(priv), SystemComponentRouter, "stable", testSystemRelease("v0.18.0"), SystemPromoteOptions{Actor: "paul", Spread: 5 * time.Minute}) if err != nil { t.Fatal(err) } if p.Current.Version != "v0.18.0" || p.Spread != "5m0s" || p.Schema != 1 || p.PromotedAt.IsZero() { t.Fatalf("promoted pointer = %+v", p) } got, etag, err := GetSystemPointer(ctx, s, pub, SystemComponentRouter, "stable") if err != nil || etag == "" { t.Fatalf("get: %v etag=%q", err, etag) } if got.Current.Artifacts["linux-arm64"].SHA256 != strings.Repeat("ab", 32) { t.Fatalf("artifact lost: %+v", got.Current) } if got.SpreadDuration() != 5*time.Minute { t.Fatalf("spread = %v", got.SpreadDuration()) } if len(got.Audit) != 1 || got.Audit[0].Actor != "paul" || got.Audit[0].Version != "v0.18.0" { t.Fatalf("audit = %+v", got.Audit) } } func TestSystemPromoteKeepsWholeReleaseInHistoryAndRollbackRestoresIt(t *testing.T) { priv, pub := testKeys(t) s := NewDirStore(t.TempDir()) ctx := context.Background() sg := RootSigner(priv) if _, err := PromoteSystem(ctx, s, sg, "router", "canary", testSystemRelease("v0.18.0"), SystemPromoteOptions{}); err != nil { t.Fatal(err) } first, _, _ := GetSystemPointer(ctx, s, pub, "router", "canary") time.Sleep(1100 * time.Millisecond) // PromotedAt is second-truncated; the rollback must be NEWER if _, err := PromoteSystem(ctx, s, sg, "router", "canary", testSystemRelease("v0.19.0"), SystemPromoteOptions{}); err != nil { t.Fatal(err) } p, _, _ := GetSystemPointer(ctx, s, pub, "router", "canary") if len(p.History) != 1 || p.History[0].Version != "v0.18.0" || p.History[0].Artifacts["linux-arm64"].Key == "" { t.Fatalf("history must carry the whole release: %+v", p.History) } time.Sleep(1100 * time.Millisecond) rb, err := RollbackSystem(ctx, s, sg, "router", "canary", "paul") if err != nil { t.Fatal(err) } if rb.Current.Version != "v0.18.0" || rb.Current.Artifacts["linux-arm64"].Key != SystemArtifactKey("v0.18.0", "linux-arm64") { t.Fatalf("rollback current = %+v", rb.Current) } if !rb.PromotedAt.After(first.PromotedAt) || !rb.PromotedAt.After(p.PromotedAt) { t.Fatalf("a rollback is a NEW promote: promoted_at %v must be newer than %v and %v", rb.PromotedAt, first.PromotedAt, p.PromotedAt) } if len(rb.History) != 0 { t.Fatalf("history after rollback = %+v", rb.History) } if _, err := RollbackSystem(ctx, s, sg, "router", "canary", "paul"); !errors.Is(err, ErrNoSystemHistory) { t.Fatalf("second rollback err = %v", err) } } func TestSystemPromoteSameVersionDoesNotGrowHistory(t *testing.T) { priv, pub := testKeys(t) s := NewDirStore(t.TempDir()) ctx := context.Background() sg := RootSigner(priv) for i := 0; i < 2; i++ { if _, err := PromoteSystem(ctx, s, sg, "router", "stable", testSystemRelease("v1.0.0"), SystemPromoteOptions{}); err != nil { t.Fatal(err) } } p, _, _ := GetSystemPointer(ctx, s, pub, "router", "stable") if len(p.History) != 0 { t.Fatalf("re-promoting the running version must not push it into history: %+v", p.History) } } func TestSystemPointerRefusesScopedSigner(t *testing.T) { _, _, sg := scopedFixture(t, []string{RungCanary, RungEdge}, 30*24*time.Hour) s := NewDirStore(t.TempDir()) _, err := PromoteSystem(context.Background(), s, sg, "router", "canary", testSystemRelease("v1.0.0"), SystemPromoteOptions{}) if err == nil || !strings.Contains(err.Error(), "root key") { t.Fatalf("scoped signer signed a system pointer: err = %v", err) } } func TestSystemPointerRefusesAGrantOnTheWire(t *testing.T) { // A wrapper carrying a grant is refused BEFORE the signature is checked, // like the production flag (production.go) and the pipeline. priv, pub := testKeys(t) s := NewDirStore(t.TempDir()) ctx := context.Background() if _, err := PromoteSystem(ctx, s, RootSigner(priv), "router", "stable", testSystemRelease("v1.0.0"), SystemPromoteOptions{}); err != nil { t.Fatal(err) } body, etag, _ := s.Get(ctx, SystemPointerKey("router", "stable")) var sw signedWrapper if err := json.Unmarshal(body, &sw); err != nil { t.Fatal(err) } sw.Grant = &signedGrant{Payload: "x", Sig: "y"} tampered, _ := json.Marshal(sw) if _, err := s.Put(ctx, SystemPointerKey("router", "stable"), tampered, etag); err != nil { t.Fatal(err) } if _, _, err := GetSystemPointer(ctx, s, pub, "router", "stable"); err == nil || !strings.Contains(err.Error(), "root key") { t.Fatalf("grant-bearing wrapper accepted: err = %v", err) } } func TestSystemPointerTamperAndCrossChannelRefused(t *testing.T) { priv, pub := testKeys(t) s := NewDirStore(t.TempDir()) ctx := context.Background() if _, err := PromoteSystem(ctx, s, RootSigner(priv), "router", "canary", testSystemRelease("v1.0.0"), SystemPromoteOptions{}); err != nil { t.Fatal(err) } body, _, _ := s.Get(ctx, SystemPointerKey("router", "canary")) // Cross-channel replay: the canary wrapper planted at the stable key. if _, err := s.Put(ctx, SystemPointerKey("router", "stable"), body, ""); err != nil { t.Fatal(err) } // Refusals are typed, not stringly: a box tells "not authority" (refuse) // from "the bucket is unreachable" (defer) with errors.Is. if _, _, err := GetSystemPointer(ctx, s, pub, "router", "stable"); err == nil || !errors.Is(err, ErrBadSystemPointer) { t.Fatalf("a canary pointer verified as stable: err = %v", err) } // Tampered signature. var sw signedWrapper _ = json.Unmarshal(body, &sw) sw.Sig = "AA" + sw.Sig[2:] bad, _ := json.Marshal(sw) _, etag, _ := s.Get(ctx, SystemPointerKey("router", "canary")) if _, err := s.Put(ctx, SystemPointerKey("router", "canary"), bad, etag); err != nil { t.Fatal(err) } if _, _, err := GetSystemPointer(ctx, s, pub, "router", "canary"); err == nil || !errors.Is(err, ErrBadSystemPointer) { t.Fatalf("tampered signature verified: err = %v", err) } } func TestSystemPointerValidation(t *testing.T) { priv, _ := testKeys(t) sg := RootSigner(priv) ctx := context.Background() cases := map[string]SystemRelease{ "dev version": {Version: "dev", Artifacts: testSystemRelease("x").Artifacts}, "no artifacts": {Version: "v1.0.0"}, "bad platform": {Version: "v1.0.0", Artifacts: map[string]SystemArtifact{"linux_arm64": {Key: "bootstrap/router/v1.0.0/carlos-linux_arm64", SHA256: strings.Repeat("a", 64)}}}, "key not derived": {Version: "v1.0.0", Artifacts: map[string]SystemArtifact{"linux-arm64": {Key: "bootstrap/carlos", SHA256: strings.Repeat("a", 64)}}}, "short sha": {Version: "v1.0.0", Artifacts: map[string]SystemArtifact{"linux-arm64": {Key: SystemArtifactKey("v1.0.0", "linux-arm64"), SHA256: "abc"}}}, "version traversal": {Version: "../x", Artifacts: testSystemRelease("../x").Artifacts}, } for name, rel := range cases { s := NewDirStore(t.TempDir()) if _, err := PromoteSystem(ctx, s, sg, "router", "stable", rel, SystemPromoteOptions{}); err == nil { t.Errorf("%s: accepted", name) } } s := NewDirStore(t.TempDir()) if _, err := PromoteSystem(ctx, s, sg, "Router", "stable", testSystemRelease("v1.0.0"), SystemPromoteOptions{}); err == nil { t.Error("bad component accepted") } if _, err := PromoteSystem(ctx, s, sg, "router", "stable", testSystemRelease("v1.0.0"), SystemPromoteOptions{Spread: 48 * time.Hour}); err == nil { t.Error("48h spread accepted") } } func TestSystemPromoteCASConflict(t *testing.T) { priv, _ := testKeys(t) ctx := context.Background() inner := NewDirStore(t.TempDir()) // A store whose Put always says "someone else moved it". s := conflictingStore{Store: inner} if _, err := PromoteSystem(ctx, s, RootSigner(priv), "router", "stable", testSystemRelease("v1.0.0"), SystemPromoteOptions{}); !errors.Is(err, ErrCASConflict) { t.Fatalf("err = %v, want ErrCASConflict", err) } } type conflictingStore struct{ Store } func (c conflictingStore) Put(ctx context.Context, key string, body []byte, ifMatch string) (string, error) { return "", ErrCASConflict }