package accessruleaudit import ( "testing" "time" ) func TestVerifyMigrationAcceptsMatchingArchiveAndUnchangedDeny(t *testing.T) { before := auditSnapshot(3, "allow-before", 2, "deny-before", nil) after := auditSnapshot(0, "", 2, "deny-before", &ArchiveManifest{ MigrationBatch: MigrationBatch, ManifestAllowCount: 3, ManifestAllowSHA: sha256Hex("allow-before"), ArchivedAllowCount: 3, ArchivedAllowSHA: sha256Hex("allow-before"), ManifestDenyCount: 2, ManifestDenySHA: sha256Hex("deny-before"), Consistent: true, }) if err := VerifyMigration(before, after); err != nil { t.Fatalf("verify matching migration: %v", err) } } func TestVerifyMigrationRejectsChangedDenyOrMissingArchive(t *testing.T) { before := auditSnapshot(1, "allow", 1, "deny", nil) withoutArchive := auditSnapshot(0, "", 1, "deny", nil) if err := VerifyMigration(before, withoutArchive); err == nil { t.Fatal("missing archive must fail verification") } changedDeny := auditSnapshot(0, "", 1, "changed-deny", &ArchiveManifest{ MigrationBatch: MigrationBatch, ManifestAllowCount: 1, ManifestAllowSHA: sha256Hex("allow"), ArchivedAllowCount: 1, ArchivedAllowSHA: sha256Hex("allow"), ManifestDenyCount: 1, ManifestDenySHA: sha256Hex("deny"), Consistent: true, }) if err := VerifyMigration(before, changedDeny); err == nil { t.Fatal("changed deny hash must fail verification") } } func auditSnapshot(allowCount int64, allowSeed string, denyCount int64, denySeed string, archive *ArchiveManifest) Snapshot { counts := make([]RuleCount, 0, 2) if allowCount > 0 { counts = append(counts, RuleCount{SubjectType: "api_key", Effect: "allow", ResourceType: "platform_model", Status: "active", Count: allowCount}) } if denyCount > 0 { counts = append(counts, RuleCount{SubjectType: "api_key", Effect: "deny", ResourceType: "platform_model", Status: "active", Count: denyCount}) } return Snapshot{ SchemaVersion: SchemaVersion, GeneratedAt: time.Date(2026, 8, 3, 0, 0, 0, 0, time.UTC), SecretSafe: true, Live: RuleSet{ Total: allowCount + denyCount, SHA256: sha256Hex("all-" + allowSeed + "-" + denySeed), AllowCount: allowCount, AllowSHA256: sha256Hex(allowSeed), DenyCount: denyCount, DenySHA256: sha256Hex(denySeed), Counts: counts, }, Archive: archive, } }