affaan-m/ECC · error

harness health evidence is inconsistent with audit outcome

Error message

harness health evidence is inconsistent with audit outcome

What it means

Beyond cryptographic integrity, the verifier enforces semantic consistency: the event type must agree with the evidence. 'promoted' requires status 'healthy' with asserted_healthy=true, 'promotion_rolled_back' requires 'unhealthy' with asserted=false, and 'health_check_error_rolled_back' requires status 'error'. Anything else fails this check.

Solutions

  1. Capture a fresh health snapshot at the moment of the event and attach the one matching the outcome
  2. Make the event-writing code derive event_type and evidence from the same health-check result so they cannot diverge
  3. If you added a new event type, extend the match in the verifier to define its required (status, asserted) combination

Example fix

// before
audit_event("promoted", evidence_from_last_check); // may carry stale/unhealthy evidence
// after
let check = run_health_check();
audit_event(if check.healthy { "promoted" } else { "promotion_rolled_back" }, check.into_snapshot());
Defensive patterns

Strategy: validation

Validate before calling

// Rust: enforce outcome/status coherence before writing the event
fn event_matches_outcome(event_type: &str, status: &str, asserted: bool) -> bool {
    match event_type {
        "promoted" => status == "healthy" && asserted,
        "promotion_rolled_back" => status == "unhealthy" && !asserted,
        "health_check_error_rolled_back" => status == "error",
        _ => false,
    }
}

Prevention

When it happens

Trigger: Recording a 'promoted' event while the health evidence shows status 'unhealthy' or asserted=false; a rollback event backed by evidence asserting healthy; an unknown event_type falling into the `_ => false` arm.

Common situations: A promotion pipeline that writes the audit event before the health check result is known; code that reuses a healthy snapshot when logging a rollback; a typo'd or new event_type string not covered by the match.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/b3ea3b57a6c1f5a9. Report an issue: GitHub.

Appendix: source

Thrown at ecc2/src/session/store.rs:5618

        }
        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
                != (
                    Some(json.clone()),
                    Some(digest.clone()),
                    Some(asserted),
                    Some(status.clone()),
                    false,
                )
            {
                anyhow::bail!("audit health evidence does not match its evaluation");
            }

View on GitHub (pinned to 8321021c54)