mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-05-07 00:37:36 +00:00
110 lines
3.5 KiB
Go
110 lines
3.5 KiB
Go
package ai
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
unifiedresources "github.com/rcourtman/pulse-go-rewrite/internal/unifiedresources"
|
|
)
|
|
|
|
func TestRecordUnifiedResourceExport_UsesCanonicalPrivacyHelpers(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
counts map[unifiedresources.ResourceSensitivity]int
|
|
localOnlyCount int
|
|
redactionHints []unifiedresources.ResourceRedactionHint
|
|
wantDecision unifiedresources.ExportDecision
|
|
wantReason string
|
|
wantRedactions []string
|
|
}{
|
|
{
|
|
name: "public",
|
|
counts: map[unifiedresources.ResourceSensitivity]int{unifiedresources.ResourceSensitivityPublic: 1},
|
|
wantDecision: unifiedresources.ExportAllowed,
|
|
wantReason: "public unified resource context",
|
|
wantRedactions: nil,
|
|
},
|
|
{
|
|
name: "internal",
|
|
counts: map[unifiedresources.ResourceSensitivity]int{unifiedresources.ResourceSensitivityInternal: 1},
|
|
wantDecision: unifiedresources.ExportRequiresConsent,
|
|
wantReason: "internal unified resource context requires export consent",
|
|
wantRedactions: nil,
|
|
},
|
|
{
|
|
name: "redacted",
|
|
counts: map[unifiedresources.ResourceSensitivity]int{unifiedresources.ResourceSensitivitySensitive: 1},
|
|
localOnlyCount: 1,
|
|
redactionHints: []unifiedresources.ResourceRedactionHint{
|
|
unifiedresources.ResourceRedactionHostname,
|
|
unifiedresources.ResourceRedactionHostname,
|
|
unifiedresources.ResourceRedactionPath,
|
|
},
|
|
wantDecision: unifiedresources.ExportRedacted,
|
|
wantReason: "governed unified resource context exported in redacted form",
|
|
wantRedactions: []string{"Hostname", "Path"},
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
store := unifiedresources.NewMemoryStore()
|
|
svc := &Service{
|
|
orgID: "org-1",
|
|
resourceExportStore: store,
|
|
resourceExportStoreOrgID: "org-1",
|
|
}
|
|
|
|
svc.recordUnifiedResourceExport(
|
|
"anthropic:test-model",
|
|
"canonical summary",
|
|
unifiedresources.ResourceStats{
|
|
Total: 1,
|
|
ByType: map[unifiedresources.ResourceType]int{
|
|
unifiedresources.ResourceTypeAgent: 1,
|
|
},
|
|
},
|
|
tc.counts,
|
|
tc.localOnlyCount,
|
|
tc.redactionHints,
|
|
)
|
|
|
|
audits, err := store.GetExportAudits(time.Time{}, 10)
|
|
if err != nil {
|
|
t.Fatalf("GetExportAudits: %v", err)
|
|
}
|
|
if len(audits) != 1 {
|
|
t.Fatalf("expected 1 export audit, got %d", len(audits))
|
|
}
|
|
if audits[0].Decision != tc.wantDecision {
|
|
t.Fatalf("decision = %q, want %q", audits[0].Decision, tc.wantDecision)
|
|
}
|
|
if audits[0].Destination != "anthropic:test-model" {
|
|
t.Fatalf("destination = %q, want anthropic:test-model", audits[0].Destination)
|
|
}
|
|
if audits[0].EnvelopeHash == "" {
|
|
t.Fatal("expected envelope hash to be recorded")
|
|
}
|
|
if len(audits[0].Redactions) != len(tc.wantRedactions) {
|
|
t.Fatalf("redactions = %#v, want %#v", audits[0].Redactions, tc.wantRedactions)
|
|
}
|
|
for i := range tc.wantRedactions {
|
|
if audits[0].Redactions[i] != tc.wantRedactions[i] {
|
|
t.Fatalf("redactions = %#v, want %#v", audits[0].Redactions, tc.wantRedactions)
|
|
}
|
|
}
|
|
|
|
decision, reason := unifiedresources.ExportDecisionForContext(
|
|
unifiedresources.ExportSensitivityFloor(tc.counts),
|
|
tc.localOnlyCount,
|
|
len(tc.wantRedactions),
|
|
)
|
|
if decision != tc.wantDecision {
|
|
t.Fatalf("shared decision = %q, want %q", decision, tc.wantDecision)
|
|
}
|
|
if reason != tc.wantReason {
|
|
t.Fatalf("shared reason = %q, want %q", reason, tc.wantReason)
|
|
}
|
|
})
|
|
}
|
|
}
|