Pyramid web app for inspecting arborist Merkle trees over sharded SQLite: document roots, inclusion proofs, an interactive 3D Merkle lattice (six.js / WebGL with graceful fallback), audit-chain linkage, and a live SSE event stream. Generated artifacts (env/, vendored static/six/ bundles, demo databases) are gitignored and rebuilt via the Makefile (venv, six, init-db, serve).
95 lines
3.8 KiB
Django/Jinja
95 lines
3.8 KiB
Django/Jinja
{% extends "base.jinja2" %}
|
|
|
|
{% block body %}
|
|
<div class="proof"
|
|
data-root-hash="{{ root_hash }}"
|
|
data-leaf-index="{{ leaf_index or '' }}"
|
|
data-cache-key="{{ cache_key or '' }}">
|
|
|
|
<aside class="dash-side">
|
|
<h2 class="dash-h2">Root</h2>
|
|
<pre class="root-hash-block" id="root-hash">{{ root_hash | hex_chunk }}</pre>
|
|
|
|
<h2 class="dash-h2">Inclusion proof</h2>
|
|
<div id="proof-card" class="proof-card">
|
|
<p class="muted">select a leaf to compute its inclusion proof…</p>
|
|
</div>
|
|
|
|
<h2 class="dash-h2">Leaf content
|
|
<span class="muted" id="content-mode-label"></span>
|
|
</h2>
|
|
<div class="content-toggle" id="content-toggle" hidden>
|
|
<button type="button" data-mode="prose" class="active">prose</button>
|
|
<button type="button" data-mode="raw">raw</button>
|
|
<span class="muted" id="content-base-version"></span>
|
|
</div>
|
|
<div id="leaf-content" class="leaf-content muted">select a leaf to view its chunk text…</div>
|
|
|
|
<h2 class="dash-h2">Audit linkage</h2>
|
|
<div id="audit-link" class="muted">looking up…</div>
|
|
|
|
<h2 class="dash-h2">Live stream</h2>
|
|
<div class="dash-stream" id="sse-status">
|
|
<span class="dot dot-off"></span>
|
|
<span class="lbl">disconnected</span>
|
|
</div>
|
|
<pre class="dash-events" id="sse-events" aria-live="polite"></pre>
|
|
</aside>
|
|
|
|
<section class="proof-stage">
|
|
<div class="lattice-bar">
|
|
<span class="widget-type">[merkle-lattice-3d]</span>
|
|
<span id="lattice-status">loading…</span>
|
|
<button id="btn-pulse" disabled>pulse proof path</button>
|
|
<button id="btn-reset">reset</button>
|
|
<span class="lattice-legend muted">
|
|
<span class="legend-swatch swatch-leaf"></span>leaves
|
|
<span class="legend-swatch swatch-interior"></span>interior
|
|
<span class="legend-swatch swatch-root"></span>root
|
|
<span class="legend-swatch swatch-selected"></span>selected
|
|
</span>
|
|
</div>
|
|
<div id="lattice-canvas" class="lattice-canvas"></div>
|
|
<div id="node-inspect" class="node-inspect muted">click any node — leaves compute an inclusion proof, interior + root reveal their hash here.</div>
|
|
|
|
<div class="leaves-strip" id="leaves-strip">
|
|
<span class="muted">leaves load with the tree…</span>
|
|
</div>
|
|
|
|
<!-- Context-root variant: shown only when /api/root/{hash} returns
|
|
kind=context_root. The Merkle lattice + leaves strip still render
|
|
the tree; this panel adds the QA card + evidence manifest. Each
|
|
source is stamped with its 0-based context-tree leaf index so the
|
|
manifest, leaf chips, and inclusion proof all agree. -->
|
|
<article id="context-panel" class="widget" hidden>
|
|
<header class="widget-head">
|
|
<span class="widget-type">[context-root]</span>
|
|
<span class="widget-title">multi-source evidence</span>
|
|
</header>
|
|
<div class="widget-body">
|
|
<div id="qa-card" class="qa-card" hidden></div>
|
|
<ul id="sources-list" class="sources-list"></ul>
|
|
</div>
|
|
</article>
|
|
</section>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block scripts %}
|
|
<script type="module">
|
|
import { mountProofPage } from "{{ request.static_url('arborist_viz:static/viz/proof-page.js') }}?v={{ request.static_version }}";
|
|
import { connectSSE } from "{{ request.static_url('arborist_viz:static/viz/sse-client.js') }}?v={{ request.static_version }}";
|
|
|
|
const root = document.querySelector(".proof");
|
|
const rootHash = root.dataset.rootHash;
|
|
const leafIndex = root.dataset.leafIndex ? parseInt(root.dataset.leafIndex, 10) : null;
|
|
const cacheKey = root.dataset.cacheKey || null;
|
|
|
|
mountProofPage(rootHash, leafIndex, cacheKey);
|
|
|
|
connectSSE(`/sse/root/${encodeURIComponent(rootHash)}`, {
|
|
statusEl: document.getElementById("sse-status"),
|
|
eventsEl: document.getElementById("sse-events"),
|
|
});
|
|
</script>
|
|
{% endblock %}
|