package planner import ( "testing" "time" ) func TestBuildPlan(t *testing.T) { now := time.Date(2026, 9, 25, 12, 0, 0, 0, time.UTC) i := validIntent() p, err := Build(i, now) if err != nil { t.Fatal(err) } if p.ProjectName != "sd-git-one" || p.DataPath != "/var/lib/server-deploy/instances/git-one" { t.Fatalf("wrong instance resources: %+v", p) } if p.ExpiresAt.Sub(p.CreatedAt) != 15*time.Minute { t.Fatal("wrong expiration") } if err := p.Verify(i, now); err != nil { t.Fatal(err) } again, _ := Build(i, now) if again.Hash != p.Hash { t.Fatal("unstable plan hash") } i.InstanceID = "git-two" other, _ := Build(i, now) if other.Hash == p.Hash || other.ProjectName == p.ProjectName || other.DataPath == p.DataPath { t.Fatal("instances share identity") } } func TestVerifyRejectsChangedOrExpiredPlan(t *testing.T) { now := time.Date(2026, 9, 25, 12, 0, 0, 0, time.UTC) i := validIntent() original, _ := Build(i, now) cases := []struct { name string change func(*Plan, *Intent, *time.Time) }{ {"expired", func(p *Plan, i *Intent, n *time.Time) { *n = p.ExpiresAt }}, {"future", func(p *Plan, i *Intent, n *time.Time) { *n = p.CreatedAt.Add(-time.Second) }}, {"tampered hash", func(p *Plan, i *Intent, n *time.Time) { p.Hash = "bad" }}, {"tampered path", func(p *Plan, i *Intent, n *time.Time) { p.DataPath = "/" }}, {"tampered project", func(p *Plan, i *Intent, n *time.Time) { p.ProjectName = "other" }}, {"tampered expiry", func(p *Plan, i *Intent, n *time.Time) { p.ExpiresAt = p.ExpiresAt.Add(time.Hour) }}, {"state drift", func(p *Plan, i *Intent, n *time.Time) { i.ObservedStateDigest = i.PackageDigest }}, {"host drift", func(p *Plan, i *Intent, n *time.Time) { i.HostID = "another-host" }}, {"domain drift", func(p *Plan, i *Intent, n *time.Time) { i.Domain = "other.example.com" }}, {"intent tamper", func(p *Plan, i *Intent, n *time.Time) { p.Intent.InstanceID = "other" }}, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { p, current, at := original, i, now tc.change(&p, ¤t, &at) if p.Verify(current, at) == nil { t.Fatal("accepted invalid plan") } }) } } func TestBuildRejectsInvalidIntent(t *testing.T) { i := validIntent() i.InstanceID = "../bad" if _, err := Build(i, time.Now()); err == nil { t.Fatal("built invalid plan") } }