package redaction_test import ( "encoding/json" "math" "os" "path/filepath" "strings" "testing" "gitea.maximumdirect.net/eric/audita/internal/core/diagnostics" "gitea.maximumdirect.net/eric/audita/internal/core/redaction" "gitea.maximumdirect.net/eric/audita/internal/core/schema" ) func TestStringRedactionPreservesSerializationAndDomainData(t *testing.T) { secrets := []string{"2", `quoted"\key`, "overlap", "overlap-long", "REDACTED"} r := redaction.New(secrets) original := map[string]any{"number": 2, "large": json.Number("9007199254740993"), "bool": true, "text": `echo:2 quoted"\key overlap-long overlap`} raw, err := r.JSON(original) if err != nil { t.Fatal(err) } var decoded map[string]any if err := json.Unmarshal(raw, &decoded); err != nil { t.Fatal(err) } if decoded["number"] != float64(2) || decoded["bool"] != true || !strings.Contains(string(raw), "9007199254740993") { t.Fatalf("changed scalar meanings: %s", raw) } if decoded["text"] != "echo:[REDACTED] [REDACTED] [REDACTED] [REDACTED]" { t.Fatalf("redaction: %s", raw) } if original["text"] != `echo:2 quoted"\key overlap-long overlap` { t.Fatal("mutated domain data") } if raw, err := r.JSON(math.NaN()); err == nil || raw != nil { t.Fatalf("unsafe fallback: %s %v", raw, err) } if raw, err := r.JSON(map[string]string{"overlap": "first", "overlap-long": "second"}); err == nil || raw != nil { t.Fatalf("colliding redacted keys: %s %v", raw, err) } nested, _ := json.Marshal(map[string]string{"reason": `quoted"\key`}) raw, err = r.JSON(map[string]string{"final_content": string(nested)}) if err != nil || strings.Contains(string(raw), "key") { t.Fatalf("nested content: %s %v", raw, err) } yaml, err := r.YAML([]byte("version: 2\nenabled: true\nmessage: echo:2\n")) if err != nil || !strings.Contains(string(yaml), "version: 2") || !strings.Contains(string(yaml), "echo:[REDACTED]") { t.Fatalf("YAML: %s %v", yaml, err) } } func TestDebugWritersRedactSourceAndNormalizedSnapshots(t *testing.T) { dir := t.TempDir() run, err := diagnostics.NewRunDirectory(dir, "run-test", "2") if err != nil { t.Fatal(err) } if err := run.WriteSourceTranscript(&schema.SourceTranscript{}, []byte(`{"segments":[{"text":"echo:2","id":2}]}`)); err != nil { t.Fatal(err) } if err := run.WriteNormalizedTranscript(&schema.Transcript{Segments: []schema.Segment{{ID: 2, Text: "echo:2"}}}); err != nil { t.Fatal(err) } for _, path := range []string{filepath.Join(run.Path(), diagnostics.ArtifactSourceTranscript), filepath.Join(run.Path(), diagnostics.ArtifactNormalizedTranscript)} { raw, err := os.ReadFile(path) if err != nil { t.Fatal(err) } if strings.Contains(string(raw), "echo:2") || !strings.Contains(string(raw), "echo:[REDACTED]") || !strings.Contains(string(raw), `"id": 2`) { t.Fatalf("snapshot: %s", raw) } } if err := run.WriteJSONArtifact("invalid.json", map[string]any{"secret": "echo:2", "invalid": math.NaN()}); err == nil { t.Fatal("expected serialization failure") } if _, err := os.Stat(filepath.Join(run.Path(), "invalid.json")); !os.IsNotExist(err) { t.Fatalf("failed artifact persisted: %v", err) } }