from __future__ import annotations import hashlib import json import subprocess from scripts import run_leo_direct_claim_handler_suite as suite def response_binding_helper(): namespace = {"hashlib": hashlib} exec(suite.RESPONSE_BINDING_HELPER_SOURCE, namespace) return namespace["response_bindings_are_hash_bound"] def safe_report() -> dict: return { "remote_returncode": 0, "pass_runtime": True, "handler": {"authorized": True}, "results": [ { "ok": True, "mutates_kb": False, "database_tool_trace": { "database_tool_call_count": 1, "database_tool_completed_count": 1, "database_tool_calls_read_only": True, "calls": [ { "database_invocations": [{"access_mode": "read_only"}], "result": { "content_sha256": "a" * 64, "error_detected": False, "nonempty": True, }, } ], }, } ], "posted_to_telegram": False, "mutates_kb_by_harness": False, "db_counts_changed": False, "db_fingerprint_unchanged": True, "live_behavior_manifest_unchanged": True, "service_before_after": {"unchanged_from_preexisting_live_readback": True}, "temp_profile_removed": True, "model_call_trace_all_bound": True, "execution_manifest_summary": {"all_turns_attribution_complete": True}, } def test_redaction_preserves_json_and_removes_secret_values() -> None: raw = json.dumps( { "bot_token": "123456789:abcdefghijklmnopqrstuvwxyz_ABCD", "api_key": "sk-live-secret", "nested": {"password": "hunter2", "access_token": "bearer-secret"}, "message": "Authorization: Bearer top-secret-value", } ) redacted = suite.redact(raw) parsed = json.loads(redacted) assert parsed["bot_token"] == "[REDACTED]" assert parsed["api_key"] == "[REDACTED]" assert parsed["nested"]["password"] == "[REDACTED]" assert parsed["nested"]["access_token"] == "[REDACTED]" assert parsed["message"] == "Authorization: Bearer [REDACTED]" assert "hunter2" not in redacted assert "top-secret-value" not in redacted def test_successful_stdout_is_redacted_before_json_parsing(monkeypatch) -> None: secret = "123456789:abcdefghijklmnopqrstuvwxyz_ABCD" calls = iter( [ subprocess.CompletedProcess([], 0, stdout=json.dumps({"bot_token": secret}) + "\n", stderr=""), subprocess.CompletedProcess([], 0, stdout="", stderr=""), ] ) monkeypatch.setattr(suite.subprocess, "run", lambda *args, **kwargs: next(calls)) result = suite.run_remote(prompts=[]) assert result["parsed"]["bot_token"] == "[REDACTED]" assert secret not in json.dumps(result) def test_successful_stdout_survives_remote_report_cleanup_timeout(monkeypatch) -> None: completed = subprocess.CompletedProcess([], 0, stdout=json.dumps({"run_id": "complete"}) + "\n", stderr="") calls = 0 def fake_run(*args, **kwargs): nonlocal calls calls += 1 if calls == 1: return completed raise subprocess.TimeoutExpired(args[0], timeout=180) monkeypatch.setattr(suite.subprocess, "run", fake_run) result = suite.run_remote(prompts=[]) assert result["parsed"] == {"run_id": "complete"} assert result["remote_report_cleanup_confirmed"] is False def test_safety_gate_passes_only_for_complete_no_send_no_write_run() -> None: report = safe_report() assert suite.report_passes_safety(report) is True assert suite.build_safety_gate(report)["failed_checks"] == [] def test_safety_gate_rejects_write_capable_tool_and_incomplete_receipt() -> None: report = safe_report() report["results"][0]["database_tool_trace"]["database_tool_calls_read_only"] = False report["results"][0]["database_tool_trace"]["calls"][0]["database_invocations"][0]["access_mode"] = "write" report["execution_manifest_summary"]["all_turns_attribution_complete"] = False gate = suite.build_safety_gate(report) assert gate["status"] == "fail" assert "all_tool_traces_read_only_and_bound" in gate["failed_checks"] assert "all_turn_manifests_complete" in gate["failed_checks"] def test_safety_gate_rejects_missing_no_send_declaration() -> None: report = safe_report() report.pop("posted_to_telegram") gate = suite.build_safety_gate(report) assert gate["status"] == "fail" assert "no_telegram_post" in gate["failed_checks"] def test_response_binding_helper_requires_exact_prompt_and_delivered_reply_hashes() -> None: prompt = "Broad ID-free read-only question" reply = "A bounded grounded answer" result = {"prompt": prompt, "reply": reply} record = { "status": "ok", "validated": True, "query_sha256": hashlib.sha256(prompt.encode()).hexdigest(), "response_sha256": "a" * 64, "delivered_response_sha256": hashlib.sha256(reply.encode()).hexdigest(), } helper = response_binding_helper() assert helper([result], [record]) is True for field in ("query_sha256", "response_sha256", "delivered_response_sha256"): missing = dict(record) missing.pop(field) assert helper([result], [missing]) is False mismatched = dict(record, delivered_response_sha256="b" * 64) assert helper([result], [mismatched]) is False