"""The LTL website, served at the log's base path — one self-contained HTML page (inline CSS + inline SVG, no external assets: works air-gapped behind any reverse proxy). Rendered from the LIVE log state, so the graphic and every number on the page are the accumulator, not a brochure about it.""" from __future__ import annotations from html import escape from typing import Any from pacta.transparency import node_hash from .transparency_log import LogEntry, TransparencyLog _STYLE = """ :root{--ink:#1c2430;--ink2:#5a6675;--line:#dde2e9;--ok:#1e7f4f;--okbg:#e2f2e9; --warn:#a86a10;--warnbg:#fdf0da;--accent:#3b4d8f;--accentbg:#eef0f7;--bg:#f8f9fa} *{box-sizing:border-box} body{font-family:system-ui,sans-serif;max-width:66rem;margin:0 auto;padding:2rem 1.2rem 4rem; color:var(--ink);line-height:1.6;background:var(--bg)} h1{font-size:2rem;margin:.2rem 0 0;letter-spacing:-.01em} h2{font-size:1.2rem;margin-top:2.6rem;border-bottom:2px solid var(--line);padding-bottom:.3rem} .tagline{font-size:1.05rem;color:var(--ink2);max-width:46rem} code,pre{font-family:ui-monospace,Menlo,Consolas,monospace;background:#eef0f3;border-radius:4px} code{padding:.1rem .3rem;font-size:.9em} pre{padding:.9rem;overflow-x:auto;font-size:.85rem} table{border-collapse:collapse;width:100%;font-size:.93rem;background:#fff} td,th{border:1px solid var(--line);padding:.5rem .7rem;text-align:left;vertical-align:top} th{background:var(--accentbg)} .pill{display:inline-block;border-radius:9px;padding:.08rem .6rem;font-size:.78rem;font-weight:600} .ok{background:var(--okbg);color:var(--ok)} .warn{background:var(--warnbg);color:var(--warn)} .acc{background:var(--accentbg);color:var(--accent)} .muted{color:var(--ink2);font-size:.9rem} .card{background:#fff;border:1px solid var(--line);border-radius:8px;padding:1rem 1.2rem;margin:.8rem 0} .steps{counter-reset:s} .steps .card{position:relative;padding-left:3.2rem} .steps .card::before{counter-increment:s;content:counter(s);position:absolute;left:1rem;top:1rem; width:1.6rem;height:1.6rem;border-radius:50%;background:var(--accent);color:#fff; display:flex;align-items:center;justify-content:center;font-weight:700;font-size:.9rem} svg{max-width:100%;height:auto;display:block;margin:1rem auto;background:#fff; border:1px solid var(--line);border-radius:8px} a{color:var(--accent)} .legend{display:flex;gap:1.4rem;flex-wrap:wrap;font-size:.85rem;color:var(--ink2);justify-content:center} .sw{display:inline-block;width:.8rem;height:.8rem;border-radius:3px;vertical-align:-1px;margin-right:.3rem} """ def _leaf_ok(entry: LogEntry) -> bool: certificates = ((entry.leaf.get("attestation") or {}).get("certificates")) or [] return bool(certificates) and all( certificate.get("status") == "proven" and certificate.get("axiom_status") == "clean" for certificate in certificates ) def _svg_tree(entries: list[LogEntry], root_hex: str, signing_backend: str) -> str: """The accumulator, drawn from its real leaves.""" if not entries: return "

(log is empty)

" hashes = [bytes.fromhex(entry.leaf_hash) for entry in entries] levels: list[list[bytes]] = [hashes] while len(levels[-1]) > 1: level = levels[-1] nxt = [node_hash(level[i], level[i + 1]) for i in range(0, len(level) - 1, 2)] if len(level) % 2: nxt.append(level[-1]) levels.append(nxt) width, level_gap = 1000, 86 height = 150 + level_gap * len(levels) out = [f''] positions: dict[tuple[int, int], tuple[float, float]] = {} for level_index, level in enumerate(levels): y = height - 56 - level_index * level_gap span = width / (len(level) + 1) for node_index, node in enumerate(level): x = span * (node_index + 1) positions[(level_index, node_index)] = (x, y) if level_index == 0: entry = entries[node_index] ok = _leaf_ok(entry) component = (((entry.leaf.get("attestation") or {}).get("subject")) or {}).get("component", "?") fill, stroke = ("#e2f2e9", "#1e7f4f") if ok else ("#f4f4f6", "#8a93a0") out.append(f'') out.append(f'leaf {node_index}') short = escape(str(component).replace("-ed25519-verified", "")) label = short if ok else f"{short} ✗" out.append(f'{label}') out.append(f'{node.hex()[:10]}…') else: is_root = level_index == len(levels) - 1 out.append(f'') out.append(f'{"ROOT" if is_root else "node"}') out.append(f'{node.hex()[:10]}…') for child in (2 * node_index, 2 * node_index + 1): if (level_index - 1, child) in positions: cx, cy = positions[(level_index - 1, child)] out.append(f'') root_x, root_y = positions[(len(levels) - 1, 0)] out.append(f'') out.append(f'Signed Tree Head — Ed25519({root_hex[:12]}…)') out.append(f'signed by: {escape(signing_backend)} (the proof-attested library itself)') out.append(f'') out.append("") 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 ( '
missing This deployment ' "does not expose its public key in the log directory - fetch it from the " f'mirror instead.
' ) pem = escape(key_path.read_text(encoding="utf-8").strip()) return f"""

This key is the only thing you take on trust, once. 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 mirror copy; they must be identical.

{pem}

SHA-256 fingerprint {escape(fingerprint)}  ·  raw: {base or ''}/log-public-key  ·  curl -s ltl.zkdefi.org/log-public-key

""" def render_docs(log: TransparencyLog, base_path: str) -> str: base = "/" + base_path.strip("/") if base_path.strip("/") else "" metadata = log.metadata() history = log.sth_history() latest: dict[str, Any] = history[-1] if history else {} entries = log.entries() ed = (latest.get("signatures") or {}).get("ed25519") or {} provenance = ed.get("signing_provenance") or {} signing_backend = str(ed.get("signing_backend", "openssl")) components = sorted({ component for entry in entries if _leaf_ok(entry) and (component := ((entry.leaf.get("attestation") or {}).get("subject") or {}).get("component")) }) mirror = "https://github.com/saymrwulf/lean-transparency-log" rows = "".join( f"{escape(c)}" f"attestation" f"inclusion proof" f"16/16 proven" for c in components ) tree_svg = _svg_tree(entries, str(latest.get("root_hash", "")), signing_backend) return f""" LTL — Lean Transparency Log

zkdefi · notes · code · cv

LTL — the Lean Transparency Log

One sentence: a public, append-only Merkle accumulator of signed statements that the Lean 4 formal proofs of specific cryptographic Rust libraries, at specific git commits, machine-re-check with exactly their documented assumptions — so that you can trust a proof result by checking one signature and ~{max(1,(latest.get('tree_size') or 1).bit_length())} hashes in milliseconds, instead of running a theorem prover for hours.

The trust anchor — pin this key

{_trust_anchor_html(log, metadata, base, mirror)}

The accumulator, live

{tree_svg}

verified attestation (all certificates proven, axiom cones boundary-exact) historical audit-failure attestation — kept forever; an append-only ledger does not erase its bad day

Every box above is computed from the live log at page render — leaf hashes, internal nodes, the root, and the signature are the real ones. Before signing this root, the provider Merkle-verified its own signing library's leaf (index {provenance.get('signing_library_leaf_index','?')}, certificates {escape(str(provenance.get('signing_library_certificates_proven','?')))}) against this very tree — the signature vouches for the code that produced it, and the tree vouches for the signature's code. Tree size {latest.get('tree_size',0)}, log id {escape(str(metadata.get('log_id',''))[:16])}….

What do I download? — the three artifacts, unambiguously

To benefit from the accumulator you need exactly three files per library, plus optionally the whole mirror. Nothing else.

#ArtifactWhat it isWhere
1provider.ed25519.pub The trust anchor. The provider's public key — the only thing you take on trust, once. Fetch it from BOTH independent locations and compare; the copies must be identical. this site · mirror
2<library>.attestation.json The claim. Which repo, which exact git commit, which theorems, which observed axiom cones, what machine protection — signed by the provider. table above, or mirror entries/
3<library>.receipt.json The proof of inclusion. Binds artifact 2 into the signed tree: leaf index, sibling hashes, the Signed Tree Head. ~25 lines of stdlib Python verify it. table above, or mirror receipts/
+the full mirror clone Maximal benefit: become a witness. Every leaf + every signed head ever issued + verify.py (stdlib-only). python3 verify.py --all recomputes the entire tree and every historical head — you then hold proof the log never equivocated within your clone. git clone {mirror}

Attested libraries

{rows}
componentartifact 2artifact 3status

Three ways to use it

Quick check (any machine, milliseconds): download artifacts 1–3, then
pacta receipt-verify --attestation … --receipt … --log-public-key provider.ed25519.pub
No Lean, no Rust, no account. Add --sth-store pins.json for split-view defense.
Zero-install audit: git clone {mirror} && python3 verify.py --all
Standard-library Python only. You become a witness of the whole history.
Autonomous agent: the pacta tool adds STH pinning, freshness policy, online refresh from this service, risk scoring (R0–R5) with policy-gated consequences, and optionally verifies every signature through the proof-attested Ed25519 code path itself (--require-verified-verifier).

API

GET {base}/v1/sth                      latest Signed Tree Head
GET {base}/v1/sth-history              every head ever signed (witness material)
GET {base}/v1/sth-consistency?first=N  consistency proof from your pinned size
GET {base}/v1/proof?component=NAME     inclusion proof (artifact 3, freshly issued)
GET {base}/v1/attestation?component=NAME   the claim (artifact 2)
GET {base}/v1/entries?start=N&end=M    raw leaves
GET {base}/v1/metadata                 log identity
GET {base}/healthz

What a verified inclusion means — and what it does not

means The provider whose key you hold attests: the Lean proofs of the named repository at the named git commit re-check with exactly the documented assumptions — and that statement is irrevocably part of the log every other customer and witness sees.
does not mean A verified binary. The proofs cover Rust source; clone the attested commit (the git hash is the content hash) and build it yourself — compiler and build are declared trusted base until the reproducible-builds program (R5) lands. Every attestation carries its full residual-risk list. Honesty about the boundary is the product.

You hold the ruler

The list of assumptions a certificate is allowed to rest on is not something this site hands you at verification time — it is a requirements card that lives in your tooling, on your disk, and that you can read in five minutes or rewrite from first principles: Lean's three foundational axioms, plus — for the signature tiers only — named placeholders for SHA-512 and the wire format. Your tooling ignores this operator's pass/fail labels entirely and re-derives every verdict by comparing the attestation's observed axiom list against your card, name by name. The operator is trusted to copy down what the proof kernel printed — never to interpret it.
A card you write yourself will match this log's supply exactly — and that is engineered, not coincidence: the corpus was shrunk until every remaining axiom justifies its existence. If your card is stricter (say: "SHA-512 itself must be proven"), there is nothing here to negotiate — the gap is itemized, never blurred, and you have three honest options: accept a named line item, walk away, or prove the missing piece and enter it into this same log. If your ruler is stricter than our supply, your ruler is our roadmap. (The full walk-through is lecture 11 in the course.)

The paper

LTL: Lean Transparency Log (PDF, 4 pages) — the design in full: the trust model (observations, never verdicts), the self-certifying signature, the deployment with its retained failure leaves, and an exact account of what a verified receipt does and does not establish.

Log heads are signed offline; this service is read-only and holds no key material. Provider tooling, agent tooling, and the full course (12 Jupyter lectures) live in the pacta repository.

"""