perf(m49): verify source payloads during assembly
This commit is contained in:
@@ -31,6 +31,7 @@ from k1link.observatory.m49_portable_source import (
|
||||
materialize_m49_portable_source,
|
||||
read_m49_source_index,
|
||||
validate_m49_portable_source_stage,
|
||||
validate_m49_portable_source_stage_binding,
|
||||
)
|
||||
from k1link.observatory.portable_result_contract import (
|
||||
PortableResultPackageManifest,
|
||||
@@ -566,6 +567,36 @@ def test_fresh_source_stage_defers_full_validation_until_execution_boundary(
|
||||
assert validated_roots == [first_root]
|
||||
|
||||
|
||||
def test_bound_source_stage_rechecks_small_documents_without_rehashing_sequence(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
stage_root, _expected = _materialized_source(tmp_path, monkeypatch)
|
||||
stage = validate_m49_portable_source_stage(stage_root)
|
||||
|
||||
def unexpected_sequence_rehash(*_args: object, **_kwargs: object) -> None:
|
||||
raise AssertionError("bound-stage validation rehashed the point sequence")
|
||||
|
||||
monkeypatch.setattr(source_module, "_verify_sequence_files", unexpected_sequence_rehash)
|
||||
rebound = validate_m49_portable_source_stage_binding(stage)
|
||||
|
||||
assert rebound == stage
|
||||
|
||||
|
||||
@pytest.mark.parametrize("relative_path", ["schedule.tsv", "sequence-index.ndjson"])
|
||||
def test_bound_source_stage_rejects_changed_small_documents(
|
||||
tmp_path: Path,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
relative_path: str,
|
||||
) -> None:
|
||||
stage_root, _expected = _materialized_source(tmp_path, monkeypatch)
|
||||
stage = validate_m49_portable_source_stage(stage_root)
|
||||
artifact = stage.root / relative_path
|
||||
artifact.write_bytes(artifact.read_bytes() + b"changed")
|
||||
|
||||
with pytest.raises(M49PortableSourceError):
|
||||
validate_m49_portable_source_stage_binding(stage)
|
||||
|
||||
|
||||
def test_source_materializer_rejects_unadmitted_adjacent_metadata(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
@@ -756,20 +787,18 @@ def test_result_v2_assembler_and_exact_validator_round_trip(
|
||||
created_at_utc=lambda: NOW,
|
||||
invoker=fake_invoke,
|
||||
)
|
||||
draft = runner.run(
|
||||
PortableWorkerRuntimePlan(
|
||||
job_id=sealed.job_id,
|
||||
adapter_id="m49-tgs-worker006-portable-v2",
|
||||
candidate_sha256="f" * 64,
|
||||
setup_id=sealed.setup_id,
|
||||
definition_sha256=sealed.definition_sha256,
|
||||
source_bundle_sha256=sealed.source_bundle_sha256,
|
||||
source_capability_manifest_sha256=sealed.source_capability_manifest_sha256,
|
||||
result_contract_sha256=definition.result_contract.contract_sha256,
|
||||
phases=M49_PORTABLE_RUNTIME_PHASES,
|
||||
),
|
||||
bound_source,
|
||||
plan = PortableWorkerRuntimePlan(
|
||||
job_id=sealed.job_id,
|
||||
adapter_id="m49-tgs-worker006-portable-v2",
|
||||
candidate_sha256="f" * 64,
|
||||
setup_id=sealed.setup_id,
|
||||
definition_sha256=sealed.definition_sha256,
|
||||
source_bundle_sha256=sealed.source_bundle_sha256,
|
||||
source_capability_manifest_sha256=sealed.source_capability_manifest_sha256,
|
||||
result_contract_sha256=definition.result_contract.contract_sha256,
|
||||
phases=M49_PORTABLE_RUNTIME_PHASES,
|
||||
)
|
||||
draft = runner.run(plan, bound_source)
|
||||
package = PortableResultPackageManifest.from_bytes((draft.root / "manifest.json").read_bytes())
|
||||
assert draft.root.name == package.manifest_sha256
|
||||
assert draft.result_id.startswith("m49-tgs-portable-review-")
|
||||
@@ -816,6 +845,18 @@ def test_result_v2_assembler_and_exact_validator_round_trip(
|
||||
)
|
||||
)
|
||||
|
||||
source_rows = read_m49_source_index(
|
||||
source_stage.root / "sequence-index.ndjson",
|
||||
expected_frame_count=source_stage.timeline_frame_count,
|
||||
)
|
||||
available_row = next(row for row in source_rows if row["sample_available"] is True)
|
||||
native_path = source_stage.root / cast(str, available_row["relative_path"])
|
||||
native_payload = bytearray(native_path.read_bytes())
|
||||
native_payload[-1] ^= 0x01
|
||||
native_path.write_bytes(native_payload)
|
||||
with pytest.raises(M49PortableResultError, match="digest changed"):
|
||||
runner.run(plan, bound_source)
|
||||
|
||||
|
||||
def test_executor_release_candidate_is_deterministic_blocked_and_tamper_evident(
|
||||
tmp_path: Path,
|
||||
|
||||
Reference in New Issue
Block a user