teleo-infrastructure/tests/test_leo_identity_manifest.py

721 lines
30 KiB
Python

from __future__ import annotations
import argparse
import copy
import json
import os
import subprocess
import time
from pathlib import Path
import pytest
from scripts import leo_behavior_manifest as behavior
from scripts import leo_identity_manifest as identity
from scripts import leo_identity_profile as profile_runtime
from scripts import run_leo_identity_reconstruction_canary as canary
ROOT = Path(__file__).resolve().parents[1]
def _write(path: Path, value: str) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(value, encoding="utf-8")
def _write_json(path: Path, value: dict) -> None:
_write(path, json.dumps(value, indent=2, sort_keys=True) + "\n")
def _fixture(tmp_path: Path) -> dict[str, Path | dict]:
repo = tmp_path / "repo"
profile = repo / "profile-template"
hermes = repo / "hermes-runtime"
compiled = tmp_path / "compiled-profile"
_write(
profile / "config.yaml",
"""model:
provider: fixture-local
default: identity-v1
max_tokens: 512
memory:
enabled: false
gateway:
execution_mode: local_no_send
telegram:
bot_token: never-emit-this-fixture-value
transport:
endpoint: https://fixture-user:fixture-password@example.invalid/v1
headers: ['Authorization: Bearer fixture-secret']
tools:
allowed: [identity_readback]
write_enabled: false
identity_runtime:
network_send_enabled: false
database_write_enabled: false
allowed_tools: [identity_readback]
""",
)
_write(profile / "skills" / "identity" / "SKILL.md", "# identity readback\n")
_write(profile / "plugins" / "identity" / "__init__.py", "BOUNDARY = True\n")
_write(profile / "bin" / "identity_readback.py", "READ_ONLY = True\n")
_write(hermes / "run_agent.py", "RUNTIME = 'identity-v1'\n")
_write(hermes / "agent" / "prompt_builder.py", "SOUL_IS_GENERATED = True\n")
_write(hermes / "gateway" / "run.py", "SESSION_IS_IDENTITY = False\n")
_write(hermes / "hermes_cli" / "tools_config.py", "TOOLS = ('identity_readback',)\n")
_write(hermes / "tools" / "registry.py", "READ_ONLY = True\n")
for name in (
"leo_behavior_manifest.py",
"leo_identity_manifest.py",
"leo_identity_profile.py",
"run_leo_identity_reconstruction_canary.py",
):
_write(repo / "scripts" / name, (ROOT / "scripts" / name).read_text(encoding="utf-8"))
fingerprint_path = repo / "fixtures" / "database-fingerprint.json"
constitution_path = repo / "fixtures" / "constitution.json"
database_identity_path = repo / "fixtures" / "database-identity.json"
fingerprint = {
"schema": identity.DATABASE_FINGERPRINT_SCHEMA,
"status": "ok",
"environment": "disposable_fixture",
"fingerprint_sha256": "1" * 64,
"table_rows_sha256": "2" * 64,
"structure_sha256": "3" * 64,
"table_count": 2,
"total_rows": 2,
"read_consistency": {
"status": "stable_wal_marker",
"before": {
"database": "fixture",
"database_user": "reader",
"system_identifier": "12345",
"wal_lsn": "0/1",
},
"after": {
"database": "fixture",
"database_user": "reader",
"system_identifier": "12345",
"wal_lsn": "0/1",
},
},
}
constitution = {
"schema": identity.CONSTITUTION_SCHEMA,
"identity_name": "Leo",
"rules": [
{"id": "evidence", "text": "Never use temporary session memory as canonical evidence."},
{"id": "truth", "text": "Fail closed when a pinned identity input drifts."},
],
}
database_identity = {
"schema": identity.DATABASE_IDENTITY_SCHEMA,
"identity_name": "Leo",
"database_fingerprint_sha256": "1" * 64,
"source_provenance": {
"mode": identity.SYNTHETIC_DATABASE_MODE,
"canonical_authority_granted": False,
"same_transaction_as_fingerprint": False,
"export_receipt_sha256": None,
},
"records": [
{
"table": "public.personas",
"row_id": "persona-1",
"kind": "persona",
"rank": 0,
"text": "Leo is an evidence-bound reasoning interface.",
"status": "active",
"evidence_sha256": "a" * 64,
},
{
"table": "public.beliefs",
"row_id": "belief-1",
"kind": "belief",
"rank": 0,
"text": "Exact provenance is stronger than plausible recollection.",
"status": "active",
"evidence_sha256": "b" * 64,
},
],
}
_write_json(fingerprint_path, fingerprint)
_write_json(constitution_path, constitution)
_write_json(database_identity_path, database_identity)
subprocess.run(["git", "init", "-q", str(repo)], check=True)
subprocess.run(["git", "-C", str(repo), "config", "user.email", "test@example.com"], check=True)
subprocess.run(["git", "-C", str(repo), "config", "user.name", "Test"], check=True)
subprocess.run(["git", "-C", str(repo), "add", "."], check=True)
subprocess.run(
["git", "-C", str(repo), "commit", "-qm", "fixture"],
check=True,
env={
**dict(__import__("os").environ),
"GIT_AUTHOR_DATE": "2026-01-01T00:00:00Z",
"GIT_COMMITTER_DATE": "2026-01-01T00:00:00Z",
},
)
behavior_manifest = behavior.build_manifest(profile, hermes, repo)
manifest = identity.build_identity_manifest(
behavior_manifest=behavior_manifest,
database_fingerprint_path=fingerprint_path,
constitution_path=constitution_path,
database_identity_path=database_identity_path,
source_root=repo,
)
return {
"repo": repo,
"profile": profile,
"hermes": hermes,
"compiled": compiled,
"fingerprint": fingerprint_path,
"constitution": constitution_path,
"database_identity": database_identity_path,
"behavior": behavior_manifest,
"manifest": manifest,
}
def _fully_rehash_manifest(fixture: dict[str, Path | dict], manifest: dict) -> None:
identity_hash = behavior.canonical_sha256(manifest["identity_inputs"])
manifest["identity_inputs_sha256"] = identity_hash
fingerprint = identity.load_json(fixture["fingerprint"], "database fingerprint")
rules = identity.canonical_rules(identity.load_json(fixture["constitution"], "constitution"))
records = identity.canonical_database_records(
identity.load_json(fixture["database_identity"], "database identity"),
fingerprint_sha256=fingerprint["fingerprint_sha256"],
)
database_provenance = identity.database_identity_provenance(
identity.load_json(fixture["database_identity"], "database identity"),
fingerprint=fingerprint,
)
rendered = identity.render_identity_views(
identity_inputs_sha256=identity_hash,
database_fingerprint_sha256=fingerprint["fingerprint_sha256"],
database_provenance=database_provenance,
rules=rules,
records=records,
)
for name, content in rendered.items():
manifest["compiled_views"][name]["sha256"] = behavior.sha256_bytes(content.encode("utf-8"))
manifest["compiled_views"][name]["generated_from_identity_inputs_sha256"] = identity_hash
stable = {key: value for key, value in manifest.items() if key != "manifest_sha256"}
manifest["manifest_sha256"] = behavior.canonical_sha256(stable)
def _rehash_behavior_manifest(manifest: dict) -> None:
manifest["identity_runtime_sha256"] = behavior.canonical_sha256(behavior.identity_runtime_payload(manifest))
manifest["static_runtime_sha256"] = behavior.canonical_sha256(behavior.static_runtime_payload(manifest))
manifest["behavior_sha256"] = behavior.canonical_sha256(behavior.stable_manifest_payload(manifest))
def _canary_args(fixture: dict[str, Path | dict], output: Path, *, inject_drift: bool = False) -> argparse.Namespace:
return argparse.Namespace(
profile_template=fixture["profile"],
hermes_root=fixture["hermes"],
deployment_root=fixture["repo"],
source_root=fixture["repo"],
database_fingerprint=fixture["fingerprint"],
constitution=fixture["constitution"],
database_identity=fixture["database_identity"],
output=output,
inject_drift_before_restart=inject_drift,
)
def test_manifest_compiles_generated_views_and_reproduces_identity_across_queries(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
manifest = fixture["manifest"]
assert isinstance(manifest, dict)
rebuilt = identity.build_identity_manifest(
behavior_manifest=fixture["behavior"],
database_fingerprint_path=fixture["fingerprint"],
constitution_path=fixture["constitution"],
database_identity_path=fixture["database_identity"],
source_root=fixture["repo"],
)
assert rebuilt == manifest
compile_receipt = profile_runtime.compile_profile(
manifest,
source_root=fixture["repo"],
profile_template=fixture["profile"],
profile=fixture["compiled"],
hermes_root=fixture["hermes"],
deployment_root=fixture["repo"],
)
first = profile_runtime.query_profile(
fixture["compiled"],
query=profile_runtime.FIXED_QUERY,
source_root=fixture["repo"],
hermes_root=fixture["hermes"],
deployment_root=fixture["repo"],
)
second = profile_runtime.query_profile(
fixture["compiled"],
query=profile_runtime.FIXED_QUERY,
source_root=fixture["repo"],
hermes_root=fixture["hermes"],
deployment_root=fixture["repo"],
)
assert compile_receipt["status"] == "pass"
assert "never-emit-this-fixture-value" not in (fixture["compiled"] / "config.yaml").read_text(encoding="utf-8")
assert "fixture-password" not in (fixture["compiled"] / "config.yaml").read_text(encoding="utf-8")
assert "fixture-secret" not in (fixture["compiled"] / "config.yaml").read_text(encoding="utf-8")
assert (fixture["compiled"] / "SOUL.md").read_text(encoding="utf-8").startswith("<!-- GENERATED FILE")
assert first["manifest_sha256"] == second["manifest_sha256"]
assert first["identity_inputs_sha256"] == second["identity_inputs_sha256"]
assert first["answer_sha256"] == second["answer_sha256"]
assert first["output_provenance"] == second["output_provenance"]
assert first["runtime_instance_id"] != second["runtime_instance_id"]
assert first["session"]["included_in_output_provenance"] is False
assert first["output_provenance"]["database_canonical_authority_granted"] is False
assert first["authorization"]["authorization_decision_observed"] is False
assert "synthetic noncanonical fixture" in first["answer"]
assert len(list((fixture["compiled"] / "sessions").glob("*.json"))) == 2
def test_profile_and_bound_source_drift_fail_closed(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
profile_runtime.compile_profile(
fixture["manifest"],
source_root=fixture["repo"],
profile_template=fixture["profile"],
profile=fixture["compiled"],
hermes_root=fixture["hermes"],
deployment_root=fixture["repo"],
)
with (fixture["compiled"] / "SOUL.md").open("a", encoding="utf-8") as handle:
handle.write("drift\n")
with pytest.raises(identity.IdentityManifestError, match="compiled view drift detected"):
profile_runtime.query_profile(
fixture["compiled"],
query=profile_runtime.FIXED_QUERY,
source_root=fixture["repo"],
hermes_root=fixture["hermes"],
deployment_root=fixture["repo"],
)
_write(fixture["constitution"], fixture["constitution"].read_text(encoding="utf-8") + "\n")
with pytest.raises(identity.IdentityManifestError, match="constitution source content drift"):
identity.verify_bound_sources(fixture["manifest"], fixture["repo"])
@pytest.mark.parametrize(
("relative_path", "content", "message"),
[
("memories/USER.md", "untrusted memory\n", "forbidden nonauthoritative"),
("MEMORY.md", "untrusted top-level memory\n", "forbidden nonauthoritative"),
("USER.md", "untrusted top-level user memory\n", "forbidden nonauthoritative"),
("platforms/pairing/telegram.json", "{}\n", "forbidden nonauthoritative"),
(".env", "LEO_SECRET=untrusted\n", "profile entry set is not exact"),
("gateway.json", "{}\n", "profile entry set is not exact"),
("unexpected.txt", "untrusted input\n", "profile entry set is not exact"),
("sessions/injected.txt", "untrusted session\n", "unsafe session entry"),
("state/injected.json", "{}\n", "state directory must remain empty"),
],
)
def test_profile_rechecks_nonauthoritative_surfaces_before_every_query(
tmp_path: Path, relative_path: str, content: str, message: str
) -> None:
fixture = _fixture(tmp_path)
profile_runtime.compile_profile(
fixture["manifest"],
source_root=fixture["repo"],
profile_template=fixture["profile"],
profile=fixture["compiled"],
hermes_root=fixture["hermes"],
deployment_root=fixture["repo"],
)
_write(fixture["compiled"] / relative_path, content)
with pytest.raises(profile_runtime.IdentityProfileError, match=message):
profile_runtime.query_profile(
fixture["compiled"],
query=profile_runtime.FIXED_QUERY,
source_root=fixture["repo"],
hermes_root=fixture["hermes"],
deployment_root=fixture["repo"],
)
def test_manifest_rejects_rehashed_core_tampering(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
tampered = copy.deepcopy(fixture["manifest"])
tampered["identity_inputs"]["session_boundary"]["may_be_used_as_evidence"] = True
stable = {key: value for key, value in tampered.items() if key != "manifest_sha256"}
tampered["manifest_sha256"] = behavior.canonical_sha256(stable)
with pytest.raises(identity.IdentityManifestError, match="identity input hash drift"):
identity.validate_identity_manifest(tampered)
@pytest.mark.parametrize(
("path", "value", "message"),
[
(("permissions", "runtime_policy", "network_send_enabled"), True, "exact local readback policy"),
(("session_boundary", "may_be_used_as_evidence"), True, "session authority boundary"),
],
)
def test_manifest_rejects_fully_rehashed_safety_invariant_tampering(
tmp_path: Path, path: tuple[str, ...], value: object, message: str
) -> None:
fixture = _fixture(tmp_path)
tampered = copy.deepcopy(fixture["manifest"])
target = tampered["identity_inputs"]
for key in path[:-1]:
target = target[key]
target[path[-1]] = value
_fully_rehash_manifest(fixture, tampered)
with pytest.raises(identity.IdentityManifestError, match=message):
identity.verify_bound_sources(tampered, fixture["repo"])
def test_behavior_manifest_rejects_unhashed_model_claim_tampering(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
tampered_behavior = copy.deepcopy(fixture["behavior"])
tampered_behavior["model_runtime"]["default_model"] = "tampered-unobserved-model"
with pytest.raises(identity.IdentityManifestError, match="behavior identity runtime hash drift"):
identity.build_identity_manifest(
behavior_manifest=tampered_behavior,
database_fingerprint_path=fixture["fingerprint"],
constitution_path=fixture["constitution"],
database_identity_path=fixture["database_identity"],
source_root=fixture["repo"],
)
def test_profile_rejects_a_dangling_extra_symlink(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
profile_runtime.compile_profile(
fixture["manifest"],
source_root=fixture["repo"],
profile_template=fixture["profile"],
profile=fixture["compiled"],
hermes_root=fixture["hermes"],
deployment_root=fixture["repo"],
)
(fixture["compiled"] / ".env").symlink_to(tmp_path / "missing-env")
with pytest.raises(profile_runtime.IdentityProfileError, match="profile entry set is not exact"):
profile_runtime.query_profile(
fixture["compiled"],
query=profile_runtime.FIXED_QUERY,
source_root=fixture["repo"],
hermes_root=fixture["hermes"],
deployment_root=fixture["repo"],
)
def test_profile_rejects_a_symlink_in_an_allowed_entry(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
profile_runtime.compile_profile(
fixture["manifest"],
source_root=fixture["repo"],
profile_template=fixture["profile"],
profile=fixture["compiled"],
hermes_root=fixture["hermes"],
deployment_root=fixture["repo"],
)
external_config = tmp_path / "external-config.yaml"
external_config.write_bytes((fixture["compiled"] / "config.yaml").read_bytes())
(fixture["compiled"] / "config.yaml").unlink()
(fixture["compiled"] / "config.yaml").symlink_to(external_config)
with pytest.raises(profile_runtime.IdentityProfileError, match="profile entries must not be symlinks"):
profile_runtime.query_profile(
fixture["compiled"],
query=profile_runtime.FIXED_QUERY,
source_root=fixture["repo"],
hermes_root=fixture["hermes"],
deployment_root=fixture["repo"],
)
@pytest.mark.parametrize(
("mutation", "message"),
[
("unreadable_file", "unreadable inputs"),
("symlink", "unsupported symlinks"),
("forged_structure", "is empty"),
],
)
def test_behavior_manifest_rejects_unreplayable_identity_components(
tmp_path: Path, mutation: str, message: str
) -> None:
fixture = _fixture(tmp_path)
tampered_behavior = copy.deepcopy(fixture["behavior"])
content = tampered_behavior["components"]["procedural_skills"]["content"]
if mutation == "unreadable_file":
content["files"][0].pop("sha256")
content["files"][0]["status"] = "unavailable"
elif mutation == "symlink":
content["symlinks"].append(
{
"path": "skills/identity/link",
"target": "/outside/checkout",
"target_fingerprint": {"kind": "unavailable", "error": "FileNotFoundError"},
}
)
else:
content["files"] = []
content["sha256"] = behavior.canonical_sha256({key: content[key] for key in ("files", "missing", "symlinks")})
_rehash_behavior_manifest(tampered_behavior)
with pytest.raises(identity.IdentityManifestError, match=message):
identity.validate_behavior_manifest(tampered_behavior)
def test_fully_rehashed_model_claim_must_match_observed_runtime(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
tampered = copy.deepcopy(fixture["manifest"])
tampered["identity_inputs"]["model"]["default_model"] = "tampered-unobserved-model"
_fully_rehash_manifest(fixture, tampered)
identity.validate_identity_manifest(tampered)
with pytest.raises(
profile_runtime.IdentityProfileError, match="model runtime binding drift detected: default_model"
):
profile_runtime.compile_profile(
tampered,
source_root=fixture["repo"],
profile_template=fixture["profile"],
profile=fixture["compiled"],
hermes_root=fixture["hermes"],
deployment_root=fixture["repo"],
)
assert not fixture["compiled"].exists()
def test_restart_canary_uses_distinct_processes_and_cleans_up(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
report, exit_code = canary.run_canary(_canary_args(fixture, tmp_path / "restart-receipt.json"))
assert exit_code == 0
assert report["status"] == "pass"
assert report["gates"]["restart_process_is_distinct"] is True
assert report["gates"]["restart_profile_recompiled_from_manifest"] is True
assert report["restart_compile"]["session_directories_started_empty"] is True
assert report["drift_compile"]["session_directories_started_empty"] is True
first_profile = report["first_start"]["command"][report["first_start"]["command"].index("--profile") + 1]
restart_profile = report["restart"]["command"][report["restart"]["command"].index("--profile") + 1]
assert first_profile != restart_profile
assert report["first_start"]["launcher_pid"] != report["restart"]["launcher_pid"]
assert report["first_start"]["process_group_absent_after_wait"] is True
assert report["restart"]["process_group_absent_after_wait"] is True
assert report["drift_negative"]["fail_closed"] is True
assert report["drift_negative"]["process_group_absent_after_wait"] is True
assert report["goal_tier_satisfied"] is True
assert report["current_tier"] == "T2_runtime"
assert report["cleanup"]["temporary_root_removed"] is True
assert behavior.git_state(fixture["repo"])["worktree_clean"] is True
def test_restart_canary_rejects_drift_before_second_start(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
report, exit_code = canary.run_canary(_canary_args(fixture, tmp_path / "drift-receipt.json", inject_drift=True))
assert exit_code == 0
assert report["status"] == "pass"
assert report["gates"]["drift_detected_before_restart"] is True
assert report["second_start_attempted"] is False
assert "restart" not in report
assert report["pre_restart_drift"]["process_group_absent_after_wait"] is True
assert all(report["gates"].values())
assert report["goal_tier_satisfied"] is False
assert report["current_tier"] == "T1_model"
assert report["cleanup"]["temporary_root_removed"] is True
def test_query_child_timeout_terminates_process_group(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
marker = tmp_path / "descendant.pid"
sleeping_module = f"""import subprocess
import sys
import time
from pathlib import Path
child = subprocess.Popen([sys.executable, '-c', 'import time; time.sleep(60)'])
Path({str(marker)!r}).write_text(str(child.pid), encoding='utf-8')
time.sleep(60)
"""
_write(fixture["repo"] / "scripts" / "leo_identity_profile.py", sleeping_module)
result = canary._run_query_child(
deployment_root=fixture["repo"],
profile=fixture["compiled"],
source_root=fixture["repo"],
hermes_root=fixture["hermes"],
timeout_seconds=0.5,
)
assert result["timed_out"] is True
assert result["terminated_with"] in {"SIGTERM", "SIGKILL"}
assert result["returncode"] != 0
assert result["process_group_absent_after_wait"] is True
descendant_pid = int(marker.read_text(encoding="utf-8"))
deadline = time.monotonic() + 5
while time.monotonic() < deadline:
try:
os.kill(descendant_pid, 0)
except ProcessLookupError:
break
time.sleep(0.02)
with pytest.raises(ProcessLookupError):
os.kill(descendant_pid, 0)
def test_query_child_cleans_and_rejects_orphan_from_completed_launcher(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
marker = tmp_path / "completed-descendant.pid"
query_payload = {"schema": profile_runtime.QUERY_RECEIPT_SCHEMA, "status": "pass"}
leaking_module = f"""import json
import subprocess
import sys
from pathlib import Path
child = subprocess.Popen(
[sys.executable, '-c', 'import time; time.sleep(60)'],
stdin=subprocess.DEVNULL,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
Path({str(marker)!r}).write_text(str(child.pid), encoding='utf-8')
print(json.dumps({query_payload!r}))
"""
_write(fixture["repo"] / "scripts" / "leo_identity_profile.py", leaking_module)
result = canary._run_query_child(
deployment_root=fixture["repo"],
profile=fixture["compiled"],
source_root=fixture["repo"],
hermes_root=fixture["hermes"],
timeout_seconds=5,
)
assert result["returncode"] == 0
assert result["orphan_cleanup_required"] is True
assert result["terminated_with"] in {"SIGTERM", "SIGKILL"}
assert result["process_group_absent_after_wait"] is True
assert canary._query_passed(result) is False
def test_wal_capture_marker_is_not_an_identity_input(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
original = fixture["manifest"]
fingerprint = json.loads(fixture["fingerprint"].read_text(encoding="utf-8"))
fingerprint["read_consistency"]["before"]["wal_lsn"] = "0/2"
fingerprint["read_consistency"]["after"]["wal_lsn"] = "0/2"
_write_json(fixture["fingerprint"], fingerprint)
rebuilt = identity.build_identity_manifest(
behavior_manifest=fixture["behavior"],
database_fingerprint_path=fixture["fingerprint"],
constitution_path=fixture["constitution"],
database_identity_path=fixture["database_identity"],
source_root=fixture["repo"],
)
assert rebuilt["identity_inputs_sha256"] == original["identity_inputs_sha256"]
assert rebuilt["manifest_sha256"] == original["manifest_sha256"]
def test_database_identity_and_system_markers_are_identity_inputs(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
original = fixture["manifest"]
fingerprint = json.loads(fixture["fingerprint"].read_text(encoding="utf-8"))
for marker in (fingerprint["read_consistency"]["before"], fingerprint["read_consistency"]["after"]):
marker["database"] = "different_database"
marker["database_user"] = "different_reader"
marker["system_identifier"] = "99999"
_write_json(fixture["fingerprint"], fingerprint)
rebuilt = identity.build_identity_manifest(
behavior_manifest=fixture["behavior"],
database_fingerprint_path=fixture["fingerprint"],
constitution_path=fixture["constitution"],
database_identity_path=fixture["database_identity"],
source_root=fixture["repo"],
)
assert rebuilt["identity_inputs_sha256"] != original["identity_inputs_sha256"]
with pytest.raises(identity.IdentityManifestError, match="database fingerprint semantic drift"):
identity.verify_bound_sources(original, fixture["repo"])
def test_synthetic_database_rows_cannot_claim_canonical_authority(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
database_identity = json.loads(fixture["database_identity"].read_text(encoding="utf-8"))
database_identity["source_provenance"] = {
"mode": identity.CANONICAL_DATABASE_MODE,
"canonical_authority_granted": True,
"same_transaction_as_fingerprint": True,
"export_receipt_sha256": "f" * 64,
}
_write_json(fixture["database_identity"], database_identity)
with pytest.raises(identity.IdentityManifestError, match="independently verified output"):
identity.build_identity_manifest(
behavior_manifest=fixture["behavior"],
database_fingerprint_path=fixture["fingerprint"],
constitution_path=fixture["constitution"],
database_identity_path=fixture["database_identity"],
source_root=fixture["repo"],
)
def test_self_hashed_database_export_receipt_cannot_grant_canonical_authority(tmp_path: Path) -> None:
fixture = _fixture(tmp_path)
fingerprint = json.loads(fixture["fingerprint"].read_text(encoding="utf-8"))
fingerprint["environment"] = "canonical_readonly_capture"
_write_json(fixture["fingerprint"], fingerprint)
database_identity = json.loads(fixture["database_identity"].read_text(encoding="utf-8"))
records = identity.canonical_database_records(
database_identity,
fingerprint_sha256=fingerprint["fingerprint_sha256"],
)
marker = fingerprint["read_consistency"]["before"]
receipt_stable = {
"schema": "livingip.untrustedCallerSuppliedExportReceipt.v1",
"read_only": True,
"same_transaction_as_fingerprint": True,
"transaction_isolation": "repeatable_read_read_only",
"database": marker["database"],
"database_user": marker["database_user"],
"system_identifier": marker["system_identifier"],
"database_fingerprint_sha256": fingerprint["fingerprint_sha256"],
"records_sha256": behavior.canonical_sha256(records),
}
receipt_hash = behavior.canonical_sha256(receipt_stable)
database_identity["source_provenance"] = {
"mode": identity.CANONICAL_DATABASE_MODE,
"canonical_authority_granted": True,
"same_transaction_as_fingerprint": True,
"export_receipt_sha256": receipt_hash,
}
database_identity["export_receipt"] = {**receipt_stable, "receipt_sha256": receipt_hash}
_write_json(fixture["database_identity"], database_identity)
with pytest.raises(identity.IdentityManifestError, match="independently verified output"):
identity.build_identity_manifest(
behavior_manifest=fixture["behavior"],
database_fingerprint_path=fixture["fingerprint"],
constitution_path=fixture["constitution"],
database_identity_path=fixture["database_identity"],
source_root=fixture["repo"],
)
def test_same_clean_commit_reproduces_identity_from_different_checkout_paths(tmp_path: Path) -> None:
first = _fixture(tmp_path / "checkout-a")
second = _fixture(tmp_path / "checkout-b")
assert (
first["behavior"]["teleo_infrastructure_runtime"]["git_head"]
== second["behavior"]["teleo_infrastructure_runtime"]["git_head"]
)
assert first["behavior"]["identity_runtime_sha256"] == second["behavior"]["identity_runtime_sha256"]
assert first["manifest"]["identity_inputs_sha256"] == second["manifest"]["identity_inputs_sha256"]
assert first["manifest"]["manifest_sha256"] == second["manifest"]["manifest_sha256"]