Classify I and A as mechanical and calibrate V observations offline.

WHITEHAT-WP-0012 records that identity and authorization evidence belongs in the declaring service's CI, and adds an in-process V2/V3/V4 observation judge that injects no failure. Live E4, R4, and V stay wait on an unnamed owner or operator, so the plan is blocked. No packet is authorized.

Assistant: grok
Assistant-Session: 01a10450-dda4-7253-91a9-b8dccb2f0173
This commit is contained in:
tegwick 2026-10-04 11:15:01 +02:00
parent 3cd8a81d77
commit eebcc39a12
18 changed files with 678 additions and 25 deletions

View file

@ -42,7 +42,7 @@ def register() -> dict:
"declared_interval": None,
"scheduled": False,
"exposure_window": "No live target and no schedule, so no detection window.",
"live_owner": None,
"live_owner": "WHITEHAT-WP-0012-T03",
},
{
"family": "P1/P2",
@ -58,7 +58,18 @@ def register() -> dict:
"declared_interval": None,
"scheduled": False,
"exposure_window": "No live target and no schedule, so no detection window.",
"live_owner": None,
"live_owner": "WHITEHAT-WP-0012-T04",
},
{
"family": "V2/V3/V4",
"executable": "whitehat v-fixtures",
"declared_interval": None,
"scheduled": False,
"exposure_window": (
"An operator-approved failure-injection window only. "
"The harness injects no failure. V1 is not this family."
),
"live_owner": "WHITEHAT-WP-0012-T05",
},
{
"family": "ASM T-01..T-10",

View file

@ -14,6 +14,7 @@ from .cadence import register as cadence_register
from .e3 import CADENCE, PROBES, e3_calibration
from .e4 import e4_calibration
from .r4 import r4_calibration
from .v import v_calibration
from .engagement import AuthorizationError, Engagement
from .fixtures import FixtureService, probe_suite
from .model import RunReport, utc_now
@ -107,6 +108,10 @@ def main(argv: list[str] | None = None) -> None:
e4_fix.add_argument("--output")
r4_fix = commands.add_parser("r4-fixtures", help="calibrate R4 probes offline")
r4_fix.add_argument("--output")
v_fix = commands.add_parser(
"v-fixtures", help="calibrate V observation shapes offline"
)
v_fix.add_argument("--output")
capacity_fix = commands.add_parser(
"capacity-fixture", help="calibrate P1/P2 evaluator offline"
)
@ -240,6 +245,14 @@ def main(argv: list[str] | None = None) -> None:
else:
print(rendered, end="")
raise SystemExit(0 if result["outcome"] == "pass" else 1)
if args.command == "v-fixtures":
result = v_calibration()
rendered = json.dumps(result, indent=2, sort_keys=True) + "\n"
if args.output:
Path(args.output).write_text(rendered, encoding="utf-8")
else:
print(rendered, end="")
raise SystemExit(0 if result["outcome"] == "pass" else 1)
if args.command == "e3-fixtures":
result = e3_calibration()
rendered = json.dumps(result, indent=2, sort_keys=True) + "\n"

View file

@ -30,10 +30,11 @@ APPROVAL_CLASSES = {
"asm": frozenset({"asm-assurance"}),
"fixture-e4": frozenset({"e4-confinement"}),
"fixture-r4": frozenset({"r4-erasure"}),
"fixture-v": frozenset({"v-observation"}),
}
FIXTURE_CLASSES = frozenset({
"fixture-e2", "fixture-e3", "fixture-capacity", "fixture-asm",
"fixture-e4", "fixture-r4",
"fixture-e4", "fixture-r4", "fixture-v",
})

View file

@ -45,12 +45,14 @@ def load_registration(path: str | Path) -> dict[str, Any]:
raise AuthorizationError(f"{path}: E3 registration must project one runtime identity")
if classes & {"fixture-capacity", "capacity"} and count not in {0, 1}:
raise AuthorizationError(f"{path}: capacity registration projects at most one aggressor identity")
if classes & {"fixture-e4", "fixture-r4"} and count != 0:
raise AuthorizationError(f"{path}: E4 and R4 fixtures project no credential")
if (classes & {"fixture-e4", "fixture-r4"}) and (
if classes & {"fixture-e4", "fixture-r4", "fixture-v"} and count != 0:
raise AuthorizationError(f"{path}: E4, R4, and V fixtures project no credential")
if (classes & {"fixture-e4", "fixture-r4", "fixture-v"}) and (
classes & {"live-e2", "e3", "capacity", "asm"}
):
raise AuthorizationError(f"{path}: E4 and R4 fixtures cannot carry a live approval class")
raise AuthorizationError(
f"{path}: E4, R4, and V fixtures cannot carry a live approval class"
)
if classes & {"fixture-asm", "asm"} and count not in {0, 1, 2}:
raise AuthorizationError(f"{path}: ASM registration projects at most two identities")
if classes & {"fixture-asm", "asm"} and not data.get("test_id"):

203
src/whitehat_security/v.py Normal file
View file

@ -0,0 +1,203 @@
"""Judge a supplied availability observation. Injects no failure."""
from __future__ import annotations
from dataclasses import dataclass
from .model import Outcome, utc_now
_LEVELS = frozenset({"V1", "V2", "V3", "V4"})
_KIND = {
"V2": "instance-terminated",
"V3": "failure-domain-removed",
"V4": "region-unavailable",
}
@dataclass(frozen=True)
class VObservation:
"""Supplied record. This process never sets a failure in a cluster."""
probe_id: str
claimed_level: str
operation: str = ""
failure_injected: bool = False
failure_kind: str = ""
traffic_continued_or_recovered: bool = False
rto_recorded: bool = False
rpo_recorded: bool = False
shared_failure_domain_recorded: bool = False
critical_path_observed: bool = False
degraded_modes_observed: bool = False
alternate_region_recovered: bool = False
@dataclass(frozen=True)
class VResult:
probe_id: str
outcome: Outcome
reason: str
def evaluate(observation: VObservation) -> VResult:
"""Judge one supplied observation against Tenancy Posture §13.
V1 is a mechanical restart exercise and cannot pass here. V2, V3, and V4
require a recorded failure injection of the matching kind. A missing
measurement stays inconclusive. A pass is a complete observation shape.
"""
if observation.claimed_level not in _LEVELS:
return VResult(observation.probe_id, "aborted", "unknown availability claim")
if observation.claimed_level == "V1":
return VResult(
observation.probe_id, "inconclusive",
"V1 is a mechanical restart exercise and is not evidence from this harness",
)
if observation.failure_kind == "restart":
return VResult(
observation.probe_id, "finding",
"a restart or recreate is not V2, V3, or V4",
)
if not observation.failure_injected:
return VResult(
observation.probe_id, "finding",
"no failure was injected",
)
required = _KIND[observation.claimed_level]
if observation.failure_kind != required:
return VResult(
observation.probe_id, "finding",
"failure kind does not match the claimed level",
)
if not observation.operation.strip():
return VResult(
observation.probe_id, "inconclusive",
"the claim does not name the operation",
)
if not observation.rto_recorded or not observation.rpo_recorded:
return VResult(
observation.probe_id, "inconclusive",
"measured RTO and RPO are absent",
)
if observation.claimed_level == "V2":
if not observation.traffic_continued_or_recovered:
return VResult(
observation.probe_id, "finding",
"traffic did not continue or recover",
)
if not observation.shared_failure_domain_recorded:
return VResult(
observation.probe_id, "inconclusive",
"remaining shared failure domain was not recorded",
)
return VResult(
observation.probe_id, "pass",
"observation shape matches V2; this harness injected no failure",
)
if observation.claimed_level == "V3":
if not observation.critical_path_observed or not observation.degraded_modes_observed:
return VResult(
observation.probe_id, "inconclusive",
"critical path or degraded modes were not observed",
)
return VResult(
observation.probe_id, "pass",
"observation shape matches V3; this harness injected no failure",
)
if not observation.alternate_region_recovered:
return VResult(
observation.probe_id, "finding",
"traffic and state did not recover in the alternate region",
)
return VResult(
observation.probe_id, "pass",
"observation shape matches V4; this harness injected no failure",
)
def _observation(probe_id: str, level: str, **overrides: object) -> VObservation:
kind = {"V1": "restart", "V2": "instance-terminated",
"V3": "failure-domain-removed", "V4": "region-unavailable"}[level]
fields: dict[str, object] = {
"probe_id": probe_id,
"claimed_level": level,
"operation": "read",
"failure_injected": level != "V1",
"failure_kind": kind,
"traffic_continued_or_recovered": True,
"rto_recorded": True,
"rpo_recorded": True,
"shared_failure_domain_recorded": True,
"critical_path_observed": True,
"degraded_modes_observed": True,
"alternate_region_recovered": level == "V4",
}
fields.update(overrides)
return VObservation(
probe_id=str(fields["probe_id"]),
claimed_level=str(fields["claimed_level"]),
operation=str(fields["operation"]),
failure_injected=bool(fields["failure_injected"]),
failure_kind=str(fields["failure_kind"]),
traffic_continued_or_recovered=bool(fields["traffic_continued_or_recovered"]),
rto_recorded=bool(fields["rto_recorded"]),
rpo_recorded=bool(fields["rpo_recorded"]),
shared_failure_domain_recorded=bool(fields["shared_failure_domain_recorded"]),
critical_path_observed=bool(fields["critical_path_observed"]),
degraded_modes_observed=bool(fields["degraded_modes_observed"]),
alternate_region_recovered=bool(fields["alternate_region_recovered"]),
)
def v_calibration() -> dict:
"""Known-bad must fail before a known-good pass is trusted. No injection."""
started = utc_now()
known_bad = [
evaluate(_observation("restart-as-v2", "V2", failure_kind="restart")),
evaluate(_observation("no-injection", "V2", failure_injected=False)),
evaluate(_observation("missing-rto-rpo", "V2", rto_recorded=False, rpo_recorded=False)),
evaluate(_observation("traffic-stopped", "V2", traffic_continued_or_recovered=False)),
evaluate(_observation("missing-failure-domain", "V2", shared_failure_domain_recorded=False)),
evaluate(_observation("unnamed-operation", "V2", operation="")),
evaluate(_observation("v1-restart", "V1")),
evaluate(_observation("v3-wrong-kind", "V3", failure_kind="instance-terminated")),
evaluate(_observation("v4-no-alternate", "V4", alternate_region_recovered=False)),
]
expected = {
"restart-as-v2": "finding",
"no-injection": "finding",
"missing-rto-rpo": "inconclusive",
"traffic-stopped": "finding",
"missing-failure-domain": "inconclusive",
"unnamed-operation": "inconclusive",
"v1-restart": "inconclusive",
"v3-wrong-kind": "finding",
"v4-no-alternate": "finding",
}
bad_held = all(result.outcome == expected[result.probe_id] for result in known_bad)
known_good = [
evaluate(_observation("v2-shape", "V2")),
evaluate(_observation("v3-shape", "V3")),
evaluate(_observation("v4-shape", "V4")),
] if bad_held else []
good_held = bool(known_good) and all(result.outcome == "pass" for result in known_good)
return {
"schema_version": "whitehat-v-calibration/v1",
"evidence_class": "fixture",
"failure_injected_by_harness": False,
"run_id": f"v-calibration-{started}",
"started_at": started,
"ended_at": utc_now(),
"outcome": "pass" if bad_held and good_held else "finding",
"known_bad_failed_first": bad_held,
"known_good": [result.__dict__ for result in known_good],
"known_bad": [result.__dict__ for result in known_bad],
"limitations": [
"Offline V calibration evaluates the harness; it is not target assurance.",
"No instance was terminated, no failure domain was removed, and no region was made unavailable.",
"No cluster call, packet, database connection, or load was made.",
"A pass is a complete observation shape. It is not availability of a service.",
"V1 is a mechanical exercise and stays inconclusive here.",
"Identity and authorization evidence is not judged by this command.",
],
}