#!/usr/bin/env python3 """Self-check for viz/life.html (Lifestrument). Stdlib only, no deps. Asserts the three things that keep the fun page honest: 1. life.html parses as balanced HTML (well-formed tags). 2. every hub source it wires is a real config.json signal (or a local me.* one). 3. the banned families (money & machinery) appear NOWHERE in the file. Run: python3 test_lifestrument.py """ import json import os import re import sys from html.parser import HTMLParser HERE = os.path.dirname(os.path.abspath(__file__)) LIFE = os.path.join(HERE, "viz", "life.html") CONFIG = os.path.join(HERE, "config.json") BANNED_PREFIXES = ("crypto.", "fx.", "market.", "econ.", "debt.", "quake.", "planes.", "iss.") # void elements never need a close tag VOID = {"area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr"} class Balance(HTMLParser): def __init__(self): super().__init__() self.stack = [] self.errors = [] def handle_starttag(self, tag, attrs): if tag not in VOID: self.stack.append(tag) def handle_startendtag(self, tag, attrs): pass # self-closing, balanced by definition def handle_endtag(self, tag): if tag in VOID: return if not self.stack: self.errors.append(f"stray ") return if self.stack[-1] == tag: self.stack.pop() elif tag in self.stack: # close intervening (lenient, like a browser) but flag it while self.stack and self.stack[-1] != tag: self.stack.pop() if self.stack: self.stack.pop() else: self.errors.append(f"unexpected ") def test_balanced_html(html): p = Balance() p.feed(html) assert not p.errors, f"HTML tag errors: {p.errors}" assert not p.stack, f"unclosed tags: {p.stack}" print(" ok: HTML is balanced") def test_no_banned(html): hits = [] for pref in BANNED_PREFIXES: # word-ish boundary so 'econ.' doesn't match e.g. 'second.' — require a # quote/backtick/space before the prefix, as our source keys always are. for m in re.finditer(r'["\'`\s(]' + re.escape(pref), html): frag = html[m.start():m.start() + 40].replace("\n", " ") hits.append(f"{pref!r} near: …{frag}…") assert not hits, "banned money/machinery keys present:\n " + "\n ".join(hits) print(f" ok: none of {BANNED_PREFIXES} appear") def test_whitelist_valid(html): signals = set(json.load(open(CONFIG))["signals"].keys()) # pull the WHITELIST Set literal from the source m = re.search(r"const WHITELIST = new Set\(\[(.*?)\]\)", html, re.S) assert m, "could not find WHITELIST Set in life.html" keys = re.findall(r'"([^"]+)"', m.group(1)) assert len(keys) >= 20, f"whitelist suspiciously small: {len(keys)} keys" missing = [k for k in keys if k not in signals] assert not missing, f"whitelist keys not in config.json signals: {missing}" # none of the whitelisted keys may themselves be banned bad = [k for k in keys if k.startswith(BANNED_PREFIXES)] assert not bad, f"whitelist contains banned keys: {bad}" print(f" ok: all {len(keys)} whitelist keys exist in config.json, none banned") def test_reuses_real_endpoints(html): for ep in ("/api/login", "/api/signup", "/api/me", "/api/logout"): assert ep in html, f"missing expected auth endpoint {ep}" # exact field names the hub expects assert "identifier:" in html, "login must send {identifier, password}" assert "invite:" in html, "signup must send an invite code" print(" ok: reuses the real /api/* auth endpoints with correct fields") def main(): html = open(LIFE, encoding="utf-8").read() print("test_lifestrument.py — checking viz/life.html") test_balanced_html(html) test_no_banned(html) test_whitelist_valid(html) test_reuses_real_endpoints(html) print("ALL CHECKS PASSED") if __name__ == "__main__": try: main() except AssertionError as e: print("FAIL:", e) sys.exit(1)