cloudronin's picture
push build context (uofa source + packs + space app)
a28ec65 verified
Raw
History Blame Contribute Delete
2.31 kB
"""Load and validate SIP evidence bundles against the frozen contract schema.
The schema lives on disk at ``specs/sip_evidence_bundle_schema.json`` (the G3
contract freeze) and is the single integration boundary between SIP and the
UofA surrogate pack. Validation runs at bundle-emit time (before signing) and
again at UofA-ingest time (v2).
``jsonschema`` is an optional dependency shipped in the ``[interrogate]`` extra;
an import error surfaces an install hint rather than a bare ``ModuleNotFound``.
The schema must be reachable both from a source checkout and from an installed
wheel. ``paths.find_repo_root()`` returns the wheel-bundled ``_data/repo``
snapshot when running from a pip install, so ``specs/`` must be force-included
into the wheel (``pyproject.toml``) for the firewall's schema layer to run for
real users — see ``AGENTS.md`` §12.
"""
from __future__ import annotations
import json
from pathlib import Path
from uofa_cli.paths import find_repo_root
SCHEMA_FILENAME = "sip_evidence_bundle_schema.json"
def schema_path(root: Path | None = None) -> Path:
"""Return the on-disk path to the SIP evidence-bundle schema."""
root = root or find_repo_root()
return root / "specs" / SCHEMA_FILENAME
def load_schema(root: Path | None = None) -> dict:
"""Load and parse the SIP evidence-bundle schema.
Returns a fresh dict each call (no caching) so callers may freely mutate
the result without poisoning a shared instance.
"""
return json.loads(schema_path(root).read_text(encoding="utf-8"))
def validate_bundle(bundle: dict, root: Path | None = None) -> None:
"""Validate ``bundle`` against the SIP contract schema; raise if invalid.
Raises ``jsonschema.ValidationError`` when the bundle violates the
contract — including carrying any forbidden verdict field (the firewall).
Callers must invoke this *before* signing so a forbidden field can never be
given a signature.
"""
try:
import jsonschema
except ImportError as exc: # pragma: no cover - exercised only without the extra
raise RuntimeError(
"jsonschema is required to validate SIP evidence bundles. "
"Install with: pip install uofa[interrogate]"
) from exc
jsonschema.validate(bundle, load_schema(root))