affaan-m/ECC · critical · anyhow::Error
harness health evidence integrity verification failed
Error message
harness health evidence integrity verification failed
What it means
Round-trip verification of stored health evidence failed: re-parsing health_evidence_json into a HealthEvidenceSnapshot and recomputing canonical_json() and digest() does not reproduce the stored digest, or snapshot.asserted_healthy != stored asserted, or the resolved snapshot candidate_id != entry.candidate_id. This is the tamper/corruption detector.
Source
Thrown at ecc2/src/session/store.rs:5609
return Ok(());
}
anyhow::bail!("missing harness health evidence integrity metadata");
}
let (Some(json), Some(digest), Some(asserted), Some(status)) = fields else {
anyhow::bail!("incomplete harness health evidence integrity metadata");
};
if json.len() > 8192 {
anyhow::bail!("harness health evidence exceeds integrity verification bound");
}
let snapshot: HealthEvidenceSnapshot = serde_json::from_str(json)?;
let snapshot_candidate_id =
Self::resolve_harness_candidate_id(&self.conn, &snapshot.candidate_id)?;
if snapshot.canonical_json()? != *json
|| snapshot.digest()? != *digest
|| snapshot.asserted_healthy != asserted
|| snapshot_candidate_id != entry.candidate_id
{
anyhow::bail!("harness health evidence integrity verification failed");
}
let event_consistent = match entry.event_type.as_str() {
"promoted" => status == "healthy" && asserted,
"promotion_rolled_back" => status == "unhealthy" && !asserted,
"health_check_error_rolled_back" => status == "error",
_ => false,
};
if !event_consistent {
anyhow::bail!("harness health evidence is inconsistent with audit outcome");
}
if let Some(evaluation_id) = entry.evaluation_id {
let evaluation: (Option<String>, Option<String>, Option<bool>, Option<String>, bool) = self.conn.query_row(
"SELECT health_evidence_json, health_evidence_sha256, asserted_health, health_check_status, legacy_unverifiable FROM harness_evaluations WHERE id = ?1",
[evaluation_id],
|row| Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?, row.get(4)?)),
)?;
if evaluation
!= (View on GitHub (pinned to 01e15490f0)
Solutions
- Recompute and rewrite the health evidence (json, sha256, asserted, status) from the authoritative source so the round-trip holds.
- Never edit health_evidence_json / health_evidence_sha256 / asserted_health columns directly.
- Pin the canonical_json + digest algorithm to a versioned implementation so writes and verifies agree.
Defensive patterns
Strategy: try-catch
Validate before calling
// Proactive round-trip check at write time so verification can never fail later. let json = health_evidence.canonical_json()?; let digest = health_evidence.digest()?; let round_trip: HealthEvidenceSnapshot = serde_json::from_str(&json)?; assert_eq!(round_trip.canonical_json()?, json, "canonical_json not stable"); assert_eq!(round_trip.digest()?, digest, "digest not stable"); assert_eq!(round_trip.asserted_healthy, health_evidence.asserted_healthy); assert_eq!(round_trip.candidate_id, health_evidence.candidate_id);
Type guard
fn health_evidence_round_trips(he: &HealthEvidenceSnapshot) -> bool {
let Ok(json) = he.canonical_json() else { return false; };
let Ok(digest) = he.digest() else { return false; };
let Ok(rt) = serde_json::from_str::<HealthEvidenceSnapshot>(&json) else { return false; };
rt.canonical_json().ok().as_deref() == Some(json.as_str())
&& rt.digest().ok().as_deref() == Some(digest.as_str())
&& rt.asserted_healthy == he.asserted_healthy
&& rt.candidate_id == he.candidate_id
} Try / catch
match verify_audit_entry(&store, &entry) {
Ok(()) => { /* ok */ }
Err(e) if e.to_string().contains("integrity verification failed") => {
// tamper/corruption detected. Quarantine the row, recompute from the authoritative
// source, and alert — do not silently overwrite.
}
Err(e) => return Err(e),
} Prevention
- Never edit health_evidence_json, health_evidence_sha256, or asserted_health directly.
- Pin the canonical_json/digest algorithm to a versioned implementation shared by writers and verifiers.
- Write a round-trip unit test and run it on every release that touches serialization.
When it happens
Trigger: Any of: health_evidence_json was edited after writing; health_evidence_sha256 is stale; asserted_health was flipped; the snapshot's candidate_id (after alias resolution) differs from the audit entry's candidate_id.
Common situations: Manual DB edits to any of the four columns; a serialization/hash algorithm change between write and verify; bit rot; a malicious or buggy write that did not compute the digest canonically.
Related errors
- candidate alias collision with physical candidate id
- candidate id collision with different immutable content
- missing harness health evidence integrity metadata
- incomplete harness health evidence integrity metadata
- audit health evidence does not match its evaluation
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/8d84a3067a3c20eb.
Report an issue: GitHub.