Import AITURK IDE 1.0.0-beta.1 from Hermes 63279301; preserve MIT license
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
"""Image-managed refusal contract tests (#91277 Phase 3).
|
||||
|
||||
Marker semantics (image_provenance.py, salvaged from #92545 @andrexibiza):
|
||||
absent → None; present-and-valid → provenance; present-but-broken →
|
||||
fail-closed invalid. Admission gate (update_contract.py): marker first,
|
||||
docker/nix/apt heuristics second; refusals record a `refused` receipt.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from hermes_cli.image_provenance import read_image_provenance
|
||||
from hermes_cli.update_contract import (
|
||||
UpdateRefusal,
|
||||
evaluate_update_admission,
|
||||
record_refusal_receipt,
|
||||
)
|
||||
|
||||
|
||||
def _valid_marker(tmp_path: Path) -> Path:
|
||||
marker = tmp_path / "image-provenance.json"
|
||||
marker.write_text(json.dumps({
|
||||
"schema": 1,
|
||||
"deployment_kind": "image",
|
||||
"manager": "docker",
|
||||
"image": "nousresearch/hermes-agent",
|
||||
"version": "1.0.0",
|
||||
"revision": "a" * 40,
|
||||
}))
|
||||
return marker
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Marker reader
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def test_reader_absent_marker_means_none(tmp_path):
|
||||
assert read_image_provenance(tmp_path / "nope.json") is None
|
||||
|
||||
|
||||
def test_reader_valid_marker(tmp_path):
|
||||
provenance = read_image_provenance(_valid_marker(tmp_path))
|
||||
assert provenance is not None and provenance.valid
|
||||
assert provenance.manager == "docker"
|
||||
assert provenance.version == "1.0.0"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"payload,reason_prefix",
|
||||
[
|
||||
("not json {", "marker_unreadable"),
|
||||
(json.dumps([1, 2]), "marker_not_object"),
|
||||
(json.dumps({"schema": True, "deployment_kind": "image", "manager": "docker"}), "unsupported_marker_schema"),
|
||||
(json.dumps({"schema": 2, "deployment_kind": "image", "manager": "docker"}), "unsupported_marker_schema"),
|
||||
(json.dumps({"schema": 1, "deployment_kind": "source", "manager": "docker"}), "invalid_deployment_kind"),
|
||||
(json.dumps({"schema": 1, "deployment_kind": "image", "manager": " "}), "missing_manager"),
|
||||
],
|
||||
)
|
||||
def test_reader_fails_closed_on_malformed(tmp_path, payload, reason_prefix):
|
||||
marker = tmp_path / "image-provenance.json"
|
||||
marker.write_text(payload)
|
||||
provenance = read_image_provenance(marker)
|
||||
assert provenance is not None and not provenance.valid
|
||||
assert provenance.error.startswith(reason_prefix)
|
||||
|
||||
|
||||
def test_reader_rejects_symlink_marker(tmp_path):
|
||||
real = _valid_marker(tmp_path)
|
||||
link = tmp_path / "link.json"
|
||||
try:
|
||||
link.symlink_to(real)
|
||||
except (OSError, NotImplementedError):
|
||||
pytest.skip("symlinks unavailable")
|
||||
provenance = read_image_provenance(link)
|
||||
assert provenance is not None and not provenance.valid
|
||||
assert provenance.error == "marker_not_regular_file"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Admission gate
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def test_admission_marker_refuses_even_on_git_checkout(tmp_path, monkeypatch):
|
||||
"""The bind-mounted-checkout case: heuristics say git, marker says image
|
||||
— the marker wins."""
|
||||
import hermes_cli.image_provenance as ip
|
||||
|
||||
monkeypatch.setattr(ip, "IMAGE_PROVENANCE_PATH", _valid_marker(tmp_path))
|
||||
monkeypatch.setattr(
|
||||
"hermes_cli.config.detect_install_method", lambda *a, **k: "git"
|
||||
)
|
||||
refusal = evaluate_update_admission(tmp_path)
|
||||
assert refusal is not None
|
||||
assert refusal.code == "image-marker"
|
||||
assert "docker pull" in refusal.update_command
|
||||
|
||||
|
||||
def test_admission_invalid_marker_fails_closed(tmp_path, monkeypatch):
|
||||
import hermes_cli.image_provenance as ip
|
||||
|
||||
bad = tmp_path / "image-provenance.json"
|
||||
bad.write_text("corrupted {{{")
|
||||
monkeypatch.setattr(ip, "IMAGE_PROVENANCE_PATH", bad)
|
||||
refusal = evaluate_update_admission(tmp_path)
|
||||
assert refusal is not None
|
||||
assert refusal.code == "image-marker-invalid"
|
||||
assert "docker pull" in refusal.update_command
|
||||
|
||||
|
||||
def test_admission_no_marker_falls_back_to_heuristics(tmp_path, monkeypatch):
|
||||
import hermes_cli.image_provenance as ip
|
||||
|
||||
monkeypatch.setattr(ip, "IMAGE_PROVENANCE_PATH", tmp_path / "absent.json")
|
||||
monkeypatch.setattr(
|
||||
"hermes_cli.config.detect_install_method", lambda *a, **k: "docker"
|
||||
)
|
||||
refusal = evaluate_update_admission(tmp_path)
|
||||
assert refusal is not None and refusal.code == "docker"
|
||||
|
||||
|
||||
def test_admission_git_checkout_no_marker_is_admitted(tmp_path, monkeypatch):
|
||||
import hermes_cli.image_provenance as ip
|
||||
|
||||
monkeypatch.setattr(ip, "IMAGE_PROVENANCE_PATH", tmp_path / "absent.json")
|
||||
monkeypatch.setattr(
|
||||
"hermes_cli.config.detect_install_method", lambda *a, **k: "git"
|
||||
)
|
||||
assert evaluate_update_admission(tmp_path) is None
|
||||
|
||||
|
||||
def test_admission_apt_and_nix_refuse(tmp_path, monkeypatch):
|
||||
import hermes_cli.image_provenance as ip
|
||||
|
||||
monkeypatch.setattr(ip, "IMAGE_PROVENANCE_PATH", tmp_path / "absent.json")
|
||||
for method, code in (("apt", "apt"), ("nix", "nix")):
|
||||
def _detect(*a, _m=method, **k):
|
||||
return _m
|
||||
|
||||
monkeypatch.setattr("hermes_cli.config.detect_install_method", _detect)
|
||||
refusal = evaluate_update_admission(tmp_path)
|
||||
assert refusal is not None and refusal.code == code
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Refusal receipt
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def test_refusal_receipt_written_as_refused(tmp_path, monkeypatch):
|
||||
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
|
||||
import hermes_cli.update_receipt as ur
|
||||
|
||||
monkeypatch.setattr(ur, "_receipt_dir", lambda: tmp_path / "receipts")
|
||||
|
||||
record_refusal_receipt(
|
||||
UpdateRefusal(
|
||||
code="image-marker",
|
||||
message="msg",
|
||||
update_command="docker pull nousresearch/hermes-agent:latest",
|
||||
)
|
||||
)
|
||||
receipts = list((tmp_path / "receipts").glob("*.json"))
|
||||
receipts = [p for p in receipts if p.name != "latest.json"]
|
||||
assert receipts, "a refusal receipt must be written"
|
||||
data = json.loads(receipts[0].read_text())
|
||||
assert data["outcome"] == "refused"
|
||||
assert data["stop_reason"] == "image-marker"
|
||||
steps = {s["name"]: s for s in data["steps"]}
|
||||
assert "admission" in steps and steps["admission"]["ok"] is False
|
||||
assert "docker pull" in steps["admission"]["detail"]
|
||||
Reference in New Issue
Block a user