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

  1. Recompute and rewrite the health evidence (json, sha256, asserted, status) from the authoritative source so the round-trip holds.
  2. Never edit health_evidence_json / health_evidence_sha256 / asserted_health columns directly.
  3. 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

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


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/8d84a3067a3c20eb. Report an issue: GitHub.