mirror of
https://github.com/saymrwulf/proof-aware-crypto-tooling-agent.git
synced 2026-09-03 19:53:43 +00:00
LTL front page: display the trust anchor in full, above the fold
The provider public key is the one thing a consumer takes on trust; hiding it behind /log-public-key inverted the page's priorities. New 'The trust anchor - pin this key' section at the top of the docs page shows the PEM in full with its SHA-256 fingerprint, the mirror-compare instruction, and the raw endpoint for scripts. Honest 'missing' card if a deployment lacks the key. Test asserts the page renders the key. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
be9a39cd2b
commit
3aa8d4b2bf
2 changed files with 37 additions and 3 deletions
|
|
@ -101,6 +101,31 @@ def _svg_tree(entries: list[LogEntry], root_hex: str, signing_backend: str) -> s
|
||||||
return "".join(out)
|
return "".join(out)
|
||||||
|
|
||||||
|
|
||||||
|
def _trust_anchor_html(log: TransparencyLog, metadata: dict[str, Any], base: str, mirror: str) -> str:
|
||||||
|
"""The provider public key, displayed in full on the front page. The key
|
||||||
|
is the one thing a consumer takes on trust, once - hiding it behind a
|
||||||
|
path would invert the page's priorities."""
|
||||||
|
key_path = log.log_dir / "provider.ed25519.pub"
|
||||||
|
fingerprint = str(metadata.get("ed25519_public_key_fingerprint_sha256", ""))
|
||||||
|
if not key_path.is_file():
|
||||||
|
return (
|
||||||
|
'<div class="card"><span class="pill warn">missing</span> This deployment '
|
||||||
|
"does not expose its public key in the log directory - fetch it from the "
|
||||||
|
f'<a href="{mirror}/blob/main/provider.ed25519.pub">mirror</a> instead.</div>'
|
||||||
|
)
|
||||||
|
pem = escape(key_path.read_text(encoding="utf-8").strip())
|
||||||
|
return f"""<div class="card">
|
||||||
|
<p style="margin-top:0">This key is <strong>the only thing you take on trust, once</strong>.
|
||||||
|
Everything else on this page - every attestation, every tree head - is verified against it.
|
||||||
|
Pin it, and compare this copy byte-for-byte with the independently hosted
|
||||||
|
<a href="{mirror}/blob/main/provider.ed25519.pub">mirror copy</a>; they must be identical.</p>
|
||||||
|
<pre style="margin-bottom:.4rem">{pem}</pre>
|
||||||
|
<p class="muted" style="margin:.2rem 0 0">SHA-256 fingerprint <code>{escape(fingerprint)}</code>
|
||||||
|
· raw: <a href="{base}/log-public-key"><code>{base or ''}/log-public-key</code></a>
|
||||||
|
· <code>curl -s ltl.zkdefi.org/log-public-key</code></p>
|
||||||
|
</div>"""
|
||||||
|
|
||||||
|
|
||||||
def render_docs(log: TransparencyLog, base_path: str) -> str:
|
def render_docs(log: TransparencyLog, base_path: str) -> str:
|
||||||
base = "/" + base_path.strip("/") if base_path.strip("/") else ""
|
base = "/" + base_path.strip("/") if base_path.strip("/") else ""
|
||||||
metadata = log.metadata()
|
metadata = log.metadata()
|
||||||
|
|
@ -142,6 +167,9 @@ their documented assumptions</em> — so that you can trust a proof result by ch
|
||||||
<strong>one signature and ~{max(1,(latest.get('tree_size') or 1).bit_length())} hashes in
|
<strong>one signature and ~{max(1,(latest.get('tree_size') or 1).bit_length())} hashes in
|
||||||
milliseconds</strong>, instead of running a theorem prover for hours.</p>
|
milliseconds</strong>, instead of running a theorem prover for hours.</p>
|
||||||
|
|
||||||
|
<h2>The trust anchor — pin this key</h2>
|
||||||
|
{_trust_anchor_html(log, metadata, base, mirror)}
|
||||||
|
|
||||||
<h2>The accumulator, live</h2>
|
<h2>The accumulator, live</h2>
|
||||||
{tree_svg}
|
{tree_svg}
|
||||||
<p class="legend">
|
<p class="legend">
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,11 @@ def _make_log(tmp_path, n=3):
|
||||||
|
|
||||||
def test_web_endpoints_and_online_proof_roundtrip(tmp_path):
|
def test_web_endpoints_and_online_proof_roundtrip(tmp_path):
|
||||||
# root mount: the production shape (ltl.zkdefi.org serves from /)
|
# root mount: the production shape (ltl.zkdefi.org serves from /)
|
||||||
|
import shutil
|
||||||
|
|
||||||
_make_log(tmp_path)
|
_make_log(tmp_path)
|
||||||
|
# trust anchor present at render time: front page must display it in full
|
||||||
|
shutil.copy2(tmp_path / "k.pub", tmp_path / "log" / "provider.ed25519.pub")
|
||||||
server = serve(str(tmp_path / "log"), port=0)
|
server = serve(str(tmp_path / "log"), port=0)
|
||||||
port = server.server_address[1]
|
port = server.server_address[1]
|
||||||
threading.Thread(target=server.serve_forever, daemon=True).start()
|
threading.Thread(target=server.serve_forever, daemon=True).start()
|
||||||
|
|
@ -60,11 +64,13 @@ def test_web_endpoints_and_online_proof_roundtrip(tmp_path):
|
||||||
assert r.headers["Content-Type"] == "application/pdf"
|
assert r.headers["Content-Type"] == "application/pdf"
|
||||||
assert r.read(5) == b"%PDF-"
|
assert r.read(5) == b"%PDF-"
|
||||||
# the site's copy of the trust anchor (TOFU: two independent locations)
|
# the site's copy of the trust anchor (TOFU: two independent locations)
|
||||||
import shutil
|
|
||||||
|
|
||||||
shutil.copy2(tmp_path / "k.pub", tmp_path / "log" / "provider.ed25519.pub")
|
|
||||||
with urllib.request.urlopen(base + "/log-public-key", timeout=10) as r:
|
with urllib.request.urlopen(base + "/log-public-key", timeout=10) as r:
|
||||||
assert r.read() == (tmp_path / "k.pub").read_bytes()
|
assert r.read() == (tmp_path / "k.pub").read_bytes()
|
||||||
|
# and the front page displays the key IN FULL, above the fold
|
||||||
|
with urllib.request.urlopen(base + "/docs", timeout=10) as r:
|
||||||
|
page = r.read().decode()
|
||||||
|
assert "BEGIN PUBLIC KEY" in page
|
||||||
|
assert "pin this key" in page.lower()
|
||||||
finally:
|
finally:
|
||||||
server.shutdown()
|
server.shutdown()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue