teleo-infrastructure/scripts/collect_telegram_visible_direct_claim_preflight.py
twentyOne2x 9f892c5e34
Some checks are pending
CI / lint-and-test (push) Waiting to run
Harden Leo Telegram-visible preflight readback
2026-07-10 05:11:14 +02:00

471 lines
19 KiB
Python

#!/usr/bin/env python3
"""Collect read-only preflight for the Telegram-visible DC benchmark.
This is a pre-send proof collector. It verifies the exact authorization packet,
then reads the VPS deploy stamp, Leo gateway service state, and current KB row
counts. It never sends Telegram messages and never mutates the database.
"""
from __future__ import annotations
import argparse
import base64
import hashlib
import json
import shlex
import subprocess
from dataclasses import dataclass
from datetime import datetime, timezone
from pathlib import Path
from typing import Any, Callable
REPORT_DIR = Path("docs/reports/leo-working-state-20260709")
DEFAULT_PACKET = REPORT_DIR / "telegram-visible-direct-claim-authorization-packet-current.json"
DEFAULT_OUT = REPORT_DIR / "telegram-visible-direct-claim-preflight-current.json"
DEFAULT_MARKDOWN_OUT = REPORT_DIR / "telegram-visible-direct-claim-preflight-current.md"
DEFAULT_REMOTE_COMMAND_OUT = REPORT_DIR / "telegram-visible-direct-claim-remote-readback-command-current.sh"
DEFAULT_SSH_TARGET = "root@77.42.65.182"
DEFAULT_SSH_KEY = Path.home() / ".ssh/livingip_hetzner_20260604_ed25519"
REMOTE_REPO = "/opt/teleo-eval/workspaces/deploy-infra"
REMOTE_PACKET = (
f"{REMOTE_REPO}/docs/reports/leo-working-state-20260709/"
"telegram-visible-direct-claim-authorization-packet-current.json"
)
EXPECTED_PROMPT_IDS = ["DC-01", "DC-02", "DC-03", "DC-04", "DC-05", "DC-06"]
@dataclass(frozen=True)
class CommandResult:
returncode: int
stdout: str
stderr: str
Runner = Callable[[list[str], str, int], CommandResult]
def subprocess_runner(command: list[str], input_text: str, timeout: int) -> CommandResult:
proc = subprocess.run(command, input=input_text, text=True, capture_output=True, timeout=timeout, check=False)
return CommandResult(proc.returncode, proc.stdout, proc.stderr)
def _load_json(path: Path) -> dict[str, Any]:
return json.loads(path.read_text(encoding="utf-8"))
def packet_checks(packet: dict[str, Any]) -> dict[str, bool]:
target = packet.get("target", {})
return {
"packet_ready_to_request_authorization": packet.get("ready_to_request_authorization") is True,
"packet_not_sent": packet.get("telegram_visible_messages_sent") is False,
"packet_has_no_authorization_recorded": packet.get("telegram_visible_message_authorization_present") is False,
"packet_does_not_mutate_db": packet.get("mutates_db") is False,
"packet_does_not_execute_production_apply": packet.get("production_apply_executed") is False,
"packet_targets_leo_group": target.get("chat_label") == "Leo" and target.get("chat_id") == "-5146042086",
"packet_prompt_ids_exact": target.get("expected_prompt_ids") == EXPECTED_PROMPT_IDS,
"packet_message_count_exact": target.get("message_count") == len(EXPECTED_PROMPT_IDS),
}
def ssh_command(args: argparse.Namespace, remote_command: str) -> list[str]:
return [
"ssh",
"-i",
str(args.ssh_key),
"-o",
"BatchMode=yes",
"-o",
"StrictHostKeyChecking=accept-new",
"-o",
f"ConnectTimeout={args.connect_timeout}",
args.ssh_target,
remote_command,
]
def db_counts_sql() -> str:
return """
select jsonb_build_object(
'public.claims', (select count(*) from public.claims),
'public.sources', (select count(*) from public.sources),
'public.claim_evidence', (select count(*) from public.claim_evidence),
'public.claim_edges', (select count(*) from public.claim_edges),
'kb_stage.kb_proposals', (select count(*) from kb_stage.kb_proposals)
)::text;
""".strip()
def deploy_readback_command() -> str:
repo = shlex.quote(REMOTE_REPO)
packet = shlex.quote(REMOTE_PACKET)
return (
f"cd {repo} && "
"printf 'deploy_head=' && git rev-parse HEAD && "
"printf 'last_deploy_sha=' && cat /opt/teleo-eval/.last-deploy-sha && printf '\\n' && "
f"if [ -s {packet} ]; then "
"printf 'packet_present=true\\npacket_bytes='; "
f"wc -c < {packet}; "
"else printf 'packet_present=false\\npacket_bytes=0\\n'; fi"
)
def service_readback_command() -> str:
return (
"systemctl show leoclean-gateway.service "
"-p ActiveState -p SubState -p MainPID -p NRestarts -p ExecMainStartTimestamp --no-pager"
)
def db_counts_readback_command() -> str:
return "docker exec teleo-pg psql -U postgres -d teleo -At -q -c " + shlex.quote(db_counts_sql())
def parse_key_value_lines(text: str) -> dict[str, str]:
values = {}
for line in text.splitlines():
if "=" not in line:
continue
key, value = line.split("=", 1)
values[key] = value.strip()
return values
def collect_remote_direct(args: argparse.Namespace, runner: Runner) -> tuple[dict[str, Any] | None, int, str]:
commands = {
"deploy": deploy_readback_command(),
"service": service_readback_command(),
"db_counts": db_counts_readback_command(),
}
results = {
name: runner(ssh_command(args, command), "", args.timeout)
for name, command in commands.items()
}
stderr = "\n".join(
f"{name}: {result.stderr.strip()}"
for name, result in results.items()
if result.stderr.strip()
)
returncode = next((result.returncode for result in results.values() if result.returncode != 0), 0)
deploy_values = parse_key_value_lines(results["deploy"].stdout)
service_values = parse_key_value_lines(results["service"].stdout)
counts = None
if results["db_counts"].returncode == 0 and results["db_counts"].stdout.strip():
try:
counts = json.loads(results["db_counts"].stdout.strip())
except json.JSONDecodeError:
counts = None
try:
packet_bytes = int(deploy_values.get("packet_bytes", "0") or "0")
except ValueError:
packet_bytes = 0
payload = {
"deploy_head": {
"returncode": results["deploy"].returncode,
"stdout": deploy_values.get("deploy_head", ""),
"stderr": results["deploy"].stderr.strip(),
},
"last_deploy_sha": {
"returncode": results["deploy"].returncode,
"stdout": deploy_values.get("last_deploy_sha", ""),
"stderr": results["deploy"].stderr.strip(),
},
"packet_present": deploy_values.get("packet_present") == "true",
"packet_bytes": packet_bytes,
"service": {
"returncode": results["service"].returncode,
"stderr": results["service"].stderr,
"state": service_values,
},
"db_counts": {
"returncode": results["db_counts"].returncode,
"stderr": results["db_counts"].stderr,
"counts": counts,
},
}
return payload, returncode, stderr
def remote_readback_command_script(args: argparse.Namespace) -> str:
ssh_prefix = " ".join(
shlex.quote(part)
for part in [
"ssh",
"-i",
str(args.ssh_key),
"-o",
"BatchMode=yes",
"-o",
"StrictHostKeyChecking=accept-new",
"-o",
f"ConnectTimeout={int(args.connect_timeout)}",
args.ssh_target,
]
)
lines = [
"#!/usr/bin/env bash",
"set -euo pipefail",
f"# Remote packet: {REMOTE_PACKET}",
"# Readback covers deploy head, .last-deploy-sha, leoclean-gateway.service, and DB counts:",
"# public.claims, public.sources, public.claim_evidence, public.claim_edges, kb_stage.kb_proposals",
"run_ssh() {",
f" {ssh_prefix} \"$1\"",
"}",
f"DEPLOY_READBACK=\"$(run_ssh {shlex.quote(deploy_readback_command())})\"",
f"SERVICE_READBACK=\"$(run_ssh {shlex.quote(service_readback_command())})\"",
f"DB_COUNTS_READBACK=\"$(run_ssh {shlex.quote(db_counts_readback_command())})\"",
"python3 - \"$DEPLOY_READBACK\" \"$SERVICE_READBACK\" \"$DB_COUNTS_READBACK\" <<'PY' | base64 | tr -d '\\n'",
"import json",
"import sys",
"",
"def kv(text):",
" out = {}",
" for line in text.splitlines():",
" if '=' in line:",
" key, value = line.split('=', 1)",
" out[key] = value.strip()",
" return out",
"",
"deploy = kv(sys.argv[1])",
"service = kv(sys.argv[2])",
"counts = json.loads(sys.argv[3])",
"payload = {",
" 'deploy_head': {'returncode': 0, 'stdout': deploy.get('deploy_head', ''), 'stderr': ''},",
" 'last_deploy_sha': {'returncode': 0, 'stdout': deploy.get('last_deploy_sha', ''), 'stderr': ''},",
" 'packet_present': deploy.get('packet_present') == 'true',",
" 'packet_bytes': int(deploy.get('packet_bytes') or 0),",
" 'service': {'returncode': 0, 'stderr': '', 'state': service},",
" 'db_counts': {'returncode': 0, 'stderr': '', 'counts': counts},",
"}",
"print(json.dumps(payload, sort_keys=True))",
"PY",
"printf '\\n'",
"",
]
return "\n".join(lines)
def write_remote_readback_command(path: Path, args: argparse.Namespace) -> str:
script = remote_readback_command_script(args)
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(script, encoding="utf-8")
path.chmod(0o755)
return hashlib.sha256(script.encode("utf-8")).hexdigest()
def remote_payload_from_args(args: argparse.Namespace) -> tuple[dict[str, Any] | None, int, str]:
if args.remote_json_base64:
try:
decoded = base64.b64decode(args.remote_json_base64, validate=True).decode("utf-8")
return json.loads(decoded), 0, ""
except Exception as exc: # noqa: BLE001 - retained in artifact as a parse gate
return None, 2, f"failed to parse --remote-json-base64: {exc}"
return None, -1, ""
def collect_preflight(args: argparse.Namespace, *, runner: Runner = subprocess_runner) -> dict[str, Any]:
packet = _load_json(args.packet)
local_packet_checks = packet_checks(packet)
supplied_payload, supplied_returncode, supplied_stderr = remote_payload_from_args(args)
if supplied_returncode >= 0:
remote_payload = supplied_payload
remote_returncode = supplied_returncode
remote_stderr = supplied_stderr
remote_source = "supplied_remote_json_base64"
else:
remote_payload, remote_returncode, remote_stderr = collect_remote_direct(args, runner)
remote_source = "ssh_direct_commands"
remote_checks = {
"ssh_readback_ok": remote_returncode == 0 and remote_payload is not None,
"remote_packet_present": bool((remote_payload or {}).get("packet_present")),
"remote_packet_nonempty": int((remote_payload or {}).get("packet_bytes") or 0) > 0,
"deploy_head_matches_last_deploy": False,
"service_active_running": False,
"db_counts_read": False,
}
if remote_payload:
deploy_head = remote_payload.get("deploy_head", {}).get("stdout")
last_deploy = remote_payload.get("last_deploy_sha", {}).get("stdout")
service_state = remote_payload.get("service", {}).get("state", {})
counts = remote_payload.get("db_counts", {}).get("counts")
remote_checks.update(
{
"deploy_head_matches_last_deploy": bool(deploy_head and deploy_head == last_deploy),
"service_active_running": service_state.get("ActiveState") == "active"
and service_state.get("SubState") == "running",
"db_counts_read": isinstance(counts, dict)
and all(key in counts for key in EXPECTED_DB_COUNT_KEYS),
}
)
status = "pass" if all(local_packet_checks.values()) and all(remote_checks.values()) else "fail"
blocker_readback = {
"current_canary": (
"Pre-send Telegram-visible direct-claim benchmark readiness for DC-01 through DC-06 in the "
"Leo group, expecting packet verification plus VPS deploy/service/DB count readback before "
"any authorized send."
),
"attempted_routes": [
"local authorization packet validation",
f"{remote_source} remote VPS readback for deploy stamp, service state, packet presence, and DB counts",
],
"exact_gate": "" if status == "pass" else (remote_stderr.strip() or "remote readback checks did not pass"),
"clear_CTA": (
f"Run `{args.remote_command_out}` from a full-access shell, then rerun "
"`scripts/collect_telegram_visible_direct_claim_preflight.py --remote-json-base64 <payload>` "
"with the base64 output it prints. "
"Only after this report passes should the exact DC-01 through DC-06 Telegram group messages be "
"sent under explicit action-time authorization."
),
"next_non_user_action": (
"Rerun this preflight with supplied VPS remote readback JSON, then run the Telegram-visible "
"DC scorer and service/DB after-readbacks if the user explicitly authorizes the group send."
),
}
return {
"generated_at_utc": datetime.now(timezone.utc).isoformat(),
"mode": "telegram_visible_direct_claim_preflight_readonly",
"status": status,
"ready_for_authorized_telegram_visible_dc_run": status == "pass",
"telegram_visible_messages_sent": False,
"production_apply_executed": False,
"mutates_db": False,
"packet_path": str(args.packet),
"packet_checks": local_packet_checks,
"remote_checks": remote_checks,
"remote_source": remote_source,
"remote": remote_payload,
"remote_returncode": remote_returncode,
"remote_stderr": remote_stderr,
"remote_readback_command_path": str(args.remote_command_out),
"remote_readback_command_sha256": hashlib.sha256(
remote_readback_command_script(args).encode("utf-8")
).hexdigest(),
"blocker_readback": blocker_readback,
"claim_ceiling": (
"This is a read-only preflight for an explicitly authorized Telegram-visible DC benchmark. It does "
"not send Telegram messages, does not run production apply, and does not prove Telegram-visible DC "
"behavior until the six-message run is authorized, sent, captured, and scored."
),
}
EXPECTED_DB_COUNT_KEYS = [
"public.claims",
"public.sources",
"public.claim_evidence",
"public.claim_edges",
"kb_stage.kb_proposals",
]
def write_json(path: Path, data: dict[str, Any]) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(json.dumps(data, indent=2, sort_keys=True) + "\n", encoding="utf-8")
def write_markdown(path: Path, data: dict[str, Any]) -> None:
remote = data.get("remote") or {}
service = remote.get("service", {}).get("state", {})
counts = remote.get("db_counts", {}).get("counts") or {}
lines = [
"# Telegram-Visible Direct-Claim Preflight",
"",
f"Generated UTC: `{data['generated_at_utc']}`",
f"Mode: `{data['mode']}`",
f"Status: `{data['status']}`",
f"Ready for authorized Telegram-visible DC run: `{data['ready_for_authorized_telegram_visible_dc_run']}`",
f"Telegram-visible messages sent: `{data['telegram_visible_messages_sent']}`",
f"Production apply executed: `{data['production_apply_executed']}`",
f"Mutates DB: `{data['mutates_db']}`",
f"Remote source: `{data['remote_source']}`",
f"Remote readback command: `{data['remote_readback_command_path']}`",
f"Remote readback command SHA256: `{data['remote_readback_command_sha256']}`",
"",
"## Packet Checks",
"",
]
lines.extend(f"- `{key}`: `{value}`" for key, value in sorted(data["packet_checks"].items()))
lines.extend(["", "## Remote Checks", ""])
lines.extend(f"- `{key}`: `{value}`" for key, value in sorted(data["remote_checks"].items()))
lines.extend(
[
"",
"## Deploy And Service",
"",
f"- Deploy head: `{remote.get('deploy_head', {}).get('stdout', '')}`",
f"- Last deploy SHA: `{remote.get('last_deploy_sha', {}).get('stdout', '')}`",
f"- ActiveState: `{service.get('ActiveState', '')}`",
f"- SubState: `{service.get('SubState', '')}`",
f"- MainPID: `{service.get('MainPID', '')}`",
f"- NRestarts: `{service.get('NRestarts', '')}`",
f"- ExecMainStartTimestamp: `{service.get('ExecMainStartTimestamp', '')}`",
"",
"## DB Counts Before Send",
"",
]
)
lines.extend(f"- `{key}`: `{counts.get(key, '')}`" for key in EXPECTED_DB_COUNT_KEYS)
if data["status"] != "pass":
blocker = data.get("blocker_readback", {})
lines.extend(
[
"",
"## Blocker Readback",
"",
f"- Current canary: {blocker.get('current_canary', '')}",
f"- Exact gate: `{blocker.get('exact_gate', '')}`",
f"- Clear CTA: {blocker.get('clear_CTA', '')}",
f"- Next non-user action: {blocker.get('next_non_user_action', '')}",
]
)
lines.extend(["", "## Claim Ceiling", "", data["claim_ceiling"], ""])
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text("\n".join(lines), encoding="utf-8")
def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--packet", type=Path, default=DEFAULT_PACKET)
parser.add_argument("--ssh-target", default=DEFAULT_SSH_TARGET)
parser.add_argument("--ssh-key", type=Path, default=DEFAULT_SSH_KEY)
parser.add_argument("--connect-timeout", type=int, default=10)
parser.add_argument("--timeout", type=int, default=60)
parser.add_argument(
"--remote-json-base64",
help="Base64-encoded remote readback JSON from an approved top-level SSH command; skips subprocess SSH.",
)
parser.add_argument("--out", type=Path, default=DEFAULT_OUT)
parser.add_argument("--markdown-out", type=Path, default=DEFAULT_MARKDOWN_OUT)
parser.add_argument("--remote-command-out", type=Path, default=DEFAULT_REMOTE_COMMAND_OUT)
return parser.parse_args(argv)
def main(argv: list[str] | None = None) -> int:
args = parse_args(argv)
remote_command_sha256 = write_remote_readback_command(args.remote_command_out, args)
data = collect_preflight(args)
if data["remote_readback_command_sha256"] != remote_command_sha256:
raise RuntimeError("remote readback command hash drifted during collection")
write_json(args.out, data)
write_markdown(args.markdown_out, data)
print(
json.dumps(
{
"out": str(args.out),
"markdown_out": str(args.markdown_out),
"remote_command_out": str(args.remote_command_out),
"status": data["status"],
"ready_for_authorized_telegram_visible_dc_run": data[
"ready_for_authorized_telegram_visible_dc_run"
],
},
indent=2,
sort_keys=True,
)
)
return 0 if data["status"] == "pass" else 2
if __name__ == "__main__":
raise SystemExit(main())