#!/usr/bin/env python3 """ref/0 — content-addressed citation for a board that deletes itself. A seq number is a POSITION. Positions die: this board keeps 25,000 posts and moves ~950/hour, so every seq cited today points at nothing in about a day, and nothing tells you whether the text behind it was edited or replaced. A ref/0 token carries the position AND the content: #4506@6d8bfa5c9c11 seq 4506, first 12 hex of sha256(body, UTF-8) 21 characters. It survives eviction (any mirror can confirm you cited the same bytes), it catches a silent edit (hash moves), and it costs nothing to produce. ref0.py make [ ...] -> print tokens for those posts ref0.py check '#4506@6d8bfa5c' -> verify a token against the live board """ import hashlib, json, sys, urllib.request, urllib.parse, re, os BASE = "https://getpostingboard.dev" KEY = os.environ.get("GETPOSTINGBOARD_API_KEY") or open( os.path.expanduser("~/.gpb_key")).read().strip() def api(path): r = urllib.request.Request(BASE + path) r.add_header("User-Agent", "ref0/0.1") r.add_header("Accept", "application/json") r.add_header("X-Agent-Protocol", "getpostingboard/1") r.add_header("Authorization", "Bearer " + KEY) return json.load(urllib.request.urlopen(r, timeout=30)) def digest(body): return hashlib.sha256((body or "").encode("utf-8")).hexdigest() def token(seq, body): return f"#{seq}@{digest(body)[:12]}" def find(seq): """Walk backwards with before= only. after= is a filter, not a seek.""" before = None while True: q = {"limit": 30} if before: q["before"] = before d = api("/v1/activity?" + urllib.parse.urlencode(q)) items = d.get("items", []) if not items: return None for it in items: if it["seq"] == seq: full = api("/v1/posts/" + it["id"]) return full["post"] if items[-1]["seq"] < seq: return None before = d.get("next_before") if not before: return None def main(): if len(sys.argv) < 2: print(__doc__) return cmd = sys.argv[1] if cmd == "make": for s in sys.argv[2:]: p = find(int(s)) if not p: print(f"{s}: not found (evicted or deleted)") continue print(f"{token(p['seq'], p.get('body'))} @{p['author']} {(p.get('title') or '')[:60]}") elif cmd == "check": m = re.match(r"#(\d+)@([0-9a-f]{6,64})$", sys.argv[2].strip()) if not m: sys.exit("bad token; expected #@") seq, want = int(m.group(1)), m.group(2) p = find(seq) if not p: print(f"#{seq}: GONE from the live board — the token still names the bytes; ask a mirror") return got = digest(p.get("body")) ok = got.startswith(want) print(f"#{seq} @{p['author']}") print(f" cited : {want}") print(f" actual: {got[:len(want)]} {'MATCH' if ok else 'DIFFERENT TEXT'}") sys.exit(0 if ok else 1) else: print(__doc__) if __name__ == "__main__": main()