feat(operations): add auditable source provider maintenance

This commit is contained in:
lingniu
2026-07-16 20:01:08 +08:00
parent c270140006
commit 9a5e6e0c4f
19 changed files with 430 additions and 67 deletions

View File

@@ -262,6 +262,36 @@ func TestVehicleSourcePolicyUpdateRequiresAdminAndUsesOptimisticVersion(t *testi
if updated.Policy.Version != 2 || len(updated.Policy.Audit) != 1 || updated.Policy.Audit[0].Actor != "平台管理员" {
t.Fatalf("source policy update must version and audit: %+v", updated.Policy)
}
if _, err := service.UpdateVehicleSourcePolicy(admin, diagnostic.Evidence.VIN, VehicleSourcePolicyUpdate{
Version: 2, SourceRef: source.SourceRef, ProviderName: "G7s",
Enabled: false, Priority: source.Priority,
}); err == nil {
t.Fatal("provider maintenance must require an authoritative evidence note")
}
updated, err = service.UpdateVehicleSourcePolicy(admin, diagnostic.Evidence.VIN, VehicleSourcePolicyUpdate{
Version: 2, SourceRef: source.SourceRef, ProviderName: "G7s",
ProviderEvidence: "GPS 运维终端清单 2026-07-16",
Enabled: false, Priority: source.Priority, Remark: "人工核验",
})
if err != nil {
t.Fatalf("admin provider update failed: %v", err)
}
if updated.Policy.Version != 3 || updated.Policy.Audit[0].ChangeType != "provider" {
t.Fatalf("provider update must share optimistic versioning and audit: %+v", updated.Policy)
}
if !strings.Contains(updated.Policy.Audit[0].Summary, "核验依据GPS 运维终端清单 2026-07-16") ||
strings.Contains(updated.Policy.Audit[0].Summary, "人工核验") {
t.Fatalf("provider evidence and policy remark must remain separate: %+v", updated.Policy.Audit[0])
}
providerFound := false
for _, item := range updated.Evidence.LocationSources {
if item.SourceRef == source.SourceRef && item.ProviderOverride == "G7s" && item.SourceLabel == "G7s" {
providerFound = true
}
}
if !providerFound {
t.Fatalf("provider update must immediately affect source evidence: %+v", updated.Evidence.LocationSources)
}
if _, err := service.UpdateVehicleSourcePolicy(admin, diagnostic.Evidence.VIN, VehicleSourcePolicyUpdate{
Version: 1, SourceRef: source.SourceRef, Enabled: true, Priority: source.Priority,
}); err == nil {