mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-11-13 09:48:18 +00:00
feat(detection-core): fact-pack admission and push-consumer contracts
This commit is contained in:
@@ -11,7 +11,9 @@ from openultrasast.core.admission import (
|
||||
validate_admission_manifest,
|
||||
)
|
||||
from openultrasast.core.budget import Budget, BudgetGateFailure, Complexity, check_budget, derive_budget
|
||||
from openultrasast.core.consumer import PushRequest, PushVerdict, consume_verdict
|
||||
from openultrasast.core.coverage import Coverage, InstrumentFailure, ResolutionOutcome, check_reads
|
||||
from openultrasast.core.factpack import FactPack, FactPackError, admit_fact_pack, verify_fact_pack
|
||||
from openultrasast.core.probes import (
|
||||
FittedComponentBlocked,
|
||||
ProbeResult,
|
||||
@@ -33,6 +35,8 @@ __all__ = [
|
||||
"BudgetGateFailure",
|
||||
"Complexity",
|
||||
"Coverage",
|
||||
"FactPack",
|
||||
"FactPackError",
|
||||
"FittedComponentBlocked",
|
||||
"Guard",
|
||||
"Hop",
|
||||
@@ -41,18 +45,23 @@ __all__ = [
|
||||
"ProbeResult",
|
||||
"ProvenClaim",
|
||||
"ProvenanceMismatch",
|
||||
"PushRequest",
|
||||
"PushVerdict",
|
||||
"ResolutionOutcome",
|
||||
"ShortcutDetected",
|
||||
"TraceRecord",
|
||||
"Witness",
|
||||
"admit_fact_pack",
|
||||
"as_clean",
|
||||
"assert_no_shortcut",
|
||||
"check_budget",
|
||||
"check_reads",
|
||||
"consume_verdict",
|
||||
"derive_budget",
|
||||
"require_admission_evidence",
|
||||
"reversed_pair_probe",
|
||||
"stamp",
|
||||
"validate_admission_manifest",
|
||||
"verify_fact_pack",
|
||||
"verify_stamp",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
"""Consumer contracts for the detection core (Req 9, 11).
|
||||
|
||||
The pre-push transaction consumes traces and verdicts through this interface within
|
||||
its (measured) budget; the proof layer attaches demonstrated evidence to a verdict.
|
||||
Every claim must carry a witness; every silence must carry a coverage reason.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Sequence
|
||||
from dataclasses import dataclass
|
||||
|
||||
from openultrasast.core.trace import TraceRecord
|
||||
from openultrasast.core.verdict import BoundedSilence, ProvenClaim
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class PushRequest:
|
||||
"""One push transaction handed to the core."""
|
||||
|
||||
base: str
|
||||
head: str
|
||||
budget_class: str
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class PushVerdict:
|
||||
"""What the push consumer receives: proven claims plus bounded silence."""
|
||||
|
||||
claims: tuple[ProvenClaim, ...]
|
||||
silence: tuple[BoundedSilence, ...]
|
||||
digests: dict[str, str]
|
||||
|
||||
|
||||
def consume_verdict(
|
||||
request: PushRequest,
|
||||
record: TraceRecord,
|
||||
claims: Sequence[ProvenClaim],
|
||||
silence: Sequence[BoundedSilence],
|
||||
) -> PushVerdict:
|
||||
"""Validate and wrap one trace's verdict for the push consumer (Req 5, 11.1).
|
||||
|
||||
A claim without a witness or a silence without a reason is refused: silence is
|
||||
never a clean bill of health.
|
||||
"""
|
||||
for claim in claims:
|
||||
if not claim.witness or not claim.path or claim.line <= 0:
|
||||
raise ValueError(f"proven claim lacks witness or exact location: {claim}")
|
||||
for entry in silence:
|
||||
if not entry.reason:
|
||||
raise ValueError(f"bounded silence lacks a coverage reason: {entry}")
|
||||
return PushVerdict(claims=tuple(claims), silence=tuple(silence), digests=dict(record.digests))
|
||||
|
||||
|
||||
__all__ = ["PushRequest", "PushVerdict", "consume_verdict"]
|
||||
@@ -0,0 +1,55 @@
|
||||
"""Family fact-pack admission contract for the detection core (Req 10).
|
||||
|
||||
New vulnerability families enter only as reviewed fact packs: the pack carries its
|
||||
family tag and a review digest, and its fact-set digest is stamped so consumers can
|
||||
refuse tampered content. The core never reads pool or admission labels.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
from collections.abc import Mapping, Sequence
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
|
||||
class FactPackError(ValueError):
|
||||
"""A fact pack is unreviewed or its content does not match its digest."""
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class FactPack:
|
||||
"""A reviewed family fact pack with provenance."""
|
||||
|
||||
family: str
|
||||
facts: tuple[dict[str, Any], ...]
|
||||
review_digest: str
|
||||
fact_set_digest: str
|
||||
|
||||
|
||||
def _digest(payload: object) -> str:
|
||||
return hashlib.sha256(json.dumps(payload, sort_keys=True, separators=(",", ":")).encode()).hexdigest()[:12]
|
||||
|
||||
|
||||
def admit_fact_pack(family: str, facts: Sequence[Mapping[str, Any]], *, review_digest: str) -> FactPack:
|
||||
"""Admit a pack only with review evidence; stamp its fact-set digest (Req 10.1)."""
|
||||
if not review_digest:
|
||||
raise FactPackError("unreviewed fact pack refused: no review digest")
|
||||
normalized = tuple(dict(fact) for fact in facts)
|
||||
return FactPack(
|
||||
family=family,
|
||||
facts=normalized,
|
||||
review_digest=review_digest,
|
||||
fact_set_digest=_digest([family, normalized]),
|
||||
)
|
||||
|
||||
|
||||
def verify_fact_pack(pack: FactPack, facts: Sequence[Mapping[str, Any]]) -> None:
|
||||
"""Refuse content that does not match the pack's stamped digest."""
|
||||
normalized = tuple(dict(fact) for fact in facts)
|
||||
if _digest([pack.family, normalized]) != pack.fact_set_digest:
|
||||
raise FactPackError(f"fact content does not match the stamped digest of pack {pack.family!r}")
|
||||
|
||||
|
||||
__all__ = ["FactPack", "FactPackError", "admit_fact_pack", "verify_fact_pack"]
|
||||
Reference in New Issue
Block a user