mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-11-13 01:48:17 +00:00
feat(access-control-prover): publish fact conformance handoff
This commit is contained in:
@@ -381,7 +381,7 @@ its final resolution, dominance, fact-acquisition and measurement semantics with
|
||||
- _Requirements: 1.1, 1.2, 1.3, 1.5, 7.2, 9.4, 13.5, 13.6_
|
||||
- _Boundary: Structural Matcher_
|
||||
- _Depends: 14.2, 14.5, 14.6_
|
||||
- [ ] 14.8 Produce the downstream conformance handoff
|
||||
- [x] 14.8 Produce the downstream conformance handoff
|
||||
- Run detection-core fact-pack, fact-match, application and full-evidence validators over target-owned fixtures after proving nonzero fixture reads.
|
||||
- Publish an immutable manifest naming every fixture, artifact digest, validator result and negative-case reason for detection-core task 9.4 to accept; do not add target fixtures to core.
|
||||
- Exercise authority substitution, producer/reviewer conflict, resolver byte substitution, lineage omission, custody contamination and deterministic replay.
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
"""No-follow filesystem primitives for the conformance handoff."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import stat
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class ConformanceFilesystemError(ValueError):
|
||||
"""A handoff path was redirected or was not the required node type."""
|
||||
|
||||
|
||||
def _open_flags(*flags: int) -> int:
|
||||
result = 0
|
||||
for flag in flags:
|
||||
result |= flag
|
||||
return result
|
||||
|
||||
|
||||
def _read_fd(fd: int) -> bytes:
|
||||
chunks: list[bytes] = []
|
||||
while chunk := os.read(fd, 1024 * 1024):
|
||||
chunks.append(chunk)
|
||||
return b"".join(chunks)
|
||||
|
||||
|
||||
def read_regular_nofollow(path: Path) -> bytes:
|
||||
"""Read one regular file without following its final path component."""
|
||||
flags = _open_flags(os.O_RDONLY, os.O_NOFOLLOW, os.O_NONBLOCK)
|
||||
try:
|
||||
fd = os.open(path, flags)
|
||||
except OSError as exc:
|
||||
raise ConformanceFilesystemError("path is not a readable regular file") from exc
|
||||
try:
|
||||
if not stat.S_ISREG(os.fstat(fd).st_mode):
|
||||
raise ConformanceFilesystemError("path is not a regular file")
|
||||
return _read_fd(fd)
|
||||
except OSError as exc:
|
||||
raise ConformanceFilesystemError("regular file could not be read") from exc
|
||||
finally:
|
||||
os.close(fd)
|
||||
|
||||
|
||||
def require_real_directory(path: Path) -> None:
|
||||
"""Require an existing directory whose final component is not a symlink."""
|
||||
flags = _open_flags(os.O_RDONLY, os.O_DIRECTORY, os.O_NOFOLLOW)
|
||||
try:
|
||||
fd = os.open(path, flags)
|
||||
except OSError as exc:
|
||||
raise ConformanceFilesystemError("path is not a real directory") from exc
|
||||
try:
|
||||
if not stat.S_ISDIR(os.fstat(fd).st_mode):
|
||||
raise ConformanceFilesystemError("path is not a real directory")
|
||||
finally:
|
||||
os.close(fd)
|
||||
|
||||
|
||||
def ensure_real_directory(path: Path) -> None:
|
||||
"""Create a directory if absent, then reject redirected final components."""
|
||||
try:
|
||||
path.mkdir(parents=True, exist_ok=True)
|
||||
except OSError as exc:
|
||||
raise ConformanceFilesystemError("directory could not be created") from exc
|
||||
require_real_directory(path)
|
||||
|
||||
|
||||
def flat_regular_census(path: Path) -> tuple[str, ...]:
|
||||
"""Return direct regular-file names and reject every other entry.
|
||||
|
||||
Whole-directory validation assumes no concurrent writer. Opening both the
|
||||
directory and subsequently read files with ``O_NOFOLLOW`` closes the usual
|
||||
check-to-open symlink race for each operation.
|
||||
"""
|
||||
flags = _open_flags(os.O_RDONLY, os.O_DIRECTORY, os.O_NOFOLLOW)
|
||||
try:
|
||||
fd = os.open(path, flags)
|
||||
except OSError as exc:
|
||||
raise ConformanceFilesystemError("census root is not a real directory") from exc
|
||||
try:
|
||||
if not stat.S_ISDIR(os.fstat(fd).st_mode):
|
||||
raise ConformanceFilesystemError("census root is not a real directory")
|
||||
with os.scandir(fd) as entries:
|
||||
names = []
|
||||
for entry in entries:
|
||||
if not entry.is_file(follow_symlinks=False) or entry.is_symlink():
|
||||
raise ConformanceFilesystemError("census contains an unsafe entry")
|
||||
names.append(entry.name)
|
||||
return tuple(sorted(names))
|
||||
except OSError as exc:
|
||||
raise ConformanceFilesystemError("directory census failed") from exc
|
||||
finally:
|
||||
os.close(fd)
|
||||
|
||||
|
||||
def persist_regular_nofollow(path: Path, content: bytes) -> None:
|
||||
"""Create an immutable-addressed file or verify an existing regular file."""
|
||||
flags = _open_flags(os.O_CREAT, os.O_EXCL, os.O_WRONLY, os.O_NOFOLLOW)
|
||||
try:
|
||||
fd = os.open(path, flags, 0o644)
|
||||
except FileExistsError:
|
||||
if read_regular_nofollow(path) != content:
|
||||
raise ConformanceFilesystemError("existing digest file has different bytes") from None
|
||||
return
|
||||
except OSError as exc:
|
||||
raise ConformanceFilesystemError("digest file could not be created") from exc
|
||||
try:
|
||||
view = memoryview(content)
|
||||
while view:
|
||||
written = os.write(fd, view)
|
||||
if written <= 0:
|
||||
raise ConformanceFilesystemError("digest file write made no progress")
|
||||
view = view[written:]
|
||||
os.fsync(fd)
|
||||
except OSError as exc:
|
||||
raise ConformanceFilesystemError("digest file could not be written") from exc
|
||||
finally:
|
||||
os.close(fd)
|
||||
|
||||
|
||||
__all__ = [
|
||||
"ConformanceFilesystemError",
|
||||
"ensure_real_directory",
|
||||
"flat_regular_census",
|
||||
"persist_regular_nofollow",
|
||||
"read_regular_nofollow",
|
||||
"require_real_directory",
|
||||
]
|
||||
@@ -0,0 +1,300 @@
|
||||
"""Negative and replay cases for the downstream entry-fact handoff."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import replace
|
||||
from pathlib import Path
|
||||
from typing import Any, NoReturn
|
||||
|
||||
from openultrasast.core import canonical, provenance
|
||||
from openultrasast.core.factmatch import validate_fact_match
|
||||
from openultrasast.core.factpack import derive_independence_attestation_digest
|
||||
from openultrasast.mapping.authority_ceremony import load_installed_authority_ceremony
|
||||
from openultrasast.mapping.entry_fact_matcher import EntryFactMatchResult, match_entry_fact
|
||||
from openultrasast.mapping.entry_packs import load_entry_pack_patterns
|
||||
from openultrasast.mapping.fact_authority import EntryFactAuthorityContext, authenticate_entry_fact_authority
|
||||
from openultrasast.mapping.fact_match_store import FactMatchArtifactWriter
|
||||
from openultrasast.mapping.installed_fact_authority import fact_pack_bytes, installed_authority_bytes
|
||||
|
||||
_AUTHENTICATE = "openultrasast.mapping.fact_authority.authenticate_entry_fact_authority"
|
||||
|
||||
|
||||
def negative_cases(
|
||||
fixture_root: Path,
|
||||
output: Path,
|
||||
sources: dict[str, tuple[str, bytes]],
|
||||
context: EntryFactAuthorityContext,
|
||||
evaluation: str,
|
||||
complete: EntryFactMatchResult,
|
||||
) -> tuple[dict[str, canonical.JsonValue], ...]:
|
||||
from openultrasast.mapping.entry_fact_conformance import (
|
||||
_CORE_ENTRY_POINTS,
|
||||
_case,
|
||||
_persist,
|
||||
_validator,
|
||||
)
|
||||
|
||||
common = (_persist(output, fact_pack_bytes(complete.pack), "fact-pack"),)
|
||||
rows = _structural_refusals(fixture_root, output, sources, context, evaluation, common)
|
||||
rows.extend(_authority_cases(output, sources, context))
|
||||
rows.append(_resolver_case(sources["resolver_byte_substitution"], common, context, evaluation, complete))
|
||||
rows.extend(_lineage_cases(sources, context, evaluation, complete, common))
|
||||
rows.append(_contaminated_case(sources["custody_contamination"], common, context, evaluation, complete))
|
||||
_legacy_only(fixture_root, output, sources, context, evaluation)
|
||||
rows.append(
|
||||
_case(
|
||||
"legacy_projection_only",
|
||||
sources["legacy_projection_only"],
|
||||
"refused",
|
||||
"name_only_match",
|
||||
common,
|
||||
(_validator(_CORE_ENTRY_POINTS[1], "refused", "name_only_match"),),
|
||||
)
|
||||
)
|
||||
return tuple(rows)
|
||||
|
||||
|
||||
def _authority_cases(
|
||||
output: Path,
|
||||
sources: dict[str, tuple[str, bytes]],
|
||||
context: EntryFactAuthorityContext,
|
||||
) -> tuple[dict[str, canonical.JsonValue], ...]:
|
||||
from openultrasast.mapping.entry_fact_conformance import _case, _installed_entries, _persist, _validator
|
||||
|
||||
bundle = context.bundle
|
||||
ceremony = load_installed_authority_ceremony(_installed_entries())
|
||||
substituted = replace(bundle, bundle_digest="0" * 64)
|
||||
_expect_error(
|
||||
lambda: authenticate_entry_fact_authority(substituted, ceremony.bootstrap, context.custody, context.resolver),
|
||||
"authority bundle digest",
|
||||
)
|
||||
substituted_case = _case(
|
||||
"authority_substitution",
|
||||
sources["authority_substitution"],
|
||||
"refused",
|
||||
"match_pack_identity_substituted",
|
||||
(_persist(output, installed_authority_bytes(substituted), "authority"),),
|
||||
(_validator("openultrasast.core.factmatch.validate_fact_match", "refused", "match_pack_identity_substituted"),),
|
||||
(_validator(_AUTHENTICATE, "refused", "authority_bundle_digest_substituted"),),
|
||||
)
|
||||
review = replace(bundle.authority_review, producer_identity=bundle.authority_review.reviewer_identity, attestation_digest="0" * 64)
|
||||
review = replace(review, attestation_digest=derive_independence_attestation_digest(review))
|
||||
conflicted = replace(bundle, authority_review=review)
|
||||
_expect_error(
|
||||
lambda: authenticate_entry_fact_authority(conflicted, ceremony.bootstrap, context.custody, context.resolver),
|
||||
"producer and reviewer",
|
||||
)
|
||||
conflict_case = _case(
|
||||
"producer_reviewer_conflict",
|
||||
sources["producer_reviewer_conflict"],
|
||||
"refused",
|
||||
"self_authored_review_evidence",
|
||||
(_persist(output, installed_authority_bytes(conflicted), "authority"),),
|
||||
(_validator("openultrasast.core.factpack.validate_fact_pack", "refused", "self_authored_review_evidence"),),
|
||||
(_validator(_AUTHENTICATE, "refused", "producer_reviewer_conflict"),),
|
||||
)
|
||||
return substituted_case, conflict_case
|
||||
|
||||
|
||||
def _resolver_case(
|
||||
source: tuple[str, bytes],
|
||||
artifacts: tuple[dict[str, canonical.JsonValue], ...],
|
||||
context: EntryFactAuthorityContext,
|
||||
evaluation: str,
|
||||
complete: EntryFactMatchResult,
|
||||
) -> dict[str, canonical.JsonValue]:
|
||||
from openultrasast.mapping.entry_fact_conformance import _CORE_ENTRY_POINTS, _case, _SubstitutingResolver, _validator
|
||||
|
||||
bundle = context.bundle
|
||||
target = complete.match.observations[0].evidence.content_digest
|
||||
resolver = _SubstitutingResolver(complete.resolver, target)
|
||||
_expect_error(
|
||||
lambda: validate_fact_match(
|
||||
complete.pack,
|
||||
complete.match.fact_id,
|
||||
complete.match,
|
||||
evaluation,
|
||||
bundle.lineages,
|
||||
context.custody,
|
||||
bundle.custody_policy,
|
||||
bundle.review_policy,
|
||||
resolver,
|
||||
),
|
||||
"resolved content digest",
|
||||
)
|
||||
return _case(
|
||||
"resolver_byte_substitution",
|
||||
source,
|
||||
"refused",
|
||||
"resolver_byte_substitution",
|
||||
artifacts,
|
||||
(_validator(_CORE_ENTRY_POINTS[1], "refused", "resolver_byte_substitution"),),
|
||||
)
|
||||
|
||||
|
||||
def _structural_refusals(
|
||||
root: Path,
|
||||
output: Path,
|
||||
sources: dict[str, tuple[str, bytes]],
|
||||
context: EntryFactAuthorityContext,
|
||||
evaluation: str,
|
||||
artifacts: tuple[dict[str, canonical.JsonValue], ...],
|
||||
) -> list[dict[str, canonical.JsonValue]]:
|
||||
from openultrasast.mapping.entry_fact_conformance import _CORE_ENTRY_POINTS, _case, _match, _match_artifacts, _validator
|
||||
|
||||
rows = []
|
||||
for case_id, reason in (("name_only", "missing_observation:receiver"), ("partial", "missing_observation:arguments")):
|
||||
result = _match(root, output, context, evaluation, sources[case_id][0])
|
||||
if result.decision.effect_eligible or reason not in result.decision.reasons:
|
||||
_fail(f"{case_id} did not refuse with its stable reason")
|
||||
case_artifacts = (*artifacts, *_match_artifacts(output, result))
|
||||
rows.append(
|
||||
_case(
|
||||
case_id,
|
||||
sources[case_id],
|
||||
"refused",
|
||||
reason,
|
||||
case_artifacts,
|
||||
(_validator(_CORE_ENTRY_POINTS[1], "refused", reason),),
|
||||
)
|
||||
)
|
||||
return rows
|
||||
|
||||
|
||||
def _lineage_cases(
|
||||
sources: dict[str, tuple[str, bytes]],
|
||||
context: EntryFactAuthorityContext,
|
||||
evaluation: str,
|
||||
complete: EntryFactMatchResult,
|
||||
artifacts: tuple[dict[str, canonical.JsonValue], ...],
|
||||
) -> tuple[dict[str, canonical.JsonValue], ...]:
|
||||
from openultrasast.mapping.entry_fact_conformance import _CORE_ENTRY_POINTS, _case, _validator
|
||||
|
||||
bundle = context.bundle
|
||||
omitted = tuple(item for item in bundle.lineages if item.manifest_digest != complete.match.matcher_lineage_manifest_digest)
|
||||
_expect_error(
|
||||
lambda: validate_fact_match(
|
||||
complete.pack,
|
||||
complete.match.fact_id,
|
||||
complete.match,
|
||||
evaluation,
|
||||
omitted,
|
||||
context.custody,
|
||||
bundle.custody_policy,
|
||||
bundle.review_policy,
|
||||
complete.resolver,
|
||||
),
|
||||
"matcher lineage",
|
||||
)
|
||||
omitted_case = _case(
|
||||
"lineage_omission",
|
||||
sources["lineage_omission"],
|
||||
"refused",
|
||||
"matcher_lineage_omitted",
|
||||
artifacts,
|
||||
(_validator(_CORE_ENTRY_POINTS[1], "refused", "matcher_lineage_omitted"),),
|
||||
)
|
||||
replay = validate_fact_match(
|
||||
complete.pack,
|
||||
complete.match.fact_id,
|
||||
complete.match,
|
||||
evaluation,
|
||||
bundle.lineages,
|
||||
context.custody,
|
||||
bundle.custody_policy,
|
||||
bundle.review_policy,
|
||||
complete.resolver,
|
||||
)
|
||||
if not replay.effect_eligible:
|
||||
_fail("deterministic replay did not remain complete")
|
||||
replay_case = _case(
|
||||
"deterministic_replay", sources["deterministic_replay"], "passed", None, artifacts, (_validator(_CORE_ENTRY_POINTS[1], "passed"),)
|
||||
)
|
||||
return omitted_case, replay_case
|
||||
|
||||
|
||||
def _contaminated_case(
|
||||
source: tuple[str, bytes],
|
||||
artifacts: tuple[dict[str, canonical.JsonValue], ...],
|
||||
context: EntryFactAuthorityContext,
|
||||
evaluation: str,
|
||||
complete: EntryFactMatchResult,
|
||||
) -> dict[str, canonical.JsonValue]:
|
||||
from openultrasast.mapping.entry_fact_conformance import _CORE_ENTRY_POINTS, _case, _Custody, _validator
|
||||
|
||||
custody = context.custody
|
||||
if not isinstance(custody, _Custody):
|
||||
_fail("conformance custody has the wrong type")
|
||||
prior = custody.current_log(evaluation)
|
||||
lineage = next(item for item in context.bundle.lineages if item.manifest_digest == complete.match.matcher_lineage_manifest_digest)
|
||||
custody.append(
|
||||
provenance.PopulationUseRequest(
|
||||
evaluation,
|
||||
lineage.arm_id,
|
||||
provenance.LineagePurpose.MATCHING_BEHAVIOR,
|
||||
True,
|
||||
complete.match.matcher_behavior_digest,
|
||||
prior.log_digest,
|
||||
)
|
||||
)
|
||||
decision = validate_fact_match(
|
||||
complete.pack,
|
||||
complete.match.fact_id,
|
||||
complete.match,
|
||||
evaluation,
|
||||
context.bundle.lineages,
|
||||
custody,
|
||||
context.bundle.custody_policy,
|
||||
context.bundle.review_policy,
|
||||
complete.resolver,
|
||||
)
|
||||
reason = next((item for item in decision.reasons if item.startswith("protected_population_labels:")), None)
|
||||
if decision.effect_eligible or reason is None:
|
||||
_fail("protected population contamination was not refused")
|
||||
return _case(
|
||||
"custody_contamination",
|
||||
source,
|
||||
"refused",
|
||||
"protected_population_contamination",
|
||||
artifacts,
|
||||
(_validator(_CORE_ENTRY_POINTS[1], "refused", "protected_population_contamination"),),
|
||||
)
|
||||
|
||||
|
||||
def _legacy_only(
|
||||
root: Path, output: Path, sources: dict[str, tuple[str, bytes]], context: EntryFactAuthorityContext, evaluation: str
|
||||
) -> None:
|
||||
content = sources["legacy_projection_only"][1].decode("utf-8")
|
||||
patterns = load_entry_pack_patterns()["javascript"]
|
||||
writer = FactMatchArtifactWriter(
|
||||
output, context.bundle.review_policy.trusted_store_identities[0], canonical.content_digest("retain-access-control-conformance-v1")
|
||||
)
|
||||
matches = match_entry_fact(
|
||||
repository_root=root,
|
||||
relative_path=sources["legacy_projection_only"][0],
|
||||
language="javascript",
|
||||
fact_id="entry:express:app-route:get",
|
||||
authority=context,
|
||||
writer=writer,
|
||||
evaluation_population_digest=evaluation,
|
||||
)
|
||||
if not any(pattern.search(content) for pattern in patterns) or matches:
|
||||
_fail("legacy-only fixture did not isolate projection recognition")
|
||||
|
||||
|
||||
def _expect_error(action: Any, fragment: str) -> None:
|
||||
try:
|
||||
action()
|
||||
except (TypeError, ValueError) as exc:
|
||||
if fragment not in str(exc):
|
||||
_fail(f"validator refusal changed: {exc}", exc)
|
||||
return
|
||||
_fail("negative conformance case unexpectedly passed")
|
||||
|
||||
|
||||
def _fail(message: str, cause: Exception | None = None) -> NoReturn:
|
||||
from openultrasast.mapping.entry_fact_conformance import EntryFactConformanceError
|
||||
|
||||
if cause is not None:
|
||||
raise EntryFactConformanceError(message) from cause
|
||||
raise EntryFactConformanceError(message)
|
||||
@@ -0,0 +1,96 @@
|
||||
"""Materialize the self-sufficient generic-core replay artifact."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Mapping
|
||||
from pathlib import Path
|
||||
|
||||
from openultrasast.core import canonical, provenance
|
||||
from openultrasast.mapping._installed_fact_authority_codec import wire_value
|
||||
from openultrasast.mapping.authority_ceremony import INSTALLED_ARTIFACT_STORE_IDENTITY
|
||||
from openultrasast.mapping.entry_fact_matcher import EntryFactMatchResult
|
||||
from openultrasast.mapping.fact_authority import EntryFactAuthorityContext
|
||||
|
||||
|
||||
def _resolver_material(
|
||||
output: Path,
|
||||
result: EntryFactMatchResult,
|
||||
) -> tuple[tuple[dict[str, canonical.JsonValue], ...], tuple[dict[str, canonical.JsonValue], ...], str]:
|
||||
from openultrasast.mapping.entry_fact_conformance import _persist
|
||||
|
||||
refs = [item.content for item in result.pack.review_evidence]
|
||||
refs.extend(item.independence.conflict_disclosure for item in result.pack.review_evidence)
|
||||
refs.extend(item.evidence for item in result.match.observations)
|
||||
refs.append(result.match_reference)
|
||||
artifacts: list[dict[str, canonical.JsonValue]] = []
|
||||
entries: list[dict[str, canonical.JsonValue]] = []
|
||||
for reference in refs:
|
||||
artifact = _persist(output, result.resolver.resolve(reference).content, "resolver-content")
|
||||
artifacts.append(artifact)
|
||||
entries.append(
|
||||
{
|
||||
"reference": wire_value(reference),
|
||||
"path": artifact["path"],
|
||||
"store_identity": INSTALLED_ARTIFACT_STORE_IDENTITY,
|
||||
}
|
||||
)
|
||||
target = result.match.observations[0].evidence
|
||||
original = result.resolver.resolve(target).content
|
||||
substituted = _persist(output, b"!" + original[1:], "substituted-content")
|
||||
artifacts.append(substituted)
|
||||
return tuple(entries), tuple(artifacts), str(substituted["path"])
|
||||
|
||||
|
||||
def replay_material(
|
||||
output: Path,
|
||||
context: EntryFactAuthorityContext,
|
||||
evaluation: str,
|
||||
result: EntryFactMatchResult,
|
||||
source: tuple[str, bytes],
|
||||
) -> tuple[dict[str, canonical.JsonValue], tuple[dict[str, canonical.JsonValue], ...]]:
|
||||
from openultrasast.mapping._entry_fact_conformance_wire import replay_envelope_bytes
|
||||
from openultrasast.mapping.entry_fact_conformance import EntryFactConformanceError, _Custody, _persist, _record
|
||||
|
||||
custody = context.custody
|
||||
if not isinstance(custody, _Custody):
|
||||
raise EntryFactConformanceError("conformance custody has the wrong type")
|
||||
contaminated = custody.current_log(evaluation)
|
||||
custodian = context.bundle.custody_policy.reviewed_custodian_digests[0]
|
||||
base_evaluation = provenance.empty_population_custody_log(evaluation, custodian)
|
||||
base_logs = tuple(base_evaluation if digest == evaluation else log for digest, log in sorted(custody.logs.items()))
|
||||
entries, artifacts, substituted_path = _resolver_material(output, result)
|
||||
record = _record(result, evaluation, canonical.bytes_digest(source[1]))
|
||||
content = replay_envelope_bytes(
|
||||
context=context,
|
||||
evaluation_population_digest=evaluation,
|
||||
result=result,
|
||||
record=record,
|
||||
base_logs=base_logs,
|
||||
contaminated_log=contaminated,
|
||||
resolver_entries=entries,
|
||||
substituted_content_path=substituted_path,
|
||||
)
|
||||
return _persist(output, content, "core-replay-envelope"), artifacts
|
||||
|
||||
|
||||
def attach_replay(
|
||||
cases: tuple[dict[str, canonical.JsonValue], ...],
|
||||
envelope: dict[str, canonical.JsonValue],
|
||||
dependencies: tuple[dict[str, canonical.JsonValue], ...],
|
||||
) -> tuple[dict[str, canonical.JsonValue], ...]:
|
||||
values = []
|
||||
for case in cases:
|
||||
artifacts = case["artifacts"]
|
||||
if not isinstance(artifacts, tuple):
|
||||
raise TypeError("case artifacts must be a tuple")
|
||||
if not all(isinstance(item, Mapping) for item in artifacts):
|
||||
raise TypeError("case artifact entries must be objects")
|
||||
existing = {str(item["path"]): item for item in artifacts if isinstance(item, Mapping)}
|
||||
existing[str(envelope["path"])] = envelope
|
||||
if case["case_id"] == "complete":
|
||||
existing.update({str(item["path"]): item for item in dependencies})
|
||||
values.append({**case, "artifacts": tuple(existing[path] for path in sorted(existing))})
|
||||
return tuple(values)
|
||||
|
||||
|
||||
__all__ = ["attach_replay", "replay_material"]
|
||||
@@ -0,0 +1,70 @@
|
||||
"""Canonical generic-core replay envelope for the entry-fact handoff."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Mapping, Sequence
|
||||
|
||||
from openultrasast.core import canonical, evidence, provenance
|
||||
from openultrasast.mapping._installed_fact_authority_codec import wire_value
|
||||
from openultrasast.mapping.entry_fact_matcher import EntryFactMatchResult
|
||||
from openultrasast.mapping.fact_authority import EntryFactAuthorityContext
|
||||
|
||||
ENTRY_FACT_REPLAY_SCHEMA = "openultrasast.access-control.entry-fact-core-replay.v1"
|
||||
|
||||
|
||||
def _case_plans() -> tuple[Mapping[str, canonical.JsonValue], ...]:
|
||||
match = "openultrasast.core.factmatch.validate_fact_match"
|
||||
return (
|
||||
{"case_id": "authority_substitution", "replay_kind": "core", "validator": match, "mutation": "match_pack_digest_substitution"},
|
||||
{"case_id": "complete", "replay_kind": "core", "validator": "all", "mutation": "none"},
|
||||
{"case_id": "custody_contamination", "replay_kind": "core", "validator": match, "mutation": "contaminated_custody"},
|
||||
{"case_id": "deterministic_replay", "replay_kind": "core", "validator": match, "mutation": "none"},
|
||||
{"case_id": "legacy_projection_only", "replay_kind": "core", "validator": match, "mutation": "qualified_name_only"},
|
||||
{"case_id": "lineage_omission", "replay_kind": "core", "validator": match, "mutation": "matcher_lineage_omission"},
|
||||
{"case_id": "name_only", "replay_kind": "core", "validator": match, "mutation": "qualified_name_only"},
|
||||
{"case_id": "partial", "replay_kind": "core", "validator": match, "mutation": "arguments_omission"},
|
||||
{
|
||||
"case_id": "producer_reviewer_conflict",
|
||||
"replay_kind": "core",
|
||||
"validator": "openultrasast.core.factpack.validate_fact_pack",
|
||||
"mutation": "self_authored_pack",
|
||||
},
|
||||
{"case_id": "resolver_byte_substitution", "replay_kind": "core", "validator": match, "mutation": "resolver_byte_substitution"},
|
||||
)
|
||||
|
||||
|
||||
def replay_envelope_bytes(
|
||||
*,
|
||||
context: EntryFactAuthorityContext,
|
||||
evaluation_population_digest: str,
|
||||
result: EntryFactMatchResult,
|
||||
record: evidence.EvidenceRecord,
|
||||
base_logs: Sequence[provenance.PopulationCustodyLog],
|
||||
contaminated_log: provenance.PopulationCustodyLog,
|
||||
resolver_entries: Sequence[Mapping[str, canonical.JsonValue]],
|
||||
substituted_content_path: str,
|
||||
) -> bytes:
|
||||
"""Serialize every family-neutral input needed for independent core replay."""
|
||||
payload: Mapping[str, canonical.JsonValue] = {
|
||||
"schema_version": ENTRY_FACT_REPLAY_SCHEMA,
|
||||
"contract": wire_value(context.bundle.contract),
|
||||
"pack": wire_value(result.pack),
|
||||
"fact_id": result.match.fact_id,
|
||||
"match": wire_value(result.match),
|
||||
"match_reference": wire_value(result.match_reference),
|
||||
"evidence_record": wire_value(record),
|
||||
"evaluation_population_digest": evaluation_population_digest,
|
||||
"lineages": wire_value(context.bundle.lineages),
|
||||
"review_policy": wire_value(context.bundle.review_policy),
|
||||
"custody_policy": wire_value(context.bundle.custody_policy),
|
||||
"custody_logs": wire_value(tuple(base_logs)),
|
||||
"contaminated_custody_log": wire_value(contaminated_log),
|
||||
"resolver_entries": tuple(resolver_entries),
|
||||
"substituted_content_path": substituted_content_path,
|
||||
"case_plans": tuple(_case_plans()),
|
||||
}
|
||||
envelope = {**payload, "envelope_digest": canonical.content_digest(payload)}
|
||||
return canonical.canonical_record_bytes(envelope, known_schema_versions=(ENTRY_FACT_REPLAY_SCHEMA,))
|
||||
|
||||
|
||||
__all__ = ["ENTRY_FACT_REPLAY_SCHEMA", "replay_envelope_bytes"]
|
||||
@@ -0,0 +1,390 @@
|
||||
"""Reproducible downstream conformance handoff for reviewed entry facts."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, replace
|
||||
from pathlib import Path
|
||||
|
||||
from openultrasast.core import canonical, evidence, family, provenance, semantics
|
||||
from openultrasast.core.factapply import apply_fact
|
||||
from openultrasast.core.factmatch import validate_fact_match
|
||||
from openultrasast.core.factpack import validate_fact_pack
|
||||
from openultrasast.core.factvalidate import validate_fact_relations
|
||||
from openultrasast.mapping._entry_fact_conformance_fs import (
|
||||
ConformanceFilesystemError,
|
||||
ensure_real_directory,
|
||||
persist_regular_nofollow,
|
||||
read_regular_nofollow,
|
||||
require_real_directory,
|
||||
)
|
||||
from openultrasast.mapping.entry_fact_matcher import EntryFactMatchResult, match_entry_fact
|
||||
from openultrasast.mapping.entry_packs import load_installed_entry_fact_authority
|
||||
from openultrasast.mapping.fact_authority import EntryFactAuthorityContext
|
||||
from openultrasast.mapping.fact_match_store import FactMatchArtifactWriter
|
||||
from openultrasast.mapping.installed_fact_authority import fact_pack_bytes
|
||||
|
||||
ENTRY_FACT_CONFORMANCE_SCHEMA = "openultrasast.access-control.entry-fact-conformance.v1"
|
||||
_CORE_ENTRY_POINTS = (
|
||||
"openultrasast.core.factapply.apply_fact",
|
||||
"openultrasast.core.factmatch.validate_fact_match",
|
||||
"openultrasast.core.factpack.validate_fact_pack",
|
||||
"openultrasast.core.factvalidate.validate_fact_relations",
|
||||
)
|
||||
_SOURCE_CASES = {
|
||||
"complete": "sources/complete.js",
|
||||
"name_only": "sources/name-only.js",
|
||||
"partial": "sources/partial.js",
|
||||
"authority_substitution": "sources/complete.js",
|
||||
"producer_reviewer_conflict": "sources/complete.js",
|
||||
"resolver_byte_substitution": "sources/complete.js",
|
||||
"lineage_omission": "sources/complete.js",
|
||||
"custody_contamination": "sources/complete.js",
|
||||
"legacy_projection_only": "sources/legacy-only.js",
|
||||
"deterministic_replay": "sources/complete.js",
|
||||
}
|
||||
|
||||
|
||||
class EntryFactConformanceError(ValueError):
|
||||
"""The target-owned conformance fixture cannot be reproduced safely."""
|
||||
|
||||
|
||||
class _UnusedCustody:
|
||||
def current_log(self, population_digest: str) -> provenance.PopulationCustodyLog:
|
||||
raise AssertionError(f"authority load read custody: {population_digest}")
|
||||
|
||||
|
||||
class _Custody:
|
||||
def __init__(self, logs: tuple[provenance.PopulationCustodyLog, ...], policy: provenance.PopulationCustodyPolicy):
|
||||
self.logs = {item.population_digest: item for item in logs}
|
||||
self.policy = policy
|
||||
|
||||
def current_log(self, population_digest: str) -> provenance.PopulationCustodyLog:
|
||||
try:
|
||||
return self.logs[population_digest]
|
||||
except KeyError as exc:
|
||||
raise provenance.PopulationCustodyError("population custody log not found") from exc
|
||||
|
||||
def append(self, request: provenance.PopulationUseRequest) -> provenance.PopulationUseReceipt:
|
||||
prior = self.current_log(request.population_digest)
|
||||
custodian = self.policy.reviewed_custodian_digests[0]
|
||||
receipt = provenance.record_population_use(request, prior, custodian, self.policy)
|
||||
self.logs[request.population_digest] = provenance.append_population_use(prior, receipt, self.policy)
|
||||
return receipt
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class _SubstitutingResolver:
|
||||
delegate: canonical.ContentResolver
|
||||
digest: str
|
||||
|
||||
def resolve(self, reference: canonical.ContentRef) -> canonical.ResolvedContent:
|
||||
resolved = self.delegate.resolve(reference)
|
||||
if reference.content_digest != self.digest:
|
||||
return resolved
|
||||
return canonical.ResolvedContent(b"!" + resolved.content[1:], resolved.receipt)
|
||||
|
||||
|
||||
def _installed_entries() -> Path:
|
||||
import openultrasast
|
||||
|
||||
return Path(openultrasast.__file__).resolve().parent / "ruleset" / "entries"
|
||||
|
||||
|
||||
def _context() -> tuple[EntryFactAuthorityContext, str, _Custody]:
|
||||
loaded = load_installed_entry_fact_authority(_UnusedCustody())
|
||||
bundle = loaded.bundle
|
||||
custodian = bundle.custody_policy.reviewed_custodian_digests[0]
|
||||
logs: dict[str, provenance.PopulationCustodyLog] = {}
|
||||
for lineage in bundle.lineages:
|
||||
for use in lineage.uses:
|
||||
prior = logs.setdefault(
|
||||
use.source_population_digest,
|
||||
provenance.empty_population_custody_log(use.source_population_digest, custodian),
|
||||
)
|
||||
request = provenance.PopulationUseRequest(
|
||||
use.source_population_digest,
|
||||
lineage.arm_id,
|
||||
use.purpose,
|
||||
use.labels_accessed,
|
||||
use.influenced_artifact_digest,
|
||||
prior.log_digest,
|
||||
)
|
||||
receipt = provenance.record_population_use(request, prior, custodian, bundle.custody_policy)
|
||||
if receipt.receipt_digest != use.population_use_receipt_digest:
|
||||
raise EntryFactConformanceError("installed lineage receipt cannot be reproduced")
|
||||
logs[use.source_population_digest] = provenance.append_population_use(prior, receipt, bundle.custody_policy)
|
||||
evaluation = canonical.content_digest("access-control-entry-conformance-population-v1")
|
||||
logs[evaluation] = provenance.empty_population_custody_log(evaluation, custodian)
|
||||
custody = _Custody(tuple(logs.values()), bundle.custody_policy)
|
||||
return replace(loaded, custody=custody), evaluation, custody
|
||||
|
||||
|
||||
def _read_sources(root: Path) -> dict[str, tuple[str, bytes]]:
|
||||
values: dict[str, tuple[str, bytes]] = {}
|
||||
try:
|
||||
require_real_directory(root / "sources")
|
||||
except ConformanceFilesystemError as exc:
|
||||
raise EntryFactConformanceError("sources require a real non-symlink directory") from exc
|
||||
for case_id, relative in _SOURCE_CASES.items():
|
||||
try:
|
||||
content = read_regular_nofollow(root / relative)
|
||||
except ConformanceFilesystemError as exc:
|
||||
raise EntryFactConformanceError(f"{case_id} requires a nonempty readable fixture") from exc
|
||||
if not content:
|
||||
raise EntryFactConformanceError(f"{case_id} requires a nonempty readable fixture")
|
||||
values[case_id] = (relative, content)
|
||||
return values
|
||||
|
||||
|
||||
def _persist(output: Path, content: bytes, kind: str) -> dict[str, canonical.JsonValue]:
|
||||
if not content:
|
||||
raise EntryFactConformanceError("handoff artifacts must be nonempty")
|
||||
digest = canonical.bytes_digest(content)
|
||||
relative = f"artifacts/sha256/{digest}"
|
||||
target = output / relative
|
||||
try:
|
||||
ensure_real_directory(output)
|
||||
ensure_real_directory(output / "artifacts")
|
||||
ensure_real_directory(target.parent)
|
||||
persist_regular_nofollow(target, content)
|
||||
except ConformanceFilesystemError as exc:
|
||||
raise EntryFactConformanceError("artifact path is unsafe or not a regular file") from exc
|
||||
return {"kind": kind, "path": relative, "content_digest": digest, "byte_length": len(content)}
|
||||
|
||||
|
||||
def _validator(name: str, status: str, reason: str | None = None) -> dict[str, canonical.JsonValue]:
|
||||
return {"name": name, "status": status, "reason": reason}
|
||||
|
||||
|
||||
def _case(
|
||||
case_id: str,
|
||||
source: tuple[str, bytes],
|
||||
expected: str,
|
||||
reason: str | None,
|
||||
artifacts: tuple[dict[str, canonical.JsonValue], ...],
|
||||
validators: tuple[dict[str, canonical.JsonValue], ...],
|
||||
downstream_validators: tuple[dict[str, canonical.JsonValue], ...] = (),
|
||||
) -> dict[str, canonical.JsonValue]:
|
||||
path, content = source
|
||||
return {
|
||||
"case_id": case_id,
|
||||
"fixture_path": path,
|
||||
"fixture_digest": canonical.bytes_digest(content),
|
||||
"fixture_byte_length": len(content),
|
||||
"expected_status": expected,
|
||||
"reason": reason,
|
||||
"artifacts": artifacts,
|
||||
"validators": validators,
|
||||
"downstream_validators": downstream_validators,
|
||||
}
|
||||
|
||||
|
||||
def _match(root: Path, output: Path, context: EntryFactAuthorityContext, evaluation: str, relative: str) -> EntryFactMatchResult:
|
||||
writer = FactMatchArtifactWriter(
|
||||
output,
|
||||
context.bundle.review_policy.trusted_store_identities[0],
|
||||
canonical.content_digest("retain-access-control-conformance-v1"),
|
||||
)
|
||||
results = match_entry_fact(
|
||||
repository_root=root,
|
||||
relative_path=relative,
|
||||
language="javascript",
|
||||
fact_id="entry:express:app-route:get",
|
||||
authority=context,
|
||||
writer=writer,
|
||||
evaluation_population_digest=evaluation,
|
||||
)
|
||||
if len(results) != 1:
|
||||
raise EntryFactConformanceError("fixture must produce exactly one structural candidate")
|
||||
return results[0]
|
||||
|
||||
|
||||
def _match_artifacts(output: Path, result: EntryFactMatchResult) -> tuple[dict[str, canonical.JsonValue], ...]:
|
||||
refs = tuple(item.evidence for item in result.match.observations) + (result.match_reference,)
|
||||
return tuple(_persist(output, result.resolver.resolve(ref).content, "match-evidence") for ref in refs)
|
||||
|
||||
|
||||
def _stamp(contract: str, evaluation: str, source_digest: str, result: EntryFactMatchResult) -> provenance.ProvenanceStamp:
|
||||
return provenance.ProvenanceStamp(
|
||||
canonical.content_digest("entry-conformance-analyzer"),
|
||||
contract,
|
||||
canonical.content_digest((result.pack.normalized_content_digest,)),
|
||||
canonical.content_digest("entry-conformance-acquisition"),
|
||||
canonical.content_digest("entry-conformance-configuration"),
|
||||
evaluation,
|
||||
source_digest,
|
||||
)
|
||||
|
||||
|
||||
def _record(result: EntryFactMatchResult, evaluation: str, source_digest: str) -> evidence.EvidenceRecord:
|
||||
location = result.match.product_location
|
||||
source = semantics.SemanticNode("constraint-source", "security_object", location)
|
||||
target = semantics.SemanticNode("constraint-target", "operation", location)
|
||||
product = semantics.EvidenceProvenance(semantics.ProvenanceKind.PRODUCT_CODE, source_digest, None, None, None)
|
||||
constraint = semantics.make_relation(
|
||||
kind=semantics.RelationKind.CONSTRAINT_EFFECT,
|
||||
role="constraint",
|
||||
source=source,
|
||||
target=target,
|
||||
location=location,
|
||||
status=semantics.RelationStatus.INCOMPLETE,
|
||||
conditions=(),
|
||||
reasons=("missing_constraint_relation",),
|
||||
provenance=product,
|
||||
)
|
||||
fields = (
|
||||
semantics.FieldValue("operation", semantics.FieldKind.TEXT, "entry-registration"),
|
||||
semantics.FieldValue("boundary", semantics.FieldKind.TEXT, "express"),
|
||||
)
|
||||
scope = evidence.AnalyzedScope("base", "head", source_digest, (evidence.SourceRegion(location.path, 1, 4),))
|
||||
contract = result.pack.family_contract_digest
|
||||
packet = evidence.EvidencePacket(
|
||||
evidence.EVIDENCE_PACKET_SCHEMA,
|
||||
result.pack.family_id,
|
||||
contract,
|
||||
family.derive_security_object_id(_context_contract().security_object, fields),
|
||||
result.pack.ecosystem,
|
||||
scope,
|
||||
(*result.relations, constraint),
|
||||
(),
|
||||
fields,
|
||||
("missing_constraint_relation",),
|
||||
_stamp(contract, evaluation, source_digest, result),
|
||||
)
|
||||
decision = evidence.Decision(
|
||||
"indeterminate",
|
||||
evidence.NeutralOutcome.INDETERMINATE,
|
||||
evidence.EvidenceBasis.DETERMINISTIC,
|
||||
scope,
|
||||
("missing_constraint_relation",),
|
||||
evidence.derive_packet_digest(packet),
|
||||
provenance.DecisionProvenance(None, None, None, None, None, None),
|
||||
)
|
||||
return evidence.EvidenceRecord(packet, decision, "")
|
||||
|
||||
|
||||
def _context_contract() -> family.FamilyContract:
|
||||
from openultrasast.semantic.obligations.core_contract import production_access_control_contract
|
||||
|
||||
return production_access_control_contract()
|
||||
|
||||
|
||||
def _complete_case(
|
||||
fixture_root: Path,
|
||||
output: Path,
|
||||
source: tuple[str, bytes],
|
||||
context: EntryFactAuthorityContext,
|
||||
evaluation: str,
|
||||
) -> tuple[dict[str, canonical.JsonValue], EntryFactMatchResult]:
|
||||
result = _match(fixture_root, output, context, evaluation, source[0])
|
||||
record = _validate_complete(result, context, evaluation, source)
|
||||
artifacts = _match_artifacts(output, result)
|
||||
artifacts += (_persist(output, fact_pack_bytes(result.pack), "fact-pack"),)
|
||||
artifacts += (_persist(output, evidence.evidence_record_bytes(record), "evidence-record"),)
|
||||
validators = tuple(_validator(name, "passed") for name in _CORE_ENTRY_POINTS)
|
||||
return _case("complete", source, "passed", None, artifacts, validators), result
|
||||
|
||||
|
||||
def _validate_complete(
|
||||
result: EntryFactMatchResult,
|
||||
context: EntryFactAuthorityContext,
|
||||
evaluation: str,
|
||||
source: tuple[str, bytes],
|
||||
) -> evidence.EvidenceRecord:
|
||||
bundle = context.bundle
|
||||
validate_fact_pack(
|
||||
result.pack,
|
||||
bundle.contract,
|
||||
evaluation,
|
||||
bundle.lineages,
|
||||
context.custody,
|
||||
bundle.custody_policy,
|
||||
bundle.review_policy,
|
||||
result.resolver,
|
||||
)
|
||||
validate_fact_match(
|
||||
result.pack,
|
||||
result.match.fact_id,
|
||||
result.match,
|
||||
evaluation,
|
||||
bundle.lineages,
|
||||
context.custody,
|
||||
bundle.custody_policy,
|
||||
bundle.review_policy,
|
||||
result.resolver,
|
||||
)
|
||||
apply_fact(
|
||||
result.pack,
|
||||
result.match.fact_id,
|
||||
result.match,
|
||||
result.match_reference,
|
||||
bundle.contract,
|
||||
evaluation,
|
||||
bundle.lineages,
|
||||
context.custody,
|
||||
bundle.custody_policy,
|
||||
bundle.review_policy,
|
||||
result.resolver,
|
||||
)
|
||||
record = _record(result, evaluation, canonical.bytes_digest(source[1]))
|
||||
_validate_record(record, result, context, evaluation)
|
||||
return record
|
||||
|
||||
|
||||
def _validate_record(
|
||||
record: evidence.EvidenceRecord,
|
||||
result: EntryFactMatchResult,
|
||||
context: EntryFactAuthorityContext,
|
||||
evaluation: str,
|
||||
) -> None:
|
||||
bundle = context.bundle
|
||||
validate_fact_relations(
|
||||
record,
|
||||
bundle.contract,
|
||||
bundle.packs,
|
||||
evaluation,
|
||||
bundle.lineages,
|
||||
context.custody,
|
||||
bundle.custody_policy,
|
||||
bundle.review_policy,
|
||||
result.resolver,
|
||||
)
|
||||
|
||||
|
||||
def build_entry_fact_conformance(fixture_root: Path, output_root: Path) -> bytes:
|
||||
"""Run the target adapter and return its canonical immutable handoff manifest."""
|
||||
fixture_root, output_root = Path(fixture_root), Path(output_root)
|
||||
sources = _read_sources(fixture_root)
|
||||
context, evaluation, _ = _context()
|
||||
complete, result = _complete_case(fixture_root, output_root, sources["complete"], context, evaluation)
|
||||
from openultrasast.mapping._entry_fact_conformance_negative import negative_cases
|
||||
from openultrasast.mapping._entry_fact_conformance_replay import attach_replay, replay_material
|
||||
|
||||
cases = (complete, *negative_cases(fixture_root, output_root, sources, context, evaluation, result))
|
||||
replay, dependencies = replay_material(output_root, context, evaluation, result, sources["complete"])
|
||||
cases = attach_replay(tuple(sorted(cases, key=lambda item: str(item["case_id"]))), replay, dependencies)
|
||||
payload: dict[str, canonical.JsonValue] = {
|
||||
"schema_version": ENTRY_FACT_CONFORMANCE_SCHEMA,
|
||||
"core_entry_points": _CORE_ENTRY_POINTS,
|
||||
"cases": cases,
|
||||
}
|
||||
manifest = {**payload, "handoff_digest": canonical.content_digest(payload)}
|
||||
return canonical.canonical_record_bytes(manifest, known_schema_versions=(ENTRY_FACT_CONFORMANCE_SCHEMA,))
|
||||
|
||||
|
||||
def write_entry_fact_conformance(fixture_root: Path, output_root: Path) -> Path:
|
||||
"""Generate artifacts and atomically-equivalent canonical manifest bytes."""
|
||||
output = Path(output_root)
|
||||
content = build_entry_fact_conformance(fixture_root, output)
|
||||
target = output / "manifest.json"
|
||||
target.parent.mkdir(parents=True, exist_ok=True)
|
||||
target.write_bytes(content)
|
||||
return target
|
||||
|
||||
|
||||
__all__ = [
|
||||
"ENTRY_FACT_CONFORMANCE_SCHEMA",
|
||||
"EntryFactConformanceError",
|
||||
"build_entry_fact_conformance",
|
||||
"write_entry_fact_conformance",
|
||||
]
|
||||
@@ -0,0 +1,284 @@
|
||||
"""Closed manifest validation for the downstream entry-fact handoff."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
from collections.abc import Mapping
|
||||
from pathlib import Path, PurePosixPath
|
||||
from typing import cast
|
||||
|
||||
from openultrasast.core import canonical
|
||||
from openultrasast.mapping._entry_fact_conformance_fs import (
|
||||
ConformanceFilesystemError,
|
||||
flat_regular_census,
|
||||
read_regular_nofollow,
|
||||
require_real_directory,
|
||||
)
|
||||
from openultrasast.mapping.entry_fact_conformance import ENTRY_FACT_CONFORMANCE_SCHEMA, EntryFactConformanceError
|
||||
|
||||
_DIGEST = re.compile(r"[0-9a-f]{64}")
|
||||
_TOP_FIELDS = {"schema_version", "handoff_digest", "core_entry_points", "cases"}
|
||||
_CASE_FIELDS = {
|
||||
"case_id",
|
||||
"fixture_path",
|
||||
"fixture_digest",
|
||||
"fixture_byte_length",
|
||||
"expected_status",
|
||||
"reason",
|
||||
"artifacts",
|
||||
"validators",
|
||||
"downstream_validators",
|
||||
}
|
||||
_ARTIFACT_FIELDS = {"kind", "path", "content_digest", "byte_length"}
|
||||
_VALIDATOR_FIELDS = {"name", "status", "reason"}
|
||||
_EXPECTED_CASES = {
|
||||
"complete",
|
||||
"name_only",
|
||||
"partial",
|
||||
"authority_substitution",
|
||||
"producer_reviewer_conflict",
|
||||
"resolver_byte_substitution",
|
||||
"lineage_omission",
|
||||
"custody_contamination",
|
||||
"legacy_projection_only",
|
||||
"deterministic_replay",
|
||||
}
|
||||
_CORE_ENTRY_POINTS = (
|
||||
"openultrasast.core.factapply.apply_fact",
|
||||
"openultrasast.core.factmatch.validate_fact_match",
|
||||
"openultrasast.core.factpack.validate_fact_pack",
|
||||
"openultrasast.core.factvalidate.validate_fact_relations",
|
||||
)
|
||||
_MATCH = "openultrasast.core.factmatch.validate_fact_match"
|
||||
_MATRIX = {
|
||||
"authority_substitution": ((_MATCH, "refused", "match_pack_identity_substituted"),),
|
||||
"complete": tuple((name, "passed", None) for name in _CORE_ENTRY_POINTS),
|
||||
"custody_contamination": ((_MATCH, "refused", "protected_population_contamination"),),
|
||||
"deterministic_replay": ((_MATCH, "passed", None),),
|
||||
"legacy_projection_only": ((_MATCH, "refused", "name_only_match"),),
|
||||
"lineage_omission": ((_MATCH, "refused", "matcher_lineage_omitted"),),
|
||||
"name_only": ((_MATCH, "refused", "missing_observation:receiver"),),
|
||||
"partial": ((_MATCH, "refused", "missing_observation:arguments"),),
|
||||
"producer_reviewer_conflict": (("openultrasast.core.factpack.validate_fact_pack", "refused", "self_authored_review_evidence"),),
|
||||
"resolver_byte_substitution": ((_MATCH, "refused", "resolver_byte_substitution"),),
|
||||
}
|
||||
_DOWNSTREAM_AUTHORITY = "openultrasast.mapping.fact_authority.authenticate_entry_fact_authority"
|
||||
_DOWNSTREAM_MATRIX: dict[str, tuple[tuple[str, str, str], ...]] = {case_id: () for case_id in _EXPECTED_CASES}
|
||||
_DOWNSTREAM_MATRIX["authority_substitution"] = ((_DOWNSTREAM_AUTHORITY, "refused", "authority_bundle_digest_substituted"),)
|
||||
_DOWNSTREAM_MATRIX["producer_reviewer_conflict"] = ((_DOWNSTREAM_AUTHORITY, "refused", "producer_reviewer_conflict"),)
|
||||
|
||||
|
||||
def _freeze(value: object) -> canonical.JsonValue:
|
||||
if value is None or isinstance(value, (str, bool, int, float)):
|
||||
return value
|
||||
if isinstance(value, list):
|
||||
return tuple(_freeze(item) for item in value)
|
||||
if isinstance(value, Mapping) and all(isinstance(key, str) for key in value):
|
||||
return {cast(str, key): _freeze(item) for key, item in value.items()}
|
||||
raise EntryFactConformanceError("manifest contains a value outside canonical JSON")
|
||||
|
||||
|
||||
def _object(value: object, fields: set[str], name: str) -> Mapping[str, object]:
|
||||
if not isinstance(value, Mapping) or set(value) != fields or not all(isinstance(key, str) for key in value):
|
||||
raise EntryFactConformanceError(f"{name} has unknown or missing fields")
|
||||
return cast(Mapping[str, object], value)
|
||||
|
||||
|
||||
def _array(value: object, name: str) -> list[object]:
|
||||
if not isinstance(value, list) or not value:
|
||||
raise EntryFactConformanceError(f"{name} must be a nonempty array")
|
||||
return value
|
||||
|
||||
|
||||
def _list(value: object, name: str) -> list[object]:
|
||||
if not isinstance(value, list):
|
||||
raise EntryFactConformanceError(f"{name} must be an array")
|
||||
return value
|
||||
|
||||
|
||||
def _text(value: object, name: str) -> str:
|
||||
if not isinstance(value, str) or not value:
|
||||
raise EntryFactConformanceError(f"{name} must be nonempty text")
|
||||
return value
|
||||
|
||||
|
||||
def _digest(value: object, name: str) -> str:
|
||||
text = _text(value, name)
|
||||
if _DIGEST.fullmatch(text) is None:
|
||||
raise EntryFactConformanceError(f"{name} must be a lowercase SHA-256 digest")
|
||||
return text
|
||||
|
||||
|
||||
def _positive(value: object, name: str) -> None:
|
||||
if isinstance(value, bool) or not isinstance(value, int) or value <= 0:
|
||||
raise EntryFactConformanceError(f"{name} must be a positive integer")
|
||||
|
||||
|
||||
def _relative(value: object, name: str) -> None:
|
||||
text = _text(value, name)
|
||||
path = PurePosixPath(text)
|
||||
if path.is_absolute() or ".." in path.parts or path.as_posix() != text:
|
||||
raise EntryFactConformanceError(f"{name} must be a normalized relative path")
|
||||
|
||||
|
||||
def _validate_case(value: object) -> str:
|
||||
row = _object(value, _CASE_FIELDS, "case")
|
||||
case_id = _text(row["case_id"], "case_id")
|
||||
if case_id not in _MATRIX:
|
||||
raise EntryFactConformanceError("case identity is unknown")
|
||||
_relative(row["fixture_path"], "fixture_path")
|
||||
_digest(row["fixture_digest"], "fixture_digest")
|
||||
_positive(row["fixture_byte_length"], "fixture_byte_length")
|
||||
status = _text(row["expected_status"], "expected_status")
|
||||
reason = row["reason"]
|
||||
if status not in {"passed", "refused"} or (reason is None) is not (status == "passed"):
|
||||
raise EntryFactConformanceError("case status and stable reason are inconsistent")
|
||||
if reason is not None:
|
||||
_text(reason, "reason")
|
||||
_validate_artifacts(row["artifacts"])
|
||||
_validate_validators(case_id, row["validators"], status, reason)
|
||||
_validate_downstream(case_id, row["downstream_validators"])
|
||||
return case_id
|
||||
|
||||
|
||||
def _validate_artifacts(value: object) -> None:
|
||||
for artifact in _array(value, "artifacts"):
|
||||
item = _object(artifact, _ARTIFACT_FIELDS, "artifact")
|
||||
_text(item["kind"], "artifact.kind")
|
||||
_relative(item["path"], "artifact.path")
|
||||
digest = _digest(item["content_digest"], "artifact.content_digest")
|
||||
if item["path"] != f"artifacts/sha256/{digest}":
|
||||
raise EntryFactConformanceError("artifact path does not equal its digest address")
|
||||
_positive(item["byte_length"], "artifact.byte_length")
|
||||
|
||||
|
||||
def _validate_validators(case_id: str, value: object, status: str, reason: object) -> None:
|
||||
actual_validators = []
|
||||
for validator in _array(value, "validators"):
|
||||
item = _object(validator, _VALIDATOR_FIELDS, "validator")
|
||||
name = _text(item["name"], "validator.name")
|
||||
if name not in _CORE_ENTRY_POINTS:
|
||||
raise EntryFactConformanceError("validator is outside the exact core entry-point set")
|
||||
validator_status = _text(item["status"], "validator.status")
|
||||
if validator_status not in {"passed", "refused"}:
|
||||
raise EntryFactConformanceError("validator status is unknown")
|
||||
if item["reason"] is not None:
|
||||
_text(item["reason"], "validator.reason")
|
||||
if validator_status != status or item["reason"] != reason:
|
||||
raise EntryFactConformanceError("validator result differs from its enclosing case")
|
||||
actual_validators.append((name, validator_status, item["reason"]))
|
||||
if tuple(actual_validators) != _MATRIX[case_id]:
|
||||
raise EntryFactConformanceError("case validator matrix is incomplete or reordered")
|
||||
|
||||
|
||||
def _validate_downstream(case_id: str, value: object) -> None:
|
||||
actual = []
|
||||
for validator in _list(value, "downstream_validators"):
|
||||
item = _object(validator, _VALIDATOR_FIELDS, "downstream validator")
|
||||
actual.append(
|
||||
(
|
||||
_text(item["name"], "downstream validator.name"),
|
||||
_text(item["status"], "downstream validator.status"),
|
||||
item["reason"],
|
||||
)
|
||||
)
|
||||
if tuple(actual) != _DOWNSTREAM_MATRIX[case_id]:
|
||||
raise EntryFactConformanceError("downstream validator matrix is incomplete or fabricated")
|
||||
|
||||
|
||||
def _validate_files(root: Path, cases: list[object]) -> None:
|
||||
declared_sources = {_text(_object(raw, _CASE_FIELDS, "case")["fixture_path"], "fixture_path") for raw in cases}
|
||||
source_root = root / "sources"
|
||||
try:
|
||||
actual_sources = {f"sources/{name}" for name in flat_regular_census(source_root)}
|
||||
except ConformanceFilesystemError as exc:
|
||||
raise EntryFactConformanceError("source filesystem census differs from declared regular fixtures") from exc
|
||||
if actual_sources != declared_sources:
|
||||
raise EntryFactConformanceError("source filesystem census differs from declared regular fixtures")
|
||||
declared = _declared_artifact_paths(cases)
|
||||
artifact_root = root / "artifacts" / "sha256"
|
||||
try:
|
||||
require_real_directory(root / "artifacts")
|
||||
actual = {f"artifacts/sha256/{name}" for name in flat_regular_census(artifact_root)}
|
||||
except ConformanceFilesystemError as exc:
|
||||
raise EntryFactConformanceError("artifact filesystem census differs from the manifest") from exc
|
||||
if actual != declared:
|
||||
raise EntryFactConformanceError("artifact filesystem census differs from the manifest")
|
||||
_validate_materialized_bytes(root, cases)
|
||||
|
||||
|
||||
def _declared_artifact_paths(cases: list[object]) -> set[str]:
|
||||
declared: set[str] = set()
|
||||
for raw in cases:
|
||||
case = _object(raw, _CASE_FIELDS, "case")
|
||||
for raw_artifact in _array(case["artifacts"], "artifacts"):
|
||||
artifact = _object(raw_artifact, _ARTIFACT_FIELDS, "artifact")
|
||||
declared.add(_text(artifact["path"], "artifact.path"))
|
||||
return declared
|
||||
|
||||
|
||||
def _safe_read(path: Path, kind: str) -> bytes:
|
||||
try:
|
||||
return read_regular_nofollow(path)
|
||||
except ConformanceFilesystemError as exc:
|
||||
raise EntryFactConformanceError(f"{kind} filesystem census differs from the manifest") from exc
|
||||
|
||||
|
||||
def _validate_materialized_bytes(root: Path, cases: list[object]) -> None:
|
||||
for raw in cases:
|
||||
case = _object(raw, _CASE_FIELDS, "case")
|
||||
fixture = root / _text(case["fixture_path"], "fixture_path")
|
||||
fixture_content = _safe_read(fixture, "source")
|
||||
if (
|
||||
not fixture_content
|
||||
or len(fixture_content) != case["fixture_byte_length"]
|
||||
or canonical.bytes_digest(fixture_content) != case["fixture_digest"]
|
||||
):
|
||||
raise EntryFactConformanceError("fixture bytes do not match the manifest")
|
||||
for raw_artifact in _array(case["artifacts"], "artifacts"):
|
||||
artifact = _object(raw_artifact, _ARTIFACT_FIELDS, "artifact")
|
||||
path = _text(artifact["path"], "artifact.path")
|
||||
materialized = _safe_read(root / path, "artifact")
|
||||
if (
|
||||
not materialized
|
||||
or len(materialized) != artifact["byte_length"]
|
||||
or canonical.bytes_digest(materialized) != artifact["content_digest"]
|
||||
):
|
||||
raise EntryFactConformanceError("artifact bytes do not match the manifest")
|
||||
|
||||
|
||||
def validate_entry_fact_conformance(content: bytes, root: Path | None = None) -> None:
|
||||
"""Refuse noncanonical, open-schema, redirected, or self-inconsistent manifests."""
|
||||
try:
|
||||
parsed = json.loads(content)
|
||||
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
|
||||
raise EntryFactConformanceError("manifest is not canonical JSON") from exc
|
||||
row = _object(parsed, _TOP_FIELDS, "manifest")
|
||||
if row["schema_version"] != ENTRY_FACT_CONFORMANCE_SCHEMA:
|
||||
raise EntryFactConformanceError("manifest schema is unknown")
|
||||
frozen = cast(Mapping[str, canonical.JsonValue], _freeze(parsed))
|
||||
if canonical.canonical_record_bytes(frozen, known_schema_versions=(ENTRY_FACT_CONFORMANCE_SCHEMA,)) != content:
|
||||
raise EntryFactConformanceError("manifest bytes are not canonical")
|
||||
entry_points = _array(row["core_entry_points"], "core_entry_points")
|
||||
if not all(isinstance(item, str) and item for item in entry_points) or len(set(entry_points)) != len(entry_points):
|
||||
raise EntryFactConformanceError("core entry points must be unique nonempty text")
|
||||
core_entry_points = tuple(cast(str, item) for item in entry_points)
|
||||
if core_entry_points != _CORE_ENTRY_POINTS:
|
||||
raise EntryFactConformanceError("core entry points differ from the exact replay set")
|
||||
cases = _array(row["cases"], "cases")
|
||||
case_ids = tuple(_validate_case(item) for item in cases)
|
||||
if set(case_ids) != _EXPECTED_CASES or case_ids != tuple(sorted(case_ids)):
|
||||
raise EntryFactConformanceError("manifest cases are missing, duplicated, or unordered")
|
||||
payload: Mapping[str, canonical.JsonValue] = {
|
||||
"schema_version": ENTRY_FACT_CONFORMANCE_SCHEMA,
|
||||
"core_entry_points": core_entry_points,
|
||||
"cases": tuple(_freeze(item) for item in cases),
|
||||
}
|
||||
if _digest(row["handoff_digest"], "handoff_digest") != canonical.content_digest(payload):
|
||||
raise EntryFactConformanceError("handoff digest cannot be re-derived")
|
||||
if root is not None:
|
||||
_validate_files(Path(root), cases)
|
||||
|
||||
|
||||
__all__ = ["validate_entry_fact_conformance"]
|
||||
@@ -0,0 +1,202 @@
|
||||
"""Isolated generic-core consumer for the downstream fact handoff."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from dataclasses import replace
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from entry_fact_core_wire import (
|
||||
FileResolver,
|
||||
MemoryCustody,
|
||||
contract,
|
||||
custody_log,
|
||||
fact_match,
|
||||
fact_pack,
|
||||
lineage_manifest,
|
||||
load_envelope,
|
||||
obj,
|
||||
reference,
|
||||
seq,
|
||||
)
|
||||
from entry_fact_evidence_wire import record
|
||||
|
||||
from openultrasast.core import custody
|
||||
from openultrasast.core.factapply import apply_fact
|
||||
from openultrasast.core.factmatch import derive_fact_match_digest, validate_fact_match
|
||||
from openultrasast.core.factpack import (
|
||||
ReviewIndependencePolicy,
|
||||
derive_independence_attestation_digest,
|
||||
validate_fact_pack,
|
||||
)
|
||||
from openultrasast.core.factvalidate import validate_fact_relations
|
||||
|
||||
|
||||
def _inputs(root: Path) -> tuple[dict[str, Any], dict[str, Any]]:
|
||||
manifest = obj(json.loads((root / "manifest.json").read_bytes()))
|
||||
envelope_path = next(
|
||||
artifact["path"] for case in manifest["cases"] for artifact in case["artifacts"] if artifact["kind"] == "core-replay-envelope"
|
||||
)
|
||||
return manifest, load_envelope(root / envelope_path)
|
||||
|
||||
|
||||
def _review_policy(value: object) -> ReviewIndependencePolicy:
|
||||
row = obj(value)
|
||||
return ReviewIndependencePolicy(
|
||||
tuple(seq(row["reviewed_reviewer_digests"])),
|
||||
tuple(tuple(pair) for pair in seq(row["forbidden_identity_pairs"])),
|
||||
tuple(seq(row["trusted_store_identities"])),
|
||||
row["maximum_evidence_bytes"],
|
||||
row["policy_digest"],
|
||||
)
|
||||
|
||||
|
||||
def _custody_policy(value: object) -> custody.PopulationCustodyPolicy:
|
||||
row = obj(value)
|
||||
return custody.PopulationCustodyPolicy(tuple(seq(row["reviewed_custodian_digests"])), row["policy_digest"])
|
||||
|
||||
|
||||
def _resolver(root: Path, envelope: dict[str, Any]) -> FileResolver:
|
||||
entries = {}
|
||||
for raw in envelope["resolver_entries"]:
|
||||
item = obj(raw)
|
||||
ref = reference(item["reference"])
|
||||
entries[ref.content_digest] = (ref, item["path"], item["store_identity"])
|
||||
return FileResolver(root, entries)
|
||||
|
||||
|
||||
def _changed_match(value: object, mutation: str):
|
||||
match = fact_match(value)
|
||||
if mutation in {"qualified_name_only", "receiver_omission", "arguments_omission"}:
|
||||
keep = {
|
||||
"qualified_name_only": {"qualified_target"},
|
||||
"receiver_omission": {"qualified_target", "call_shape", "arguments"},
|
||||
"arguments_omission": {"qualified_target", "call_shape", "receiver"},
|
||||
}[mutation]
|
||||
match = replace(
|
||||
match, observations=tuple(item for item in match.observations if item.requirement_id in keep), match_digest="0" * 64
|
||||
)
|
||||
elif mutation == "match_pack_digest_substitution":
|
||||
match = replace(match, pack_digest="0" * 64, match_digest="0" * 64)
|
||||
return replace(match, match_digest=derive_fact_match_digest(match)) if match.match_digest == "0" * 64 else match
|
||||
|
||||
|
||||
def _self_authored(value: object):
|
||||
pack = fact_pack(value)
|
||||
first = pack.review_evidence[0]
|
||||
attestation = replace(
|
||||
first.independence,
|
||||
producer_identity=first.reviewer_identity,
|
||||
reviewer_identity=first.reviewer_identity,
|
||||
attestation_digest="0" * 64,
|
||||
)
|
||||
attestation = replace(attestation, attestation_digest=derive_independence_attestation_digest(attestation))
|
||||
evidence = replace(first, producer_identity=first.reviewer_identity, independence=attestation)
|
||||
return replace(pack, review_evidence=(evidence, *pack.review_evidence[1:]))
|
||||
|
||||
|
||||
def replay_all(root: Path) -> dict[str, tuple[str, str | None]]:
|
||||
manifest, envelope = _inputs(root)
|
||||
contract_value = contract(envelope["contract"])
|
||||
pack = fact_pack(envelope["pack"])
|
||||
base_match = fact_match(envelope["match"])
|
||||
match_reference = reference(envelope["match_reference"])
|
||||
lineages = tuple(lineage_manifest(item) for item in seq(envelope["lineages"]))
|
||||
policy = _review_policy(envelope["review_policy"])
|
||||
custody_policy = _custody_policy(envelope["custody_policy"])
|
||||
base_logs = tuple(custody_log(item) for item in seq(envelope["custody_logs"]))
|
||||
population = envelope["evaluation_population_digest"]
|
||||
expected = {case["case_id"]: (case["expected_status"], case["reason"]) for case in manifest["cases"]}
|
||||
results: dict[str, tuple[str, str | None]] = {}
|
||||
for raw_plan in envelope["case_plans"]:
|
||||
plan = obj(raw_plan)
|
||||
case_id, mutation = plan["case_id"], plan["mutation"]
|
||||
match = _changed_match(envelope["match"], mutation)
|
||||
selected_lineages = lineages
|
||||
logs = base_logs
|
||||
resolver = _resolver(root, envelope)
|
||||
selected_pack = pack
|
||||
if mutation == "matcher_lineage_omission":
|
||||
selected_lineages = tuple(item for item in lineages if item.manifest_digest != base_match.matcher_lineage_manifest_digest)
|
||||
elif mutation == "contaminated_custody":
|
||||
contaminated = custody_log(envelope["contaminated_custody_log"])
|
||||
logs = tuple(contaminated if item.population_digest == population else item for item in base_logs)
|
||||
elif mutation == "resolver_byte_substitution":
|
||||
resolver.substitution = (base_match.observations[0].evidence.content_digest, envelope["substituted_content_path"])
|
||||
elif mutation == "self_authored_pack":
|
||||
selected_pack = _self_authored(envelope["pack"])
|
||||
current = MemoryCustody({item.population_digest: item for item in logs})
|
||||
results[case_id] = _run_case(
|
||||
case_id,
|
||||
plan["validator"],
|
||||
selected_pack,
|
||||
contract_value,
|
||||
match,
|
||||
match_reference,
|
||||
population,
|
||||
selected_lineages,
|
||||
current,
|
||||
custody_policy,
|
||||
policy,
|
||||
resolver,
|
||||
record(envelope["evidence_record"]),
|
||||
)
|
||||
assert results[case_id] == expected[case_id]
|
||||
return results
|
||||
|
||||
|
||||
def _run_case(
|
||||
case_id,
|
||||
validator,
|
||||
pack,
|
||||
contract_value,
|
||||
match,
|
||||
match_reference,
|
||||
population,
|
||||
lineages,
|
||||
current,
|
||||
custody_policy,
|
||||
policy,
|
||||
resolver,
|
||||
evidence_record,
|
||||
):
|
||||
try:
|
||||
if validator in {"all", "openultrasast.core.factpack.validate_fact_pack"}:
|
||||
validate_fact_pack(pack, contract_value, population, lineages, current, custody_policy, policy, resolver)
|
||||
if validator in {"all", "openultrasast.core.factmatch.validate_fact_match"}:
|
||||
decision = validate_fact_match(pack, match.fact_id, match, population, lineages, current, custody_policy, policy, resolver)
|
||||
if not decision.effect_eligible:
|
||||
return "refused", _decision_reason(case_id, decision.reasons)
|
||||
if validator == "all":
|
||||
apply_fact(
|
||||
pack, match.fact_id, match, match_reference, contract_value, population, lineages, current, custody_policy, policy, resolver
|
||||
)
|
||||
validate_fact_relations(
|
||||
evidence_record, contract_value, (pack,), population, lineages, current, custody_policy, policy, resolver
|
||||
)
|
||||
return "passed", None
|
||||
except (TypeError, ValueError) as exc:
|
||||
return "refused", _error_reason(case_id, str(exc))
|
||||
|
||||
|
||||
def _decision_reason(case_id: str, reasons: tuple[str, ...]) -> str:
|
||||
expected = {
|
||||
"custody_contamination": "protected_population_contamination",
|
||||
"legacy_projection_only": "name_only_match",
|
||||
"name_only": "missing_observation:receiver",
|
||||
"partial": "missing_observation:arguments",
|
||||
}[case_id]
|
||||
assert expected in reasons or any(item.startswith("protected_population_labels:") for item in reasons)
|
||||
return expected
|
||||
|
||||
|
||||
def _error_reason(case_id: str, message: str) -> str:
|
||||
expected = {
|
||||
"authority_substitution": ("match pack digest", "match_pack_identity_substituted"),
|
||||
"lineage_omission": ("matcher lineage", "matcher_lineage_omitted"),
|
||||
"producer_reviewer_conflict": ("producer and reviewer", "self_authored_review_evidence"),
|
||||
"resolver_byte_substitution": ("resolved content digest", "resolver_byte_substitution"),
|
||||
}[case_id]
|
||||
assert expected[0] in message
|
||||
return expected[1]
|
||||
@@ -0,0 +1,290 @@
|
||||
"""Family-neutral decoders for the checked-in fact conformance envelope."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Any, cast
|
||||
|
||||
from openultrasast.core import canonical, custody, evidence, family, lineage, semantics
|
||||
from openultrasast.core.factmatch import FactMatchEvidence, StructuralObservation
|
||||
from openultrasast.core.factpack import (
|
||||
FactPack,
|
||||
IndependenceAttestation,
|
||||
KnowledgeEvidence,
|
||||
KnowledgeEvidenceKind,
|
||||
RelationEffect,
|
||||
SemanticFact,
|
||||
StructuralRequirement,
|
||||
StructuralRequirementKind,
|
||||
)
|
||||
|
||||
REPLAY_SCHEMA = "openultrasast.access-control.entry-fact-core-replay.v1"
|
||||
|
||||
|
||||
def obj(value: object) -> dict[str, Any]:
|
||||
assert isinstance(value, dict)
|
||||
return cast(dict[str, Any], value)
|
||||
|
||||
|
||||
def seq(value: object) -> tuple[Any, ...]:
|
||||
assert isinstance(value, list)
|
||||
return tuple(value)
|
||||
|
||||
|
||||
def location(value: object) -> semantics.SourceLocation:
|
||||
row = obj(value)
|
||||
return semantics.SourceLocation(row["path"], row["line"], row["column"], row["symbol"])
|
||||
|
||||
|
||||
def reference(value: object) -> canonical.ContentRef:
|
||||
row = obj(value)
|
||||
return canonical.ContentRef(
|
||||
row["artifact_id"],
|
||||
row["content_digest"],
|
||||
row["media_type"],
|
||||
row["byte_length"],
|
||||
row["retention_policy_digest"],
|
||||
row["storage_receipt_digest"],
|
||||
)
|
||||
|
||||
|
||||
def field_spec(value: object) -> family.FieldSpec:
|
||||
row = obj(value)
|
||||
return family.FieldSpec(row["name"], semantics.FieldKind(row["kind"]), row["required"])
|
||||
|
||||
|
||||
def contract(value: object) -> family.FamilyContract:
|
||||
row = obj(value)
|
||||
security = obj(row["security_object"])
|
||||
return family.FamilyContract(
|
||||
row["family_id"],
|
||||
row["family_version"],
|
||||
row["schema_version"],
|
||||
tuple(seq(row["ecosystems"])),
|
||||
family.ObjectSpec(
|
||||
security["kind"],
|
||||
tuple(field_spec(item) for item in seq(security["fields"])),
|
||||
tuple(seq(security["identity_fields"])),
|
||||
),
|
||||
tuple(
|
||||
family.RoleSpec(
|
||||
item["role"],
|
||||
tuple(field_spec(field) for field in seq(item["fields"])),
|
||||
tuple(semantics.RelationKind(kind) for kind in seq(item["allowed_relation_kinds"])),
|
||||
family.RelationOriginPolicy(item["origin_policy"]),
|
||||
)
|
||||
for raw in seq(row["roles"])
|
||||
for item in (obj(raw),)
|
||||
),
|
||||
tuple(
|
||||
family.DecisionRule(
|
||||
item["family_code"],
|
||||
evidence.NeutralOutcome(item["outcome"]),
|
||||
tuple(seq(item["required_roles"])),
|
||||
tuple(semantics.RelationStatus(status) for status in seq(item["allowed_statuses"])),
|
||||
)
|
||||
for raw in seq(row["decisions"])
|
||||
for item in (obj(raw),)
|
||||
),
|
||||
tuple(
|
||||
family.ResidualQuestion(item["question_id"], tuple(seq(item["required_roles"])), tuple(seq(item["allowed_decisions"])))
|
||||
for raw in seq(row["residual_questions"])
|
||||
for item in (obj(raw),)
|
||||
),
|
||||
tuple(seq(row["indeterminate_reasons"])),
|
||||
)
|
||||
|
||||
|
||||
def attestation(value: object) -> IndependenceAttestation:
|
||||
row = obj(value)
|
||||
return IndependenceAttestation(
|
||||
row["subject_digest"],
|
||||
row["producer_identity"],
|
||||
row["reviewer_identity"],
|
||||
reference(row["conflict_disclosure"]),
|
||||
row["attestation_digest"],
|
||||
)
|
||||
|
||||
|
||||
def knowledge(value: object) -> KnowledgeEvidence:
|
||||
row = obj(value)
|
||||
return KnowledgeEvidence(
|
||||
KnowledgeEvidenceKind(row["kind"]),
|
||||
reference(row["content"]),
|
||||
row["producer_identity"],
|
||||
row["reviewer_identity"],
|
||||
attestation(row["independence"]),
|
||||
row["lineage_manifest_digest"],
|
||||
)
|
||||
|
||||
|
||||
def fact_pack(value: object) -> FactPack:
|
||||
row = obj(value)
|
||||
facts = tuple(
|
||||
SemanticFact(
|
||||
item["fact_id"],
|
||||
item["role"],
|
||||
tuple(
|
||||
StructuralRequirement(req["requirement_id"], StructuralRequirementKind(req["kind"]), req["field"], req["expected"])
|
||||
for raw_req in seq(item["structural_requirements"])
|
||||
for req in (obj(raw_req),)
|
||||
),
|
||||
tuple(
|
||||
RelationEffect(
|
||||
semantics.RelationKind(effect["kind"]),
|
||||
effect["role"],
|
||||
effect["source_role"],
|
||||
effect["target_role"],
|
||||
tuple(seq(effect["conditions"])),
|
||||
)
|
||||
for raw_effect in seq(item["relation_effects"])
|
||||
for effect in (obj(raw_effect),)
|
||||
),
|
||||
)
|
||||
for raw in seq(row["facts"])
|
||||
for item in (obj(raw),)
|
||||
)
|
||||
return FactPack(
|
||||
row["schema_version"],
|
||||
row["family_contract_digest"],
|
||||
row["family_id"],
|
||||
row["ecosystem"],
|
||||
row["language"],
|
||||
facts,
|
||||
row["normalized_content_digest"],
|
||||
row["review_identity"],
|
||||
tuple(knowledge(item) for item in seq(row["review_evidence"])),
|
||||
row["review_evidence_digest"],
|
||||
row["review_policy_digest"],
|
||||
)
|
||||
|
||||
|
||||
def observation(value: object) -> StructuralObservation:
|
||||
row = obj(value)
|
||||
return StructuralObservation(row["requirement_id"], location(row["location"]), row["observed"], reference(row["evidence"]))
|
||||
|
||||
|
||||
def fact_match(value: object) -> FactMatchEvidence:
|
||||
row = obj(value)
|
||||
return FactMatchEvidence(
|
||||
row["pack_digest"],
|
||||
row["fact_id"],
|
||||
location(row["product_location"]),
|
||||
tuple(observation(item) for item in seq(row["observations"])),
|
||||
row["matcher_revision"],
|
||||
row["matcher_behavior_digest"],
|
||||
row["matcher_lineage_manifest_digest"],
|
||||
row["match_digest"],
|
||||
)
|
||||
|
||||
|
||||
def lineage_use(value: object) -> lineage.LineageUse:
|
||||
row = obj(value)
|
||||
return lineage.LineageUse(
|
||||
custody.LineagePurpose(row["purpose"]),
|
||||
row["source_population_digest"],
|
||||
row["labels_accessed"],
|
||||
row["influenced_artifact_digest"],
|
||||
row["population_use_receipt_digest"],
|
||||
)
|
||||
|
||||
|
||||
def lineage_manifest(value: object) -> lineage.LineageManifest:
|
||||
row = obj(value)
|
||||
return lineage.LineageManifest(
|
||||
row["arm_id"],
|
||||
row["subject_digest"],
|
||||
tuple(lineage_use(item) for item in seq(row["uses"])),
|
||||
row["manifest_digest"],
|
||||
)
|
||||
|
||||
|
||||
def use_request(value: object) -> custody.PopulationUseRequest:
|
||||
row = obj(value)
|
||||
return custody.PopulationUseRequest(
|
||||
row["population_digest"],
|
||||
row["arm_id"],
|
||||
custody.LineagePurpose(row["purpose"]),
|
||||
row["labels_accessed"],
|
||||
row["influenced_artifact_digest"],
|
||||
row["expected_log_digest"],
|
||||
)
|
||||
|
||||
|
||||
def use_receipt(value: object) -> custody.PopulationUseReceipt:
|
||||
row = obj(value)
|
||||
return custody.PopulationUseReceipt(
|
||||
use_request(row["request"]),
|
||||
row["request_digest"],
|
||||
row["population_digest"],
|
||||
row["custodian_identity"],
|
||||
row["sequence"],
|
||||
row["predecessor_digest"],
|
||||
custody.PopulationStatus(row["prior_status"]),
|
||||
custody.PopulationStatus(row["status"]),
|
||||
tuple(seq(row["reasons"])),
|
||||
row["receipt_digest"],
|
||||
)
|
||||
|
||||
|
||||
def custody_log(value: object) -> custody.PopulationCustodyLog:
|
||||
row = obj(value)
|
||||
return custody.PopulationCustodyLog(
|
||||
row["population_digest"],
|
||||
row["custodian_identity"],
|
||||
tuple(use_receipt(item) for item in seq(row["receipts"])),
|
||||
row["receipt_count"],
|
||||
row["head_receipt_digest"],
|
||||
custody.PopulationStatus(row["status"]),
|
||||
row["log_digest"],
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class MemoryCustody:
|
||||
logs: dict[str, custody.PopulationCustodyLog]
|
||||
|
||||
def current_log(self, population_digest: str) -> custody.PopulationCustodyLog:
|
||||
return self.logs[population_digest]
|
||||
|
||||
|
||||
@dataclass
|
||||
class FileResolver:
|
||||
root: Path
|
||||
entries: dict[str, tuple[canonical.ContentRef, str, str]]
|
||||
substitution: tuple[str, str] | None = None
|
||||
|
||||
def resolve(self, value: canonical.ContentRef) -> canonical.ResolvedContent:
|
||||
expected, path, store = self.entries[value.content_digest]
|
||||
assert expected == value
|
||||
if self.substitution is not None and value.content_digest == self.substitution[0]:
|
||||
path = self.substitution[1]
|
||||
content = (self.root / path).read_bytes()
|
||||
receipt = canonical.StorageReceipt(
|
||||
store,
|
||||
value.content_digest,
|
||||
value.byte_length,
|
||||
value.retention_policy_digest,
|
||||
value.storage_receipt_digest,
|
||||
)
|
||||
return canonical.ResolvedContent(content, receipt)
|
||||
|
||||
|
||||
def load_envelope(path: Path) -> dict[str, Any]:
|
||||
content = path.read_bytes()
|
||||
assert len(content) > 0
|
||||
row = obj(json.loads(content))
|
||||
assert row["schema_version"] == REPLAY_SCHEMA
|
||||
payload = {key: value for key, value in row.items() if key != "envelope_digest"}
|
||||
assert canonical.content_digest(_freeze(payload)) == row["envelope_digest"]
|
||||
return row
|
||||
|
||||
|
||||
def _freeze(value: object) -> canonical.JsonValue:
|
||||
if isinstance(value, list):
|
||||
return tuple(_freeze(item) for item in value)
|
||||
if isinstance(value, dict):
|
||||
return {key: _freeze(item) for key, item in value.items()}
|
||||
return cast(canonical.JsonValue, value)
|
||||
@@ -0,0 +1,130 @@
|
||||
"""Family-neutral evidence-record decoder for conformance replay."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from entry_fact_core_wire import location, obj, reference, seq
|
||||
|
||||
from openultrasast.core import evidence, provenance, semantics
|
||||
|
||||
|
||||
def node(value: object) -> semantics.SemanticNode:
|
||||
row = obj(value)
|
||||
return semantics.SemanticNode(row["node_id"], row["role"], location(row["location"]))
|
||||
|
||||
|
||||
def semantic_provenance(value: object) -> semantics.EvidenceProvenance:
|
||||
row = obj(value)
|
||||
fact_match = None if row["fact_match"] is None else reference(row["fact_match"])
|
||||
return semantics.EvidenceProvenance(
|
||||
semantics.ProvenanceKind(row["kind"]),
|
||||
row["source_content_digest"],
|
||||
row["semantic_pack_digest"],
|
||||
row["semantic_fact_id"],
|
||||
fact_match,
|
||||
)
|
||||
|
||||
|
||||
def relation(value: object) -> semantics.SemanticRelation:
|
||||
row = obj(value)
|
||||
return semantics.SemanticRelation(
|
||||
row["relation_id"],
|
||||
semantics.RelationKind(row["kind"]),
|
||||
row["role"],
|
||||
node(row["source"]),
|
||||
node(row["target"]),
|
||||
location(row["location"]),
|
||||
semantics.RelationStatus(row["status"]),
|
||||
tuple(seq(row["conditions"])),
|
||||
tuple(seq(row["reasons"])),
|
||||
semantic_provenance(row["provenance"]),
|
||||
)
|
||||
|
||||
|
||||
def field(value: object) -> semantics.FieldValue:
|
||||
row = obj(value)
|
||||
return semantics.FieldValue(row["name"], semantics.FieldKind(row["kind"]), row["value"])
|
||||
|
||||
|
||||
def observation(value: object) -> semantics.Observation:
|
||||
row = obj(value)
|
||||
return semantics.Observation(
|
||||
row["observation_id"],
|
||||
row["role"],
|
||||
location(row["location"]),
|
||||
tuple(field(item) for item in seq(row["fields"])),
|
||||
semantics.RelationStatus(row["status"]),
|
||||
semantic_provenance(row["provenance"]),
|
||||
)
|
||||
|
||||
|
||||
def scope(value: object) -> evidence.AnalyzedScope:
|
||||
row = obj(value)
|
||||
return evidence.AnalyzedScope(
|
||||
row["base_revision"],
|
||||
row["head_revision"],
|
||||
row["change_digest"],
|
||||
tuple(
|
||||
evidence.SourceRegion(item["path"], item["start_line"], item["end_line"]) for raw in seq(row["regions"]) for item in (obj(raw),)
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def stamp(value: object) -> provenance.ProvenanceStamp:
|
||||
row = obj(value)
|
||||
return provenance.ProvenanceStamp(
|
||||
row["analyzer_revision"],
|
||||
row["family_contract_digest"],
|
||||
row["fact_set_digest"],
|
||||
row["acquisition_record_digest"],
|
||||
row["configuration_digest"],
|
||||
row["population_digest"],
|
||||
row["change_input_digest"],
|
||||
)
|
||||
|
||||
|
||||
def packet(value: object) -> evidence.EvidencePacket:
|
||||
row = obj(value)
|
||||
return evidence.EvidencePacket(
|
||||
row["schema_version"],
|
||||
row["family_id"],
|
||||
row["family_contract_digest"],
|
||||
row["security_object_id"],
|
||||
row["ecosystem"],
|
||||
scope(row["scope"]),
|
||||
tuple(relation(item) for item in seq(row["transitions"])),
|
||||
tuple(observation(item) for item in seq(row["observations"])),
|
||||
tuple(field(item) for item in seq(row["family_fields"])),
|
||||
tuple(seq(row["completeness_reasons"])),
|
||||
stamp(row["provenance"]),
|
||||
)
|
||||
|
||||
|
||||
def decision_provenance(value: object) -> provenance.DecisionProvenance:
|
||||
row = obj(value)
|
||||
assert row["model_identity"] is None
|
||||
return provenance.DecisionProvenance(
|
||||
None,
|
||||
row["model_result_digest"],
|
||||
row["model_declaration_digest"],
|
||||
row["proof_record_digest"],
|
||||
row["proof_producer_digest"],
|
||||
row["lineage_manifest_digest"],
|
||||
)
|
||||
|
||||
|
||||
def decision(value: object) -> evidence.Decision:
|
||||
row = obj(value)
|
||||
return evidence.Decision(
|
||||
row["family_code"],
|
||||
evidence.NeutralOutcome(row["outcome"]),
|
||||
evidence.EvidenceBasis(row["basis"]),
|
||||
scope(row["bounded_scope"]),
|
||||
tuple(seq(row["reasons"])),
|
||||
row["packet_digest"],
|
||||
decision_provenance(row["provenance"]),
|
||||
)
|
||||
|
||||
|
||||
def record(value: object) -> evidence.EvidenceRecord:
|
||||
row = obj(value)
|
||||
return evidence.EvidenceRecord(packet(row["packet"]), decision(row["decision"]), row["record_id"])
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"location":{"column":0,"line":3,"path":"sources/complete.js","symbol":"app.get->adminHandler@sources/complete.js:4:9"},"observed":"app.get","requirement_id":"qualified_target","schema_version":"openultrasast.detection-core.structural-observation.v2"}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"location":{"column":0,"line":1,"path":"sources/name-only.js","symbol":"app.get->adminHandler@sources/name-only.js:2:9"},"observed":"app.get","requirement_id":"qualified_target","schema_version":"openultrasast.detection-core.structural-observation.v2"}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"location":{"column":0,"line":3,"path":"sources/partial.js","symbol":"app.get"},"observed":"express_application","requirement_id":"receiver","schema_version":"openultrasast.detection-core.structural-observation.v2"}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"authority_review":{"attestation_digest":"c07b5c22c2724b13dd34134b112c66ad9e2885e2e6947e23cde6245b3bbc9061","conflict_disclosure":{"artifact_id":"installed-entry-authority-conflicts-v1","byte_length":113,"content_digest":"a8bf581d321560f2730aae3d5a7c9114c2d8f81f7a702fa3681a87e7be4cb9e1","media_type":"application/json","retention_policy_digest":"09a0fe8a253780b3666ef016d575a212bf0570da392dd5bf1a834dce2edf703f","storage_receipt_digest":"ee92fde020e9b4d316ad285f3f904032c52d902fe1c7c0a94cb0d61d9c0136ce"},"producer_identity":"f12a7e897cbaf3059619517e1f8a725b90049a0edf3af08efa12fb1ef7fdee43","reviewer_identity":"f12a7e897cbaf3059619517e1f8a725b90049a0edf3af08efa12fb1ef7fdee43","subject_digest":"0fa8f607297aa5364a0ca6c9b8d47bfcdef28456b7f062ddb251f8f8b9a67da4"},"bundle_digest":"0fa8f607297aa5364a0ca6c9b8d47bfcdef28456b7f062ddb251f8f8b9a67da4","custody_policy":{"policy_digest":"415b1c13adc918c162932a38e79548a7d9867f5331860eb409238c51b1cca1f0","reviewed_custodian_digests":["4fe8ca2923ee759a24fd8e5b91673faa6859a7a0c2df6e7c7ea5e23968708632"]},"lineages":[{"arm_id":"installed-entry-facts:javascript","manifest_digest":"f3b4b192dadd6b7d0d298286008480dadfd8640e9603020b0f24d13dce9bda04","subject_digest":"331e8c2261cb030f4257a8650448560eb94941554df47cb275882e24b8f8923f","uses":[{"influenced_artifact_digest":"331e8c2261cb030f4257a8650448560eb94941554df47cb275882e24b8f8923f","labels_accessed":false,"population_use_receipt_digest":"36ccebd06b60601775ab24a2f7ec9f2b49c2eac6b273816eaf9e867f6c445915","purpose":"semantic_fact","source_population_digest":"0ec4bbe3712a691a76f6525aca59f15d0492adc1e7ec8d7e9bb42e8ee42795ce"}]},{"arm_id":"installed-entry-facts:typescript","manifest_digest":"b7a6a95ddcdd8f6e6dbcd2b90cb707eda9833ec7479cb4d7aae3c91cfe0059ca","subject_digest":"b6d1157e99537bd4928303ec0d887628bc53f0aa9e770427580a32e3948babd9","uses":[{"influenced_artifact_digest":"b6d1157e99537bd4928303ec0d887628bc53f0aa9e770427580a32e3948babd9","labels_accessed":false,"population_use_receipt_digest":"7dc5fe36b1e111ab6cf979137c40bf67b885b2a9deda944aff78e3031cb5a553","purpose":"semantic_fact","source_population_digest":"0ec4bbe3712a691a76f6525aca59f15d0492adc1e7ec8d7e9bb42e8ee42795ce"}]},{"arm_id":"installed-entry-structural-matcher","manifest_digest":"5f7ffd58a773b61d1f8e2ba0ca019e27d778166e13cec770e6f25c16b1f1a994","subject_digest":"0ad18521beeb3708e12f8c9941b3f29b3e1312fe78b9320e5aaf15bc9db8831a","uses":[{"influenced_artifact_digest":"0ad18521beeb3708e12f8c9941b3f29b3e1312fe78b9320e5aaf15bc9db8831a","labels_accessed":false,"population_use_receipt_digest":"a602c8bccc6afc2ff9d857119131a2847509bc693a80192bf8459b9dcba9cbda","purpose":"matching_behavior","source_population_digest":"0ec4bbe3712a691a76f6525aca59f15d0492adc1e7ec8d7e9bb42e8ee42795ce"}]}],"matcher_behavior_digest":"0ad18521beeb3708e12f8c9941b3f29b3e1312fe78b9320e5aaf15bc9db8831a","matcher_lineage_manifest_digest":"5f7ffd58a773b61d1f8e2ba0ca019e27d778166e13cec770e6f25c16b1f1a994","matcher_revision":"entry-structural-matcher-v1","pack_files":["express.javascript.v2.json","express.typescript.v2.json"],"recognition_projection":{"artifact_id":"express-recognition-projection-v1","byte_length":628,"content_digest":"529d18ba2b351a8de985a9cf416261d717ef55a4b7a9d9d65bce53b97d59ab35","media_type":"application/json","retention_policy_digest":"09a0fe8a253780b3666ef016d575a212bf0570da392dd5bf1a834dce2edf703f","storage_receipt_digest":"3a85c0641cddcfc8c926fd01e230360c042606bda78e14a39489de14f88944b4"},"review_policy":{"forbidden_identity_pairs":[],"maximum_evidence_bytes":1048576,"policy_digest":"cb023a4f7e727ec4abfee583256194fe3f11c064a10960f297c1f7bf2e6fecde","reviewed_reviewer_digests":["f12a7e897cbaf3059619517e1f8a725b90049a0edf3af08efa12fb1ef7fdee43"],"trusted_store_identities":["openultrasast-installed-entry-artifacts-v1"]},"schema_version":"openultrasast.access-control.installed-entry-authority.v1"}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"fact_id":"entry:express:app-route:get","matcher_behavior_digest":"0ad18521beeb3708e12f8c9941b3f29b3e1312fe78b9320e5aaf15bc9db8831a","matcher_lineage_manifest_digest":"5f7ffd58a773b61d1f8e2ba0ca019e27d778166e13cec770e6f25c16b1f1a994","matcher_revision":"entry-structural-matcher-v1","observations":[{"evidence":{"artifact_id":"structural-observation:0494c5e2973965bbfc12cee1db3971cfa700a41d9b5e11309d45eb529837d556","byte_length":253,"content_digest":"0494c5e2973965bbfc12cee1db3971cfa700a41d9b5e11309d45eb529837d556","media_type":"application/json","retention_policy_digest":"445c538acfffe5dde50f57bc699da2732e237207f0953c59dd8559f66c1a6708","storage_receipt_digest":"d364b9ac443e85a5cf7f4de2bea24f0a5d16719ede85486ef93800ac99702267"},"location":{"column":0,"line":1,"path":"sources/name-only.js","symbol":"app.get->adminHandler@sources/name-only.js:2:9"},"observed":"app.get","requirement_id":"qualified_target"},{"evidence":{"artifact_id":"structural-observation:60fe67b0d61dbfcedf97ce1470219bdb7b8cc5590c04d90401fede5bcd6e9064","byte_length":251,"content_digest":"60fe67b0d61dbfcedf97ce1470219bdb7b8cc5590c04d90401fede5bcd6e9064","media_type":"application/json","retention_policy_digest":"445c538acfffe5dde50f57bc699da2732e237207f0953c59dd8559f66c1a6708","storage_receipt_digest":"305af51d6f3af6440f732ddcb13971c2ffe9f3327452915ca126061eb08c896b"},"location":{"column":0,"line":1,"path":"sources/name-only.js","symbol":"app.get->adminHandler@sources/name-only.js:2:9"},"observed":"member_call","requirement_id":"call_shape"},{"evidence":{"artifact_id":"structural-observation:aba7fbac17cbc9095715999b1584daa07cf20552ea17c0b71948890aa88e9ece","byte_length":261,"content_digest":"aba7fbac17cbc9095715999b1584daa07cf20552ea17c0b71948890aa88e9ece","media_type":"application/json","retention_policy_digest":"445c538acfffe5dde50f57bc699da2732e237207f0953c59dd8559f66c1a6708","storage_receipt_digest":"c36686f481771721e444b10f632990f18951f4cdef1e0c0d02e5a3325b19c6d5"},"location":{"column":0,"line":1,"path":"sources/name-only.js","symbol":"app.get->adminHandler@sources/name-only.js:2:9"},"observed":"route_path_and_handler","requirement_id":"arguments"}],"pack_digest":"331e8c2261cb030f4257a8650448560eb94941554df47cb275882e24b8f8923f","product_location":{"column":0,"line":1,"path":"sources/name-only.js","symbol":"app.get->adminHandler@sources/name-only.js:2:9"},"schema_version":"openultrasast.detection-core.fact-match.v2"}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"decision":{"basis":"deterministic","bounded_scope":{"base_revision":"base","change_digest":"531bb28a24082947325ef7b3108f5586a4e8187dbf094409be514d6510bb9f27","head_revision":"head","regions":[{"end_line":4,"path":"sources/complete.js","start_line":1}]},"family_code":"indeterminate","outcome":"indeterminate","packet_digest":"9d2e3db2b44ba56d5f017a5deab969abe8603aa9f3c6908d5412d2939432a235","provenance":{"lineage_manifest_digest":null,"model_declaration_digest":null,"model_identity":null,"model_result_digest":null,"proof_producer_digest":null,"proof_record_digest":null},"reasons":["missing_constraint_relation"]},"packet":{"completeness_reasons":["missing_constraint_relation"],"ecosystem":"express","family_contract_digest":"d3aea166bdad9186843b78ce1e3a6a4c135473f3d918ff580b096dbed61c787a","family_fields":[{"kind":"text","name":"operation","value":"entry-registration"},{"kind":"text","name":"boundary","value":"express"}],"family_id":"access_control","observations":[],"provenance":{"acquisition_record_digest":"f978265cdc2549cc1c5b2c757bb41934a467ddc9a042a10d1af67acd5bc6905a","analyzer_revision":"dc2816e78d1aca97801ab5a22fb316ae6c354a6e65260ade31ebcbbfa83f9fc0","change_input_digest":"531bb28a24082947325ef7b3108f5586a4e8187dbf094409be514d6510bb9f27","configuration_digest":"3f167eebbd83522e30a8258e23a2b7bf3761880276a05965b0865c8f766b6214","fact_set_digest":"7438561f434fb5999d22aaccae44813d3d7c7cbff588a37cc497bb846c93bc75","family_contract_digest":"d3aea166bdad9186843b78ce1e3a6a4c135473f3d918ff580b096dbed61c787a","population_digest":"c03e2c11dd18a4a5ada83492740946ed9e1ff1201ded765e9e2c75d34a445fce"},"schema_version":"openultrasast.detection-core.evidence-packet.v2","scope":{"base_revision":"base","change_digest":"531bb28a24082947325ef7b3108f5586a4e8187dbf094409be514d6510bb9f27","head_revision":"head","regions":[{"end_line":4,"path":"sources/complete.js","start_line":1}]},"security_object_id":"33bf0ef7a2efd0c79d89da501e49fe2f44a57931a0252bd95783bf9237256b6a","transitions":[{"conditions":[],"kind":"registration","location":{"column":0,"line":3,"path":"sources/complete.js","symbol":"app.get->adminHandler@sources/complete.js:4:9"},"provenance":{"fact_match":{"artifact_id":"fact-match:db111c965603bb4cf9d83ba07b0e22a57a537ba6a05448158ef7d7615efb18d3","byte_length":3037,"content_digest":"db111c965603bb4cf9d83ba07b0e22a57a537ba6a05448158ef7d7615efb18d3","media_type":"application/json","retention_policy_digest":"445c538acfffe5dde50f57bc699da2732e237207f0953c59dd8559f66c1a6708","storage_receipt_digest":"cd74cb0a824a618a2ae3f822e9988bb5703fdafc41e41e88bf941b71a31fd602"},"kind":"semantic_fact","semantic_fact_id":"entry:express:app-route:get","semantic_pack_digest":"331e8c2261cb030f4257a8650448560eb94941554df47cb275882e24b8f8923f","source_content_digest":"db111c965603bb4cf9d83ba07b0e22a57a537ba6a05448158ef7d7615efb18d3"},"reasons":[],"relation_id":"89785eb0e81e26cab8dbdb8c029290d46f47cae9454f21cf07f6a8157d279f8c","role":"entry_registration","source":{"location":{"column":0,"line":3,"path":"sources/complete.js","symbol":"app.get->adminHandler@sources/complete.js:4:9"},"node_id":"3dbe3056740381221072862da39a5d10c3502ee776445560efcd27c54091fe29","role":"framework_instance"},"status":"complete","target":{"location":{"column":0,"line":3,"path":"sources/complete.js","symbol":"app.get->adminHandler@sources/complete.js:4:9"},"node_id":"f17ecafe6356afc2325229cc686f3953e3bcbf8d37d9c5a24cc300ff43829547","role":"entry_handler"}},{"conditions":[],"kind":"constraint_effect","location":{"column":0,"line":3,"path":"sources/complete.js","symbol":"app.get->adminHandler@sources/complete.js:4:9"},"provenance":{"fact_match":null,"kind":"product_code","semantic_fact_id":null,"semantic_pack_digest":null,"source_content_digest":"531bb28a24082947325ef7b3108f5586a4e8187dbf094409be514d6510bb9f27"},"reasons":["missing_constraint_relation"],"relation_id":"ac7cedfbee67ec3f24eefa0fe0cc88076367eb70873345f37f1b3f1ceb30712a","role":"constraint","source":{"location":{"column":0,"line":3,"path":"sources/complete.js","symbol":"app.get->adminHandler@sources/complete.js:4:9"},"node_id":"constraint-source","role":"security_object"},"status":"incomplete","target":{"location":{"column":0,"line":3,"path":"sources/complete.js","symbol":"app.get->adminHandler@sources/complete.js:4:9"},"node_id":"constraint-target","role":"operation"}}]},"schema_version":"openultrasast.detection-core.evidence-record.v2"}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"location":{"column":0,"line":3,"path":"sources/partial.js","symbol":"app.get"},"observed":"app.get","requirement_id":"qualified_target","schema_version":"openultrasast.detection-core.structural-observation.v2"}
|
||||
+1
File diff suppressed because one or more lines are too long
+1
@@ -0,0 +1 @@
|
||||
{"location":{"column":0,"line":1,"path":"sources/name-only.js","symbol":"app.get->adminHandler@sources/name-only.js:2:9"},"observed":"member_call","requirement_id":"call_shape","schema_version":"openultrasast.detection-core.structural-observation.v2"}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"authority_review":{"attestation_digest":"aeeb9120c10d8bf83159a9cbd14ad8a070a0ceb99a53b5a1daa616a315c84b55","conflict_disclosure":{"artifact_id":"installed-entry-authority-conflicts-v1","byte_length":113,"content_digest":"a8bf581d321560f2730aae3d5a7c9114c2d8f81f7a702fa3681a87e7be4cb9e1","media_type":"application/json","retention_policy_digest":"09a0fe8a253780b3666ef016d575a212bf0570da392dd5bf1a834dce2edf703f","storage_receipt_digest":"ee92fde020e9b4d316ad285f3f904032c52d902fe1c7c0a94cb0d61d9c0136ce"},"producer_identity":"9635025424be37e1615e597185a425a5443242fa210d6136c38250101088e7b4","reviewer_identity":"f12a7e897cbaf3059619517e1f8a725b90049a0edf3af08efa12fb1ef7fdee43","subject_digest":"0fa8f607297aa5364a0ca6c9b8d47bfcdef28456b7f062ddb251f8f8b9a67da4"},"bundle_digest":"0000000000000000000000000000000000000000000000000000000000000000","custody_policy":{"policy_digest":"415b1c13adc918c162932a38e79548a7d9867f5331860eb409238c51b1cca1f0","reviewed_custodian_digests":["4fe8ca2923ee759a24fd8e5b91673faa6859a7a0c2df6e7c7ea5e23968708632"]},"lineages":[{"arm_id":"installed-entry-facts:javascript","manifest_digest":"f3b4b192dadd6b7d0d298286008480dadfd8640e9603020b0f24d13dce9bda04","subject_digest":"331e8c2261cb030f4257a8650448560eb94941554df47cb275882e24b8f8923f","uses":[{"influenced_artifact_digest":"331e8c2261cb030f4257a8650448560eb94941554df47cb275882e24b8f8923f","labels_accessed":false,"population_use_receipt_digest":"36ccebd06b60601775ab24a2f7ec9f2b49c2eac6b273816eaf9e867f6c445915","purpose":"semantic_fact","source_population_digest":"0ec4bbe3712a691a76f6525aca59f15d0492adc1e7ec8d7e9bb42e8ee42795ce"}]},{"arm_id":"installed-entry-facts:typescript","manifest_digest":"b7a6a95ddcdd8f6e6dbcd2b90cb707eda9833ec7479cb4d7aae3c91cfe0059ca","subject_digest":"b6d1157e99537bd4928303ec0d887628bc53f0aa9e770427580a32e3948babd9","uses":[{"influenced_artifact_digest":"b6d1157e99537bd4928303ec0d887628bc53f0aa9e770427580a32e3948babd9","labels_accessed":false,"population_use_receipt_digest":"7dc5fe36b1e111ab6cf979137c40bf67b885b2a9deda944aff78e3031cb5a553","purpose":"semantic_fact","source_population_digest":"0ec4bbe3712a691a76f6525aca59f15d0492adc1e7ec8d7e9bb42e8ee42795ce"}]},{"arm_id":"installed-entry-structural-matcher","manifest_digest":"5f7ffd58a773b61d1f8e2ba0ca019e27d778166e13cec770e6f25c16b1f1a994","subject_digest":"0ad18521beeb3708e12f8c9941b3f29b3e1312fe78b9320e5aaf15bc9db8831a","uses":[{"influenced_artifact_digest":"0ad18521beeb3708e12f8c9941b3f29b3e1312fe78b9320e5aaf15bc9db8831a","labels_accessed":false,"population_use_receipt_digest":"a602c8bccc6afc2ff9d857119131a2847509bc693a80192bf8459b9dcba9cbda","purpose":"matching_behavior","source_population_digest":"0ec4bbe3712a691a76f6525aca59f15d0492adc1e7ec8d7e9bb42e8ee42795ce"}]}],"matcher_behavior_digest":"0ad18521beeb3708e12f8c9941b3f29b3e1312fe78b9320e5aaf15bc9db8831a","matcher_lineage_manifest_digest":"5f7ffd58a773b61d1f8e2ba0ca019e27d778166e13cec770e6f25c16b1f1a994","matcher_revision":"entry-structural-matcher-v1","pack_files":["express.javascript.v2.json","express.typescript.v2.json"],"recognition_projection":{"artifact_id":"express-recognition-projection-v1","byte_length":628,"content_digest":"529d18ba2b351a8de985a9cf416261d717ef55a4b7a9d9d65bce53b97d59ab35","media_type":"application/json","retention_policy_digest":"09a0fe8a253780b3666ef016d575a212bf0570da392dd5bf1a834dce2edf703f","storage_receipt_digest":"3a85c0641cddcfc8c926fd01e230360c042606bda78e14a39489de14f88944b4"},"review_policy":{"forbidden_identity_pairs":[],"maximum_evidence_bytes":1048576,"policy_digest":"cb023a4f7e727ec4abfee583256194fe3f11c064a10960f297c1f7bf2e6fecde","reviewed_reviewer_digests":["f12a7e897cbaf3059619517e1f8a725b90049a0edf3af08efa12fb1ef7fdee43"],"trusted_store_identities":["openultrasast-installed-entry-artifacts-v1"]},"schema_version":"openultrasast.access-control.installed-entry-authority.v1"}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"location":{"column":0,"line":3,"path":"sources/complete.js","symbol":"app.get->adminHandler@sources/complete.js:4:9"},"observed":"express_application","requirement_id":"receiver","schema_version":"openultrasast.detection-core.structural-observation.v2"}
|
||||
+1
File diff suppressed because one or more lines are too long
+1
@@ -0,0 +1 @@
|
||||
{"location":{"column":0,"line":3,"path":"sources/partial.js","symbol":"app.get"},"observed":"member_call","requirement_id":"call_shape","schema_version":"openultrasast.detection-core.structural-observation.v2"}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"location":{"column":0,"line":3,"path":"sources/complete.js","symbol":"app.get->adminHandler@sources/complete.js:4:9"},"observed":"route_path_and_handler","requirement_id":"arguments","schema_version":"openultrasast.detection-core.structural-observation.v2"}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"fact_id":"entry:express:app-route:get","matcher_behavior_digest":"0ad18521beeb3708e12f8c9941b3f29b3e1312fe78b9320e5aaf15bc9db8831a","matcher_lineage_manifest_digest":"5f7ffd58a773b61d1f8e2ba0ca019e27d778166e13cec770e6f25c16b1f1a994","matcher_revision":"entry-structural-matcher-v1","observations":[{"evidence":{"artifact_id":"structural-observation:4b657ac957f89e41f34c179e7519cba950f92c09b6410fbf713a16ec06eff43f","byte_length":212,"content_digest":"4b657ac957f89e41f34c179e7519cba950f92c09b6410fbf713a16ec06eff43f","media_type":"application/json","retention_policy_digest":"445c538acfffe5dde50f57bc699da2732e237207f0953c59dd8559f66c1a6708","storage_receipt_digest":"e2c2971b375d018688a4aa7e1d86907d732a6eaac6649f397b92ec6896ddd3ea"},"location":{"column":0,"line":3,"path":"sources/partial.js","symbol":"app.get"},"observed":"app.get","requirement_id":"qualified_target"},{"evidence":{"artifact_id":"structural-observation:752f84618a299286bd5a9fdd1513dc40c05b6649a2ff0a81b23175001560d490","byte_length":210,"content_digest":"752f84618a299286bd5a9fdd1513dc40c05b6649a2ff0a81b23175001560d490","media_type":"application/json","retention_policy_digest":"445c538acfffe5dde50f57bc699da2732e237207f0953c59dd8559f66c1a6708","storage_receipt_digest":"3b5f35240b90c610f28d093ad4ce49908e3650335d41ae7ae7e1b02c3eafe415"},"location":{"column":0,"line":3,"path":"sources/partial.js","symbol":"app.get"},"observed":"member_call","requirement_id":"call_shape"},{"evidence":{"artifact_id":"structural-observation:0acf81eaebbf1c67bef9d93fe7aaf061c85494cd124d1338727c230ba91cc4bd","byte_length":216,"content_digest":"0acf81eaebbf1c67bef9d93fe7aaf061c85494cd124d1338727c230ba91cc4bd","media_type":"application/json","retention_policy_digest":"445c538acfffe5dde50f57bc699da2732e237207f0953c59dd8559f66c1a6708","storage_receipt_digest":"c1ab8ae696194ecf29c8af32cbd1f8649eceff8ab5106cae75881994a06e843e"},"location":{"column":0,"line":3,"path":"sources/partial.js","symbol":"app.get"},"observed":"express_application","requirement_id":"receiver"}],"pack_digest":"331e8c2261cb030f4257a8650448560eb94941554df47cb275882e24b8f8923f","product_location":{"column":0,"line":3,"path":"sources/partial.js","symbol":"app.get"},"schema_version":"openultrasast.detection-core.fact-match.v2"}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"conflicts":[],"resolved":true,"schema_version":"openultrasast.access-control.authority-conflict-disclosure.v1"}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"location":{"column":0,"line":1,"path":"sources/name-only.js","symbol":"app.get->adminHandler@sources/name-only.js:2:9"},"observed":"route_path_and_handler","requirement_id":"arguments","schema_version":"openultrasast.detection-core.structural-observation.v2"}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"fact_id":"entry:express:app-route:get","matcher_behavior_digest":"0ad18521beeb3708e12f8c9941b3f29b3e1312fe78b9320e5aaf15bc9db8831a","matcher_lineage_manifest_digest":"5f7ffd58a773b61d1f8e2ba0ca019e27d778166e13cec770e6f25c16b1f1a994","matcher_revision":"entry-structural-matcher-v1","observations":[{"evidence":{"artifact_id":"structural-observation:02b8aa4884cb356afa9ba7960fee55f5d9a15f0e4b73fbc3573d85622d0defa9","byte_length":251,"content_digest":"02b8aa4884cb356afa9ba7960fee55f5d9a15f0e4b73fbc3573d85622d0defa9","media_type":"application/json","retention_policy_digest":"445c538acfffe5dde50f57bc699da2732e237207f0953c59dd8559f66c1a6708","storage_receipt_digest":"993681396623b12e3d9b6060c056b60c86e3027554ebe6eb403c6ec9ccb28142"},"location":{"column":0,"line":3,"path":"sources/complete.js","symbol":"app.get->adminHandler@sources/complete.js:4:9"},"observed":"app.get","requirement_id":"qualified_target"},{"evidence":{"artifact_id":"structural-observation:fc13dbdeea6d0909956de97eac4e2229a784e7cd76a51ab4fcc6db5151da6831","byte_length":249,"content_digest":"fc13dbdeea6d0909956de97eac4e2229a784e7cd76a51ab4fcc6db5151da6831","media_type":"application/json","retention_policy_digest":"445c538acfffe5dde50f57bc699da2732e237207f0953c59dd8559f66c1a6708","storage_receipt_digest":"7af07572d53abac371dbc1c5970ad5324ab23f1ef5744eeab7e3621b9f2c3f59"},"location":{"column":0,"line":3,"path":"sources/complete.js","symbol":"app.get->adminHandler@sources/complete.js:4:9"},"observed":"member_call","requirement_id":"call_shape"},{"evidence":{"artifact_id":"structural-observation:6c750f6128bd698bb27dd6db5e1260995cac678261ce2734cbf048c7b33e9b12","byte_length":255,"content_digest":"6c750f6128bd698bb27dd6db5e1260995cac678261ce2734cbf048c7b33e9b12","media_type":"application/json","retention_policy_digest":"445c538acfffe5dde50f57bc699da2732e237207f0953c59dd8559f66c1a6708","storage_receipt_digest":"a7ab3b129c07dedd077d877a3bc189b86f2da852a2b340c3496c1b729465002d"},"location":{"column":0,"line":3,"path":"sources/complete.js","symbol":"app.get->adminHandler@sources/complete.js:4:9"},"observed":"express_application","requirement_id":"receiver"},{"evidence":{"artifact_id":"structural-observation:88a8b08604bb7db69ccfc50af54701e4ab41044db5eb61cb812881a60e1b6370","byte_length":259,"content_digest":"88a8b08604bb7db69ccfc50af54701e4ab41044db5eb61cb812881a60e1b6370","media_type":"application/json","retention_policy_digest":"445c538acfffe5dde50f57bc699da2732e237207f0953c59dd8559f66c1a6708","storage_receipt_digest":"c2eec061e981fccdea378bf097a53b75de44916cd1bc908d899345cc30229bd5"},"location":{"column":0,"line":3,"path":"sources/complete.js","symbol":"app.get->adminHandler@sources/complete.js:4:9"},"observed":"route_path_and_handler","requirement_id":"arguments"}],"pack_digest":"331e8c2261cb030f4257a8650448560eb94941554df47cb275882e24b8f8923f","product_location":{"column":0,"line":3,"path":"sources/complete.js","symbol":"app.get->adminHandler@sources/complete.js:4:9"},"schema_version":"openultrasast.detection-core.fact-match.v2"}
|
||||
+1
@@ -0,0 +1 @@
|
||||
!"location":{"column":0,"line":3,"path":"sources/complete.js","symbol":"app.get->adminHandler@sources/complete.js:4:9"},"observed":"app.get","requirement_id":"qualified_target","schema_version":"openultrasast.detection-core.structural-observation.v2"}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"facts": [
|
||||
{
|
||||
"defines_handler": true,
|
||||
"handler_kind": "route",
|
||||
"id": "entry:express:app-route",
|
||||
"pattern": "app.(get|post|put|delete|patch|all|use)\\s*\\("
|
||||
},
|
||||
{
|
||||
"defines_handler": true,
|
||||
"handler_kind": "route",
|
||||
"id": "entry:express:router-route",
|
||||
"pattern": "router.(get|post|put|delete|patch|all|use)\\s*\\("
|
||||
},
|
||||
{
|
||||
"defines_handler": false,
|
||||
"handler_kind": "app",
|
||||
"id": "entry:express:express-app",
|
||||
"pattern": "express\\s*\\(\\s*\\)"
|
||||
}
|
||||
],
|
||||
"family": "access_control",
|
||||
"framework": "express",
|
||||
"kind": "entry_facts",
|
||||
"languages": [
|
||||
"javascript",
|
||||
"typescript"
|
||||
],
|
||||
"review": {
|
||||
"digest": "47866e5c15b286d7107b101bd396f78bbbda23788085676c590c3af937085e00",
|
||||
"note": "Reviewed against Express 4/5 routing docs and the pilot pool's manifest-level framework usage (2026-10-30 recognition table). Entry patterns only; no sinks, no labels."
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"location":{"column":0,"line":3,"path":"sources/complete.js","symbol":"app.get->adminHandler@sources/complete.js:4:9"},"observed":"member_call","requirement_id":"call_shape","schema_version":"openultrasast.detection-core.structural-observation.v2"}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,4 @@
|
||||
import express from "express";
|
||||
const app = express();
|
||||
app.get("/admin", adminHandler);
|
||||
function adminHandler(req, res) { res.sendStatus(204); }
|
||||
@@ -0,0 +1,2 @@
|
||||
// Legacy recognition text only: app.get("/admin", adminHandler)
|
||||
export const marker = "not a structural registration";
|
||||
@@ -0,0 +1,2 @@
|
||||
app.get("/admin", adminHandler);
|
||||
function adminHandler(req, res) { res.sendStatus(204); }
|
||||
@@ -0,0 +1,3 @@
|
||||
import express from "express";
|
||||
const app = express();
|
||||
app.get("/admin");
|
||||
@@ -0,0 +1,377 @@
|
||||
"""Immutable downstream conformance handoff for detection-core Task 9.4."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from openultrasast.core import canonical
|
||||
from openultrasast.mapping.entry_fact_conformance import (
|
||||
ENTRY_FACT_CONFORMANCE_SCHEMA,
|
||||
EntryFactConformanceError,
|
||||
build_entry_fact_conformance,
|
||||
write_entry_fact_conformance,
|
||||
)
|
||||
from openultrasast.mapping.entry_fact_conformance_manifest import validate_entry_fact_conformance
|
||||
|
||||
FIXTURE_ROOT = Path(__file__).parent / "fixtures" / "access_control" / "conformance" / "v1"
|
||||
EXPECTED_CASES = {
|
||||
"complete",
|
||||
"name_only",
|
||||
"partial",
|
||||
"authority_substitution",
|
||||
"producer_reviewer_conflict",
|
||||
"resolver_byte_substitution",
|
||||
"lineage_omission",
|
||||
"custody_contamination",
|
||||
"legacy_projection_only",
|
||||
"deterministic_replay",
|
||||
}
|
||||
EXPECTED_VALIDATORS = {
|
||||
"openultrasast.core.factpack.validate_fact_pack",
|
||||
"openultrasast.core.factmatch.validate_fact_match",
|
||||
"openultrasast.core.factapply.apply_fact",
|
||||
"openultrasast.core.factvalidate.validate_fact_relations",
|
||||
}
|
||||
|
||||
|
||||
def _freeze(value: object) -> object:
|
||||
if isinstance(value, list):
|
||||
return tuple(_freeze(item) for item in value)
|
||||
if isinstance(value, dict):
|
||||
return {key: _freeze(item) for key, item in value.items()}
|
||||
return value
|
||||
|
||||
|
||||
def _parsed(content: bytes) -> dict[str, object]:
|
||||
parsed = json.loads(content)
|
||||
assert isinstance(parsed, dict)
|
||||
assert (
|
||||
canonical.canonical_record_bytes(
|
||||
_freeze(parsed),
|
||||
known_schema_versions=(ENTRY_FACT_CONFORMANCE_SCHEMA,),
|
||||
)
|
||||
== content
|
||||
)
|
||||
return parsed
|
||||
|
||||
|
||||
def _assert_materialized(cases: list[dict[str, object]], root: Path) -> None:
|
||||
for case in cases:
|
||||
content = (FIXTURE_ROOT / case["fixture_path"]).read_bytes()
|
||||
assert len(content) == case["fixture_byte_length"] > 0
|
||||
assert canonical.bytes_digest(content) == case["fixture_digest"]
|
||||
assert case["validators"]
|
||||
for artifact in case["artifacts"]:
|
||||
artifact_content = (root / artifact["path"]).read_bytes()
|
||||
assert len(artifact_content) == artifact["byte_length"] > 0
|
||||
assert canonical.bytes_digest(artifact_content) == artifact["content_digest"]
|
||||
declared = {artifact["path"] for case in cases for artifact in case["artifacts"]}
|
||||
materialized = {path.relative_to(root).as_posix() for path in (root / "artifacts" / "sha256").iterdir()}
|
||||
assert declared == materialized
|
||||
|
||||
|
||||
def _assert_downstream_results(cases: list[dict[str, object]]) -> None:
|
||||
authority = next(case for case in cases if case["case_id"] == "authority_substitution")
|
||||
conflict = next(case for case in cases if case["case_id"] == "producer_reviewer_conflict")
|
||||
name = "openultrasast.mapping.fact_authority.authenticate_entry_fact_authority"
|
||||
assert authority["downstream_validators"] == [{"name": name, "status": "refused", "reason": "authority_bundle_digest_substituted"}]
|
||||
assert conflict["downstream_validators"] == [{"name": name, "status": "refused", "reason": "producer_reviewer_conflict"}]
|
||||
excluded = {"authority_substitution", "producer_reviewer_conflict"}
|
||||
assert all(not case["downstream_validators"] for case in cases if case["case_id"] not in excluded)
|
||||
|
||||
|
||||
def test_handoff_is_canonical_complete_and_reproducible(tmp_path: Path) -> None:
|
||||
first = build_entry_fact_conformance(FIXTURE_ROOT, tmp_path / "first")
|
||||
second = build_entry_fact_conformance(FIXTURE_ROOT, tmp_path / "second")
|
||||
|
||||
assert first == second
|
||||
manifest = _parsed(first)
|
||||
assert set(manifest) == {
|
||||
"schema_version",
|
||||
"handoff_digest",
|
||||
"core_entry_points",
|
||||
"cases",
|
||||
}
|
||||
assert set(manifest["core_entry_points"]) == EXPECTED_VALIDATORS
|
||||
cases = manifest["cases"]
|
||||
assert isinstance(cases, list)
|
||||
assert {case["case_id"] for case in cases} == EXPECTED_CASES
|
||||
assert (
|
||||
canonical.content_digest(
|
||||
{
|
||||
"schema_version": manifest["schema_version"],
|
||||
"core_entry_points": tuple(manifest["core_entry_points"]),
|
||||
"cases": _freeze(cases),
|
||||
}
|
||||
)
|
||||
== manifest["handoff_digest"]
|
||||
)
|
||||
_assert_materialized(cases, tmp_path / "first")
|
||||
complete = next(case for case in cases if case["case_id"] == "complete")
|
||||
assert {row["name"] for row in complete["validators"]} == EXPECTED_VALIDATORS
|
||||
assert {row["status"] for row in complete["validators"]} == {"passed"}
|
||||
assert complete["reason"] is None
|
||||
_assert_downstream_results(cases)
|
||||
refused = [case for case in cases if case["case_id"] not in {"complete", "deterministic_replay"}]
|
||||
assert all(case["expected_status"] == "refused" and case["reason"] for case in refused)
|
||||
|
||||
|
||||
def test_checked_in_handoff_equals_fresh_generation(tmp_path: Path) -> None:
|
||||
generated = write_entry_fact_conformance(FIXTURE_ROOT, tmp_path / "fresh")
|
||||
checked_in = FIXTURE_ROOT / "manifest.json"
|
||||
|
||||
assert generated.read_bytes() == checked_in.read_bytes()
|
||||
validate_entry_fact_conformance(checked_in.read_bytes(), FIXTURE_ROOT)
|
||||
manifest = _parsed(checked_in.read_bytes())
|
||||
declared = {artifact["path"] for case in manifest["cases"] for artifact in case["artifacts"]}
|
||||
materialized = {path.relative_to(FIXTURE_ROOT).as_posix() for path in (FIXTURE_ROOT / "artifacts" / "sha256").iterdir()}
|
||||
assert declared == materialized
|
||||
|
||||
|
||||
def test_manifest_refuses_open_schema_and_digest_substitution(tmp_path: Path) -> None:
|
||||
content = build_entry_fact_conformance(FIXTURE_ROOT, tmp_path / "output")
|
||||
manifest = json.loads(content)
|
||||
manifest["cases"][0]["artifacts"][0]["unexpected"] = True
|
||||
opened = canonical.canonical_record_bytes(
|
||||
_freeze(manifest),
|
||||
known_schema_versions=(ENTRY_FACT_CONFORMANCE_SCHEMA,),
|
||||
)
|
||||
with pytest.raises(EntryFactConformanceError, match="unknown or missing fields"):
|
||||
validate_entry_fact_conformance(opened)
|
||||
|
||||
manifest = json.loads(content)
|
||||
manifest["handoff_digest"] = "0" * 64
|
||||
substituted = canonical.canonical_record_bytes(
|
||||
_freeze(manifest),
|
||||
known_schema_versions=(ENTRY_FACT_CONFORMANCE_SCHEMA,),
|
||||
)
|
||||
with pytest.raises(EntryFactConformanceError, match="cannot be re-derived"):
|
||||
validate_entry_fact_conformance(substituted)
|
||||
|
||||
|
||||
def test_manifest_refuses_bogus_entry_point_and_fabricated_case_result(tmp_path: Path) -> None:
|
||||
content = build_entry_fact_conformance(FIXTURE_ROOT, tmp_path / "output")
|
||||
|
||||
def redigest(manifest: dict[str, object]) -> bytes:
|
||||
manifest["handoff_digest"] = canonical.content_digest(
|
||||
{
|
||||
"schema_version": manifest["schema_version"],
|
||||
"core_entry_points": tuple(manifest["core_entry_points"]),
|
||||
"cases": _freeze(manifest["cases"]),
|
||||
}
|
||||
)
|
||||
return canonical.canonical_record_bytes(_freeze(manifest), known_schema_versions=(ENTRY_FACT_CONFORMANCE_SCHEMA,))
|
||||
|
||||
bogus = json.loads(content)
|
||||
bogus["core_entry_points"][0] = "openultrasast.core.fake.accept_everything"
|
||||
with pytest.raises(EntryFactConformanceError, match="exact replay set"):
|
||||
validate_entry_fact_conformance(redigest(bogus))
|
||||
|
||||
fabricated = json.loads(content)
|
||||
complete = next(case for case in fabricated["cases"] if case["case_id"] == "complete")
|
||||
complete["expected_status"] = "refused"
|
||||
complete["reason"] = "fabricated"
|
||||
complete["validators"][0]["status"] = "refused"
|
||||
complete["validators"][0]["reason"] = "fabricated"
|
||||
with pytest.raises(EntryFactConformanceError, match="matrix|enclosing case"):
|
||||
validate_entry_fact_conformance(redigest(fabricated))
|
||||
|
||||
downstream = json.loads(content)
|
||||
authority = next(case for case in downstream["cases"] if case["case_id"] == "authority_substitution")
|
||||
authority["downstream_validators"][0]["reason"] = "fabricated"
|
||||
with pytest.raises(EntryFactConformanceError, match="downstream validator matrix"):
|
||||
validate_entry_fact_conformance(redigest(downstream))
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mutation", ("extra", "extra_directory", "missing", "non_file"))
|
||||
def test_manifest_requires_exact_regular_source_census(tmp_path: Path, mutation: str) -> None:
|
||||
root = tmp_path / mutation
|
||||
shutil.copytree(FIXTURE_ROOT, root)
|
||||
if mutation == "extra":
|
||||
(root / "sources" / "undeclared.js").write_text("export const extra = true;\n", encoding="utf-8")
|
||||
elif mutation == "extra_directory":
|
||||
(root / "sources" / "undeclared").mkdir()
|
||||
elif mutation == "missing":
|
||||
(root / "sources" / "partial.js").unlink()
|
||||
else:
|
||||
target = root / "sources" / "partial.js"
|
||||
target.unlink()
|
||||
target.mkdir()
|
||||
|
||||
with pytest.raises(EntryFactConformanceError, match="source filesystem census"):
|
||||
validate_entry_fact_conformance((root / "manifest.json").read_bytes(), root)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("declared", (False, True))
|
||||
def test_manifest_refuses_source_symlinks(tmp_path: Path, declared: bool) -> None:
|
||||
root = tmp_path / "source-symlink"
|
||||
shutil.copytree(FIXTURE_ROOT, root)
|
||||
external = tmp_path / "external.js"
|
||||
external.write_bytes((root / "sources" / "partial.js").read_bytes())
|
||||
target = root / "sources" / ("partial.js" if declared else "undeclared.js")
|
||||
if declared:
|
||||
target.unlink()
|
||||
os.symlink(external, target)
|
||||
|
||||
with pytest.raises(EntryFactConformanceError, match="source filesystem census"):
|
||||
validate_entry_fact_conformance((root / "manifest.json").read_bytes(), root)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("entry_kind", ("directory", "symlink"))
|
||||
def test_manifest_refuses_extra_artifact_entries(tmp_path: Path, entry_kind: str) -> None:
|
||||
root = tmp_path / "artifact-entry"
|
||||
shutil.copytree(FIXTURE_ROOT, root)
|
||||
target = root / "artifacts" / "sha256" / "unexpected"
|
||||
if entry_kind == "directory":
|
||||
target.mkdir()
|
||||
else:
|
||||
external = tmp_path / "external-artifact"
|
||||
external.write_bytes(b"external")
|
||||
os.symlink(external, target)
|
||||
|
||||
with pytest.raises(EntryFactConformanceError, match="artifact filesystem census"):
|
||||
validate_entry_fact_conformance((root / "manifest.json").read_bytes(), root)
|
||||
|
||||
|
||||
def test_manifest_refuses_declared_artifact_symlink_to_identical_bytes(tmp_path: Path) -> None:
|
||||
root = tmp_path / "artifact-symlink"
|
||||
shutil.copytree(FIXTURE_ROOT, root)
|
||||
manifest = json.loads((root / "manifest.json").read_bytes())
|
||||
relative = manifest["cases"][0]["artifacts"][0]["path"]
|
||||
target = root / relative
|
||||
external = tmp_path / "identical-artifact"
|
||||
external.write_bytes(target.read_bytes())
|
||||
target.unlink()
|
||||
os.symlink(external, target)
|
||||
|
||||
with pytest.raises(EntryFactConformanceError, match="artifact filesystem census"):
|
||||
validate_entry_fact_conformance((root / "manifest.json").read_bytes(), root)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("directory", ("sources", "artifacts", "artifacts/sha256"))
|
||||
def test_manifest_refuses_symlinked_census_root(tmp_path: Path, directory: str) -> None:
|
||||
root = tmp_path / "redirected-root"
|
||||
shutil.copytree(FIXTURE_ROOT, root)
|
||||
target = root / directory
|
||||
external = tmp_path / directory.replace("/", "-")
|
||||
shutil.copytree(target, external)
|
||||
shutil.rmtree(target)
|
||||
os.symlink(external, target)
|
||||
reason = "source filesystem census" if directory == "sources" else "artifact filesystem census"
|
||||
|
||||
with pytest.raises(EntryFactConformanceError, match=reason):
|
||||
validate_entry_fact_conformance((root / "manifest.json").read_bytes(), root)
|
||||
|
||||
|
||||
def test_builder_refuses_declared_source_symlink(tmp_path: Path) -> None:
|
||||
root = tmp_path / "builder-source"
|
||||
shutil.copytree(FIXTURE_ROOT, root)
|
||||
target = root / "sources" / "complete.js"
|
||||
external = tmp_path / "builder-external.js"
|
||||
external.write_bytes(target.read_bytes())
|
||||
target.unlink()
|
||||
os.symlink(external, target)
|
||||
|
||||
with pytest.raises(EntryFactConformanceError, match="nonempty readable fixture"):
|
||||
build_entry_fact_conformance(root, tmp_path / "builder-output")
|
||||
|
||||
|
||||
def test_builder_refuses_symlinked_source_root(tmp_path: Path) -> None:
|
||||
root = tmp_path / "builder-source-root"
|
||||
shutil.copytree(FIXTURE_ROOT, root)
|
||||
external = tmp_path / "external-sources"
|
||||
shutil.copytree(root / "sources", external)
|
||||
shutil.rmtree(root / "sources")
|
||||
os.symlink(external, root / "sources")
|
||||
|
||||
with pytest.raises(EntryFactConformanceError, match="real non-symlink directory"):
|
||||
build_entry_fact_conformance(root, tmp_path / "builder-output")
|
||||
|
||||
|
||||
def test_builder_refuses_existing_digest_symlink(tmp_path: Path) -> None:
|
||||
output = tmp_path / "builder-artifacts"
|
||||
build_entry_fact_conformance(FIXTURE_ROOT, output)
|
||||
target = next((output / "artifacts" / "sha256").iterdir())
|
||||
external = tmp_path / "builder-identical-artifact"
|
||||
external.write_bytes(target.read_bytes())
|
||||
target.unlink()
|
||||
os.symlink(external, target)
|
||||
|
||||
with pytest.raises(EntryFactConformanceError, match="artifact.*regular|unsafe"):
|
||||
build_entry_fact_conformance(FIXTURE_ROOT, output)
|
||||
|
||||
|
||||
def test_builder_refuses_symlinked_artifact_root(tmp_path: Path) -> None:
|
||||
output = tmp_path / "builder-artifact-root"
|
||||
(output / "artifacts").mkdir(parents=True)
|
||||
external = tmp_path / "external-artifacts"
|
||||
external.mkdir()
|
||||
os.symlink(external, output / "artifacts" / "sha256")
|
||||
|
||||
with pytest.raises(EntryFactConformanceError, match="artifact.*regular|unsafe"):
|
||||
build_entry_fact_conformance(FIXTURE_ROOT, output)
|
||||
|
||||
|
||||
def test_builder_refuses_symlinked_artifacts_directory(tmp_path: Path) -> None:
|
||||
output = tmp_path / "builder-artifacts-directory"
|
||||
output.mkdir()
|
||||
external = tmp_path / "external-artifacts-directory"
|
||||
(external / "sha256").mkdir(parents=True)
|
||||
os.symlink(external, output / "artifacts")
|
||||
|
||||
with pytest.raises(EntryFactConformanceError, match="artifact.*regular|unsafe"):
|
||||
build_entry_fact_conformance(FIXTURE_ROOT, output)
|
||||
|
||||
|
||||
def test_unreadable_or_empty_fixture_fails_before_validator_results(tmp_path: Path) -> None:
|
||||
fixture_root = tmp_path / "fixtures"
|
||||
sources = fixture_root / "sources"
|
||||
sources.mkdir(parents=True)
|
||||
for name in ("complete.js", "name-only.js", "partial.js", "legacy-only.js"):
|
||||
(sources / name).write_bytes(b"" if name == "complete.js" else b"x")
|
||||
|
||||
with pytest.raises(EntryFactConformanceError, match="nonempty readable fixture"):
|
||||
build_entry_fact_conformance(fixture_root, tmp_path / "output")
|
||||
|
||||
|
||||
def test_isolated_consumer_replays_without_mapping_or_target_imports() -> None:
|
||||
script = """
|
||||
import importlib.abc
|
||||
import pathlib
|
||||
import sys
|
||||
class BlockTargetImports(importlib.abc.MetaPathFinder):
|
||||
def find_spec(self, fullname, path=None, target=None):
|
||||
if fullname.startswith(('openultrasast.mapping', 'openultrasast.semantic')):
|
||||
raise ImportError(f'forbidden target import: {fullname}')
|
||||
return None
|
||||
sys.meta_path.insert(0, BlockTargetImports())
|
||||
sys.path.insert(0, sys.argv[2])
|
||||
sys.path.insert(0, sys.argv[3])
|
||||
from entry_fact_core_consumer import replay_all
|
||||
results = replay_all(pathlib.Path(sys.argv[1]))
|
||||
assert len(results) == 10
|
||||
print('isolated-core-replay=10')
|
||||
"""
|
||||
completed = subprocess.run(
|
||||
[
|
||||
sys.executable,
|
||||
"-I",
|
||||
"-c",
|
||||
script,
|
||||
str(FIXTURE_ROOT),
|
||||
str(Path(__file__).parent),
|
||||
str(Path(__file__).parents[1] / "src"),
|
||||
],
|
||||
check=False,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
assert completed.returncode == 0, completed.stderr
|
||||
assert completed.stdout.strip() == "isolated-core-replay=10"
|
||||
Reference in New Issue
Block a user