import json from pathlib import Path import pytest from whitehat_security.engagement import AuthorizationError from whitehat_security.targets import load_registration from whitehat_security.v import VObservation, evaluate, v_calibration def test_restart_and_missing_injection_are_not_a_pass(): restart = evaluate(VObservation( "restart", claimed_level="V2", operation="read", failure_injected=True, failure_kind="restart", traffic_continued_or_recovered=True, rto_recorded=True, rpo_recorded=True, shared_failure_domain_recorded=True, )) assert restart.outcome == "finding" absent = evaluate(VObservation( "absent", claimed_level="V2", operation="read", failure_injected=False, failure_kind="instance-terminated", traffic_continued_or_recovered=True, rto_recorded=True, rpo_recorded=True, shared_failure_domain_recorded=True, )) assert absent.outcome == "finding" def test_missing_measurements_stay_inconclusive(): missing = evaluate(VObservation( "rto", claimed_level="V2", operation="read", failure_injected=True, failure_kind="instance-terminated", traffic_continued_or_recovered=True, rto_recorded=False, rpo_recorded=True, shared_failure_domain_recorded=True, )) assert missing.outcome == "inconclusive" unnamed = evaluate(VObservation( "operation", claimed_level="V2", operation=" ", failure_injected=True, failure_kind="instance-terminated", traffic_continued_or_recovered=True, rto_recorded=True, rpo_recorded=True, shared_failure_domain_recorded=True, )) assert unnamed.outcome == "inconclusive" def test_v1_is_not_adversarial_evidence_from_this_harness(): result = evaluate(VObservation( "v1", claimed_level="V1", operation="read", failure_injected=True, failure_kind="restart", rto_recorded=True, )) assert result.outcome == "inconclusive" def test_v3_and_v4_reject_the_wrong_shape(): wrong = evaluate(VObservation( "v3", claimed_level="V3", operation="read", failure_injected=True, failure_kind="instance-terminated", rto_recorded=True, rpo_recorded=True, critical_path_observed=True, degraded_modes_observed=True, )) assert wrong.outcome == "finding" region = evaluate(VObservation( "v4", claimed_level="V4", operation="read", failure_injected=True, failure_kind="region-unavailable", rto_recorded=True, rpo_recorded=True, alternate_region_recovered=False, )) assert region.outcome == "finding" def test_unknown_claim_aborts(): assert evaluate(VObservation("nope", claimed_level="V9")).outcome == "aborted" def test_calibration_fails_known_bad_before_trusting_a_pass(): report = v_calibration() assert report["known_bad_failed_first"] is True assert report["failure_injected_by_harness"] is False assert report["evidence_class"] == "fixture" assert report["outcome"] == "pass" assert "pass" not in {item["outcome"] for item in report["known_bad"]} assert {item["outcome"] for item in report["known_good"]} == {"pass"} assert any("no cluster" in item.lower() or "no instance" in item.lower() for item in report["limitations"]) def test_fixture_v_projects_no_credential_and_no_live_class(tmp_path: Path): registration = json.loads(Path("targets/fixture-v.json").read_text(encoding="utf-8")) assert registration["identities"]["count"] == 0 assert registration["approval_classes"] == ["fixture-v"] registration["identities"]["count"] = 1 path = tmp_path / "counted.json" path.write_text(json.dumps(registration), encoding="utf-8") with pytest.raises(AuthorizationError, match="project no credential"): load_registration(path) registration["identities"]["count"] = 0 registration["approval_classes"] = ["fixture-v", "capacity"] path.write_text(json.dumps(registration), encoding="utf-8") with pytest.raises(AuthorizationError, match="cannot carry a live approval class"): load_registration(path)