verae-mcp-timestamping-server/scripts/nats_stamp.py
George Lambert 1ca834900e feat: site WIP — downloads, explorer, hasher, TestFlight enroll
Commit restored mcp.verae.ai site pages (app, register, macos, windows,
explorer), hasher/download artifacts, index/sample/hasher updates, ledger
and global_client improvements, NATS stamp helper, and TestFlight enroll
service. Ignore debug-trace/ and editor backups. Standard Readme for
download and enroll docs.
2026-09-29 11:18:59 -04:00

158 lines
5.6 KiB
Python

"""Stamp digests over core NATS. Subscribe to verae.ts.completed before requesting.
No status poll and no retry sleep. A known digest returns its certificate on the
request reply. A new digest returns a jobId, then verae.ts.completed carries the
certificate.
Usage:
python scripts/nats_stamp.py <64-hex-or-text> [...]
VERAE_NATS_URL=nats://127.0.0.1:4222 python scripts/nats_stamp.py "Hello World!"
"""
from __future__ import annotations
import hashlib
import json
import os
import socket
import sys
import time
SUBJECT_REQUEST = "verae.ts.request"
SUBJECT_COMPLETED = "verae.ts.completed"
def digest_of(text: str) -> str:
raw = text.strip().lower()
if raw.startswith("sha256:"):
raw = raw[7:]
if len(raw) == 64 and all(c in "0123456789abcdef" for c in raw):
return raw
return hashlib.sha256(text.encode()).hexdigest()
class Conn:
def __init__(self, url: str) -> None:
host_port = url.split("://", 1)[-1]
host, port_s = host_port.rsplit(":", 1)
self.sock = socket.create_connection((host, int(port_s)), timeout=5)
self.buf = b""
info = self._read_line()
if not info.startswith("INFO "):
raise RuntimeError(info)
self.queued: dict[str, list[dict]] = {}
self._send(
'CONNECT {"verbose":false,"pedantic":false,"lang":"verae-stamp","version":"1","protocol":1}\r\n'
"PING\r\n"
)
self._expect_pong()
def _send(self, text: str) -> None:
self.sock.sendall(text.encode())
def _read_line(self) -> str:
while b"\r\n" not in self.buf:
chunk = self.sock.recv(65536)
if not chunk:
raise RuntimeError("nats closed")
self.buf += chunk
line, self.buf = self.buf.split(b"\r\n", 1)
return line.decode()
def _expect_pong(self) -> None:
while True:
line = self._read_line()
if line == "PONG" or line.startswith("+OK"):
if line == "PONG":
return
continue
if line.startswith("-ERR"):
raise RuntimeError(line)
def subscribe(self, subject: str, sid: str) -> None:
self._send(f"SUB {subject} {sid}\r\n")
def request(self, subject: str, payload: dict, inbox: str, sid: str) -> dict:
raw = json.dumps(payload).encode()
self.subscribe(inbox, sid)
self._send(f"PUB {subject} {inbox} {len(raw)}\r\n")
self._send(raw.decode() + "\r\n")
return self._wait_sid(sid, 30.0)
def _read_msg(self) -> tuple[str, dict]:
while True:
line = self._read_line()
if line.startswith("PING"):
self._send("PONG\r\n")
continue
if line.startswith("PONG") or line.startswith("+OK"):
continue
if not line.startswith("MSG "):
continue
parts = line.split()
size = int(parts[-1])
msg_sid = parts[2]
while len(self.buf) < size + 2:
chunk = self.sock.recv(65536)
if not chunk:
raise RuntimeError("nats closed")
self.buf += chunk
body = self.buf[:size]
self.buf = self.buf[size + 2 :]
return msg_sid, json.loads(body.decode())
def _wait_sid(self, sid: str, timeout: float) -> dict:
queued = self.queued.get(sid) or []
if queued:
return queued.pop(0)
deadline = time.time() + timeout
while time.time() < deadline:
self.sock.settimeout(max(0.1, deadline - time.time()))
msg_sid, body = self._read_msg()
if msg_sid == sid:
return body
self.queued.setdefault(msg_sid, []).append(body)
raise TimeoutError(sid)
def next_completed(self, timeout: float) -> dict:
return self._wait_sid("done", timeout)
def main(argv: list[str]) -> int:
if not argv:
print("usage: nats_stamp.py <text-or-digest> [...]", file=sys.stderr)
return 2
url = os.environ.get("VERAE_NATS_URL", "nats://127.0.0.1:4222")
digests = [digest_of(item) for item in argv]
conn = Conn(url)
conn.subscribe(SUBJECT_COMPLETED, "done")
pending: dict[str, str] = {}
receipts: dict[str, str] = {}
t0 = time.perf_counter()
for i, digest in enumerate(digests):
started = time.perf_counter()
body = conn.request(SUBJECT_REQUEST, {"hash": digest}, f"_INBOX.{i}", f"inbox{i}")
if body.get("error"):
print(json.dumps({"hash": digest, "error": body["error"]}))
return 1
elapsed = (time.perf_counter() - started) * 1000
if body.get("receipt_id"):
receipts[digest] = body["receipt_id"]
print(json.dumps({"hash": digest, "receipt_id": body["receipt_id"], "existing": body.get("existing"), "ms": round(elapsed, 3)}))
else:
pending[body["jobId"]] = digest
print(json.dumps({"hash": digest, "jobId": body.get("jobId"), "existing": False, "ms": round(elapsed, 3)}))
while pending:
msg = conn.next_completed(30)
job_id = msg.get("jobId")
digest = pending.pop(job_id, None)
if digest is None:
continue
receipts[digest] = msg.get("receipt_id") or ""
print(json.dumps({"hash": digest, "jobId": job_id, "receipt_id": receipts[digest], "via": "verae.ts.completed"}))
print(json.dumps({"n": len(digests), "receipts": len(receipts), "wall_ms": round((time.perf_counter() - t0) * 1000, 3)}))
return 0
if __name__ == "__main__":
raise SystemExit(main(sys.argv[1:]))