coulomb-social/coulomb_social/apps/spaces/rendering_audit.py
tegwick 17d0eb67f3
Some checks failed
Use-case regression gate / usecase-regressions (push) Failing after 8m7s
Prepare actual-renderer corpus review and independent recovery custody packet
Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a17f16-d99c-7ea3-95f0-8212897fba6b
2026-10-28 00:54:17 +01:00

103 lines
5.1 KiB
Python

"""Private corpus rendering evidence using the actual product renderer."""
from __future__ import annotations
import hashlib
import html
from collections import Counter
from html.parser import HTMLParser
from urllib.parse import quote
from .content import render_markdown, render_markdown_unfiltered
class _Structure(HTMLParser):
def __init__(self, value):
super().__init__(convert_charrefs=True)
self.tags = Counter()
self.attributes = Counter()
self.text = []
self.feed(value)
def handle_starttag(self, tag, attrs):
self.tags[tag] += 1
self.attributes.update((tag, key, value) for key, value in attrs)
handle_startendtag = handle_starttag
def handle_data(self, value):
self.text.append(value)
def audit_body(body: str):
raw = render_markdown_unfiltered(body)
rendered = render_markdown(body)
before, after = _Structure(raw), _Structure(rendered)
removed_attrs = before.attributes - after.attributes
text_changed = " ".join("".join(before.text).split()) != (
" ".join("".join(after.text).split()))
markup_changed = before.tags != after.tags or before.attributes != after.attributes
return {
"body_sha256": hashlib.sha256(body.encode()).hexdigest(),
"rendered_sha256": hashlib.sha256(rendered.encode()).hexdigest(),
"sanitization_changed_html": raw != rendered,
"markup_changed_by_sanitization": markup_changed,
"serialization_only_change": raw != rendered and not markup_changed and not text_changed,
"removed_tag_counts": dict(sorted((before.tags - after.tags).items())),
"added_tag_counts": dict(sorted((after.tags - before.tags).items())),
"removed_attributes": [
{"tag": tag, "attribute": key, "value": value, "count": count}
for (tag, key, value), count in sorted(
removed_attrs.items(), key=lambda item: repr(item[0]))
],
"visible_text_changed_by_sanitization": text_changed,
"original_bubble_render_compared": False,
"productive_fidelity_accepted": False,
}, rendered
def review_card(title: str, body: str, rendered: str, audit: dict, *, source_id="") -> bytes:
# Private review files must not load source images, frames, styles or scripts.
# Inert also prevents links/forms in the rendered sample from being activated.
original = ('<p><a target="_blank" rel="noopener noreferrer" href="'
+ html.escape("https://coulomb.social/pg_chunk/" + quote(source_id, safe=""),
quote=True)
+ '">Open original Bubble view</a> (opens only when clicked)</p>'
) if source_id else ""
return ("<!doctype html><html><head><meta charset=\"utf-8\">"
'<meta http-equiv="Content-Security-Policy" content="default-src \'none\'; '
'style-src \'unsafe-inline\'; base-uri \'none\'; form-action \'none\'">'
"<title>Private rendering review</title><style>"
"body{font:16px system-ui;margin:2em}main{display:grid;grid-template-columns:1fr 1fr;"
"gap:2em}pre{white-space:pre-wrap;overflow-wrap:anywhere}section{min-width:0}"
"</style></head><body><h1>" + html.escape(title) + "</h1><p>"
"Product rendering only; compare with the original Bubble view before accepting. "
"Resources and interactive links within the sample are disabled.</p>" + original
+ "<p>Sanitization changed HTML: "
+ str(audit["sanitization_changed_html"]).lower()
+ "</p><main><section><h2>Exact captured source</h2><pre>" + html.escape(body)
+ "</pre></section><section><h2>Current product rendering</h2><div inert>"
+ rendered + "</div></section></main></body></html>").encode()
def review_index(records: list[dict]) -> bytes:
rows = []
for record in sorted(records, key=lambda r: (
not (r.get("markup_changed_by_sanitization") or r["status"] == "body_missing"), r["id"]
)):
label = html.escape(record["title"])
if record.get("card"):
label = '<a href="' + html.escape(record["card"], quote=True) + '">' + label + "</a>"
status = ("body missing" if record["status"] == "body_missing" else (
"markup change — review" if record["markup_changed_by_sanitization"] else (
"text change — review" if record["visible_text_changed_by_sanitization"]
else "no structural sanitizer change; original comparison still required")))
rows.append("<li>" + label + " — " + status + "</li>")
return ('<!doctype html><html><head><meta charset="utf-8">'
'<meta http-equiv="Content-Security-Policy" content="default-src \'none\'; '
'base-uri \'none\'; form-action \'none\'">'
'<title>Private corpus rendering review</title></head><body>'
'<h1>Private corpus rendering review</h1><p>Compare each card with the original '
'Bubble view. Sanitizer differences are observations, not acceptance verdicts. '
'Body-missing and markup-change records come first.</p><ol>'
+ "".join(rows) + '</ol></body></html>').encode()