"""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, head_label: str = "Ed25519") -> 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'") 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 ( 'Second, additive anchor — post-quantum. Heads from tree 14 on additionally carry a deterministic SLH-DSA-SHA2-128s (FIPS 205) signature over the same payload. The Ed25519 signature above remains the one every consumer must check; this one is checked where tooling allows (OpenSSL ≥ 3.5). Its verify path is the proof subject of leaf 18.
{slh_pem}
SHA-256 fingerprint {slh_fp}
· raw: {base or ''}/log-slhdsa-public-key
· mirror: provider.slhdsa.pub
This key is the sole cryptographic identity anchor: it authenticates that these statements were made by the operator (the same party the artifacts call “the provider”). It does not, by itself, make those statements true — each attestation's truth additionally rests on the replay, theorem, extraction and toolchain assumptions stated in that leaf (one signed entry of the tree below). Every tree head and attestation is signature-checked against this key. Pin it (save your own copy; from then on trust only what checks against that copy), and compare this copy byte-for-byte with the independently hosted mirror copy; they must be identical. The first fetch is trust-on-first-use; the two-host byte-comparison is what bounds it.
{pem}
SHA-256 fingerprint {escape(fingerprint)}
· raw: {base or ''}/log-public-key
· curl -s https://ltl.zkdefi.org/log-public-key
{escape(c)}One sentence: a public, append-only Merkle accumulator (a hash tree that only ever grows) of signed statements that the Lean 4 formal proofs of specific cryptographic Rust libraries, at specific git commits, re-check by machine with exactly their documented assumptions — so that you can trust a proof result by checking one required signature (Ed25519) and ~{max(1,(latest.get('tree_size') or 1).bit_length())} hashes in milliseconds, instead of running a theorem prover for hours.
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 (leaves 0–3: an early audit round that failed; leaves 4–7 re-attest the same four libraries cleanly)
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. The code that signs the log is itself an entry in the log — and checks its own entry before signing. In detail: 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 — so the signed tree contains an attestation of the source the
operator reports its signing binary was built from. (An Ed25519 signature cannot by itself prove
which binary generated it; execution provenance is reported, not proven, and the provenance
fields live in the unsigned signature metadata.) Tree size {latest.get('tree_size',0)},
log id {escape(str(metadata.get('log_id',''))[:16])}….
To benefit from the accumulator you need exactly three files per library, plus optionally the whole mirror. Nothing else.
| # | Artifact | What it is | Where |
|---|---|---|---|
| 1 | provider.ed25519.pub |
The identity anchor. The provider's public key — the sole cryptographic identity you pin. It authenticates the operator's statements; their truth rests on each leaf's stated assumptions. 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 (the exact set of assumptions each proof ultimately rests on), what machine protection — signed by the provider. | table below, 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 (STH). A one-page Python core verifies it — printed as Appendix C of the paper; the shipped verify.py wraps that core with full fail-closed binding checks (stdlib hashing; signature checks shell out to the openssl binary). |
table below, or mirror receipts/ |
| + | the full mirror clone | Maximal benefit: become a witness. Every leaf + every signed head
ever issued + verify.py (Python stdlib + the openssl binary for
signatures; fails closed without them). python3 verify.py --all
recomputes the entire tree and every historical head — you then hold a retained view that can
later EXPOSE a conflicting head shown to someone else. (A single clone cannot by itself prove the
log never split its view toward another consumer; that requires comparing heads across
consumers.) |
git clone {mirror} |
| component | artifact 2 | artifact 3 | status |
|---|
One certificate = one machine-checked theorem together with its exact assumption set (its axiom cone).
pacta receipt-verify --attestation … --receipt … --log-public-key provider.ed25519.pub
pacta CLI ships in the pacta repository (pip install . from a clone). Add --sth-store pins.json to remember every Signed Tree Head (STH) you accept — your defense against a split view (the operator showing different histories to different consumers).git clone {mirror} && cd lean-transparency-log && python3 verify.py --all
openssl binary (signature checks fail closed without it). You become a witness of the whole history.--require-verified-verifier).GET {base}/v1/sth latest Signed Tree Head
GET {base}/v1/sth-history the published head history (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
attestation.json. Honesty about the boundary is the product.sn = 0),
zero divergences after the one-line restoration, confirmed by a three-way regression.
New in v0.11: the deployment evaluated to its current nineteen-leaf, dual-signed state, an
instantiation section for the SLH-DSA (FIPS 205) verify path — eleven certificates,
five uninterpreted hash oracles, exact cones — and a certificate appendix mirroring the
Ed25519 tiers.python3 verify.py --all
re-verifies all of it, paper-era and after, from a clone of the mirror.Log heads are signed offline; this service is read-only and holds no key material. Provider tooling, agent tooling, and the full Jupyter course live in the pacta repository.
"""