240 lines
8.4 KiB
Python
240 lines
8.4 KiB
Python
from __future__ import annotations
|
|
|
|
import copy
|
|
from pathlib import Path
|
|
|
|
from scripts import build_telegram_visible_unseen_chain_packet as packet_builder
|
|
from scripts import verify_telegram_visible_unseen_chain as verifier
|
|
|
|
SUBJECT_ID = "c0000000-0000-4000-8000-000000000001"
|
|
|
|
|
|
def packet_and_path(tmp_path: Path) -> tuple[dict, Path]:
|
|
packet = packet_builder.build_packet(
|
|
handler_receipt_path=packet_builder.DEFAULT_HANDLER_RECEIPT.resolve(),
|
|
git_sha="a" * 40,
|
|
)
|
|
path = tmp_path / "packet.json"
|
|
packet_builder.write_json(path, packet)
|
|
return packet, path
|
|
|
|
|
|
def preflight(packet: dict, packet_path: Path) -> dict:
|
|
return {
|
|
"phase": "preflight",
|
|
"status": "pass",
|
|
"protocol_sha256": packet["protocol_sha256"],
|
|
"packet_file_sha256": verifier._sha256_file(packet_path),
|
|
"state_token_sha256": "1" * 64,
|
|
"remote": {
|
|
"fingerprint_after": {"fingerprint_sha256": "f" * 64},
|
|
"service_after": {
|
|
"MainPID": "123",
|
|
"NRestarts": "0",
|
|
"ExecMainStartTimestamp": "Wed 2026-07-15 00:00:00 UTC",
|
|
},
|
|
},
|
|
}
|
|
|
|
|
|
def postflight(packet: dict) -> dict:
|
|
return {
|
|
"phase": "postflight",
|
|
"status": "pass",
|
|
"protocol_sha256": packet["protocol_sha256"],
|
|
"state_token_sha256": "2" * 64,
|
|
"subject_ref": "c0000000",
|
|
"remote": {
|
|
"fingerprint_after": {"fingerprint_sha256": "f" * 64},
|
|
"service_after": {
|
|
"MainPID": "123",
|
|
"NRestarts": "0",
|
|
"ExecMainStartTimestamp": "Wed 2026-07-15 00:00:00 UTC",
|
|
},
|
|
"subject_readback": {
|
|
"subject_ref": "c0000000",
|
|
"matches": [
|
|
{
|
|
"table": "public.beliefs",
|
|
"row": {"id": SUBJECT_ID, "statement": "Coordination is the bottleneck."},
|
|
}
|
|
],
|
|
},
|
|
},
|
|
}
|
|
|
|
|
|
def good_capture(packet: dict, tmp_path: Path) -> dict:
|
|
screenshot = tmp_path / "final.png"
|
|
accessibility = tmp_path / "final.txt"
|
|
screenshot.write_bytes(b"png proof")
|
|
accessibility.write_text("telegram accessibility proof", encoding="utf-8")
|
|
replies = [
|
|
(
|
|
"The database public.beliefs object c0000000 is an axiom with confidence 0.85. What supports it in "
|
|
"the DB: nothing supports it; there are zero evidence rows and no external primary source."
|
|
),
|
|
(
|
|
"Claim c0000000 is still the coordination bottleneck belief. Assumption versus observed support: the "
|
|
"priority leap is assumed and the evidence is absent. Falsifier: a contrary case. Proposal A and "
|
|
"Proposal B are staged only for review; nothing applied and neither is live knowledge."
|
|
),
|
|
(
|
|
"Revised proposal: separate the mechanism from the business outcome. What would resolve the "
|
|
"disagreement: a randomized study and its primary source dataset. Keep it pending_review for human "
|
|
"review; approved is not apply and applied_at remains null. This is not an apply."
|
|
),
|
|
]
|
|
messages = []
|
|
for item, reply in zip(packet["exact_messages"], replies, strict=True):
|
|
sequence = item["sequence"]
|
|
turn_screenshot = tmp_path / f"turn-{sequence}.png"
|
|
turn_accessibility = tmp_path / f"turn-{sequence}.txt"
|
|
turn_screenshot.write_bytes(f"turn {sequence} screenshot".encode())
|
|
turn_accessibility.write_text(
|
|
f"Telegram message: {item['message']}\nLeo reply: {reply}\n",
|
|
encoding="utf-8",
|
|
)
|
|
messages.append(
|
|
{
|
|
"sequence": sequence,
|
|
"prompt_id": item["prompt_id"],
|
|
"sent_text": item["message"],
|
|
"reply": reply,
|
|
"sent_at_utc": f"2026-07-15T00:0{sequence}:00Z",
|
|
"reply_at_utc": f"2026-07-15T00:0{sequence}:20Z",
|
|
"telegram_message_id": f"sent-{sequence}",
|
|
"reply_message_id": f"reply-{sequence}",
|
|
"turn_screenshot": str(turn_screenshot),
|
|
"turn_accessibility": str(turn_accessibility),
|
|
}
|
|
)
|
|
return {
|
|
"protocol_sha256": packet["protocol_sha256"],
|
|
"preflight_state_token_sha256": "1" * 64,
|
|
"operator_authorization_text": packet["explicit_operator_authorization_text"],
|
|
"operator_authorization_captured_at_utc": "2026-07-15T00:00:00Z",
|
|
"extra_messages_sent": 0,
|
|
"capture_source": {
|
|
"platform": "telegram",
|
|
"transport": "authenticated_chrome_telegram_ui",
|
|
"chat_label": "Leo",
|
|
"chat_id": "-5146042086",
|
|
"captured_at_utc": "2026-07-15T00:05:00Z",
|
|
"captured_by": "codex",
|
|
"final_screenshot": str(screenshot),
|
|
"final_accessibility": str(accessibility),
|
|
},
|
|
"messages": messages,
|
|
}
|
|
|
|
|
|
def test_no_capture_returns_awaiting_authorization_template(tmp_path: Path) -> None:
|
|
packet, packet_path = packet_and_path(tmp_path)
|
|
|
|
receipt = verifier.verify_capture(
|
|
packet,
|
|
preflight(packet, packet_path),
|
|
None,
|
|
None,
|
|
packet_path=packet_path,
|
|
evidence_root=tmp_path,
|
|
)
|
|
|
|
assert receipt["status"] == "awaiting_action_time_authorization"
|
|
assert receipt["telegram_visible_messages_sent"] is False
|
|
assert receipt["capture_template"]["messages"][0]["prompt_id"] == "OOS-CHAIN-01"
|
|
|
|
|
|
def test_good_chrome_capture_and_unchanged_fingerprint_pass_t3(tmp_path: Path) -> None:
|
|
packet, packet_path = packet_and_path(tmp_path)
|
|
before = preflight(packet, packet_path)
|
|
|
|
receipt = verifier.verify_capture(
|
|
packet,
|
|
before,
|
|
good_capture(packet, tmp_path),
|
|
postflight(packet),
|
|
packet_path=packet_path,
|
|
evidence_root=tmp_path,
|
|
)
|
|
|
|
assert receipt["status"] == "pass"
|
|
assert receipt["receipt_ready"] is True
|
|
assert receipt["current_tier"] == "T3_live_readonly"
|
|
assert all(receipt["checks"].values())
|
|
assert all(receipt["outcomes"].values())
|
|
assert receipt["selected_subject"]["row_id"] == SUBJECT_ID
|
|
|
|
|
|
def test_bot_api_capture_is_rejected(tmp_path: Path) -> None:
|
|
packet, packet_path = packet_and_path(tmp_path)
|
|
capture = good_capture(packet, tmp_path)
|
|
capture["capture_source"]["transport"] = "telegram_bot_api"
|
|
|
|
receipt = verifier.verify_capture(
|
|
packet,
|
|
preflight(packet, packet_path),
|
|
capture,
|
|
postflight(packet),
|
|
packet_path=packet_path,
|
|
evidence_root=tmp_path,
|
|
)
|
|
|
|
assert receipt["status"] == "fail"
|
|
assert receipt["checks"]["authenticated_chrome_transport_proven"] is False
|
|
assert receipt["checks"]["bot_api_not_substituted"] is False
|
|
|
|
|
|
def test_postflight_fingerprint_drift_is_rejected(tmp_path: Path) -> None:
|
|
packet, packet_path = packet_and_path(tmp_path)
|
|
after = copy.deepcopy(postflight(packet))
|
|
after["remote"]["fingerprint_after"]["fingerprint_sha256"] = "0" * 64
|
|
|
|
receipt = verifier.verify_capture(
|
|
packet,
|
|
preflight(packet, packet_path),
|
|
good_capture(packet, tmp_path),
|
|
after,
|
|
packet_path=packet_path,
|
|
evidence_root=tmp_path,
|
|
)
|
|
|
|
assert receipt["status"] == "fail"
|
|
assert receipt["checks"]["canonical_fingerprint_unchanged_from_preflight"] is False
|
|
|
|
|
|
def test_message_text_drift_is_rejected(tmp_path: Path) -> None:
|
|
packet, packet_path = packet_and_path(tmp_path)
|
|
capture = good_capture(packet, tmp_path)
|
|
capture["messages"][1]["sent_text"] += " extra"
|
|
|
|
receipt = verifier.verify_capture(
|
|
packet,
|
|
preflight(packet, packet_path),
|
|
capture,
|
|
postflight(packet),
|
|
packet_path=packet_path,
|
|
evidence_root=tmp_path,
|
|
)
|
|
|
|
assert receipt["status"] == "fail"
|
|
assert receipt["checks"]["sent_text_exact"] is False
|
|
|
|
|
|
def test_copied_reply_not_present_in_accessibility_is_rejected(tmp_path: Path) -> None:
|
|
packet, packet_path = packet_and_path(tmp_path)
|
|
capture = good_capture(packet, tmp_path)
|
|
capture["messages"][0]["reply"] += " copied-only suffix"
|
|
|
|
receipt = verifier.verify_capture(
|
|
packet,
|
|
preflight(packet, packet_path),
|
|
capture,
|
|
postflight(packet),
|
|
packet_path=packet_path,
|
|
evidence_root=tmp_path,
|
|
)
|
|
|
|
assert receipt["status"] == "fail"
|
|
assert receipt["checks"]["turn_accessibility_binds_exact_messages_and_replies"] is False
|