package preflight import ( "github.com/aritmolab/thothii/tools/tht/internal/safeio" "os" "path/filepath" "strings" "testing" ) func TestPlanBindsInputsAndDetectsCredentialRotationWithoutPublicSecretHashes(t *testing.T) { root, _ := filepath.EvalSymlinks(t.TempDir()) if err := safeio.ProtectPrivateDirectory(root); err != nil { t.Fatal(err) } input := filepath.Join(root, "descriptor.yaml") secret := filepath.Join(root, "credential") for path, data := range map[string]string{input: "schemaVersion: 2\n", secret: "PRIVATE_SENTINEL"} { if err := safeio.WriteCanonicalNewPrivateFile(path, []byte(data), 0o600); err != nil { t.Fatal(err) } } plan := Plan{SchemaVersion: 1, ValidatorProtocol: Protocol, Inputs: []string{input, secret}, WorkspaceRevision: "content-snapshot", Report: NewReport()} output := filepath.Join(root, "plan.json") if err := WritePlan(output, &plan); err != nil { t.Fatal(err) } data, _ := os.ReadFile(output) if strings.Contains(string(data), "PRIVATE_SENTINEL") { t.Fatal("secret in plan") } if err := VerifyPlanInputs(output); err != nil { t.Fatal(err) } if err := WritePlan(output, &plan); err == nil { t.Fatal("existing plan replaced") } if err := os.WriteFile(secret, []byte("rotated"), 0o600); err != nil { t.Fatal(err) } if err := VerifyPlanInputs(output); err == nil { t.Fatal("credential rotation did not invalidate plan") } if err := os.WriteFile(secret, []byte("PRIVATE_SENTINEL"), 0o600); err != nil { t.Fatal(err) } if err := os.WriteFile(input, []byte("schemaVersion: 3\n"), 0o600); err != nil { t.Fatal(err) } if err := VerifyPlanInputs(output); err == nil { t.Fatal("document change did not invalidate plan") } if err := os.WriteFile(input, []byte("schemaVersion: 2\n"), 0o600); err != nil { t.Fatal(err) } absent := filepath.Join(root, "transport-override.yaml") plan.AbsentInputs = []string{absent} second := filepath.Join(root, "second-plan.json") if err := WritePlan(second, &plan); err != nil { t.Fatal(err) } if err := safeio.WriteCanonicalNewPrivateFile(absent, []byte("services: {}\n"), 0o600); err != nil { t.Fatal(err) } if VerifyPlanInputs(second) == nil { t.Fatal("newly appearing override did not invalidate plan") } }