State the harness scope and calibrate E4 and R4 offline.
SCOPE.md now matches the commands that run. E4 and R4 fail known-bad fixtures in process, and the cadence register schedules nothing. Assistant: grok Assistant-Session: 01a10450-dda4-7253-91a9-b8dccb2f0173
This commit is contained in:
parent
314e2a8bf2
commit
7a2373ae4c
24 changed files with 989 additions and 58 deletions
128
src/whitehat_security/r4.py
Normal file
128
src/whitehat_security/r4.py
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Literal
|
||||
|
||||
from .model import Outcome, utc_now
|
||||
|
||||
Route = Literal["R4-A", "R4-B"]
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class R4Case:
|
||||
"""Synthetic erasure observation. No storage client and no key material."""
|
||||
|
||||
probe_id: str
|
||||
route: Route
|
||||
horizon_elapsed: bool = False
|
||||
key_destroyed: bool = False
|
||||
inventory_complete: bool = False
|
||||
recovered: bool = False
|
||||
readable: bool = False
|
||||
usable_key_survives: bool = False
|
||||
low_entropy_oracle: bool = False
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class R4Result:
|
||||
probe_id: str
|
||||
route: Route
|
||||
outcome: Outcome
|
||||
reason: str
|
||||
|
||||
|
||||
def evaluate(case: R4Case) -> R4Result:
|
||||
"""Judge one R4 case. An incomplete inventory is inconclusive, not a pass."""
|
||||
if not case.inventory_complete:
|
||||
return R4Result(
|
||||
case.probe_id, case.route, "inconclusive",
|
||||
"declared copies were not all exercised",
|
||||
)
|
||||
if case.route == "R4-A":
|
||||
if not case.horizon_elapsed:
|
||||
return R4Result(
|
||||
case.probe_id, case.route, "inconclusive",
|
||||
"recovery before the horizon is not an R4-A result",
|
||||
)
|
||||
if case.recovered:
|
||||
return R4Result(
|
||||
case.probe_id, case.route, "finding",
|
||||
"fixture content recovered after the erasure horizon",
|
||||
)
|
||||
return R4Result(
|
||||
case.probe_id, case.route, "pass",
|
||||
"no fixture content recovered from the declared copies",
|
||||
)
|
||||
if not case.key_destroyed:
|
||||
return R4Result(
|
||||
case.probe_id, case.route, "inconclusive",
|
||||
"key destruction alone is not a pass, and destruction was not recorded",
|
||||
)
|
||||
if case.readable or case.usable_key_survives or case.low_entropy_oracle:
|
||||
return R4Result(
|
||||
case.probe_id, case.route, "finding",
|
||||
"erased fixture remains readable or confirmable",
|
||||
)
|
||||
return R4Result(
|
||||
case.probe_id, case.route, "pass",
|
||||
"retained ciphertext is unreadable and no confirmation oracle remains",
|
||||
)
|
||||
|
||||
|
||||
def r4_calibration() -> dict:
|
||||
"""Known-bad must fail before a known-good pass is trusted. No storage."""
|
||||
started = utc_now()
|
||||
known_bad = [
|
||||
evaluate(R4Case(
|
||||
"horizon-recovered", "R4-A",
|
||||
horizon_elapsed=True, inventory_complete=True, recovered=True,
|
||||
)),
|
||||
evaluate(R4Case(
|
||||
"ciphertext-readable", "R4-B",
|
||||
key_destroyed=True, inventory_complete=True, readable=True,
|
||||
)),
|
||||
evaluate(R4Case(
|
||||
"usable-key-survives", "R4-B",
|
||||
key_destroyed=True, inventory_complete=True, usable_key_survives=True,
|
||||
)),
|
||||
evaluate(R4Case(
|
||||
"low-entropy-oracle", "R4-B",
|
||||
key_destroyed=True, inventory_complete=True, low_entropy_oracle=True,
|
||||
)),
|
||||
]
|
||||
inconclusive = [
|
||||
evaluate(R4Case("inventory-incomplete", "R4-A", horizon_elapsed=True)),
|
||||
evaluate(R4Case("before-horizon", "R4-A", inventory_complete=True)),
|
||||
evaluate(R4Case("key-not-destroyed", "R4-B", inventory_complete=True)),
|
||||
]
|
||||
bad_held = all(result.outcome == "finding" for result in known_bad)
|
||||
limits_held = all(result.outcome == "inconclusive" for result in inconclusive)
|
||||
known_good = [
|
||||
evaluate(R4Case(
|
||||
"horizon-clear", "R4-A",
|
||||
horizon_elapsed=True, inventory_complete=True,
|
||||
)),
|
||||
evaluate(R4Case(
|
||||
"key-destroyed-clear", "R4-B",
|
||||
key_destroyed=True, inventory_complete=True,
|
||||
)),
|
||||
] if bad_held and limits_held else []
|
||||
good_held = all(result.outcome == "pass" for result in known_good)
|
||||
return {
|
||||
"schema_version": "whitehat-r4-calibration/v1",
|
||||
"evidence_class": "fixture",
|
||||
"run_id": f"r4-calibration-{started}",
|
||||
"started_at": started,
|
||||
"ended_at": utc_now(),
|
||||
"outcome": "pass" if bad_held and limits_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],
|
||||
"inconclusive": [result.__dict__ for result in inconclusive],
|
||||
"limitations": [
|
||||
"Offline R4 calibration evaluates the harness; it is not target assurance.",
|
||||
"No backup, replica, key, or ciphertext was accessed.",
|
||||
"audit-core is not an R4 target. No live R4 target is registered.",
|
||||
"An incomplete copy inventory stays inconclusive and is not a pass.",
|
||||
],
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue