From 494c29182d74f680b7264faa0f35a9b3918aca8f Mon Sep 17 00:00:00 2001 From: Marius Ciepluch <11855163+norandom@users.noreply.github.com> Date: Fri, 30 Oct 2026 10:13:09 +0100 Subject: [PATCH] feat(access-control-prover): 12.5 admission manifest consumption --- .kiro/specs/access-control-prover/tasks.md | 2 +- benchmarks/valid/prover_admission.py | 94 +++++++++++++++++ tests/test_prover_admission.py | 113 +++++++++++++++++++++ 3 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 benchmarks/valid/prover_admission.py create mode 100644 tests/test_prover_admission.py diff --git a/.kiro/specs/access-control-prover/tasks.md b/.kiro/specs/access-control-prover/tasks.md index 74bd501..08da970 100644 --- a/.kiro/specs/access-control-prover/tasks.md +++ b/.kiro/specs/access-control-prover/tasks.md @@ -284,7 +284,7 @@ its final resolution, dominance, fact-acquisition and measurement semantics with - _Requirements: 5.2, 5.5, 5.7, 11.8_ - _Boundary: Development Runner_ - _Depends: 12.1, 12.2, 12.3_ -- [ ] 12.5 Consume and validate an externally reviewed admission manifest +- [x] 12.5 Consume and validate an externally reviewed admission manifest - Accept only a manifest produced by valid-detection-benchmark with review, isolation and immutable digest fields. - Reject label exposure, changed acquisition output or a spent population. - Done when valid, malformed, exposed and spent manifests produce deterministic accept/refuse results. diff --git a/benchmarks/valid/prover_admission.py b/benchmarks/valid/prover_admission.py new file mode 100644 index 0000000..9df4728 --- /dev/null +++ b/benchmarks/valid/prover_admission.py @@ -0,0 +1,94 @@ +"""Admission manifest consumption for the access-control prover arm. + +Task 12.5 of the access-control-prover specification (Reqs 12.1, 12.2, 12.3, +12.6, 12.8). The admission runner only CONSUMES manifests that valid-detection-benchmark +produces and reviews; it never produces, mutates or re-labels one. A manifest is +accepted only when it names the producing benchmark, carries review and +label-isolation attestations, exposes no admission labels, matches the frozen +acquisition digest and marks its population unspent. +""" + +from dataclasses import dataclass + +from openultrasast.tools.fact_init import FORBIDDEN_LABEL_MARKERS + +__all__ = ["AdmissionManifest", "AdmissionManifestError", "validate_admission_manifest"] + + +class AdmissionManifestError(ValueError): + """Raised when an admission manifest is refused; the message names the reason.""" + + +@dataclass(frozen=True) +class AdmissionManifest: + """A validated, immutable admission manifest (design.md run-manifest fields).""" + + produced_by: str + reviewed: bool + label_isolated: bool + spent: bool + population_role: str + analyzer_revision: str + fact_set_digest: str + acquisition_record_digest: str + configuration_digest: str + population_digest: str + labels: tuple[str, ...] + + +_REQUIRED_FIELDS = ( + "produced_by", + "reviewed", + "label_isolated", + "spent", + "population_role", + "analyzer_revision", + "fact_set_digest", + "acquisition_record_digest", + "configuration_digest", + "population_digest", + "labels", +) + +_BENCHMARK_PRODUCER = "valid-detection-benchmark" + + +def _has_required_fields(payload: dict[str, object]) -> bool: + return all(field in payload for field in _REQUIRED_FIELDS) + + +def validate_admission_manifest(payload: dict[str, object], *, expected_acquisition_digest: str | None = None) -> AdmissionManifest: + """Validate an externally produced admission manifest and return it, or refuse. + + Refusal reasons, in check order: malformed, producer, unreviewed, + label-isolated, label-exposure, acquisition-output-changed, spent. + """ + if not _has_required_fields(payload): + raise AdmissionManifestError("malformed: missing required manifest fields") + if payload["produced_by"] != _BENCHMARK_PRODUCER: + raise AdmissionManifestError(f"producer: only {_BENCHMARK_PRODUCER} manifests are consumed") + if payload["reviewed"] is not True: + raise AdmissionManifestError("unreviewed: manifest lacks external review") + if payload["label_isolated"] is not True: + raise AdmissionManifestError("label-isolated: isolation attestation missing") + raw_labels = payload["labels"] + if not isinstance(raw_labels, (tuple, list)) or any(marker in str(label) for label in raw_labels for marker in FORBIDDEN_LABEL_MARKERS): + raise AdmissionManifestError("label-exposure: manifest carries admission labels") + if expected_acquisition_digest is not None and payload["acquisition_record_digest"] != expected_acquisition_digest: + raise AdmissionManifestError("acquisition-output-changed: digest mismatch") + if payload["spent"] is True: + raise AdmissionManifestError("spent: population already consumed") + labels = tuple(str(label) for label in raw_labels) + return AdmissionManifest( + produced_by=str(payload["produced_by"]), + reviewed=True, + label_isolated=True, + spent=False, + population_role=str(payload["population_role"]), + analyzer_revision=str(payload["analyzer_revision"]), + fact_set_digest=str(payload["fact_set_digest"]), + acquisition_record_digest=str(payload["acquisition_record_digest"]), + configuration_digest=str(payload["configuration_digest"]), + population_digest=str(payload["population_digest"]), + labels=labels, + ) diff --git a/tests/test_prover_admission.py b/tests/test_prover_admission.py new file mode 100644 index 0000000..22b1324 --- /dev/null +++ b/tests/test_prover_admission.py @@ -0,0 +1,113 @@ +"""Task 12.5 tests: consume and validate an externally reviewed admission manifest. + +Reqs 12.1, 12.2, 12.3, 12.6, 12.8. Valid, malformed, exposed and spent fixture +manifests must produce deterministic accept/refuse results. +""" + +from __future__ import annotations + +import copy +import sys +from pathlib import Path + +import pytest + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) + +from benchmarks.valid import prover_admission # noqa: E402 + + +def _manifest() -> dict[str, object]: + return { + "produced_by": "valid-detection-benchmark", + "reviewed": True, + "label_isolated": True, + "spent": False, + "population_role": "admission", + "analyzer_revision": "a" * 40, + "fact_set_digest": "b" * 12, + "acquisition_record_digest": "c" * 12, + "configuration_digest": "d" * 12, + "population_digest": "e" * 12, + "labels": (), + } + + +def test_valid_manifest_is_accepted() -> None: + manifest = prover_admission.validate_admission_manifest(_manifest()) + assert manifest.produced_by == "valid-detection-benchmark" + assert manifest.reviewed is True + assert manifest.label_isolated is True + assert manifest.population_role == "admission" + + +def test_malformed_manifest_is_refused() -> None: + payload = _manifest() + del payload["reviewed"] + with pytest.raises(prover_admission.AdmissionManifestError, match="malformed"): + prover_admission.validate_admission_manifest(payload) + + +def test_unreviewed_manifest_is_refused() -> None: + payload = _manifest() + payload["reviewed"] = False + with pytest.raises(prover_admission.AdmissionManifestError, match="unreviewed"): + prover_admission.validate_admission_manifest(payload) + + +def test_label_exposing_manifest_is_refused() -> None: + payload = _manifest() + payload["labels"] = ("vulnerability:case-9",) + with pytest.raises(prover_admission.AdmissionManifestError, match="label-exposure"): + prover_admission.validate_admission_manifest(payload) + + +def test_not_label_isolated_manifest_is_refused() -> None: + payload = _manifest() + payload["label_isolated"] = False + with pytest.raises(prover_admission.AdmissionManifestError, match="label-isolated"): + prover_admission.validate_admission_manifest(payload) + + +def test_non_sequence_labels_are_refused() -> None: + payload = _manifest() + payload["labels"] = None + with pytest.raises(prover_admission.AdmissionManifestError, match="label-exposure"): + prover_admission.validate_admission_manifest(payload) + + +def test_changed_acquisition_output_is_refused() -> None: + payload = _manifest() + with pytest.raises(prover_admission.AdmissionManifestError, match="acquisition-output-changed"): + prover_admission.validate_admission_manifest(payload, expected_acquisition_digest="f" * 12) + + +def test_matching_acquisition_digest_is_accepted() -> None: + manifest = prover_admission.validate_admission_manifest(_manifest(), expected_acquisition_digest="c" * 12) + assert manifest.acquisition_record_digest == "c" * 12 + + +def test_spent_population_is_refused() -> None: + payload = _manifest() + payload["spent"] = True + with pytest.raises(prover_admission.AdmissionManifestError, match="spent"): + prover_admission.validate_admission_manifest(payload) + + +def test_validation_is_deterministic() -> None: + first = prover_admission.validate_admission_manifest(_manifest()) + second = prover_admission.validate_admission_manifest(copy.deepcopy(_manifest())) + assert first == second + + +def test_admission_manifest_is_frozen() -> None: + manifest = prover_admission.validate_admission_manifest(_manifest()) + with pytest.raises(Exception): # noqa: B017 + manifest.reviewed = False # type: ignore[misc] + + +def test_non_benchmark_producer_is_refused() -> None: + payload = _manifest() + payload["produced_by"] = "someone-else" + with pytest.raises(prover_admission.AdmissionManifestError, match="producer"): + prover_admission.validate_admission_manifest(payload)