from __future__ import annotations import argparse import hashlib import json import subprocess from datetime import datetime, timezone from pathlib import Path def run_ssh(target: str, command: str) -> str: result = subprocess.run( ["ssh", target, command], check=True, capture_output=True, text=True, encoding="utf-8", errors="replace", ) return result.stdout def sha256(path: Path) -> str: digest = hashlib.sha256() with path.open("rb") as stream: for chunk in iter(lambda: stream.read(1024 * 1024), b""): digest.update(chunk) return digest.hexdigest() def main() -> int: parser = argparse.ArgumentParser(description="Collect non-secret QuantEngine evidence from a remote host") parser.add_argument("--target", required=True, help="SSH target, e.g. kjh2064@178.104.200.7") parser.add_argument("--remote-root", default="/home/kjh2064/quantengine_active") parser.add_argument("--repo-root", default=None) args = parser.parse_args() root = Path(args.repo_root).resolve() if args.repo_root else Path(__file__).resolve().parents[1] stamp = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ") out_dir = root / "Temp" / "evidence" / "remote" / stamp out_dir.mkdir(parents=True, exist_ok=True) # The command reads only public operational output. It never reads the # connection string or environment file, so secrets cannot enter evidence. journal = run_ssh( args.target, "journalctl -u quantengine --since '24 hours ago' --no-pager " "| grep -E 'daily-collection|Collection run|Collecting ticker|completed|KIS_DOTNET' || true", ) journal_path = out_dir / "quantengine-journal.log" journal_path.write_text(journal, encoding="utf-8") artifact = run_ssh( args.target, "if test -f " + args.remote_root + "/Temp/kis_dotnet_collection_v1.json; then " "cat " + args.remote_root + "/Temp/kis_dotnet_collection_v1.json; " "else exit 44; fi", ) artifact_path = out_dir / "kis_dotnet_collection_v1.json" artifact_path.write_text(artifact, encoding="utf-8") json.loads(artifact_path.read_text(encoding="utf-8")) manifest = { "formula_id": "REMOTE_WBS_EVIDENCE_MANIFEST_V1", "captured_at": datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"), "source": {"ssh_target": args.target, "remote_root": args.remote_root}, "secret_policy": "connection string and environment file were not read or copied", "artifacts": [ {"path": str(journal_path.relative_to(root)), "sha256": sha256(journal_path)}, {"path": str(artifact_path.relative_to(root)), "sha256": sha256(artifact_path)}, ], "postgresql": { "status": "NOT_INCLUDED", "reason": "Run verifier with QE_WBS_PG_DSN through an approved SSH tunnel; no password is copied.", }, } (out_dir / "manifest.json").write_text(json.dumps(manifest, indent=2), encoding="utf-8") print(json.dumps(manifest, indent=2)) return 0 if __name__ == "__main__": raise SystemExit(main())