feat: summarize official validation results

Fixes #5
This commit is contained in:
2026-07-13 01:06:37 +08:00
parent e5fcf26e19
commit 1bcb9c828a
5 changed files with 201 additions and 2 deletions
+50
View File
@@ -270,6 +270,8 @@ pub struct OfficialLocalManifestAuditItem {
/// ZIP structure validation error, when the URL or destination is a ZIP
/// and the local file did not pass ZIP structure validation.
pub zip_error: Option<String>,
/// Whether this item required and passed ZIP structure validation.
pub zip_structure_verified: bool,
}
/// Local download-manifest audit result for a pull plan.
@@ -297,6 +299,23 @@ impl OfficialLocalManifestAuditReport {
pub fn repair_needed_count(&self) -> usize {
self.items.len().saturating_sub(self.verified_count())
}
/// Returns the number of files that passed local manifest path, size, and
/// BLAKE3 validation.
pub fn manifest_blake3_verified_count(&self) -> usize {
self.items
.iter()
.filter(|item| item.status.is_verified())
.count()
}
/// Returns the number of ZIP files that passed structural validation.
pub fn zip_structure_verified_count(&self) -> usize {
self.items
.iter()
.filter(|item| item.zip_structure_verified)
.count()
}
}
/// Full local verification report for all entries currently recorded in the
@@ -334,6 +353,23 @@ impl OfficialLocalVerificationReport {
pub fn failure_count(&self) -> usize {
self.items.len().saturating_sub(self.verified_count())
}
/// Returns the number of local manifest entries that passed path, size,
/// and BLAKE3 validation.
pub fn manifest_blake3_verified_count(&self) -> usize {
self.items
.iter()
.filter(|item| item.status.is_verified())
.count()
}
/// Returns the number of ZIP files that passed structural validation.
pub fn zip_structure_verified_count(&self) -> usize {
self.items
.iter()
.filter(|item| item.zip_structure_verified)
.count()
}
}
/// Existing local state for an official pull plan.
@@ -1018,6 +1054,7 @@ impl OfficialResourcePullService {
expected_blake3: None,
actual_blake3: None,
zip_error: None,
zip_structure_verified: false,
});
};
@@ -1036,6 +1073,7 @@ impl OfficialResourcePullService {
expected_blake3,
actual_blake3: None,
zip_error: None,
zip_structure_verified: false,
});
}
@@ -1051,6 +1089,7 @@ impl OfficialResourcePullService {
expected_blake3,
actual_blake3: None,
zip_error: None,
zip_structure_verified: false,
});
}
@@ -1065,6 +1104,7 @@ impl OfficialResourcePullService {
expected_blake3,
actual_blake3: None,
zip_error: None,
zip_structure_verified: false,
});
};
@@ -1079,6 +1119,7 @@ impl OfficialResourcePullService {
expected_blake3,
actual_blake3: None,
zip_error: None,
zip_structure_verified: false,
});
}
@@ -1094,9 +1135,12 @@ impl OfficialResourcePullService {
expected_blake3,
actual_blake3: Some(actual_blake3),
zip_error: None,
zip_structure_verified: false,
});
}
let zip_structure_required =
url_or_path_has_zip_extension(url) || path_has_zip_extension(&destination);
if let Err(error) = self.validate_zip_if_needed(url, &destination) {
return Ok(OfficialLocalManifestAuditItem {
url: url.to_string(),
@@ -1108,6 +1152,7 @@ impl OfficialResourcePullService {
expected_blake3,
actual_blake3: Some(actual_blake3),
zip_error: Some(error),
zip_structure_verified: false,
});
}
@@ -1121,6 +1166,7 @@ impl OfficialResourcePullService {
expected_blake3,
actual_blake3: Some(actual_blake3),
zip_error: None,
zip_structure_verified: zip_structure_required,
})
}
@@ -1841,6 +1887,8 @@ fi
let clean_audit = service.audit_local_manifest(&plan).unwrap();
assert!(clean_audit.is_clean());
assert_eq!(clean_audit.verified_count(), first_report.items.len());
assert_eq!(clean_audit.manifest_blake3_verified_count(), 7);
assert_eq!(clean_audit.zip_structure_verified_count(), 4);
let corrupted = first_report
.items
@@ -1879,6 +1927,8 @@ fi
assert!(verification.is_clean());
assert_eq!(verification.items.len(), 7);
assert_eq!(verification.verified_count(), 7);
assert_eq!(verification.manifest_blake3_verified_count(), 7);
assert_eq!(verification.zip_structure_verified_count(), 4);
assert_eq!(verification.official_hash_pair_count, 1);
assert_eq!(verification.official_hash_verified_count, 1);