Spaces:
Running
Running
deploy(hf): sync szl-holdings/a11oy@main derived COPY set
Browse filesReusable Dockerfile-COPY-derived deploy from szl-holdings/a11oy main.
Files: 884 Pruned: 0
Derived from Dockerfile COPY sources (NO hand-maintained allowlist).
Signed-off-by: SZL Holdings <noreply@szlholdings.ai>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- static/3d/holographic.html +1 -0
- static/3d/surfaces/zkinfer.js +566 -0
static/3d/holographic.html
CHANGED
|
@@ -160,6 +160,7 @@ const SURFACES = [
|
|
| 160 |
{ id: "ctxready", title: "Context-Ready Transformer", mod: "/static/3d/surfaces/ctxready.js" },
|
| 161 |
{ id: "opera", title: "OPERA Perplexity-Reward Alignment", mod: "/static/3d/surfaces/opera.js" },
|
| 162 |
{ id: "brain", title: "Formula-Graph Brain", mod: "/static/3d/surfaces/brain.js" },
|
|
|
|
| 163 |
];
|
| 164 |
|
| 165 |
const stageEl = document.getElementById("stage");
|
|
|
|
| 160 |
{ id: "ctxready", title: "Context-Ready Transformer", mod: "/static/3d/surfaces/ctxready.js" },
|
| 161 |
{ id: "opera", title: "OPERA Perplexity-Reward Alignment", mod: "/static/3d/surfaces/opera.js" },
|
| 162 |
{ id: "brain", title: "Formula-Graph Brain", mod: "/static/3d/surfaces/brain.js" },
|
| 163 |
+
{ id: "zkinfer", title: "zkML Proof-of-Inference (Cryptographic Receipts)", mod: "/static/3d/surfaces/zkinfer.js" },
|
| 164 |
];
|
| 165 |
|
| 166 |
const stageEl = document.getElementById("stage");
|
static/3d/surfaces/zkinfer.js
ADDED
|
@@ -0,0 +1,566 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
// © 2026 Lutar, Stephen P. Jr. — SZL Holdings · ORCID 0009-0001-0110-4173 · Doctrine v11
|
| 3 |
+
//
|
| 4 |
+
// surfaces/zkinfer.js — zkML PROOF-OF-INFERENCE ("Cryptographic Receipts").
|
| 5 |
+
//
|
| 6 |
+
// The CRYPTOGRAPHIC-PROOF trust branch of verifiable inference — a prover (model host)
|
| 7 |
+
// emits a succinct zero-knowledge argument that a COMMITTED model produced a specific
|
| 8 |
+
// output, checkable against only a public weight commitment: no trusted hardware, no
|
| 9 |
+
// silicon vendor in the trust base. Orthogonal to the estate's TEE/hardware branch
|
| 10 |
+
// (ccattest, which trusts an enclave + vendor attestation service).
|
| 11 |
+
//
|
| 12 |
+
// DATA: live snapshot from the same-origin endpoint /api/a11oy/v1/frontier/zkinfer:
|
| 13 |
+
// label (MODELED, VERBATIM), proof_cost_model{ anchor_points[], cost_frontier{grid} },
|
| 14 |
+
// trust_model_matrix{ branches: crypto vs TEE }, micro_artifact{ label, verify_ok },
|
| 15 |
+
// doctrine{ trust_ceiling, lambda }, sources{}.
|
| 16 |
+
//
|
| 17 |
+
// VISUALIZES:
|
| 18 |
+
// 1. a layerwise prover→verifier PROOF-PACKET TUNNEL — stacked model-layer planes; a
|
| 19 |
+
// proof-teal packet travels layer-by-layer and collapses into a single small glyph at
|
| 20 |
+
// the verifier, whose size is scaled to the MODELED proof size (kB) — "succinct".
|
| 21 |
+
// 2. a COST-FRONTIER RIBBON — x = model size, y = sequence length, z = prover time, from
|
| 22 |
+
// the literature-parameterized grid; each cell MODELED (never a benchmark).
|
| 23 |
+
// 3. TRUST-BASE CONTRAST PILLARS — "cryptographic (this)" vs "TEE / ccattest"; the
|
| 24 |
+
// silicon-vendor node on the crypto pillar is GREYED-OUT (outside the trust base).
|
| 25 |
+
// 4. a LIVE ROUNDTRIP PULSE — when the real commit→prove→verify micro-artifact returns
|
| 26 |
+
// MEASURED, one proof-teal pulse fires prover→verifier; on HONEST-STUB it is dim grey
|
| 27 |
+
// and labeled STUB. No green "1.0 / VERIFIED" state anywhere.
|
| 28 |
+
//
|
| 29 |
+
// PRIMARY SOURCES (cited verbatim on-surface; IDs only — 0 runtime CDN, no URL fetch):
|
| 30 |
+
// zkLLM arXiv:2404.16109 (CCS'24) · Kang et al. arXiv:2210.08674 · ZKML EuroSys'24
|
| 31 |
+
// DOI 10.1145/3627703.3650088 · South et al. arXiv:2402.02675 · Peng et al. survey
|
| 32 |
+
// arXiv:2502.18535.
|
| 33 |
+
//
|
| 34 |
+
// HONESTY LABEL: MODELED — literature-parameterized cost model + trust matrix, explicitly
|
| 35 |
+
// NOT VERIFIED; no live LLM-scale proof is produced. The ONE narrowly MEASURED tile is the
|
| 36 |
+
// toy commit-verify roundtrip (plumbing only; reveals weights; not LLM-scale). Read
|
| 37 |
+
// VERBATIM from JSON; never upgraded here. Trust ceiling 0.97, NEVER 100%.
|
| 38 |
+
// COLOURS: lattice-blue 0x5b8dee, violet-blue 0x8a6bff (data-viz marker), proof-teal
|
| 39 |
+
// 0x3af4c8 (packet / MEASURED pulse), greys (pending / TEE / greyed vendor / STUB).
|
| 40 |
+
// PURPLE BANNED. No green/1.0 verified state.
|
| 41 |
+
// 0 RUNTIME CDN. Vendored three.js r170 via page importmap (ctx.THREE).
|
| 42 |
+
// DOCTRINE v11: adds NOTHING to the locked-8 {F1,F4,F7,F11,F12,F18,F19,F22} @ c7c0ba17;
|
| 43 |
+
// Λ stays Conjecture 1; introduces no theorem. Degrades grey on 404/error; label shown.
|
| 44 |
+
|
| 45 |
+
const ID = "zkinfer";
|
| 46 |
+
const TITLE = "zkML Proof-of-Inference · Cryptographic Receipts (live)";
|
| 47 |
+
|
| 48 |
+
// same-origin, relative — no CDN, no cross-origin fetch.
|
| 49 |
+
const EP = "/api/a11oy/v1/frontier/zkinfer";
|
| 50 |
+
|
| 51 |
+
// data-viz hues — purple BANNED, no green
|
| 52 |
+
const C_LAYER = 0x5b8dee; // lattice-blue (model-layer planes, tunnel body)
|
| 53 |
+
const C_PACKET = 0x3af4c8; // proof-teal (proof packet / MEASURED roundtrip pulse)
|
| 54 |
+
const C_MARKER = 0x8a6bff; // violet-blue (verifier glyph / data-viz marker)
|
| 55 |
+
const C_DIM = 0x42505d; // grey (pending / greyed vendor / STUB / no-live-data)
|
| 56 |
+
const C_GRID = 0x1b3a44; // floor / link colour
|
| 57 |
+
const C_RIBBON = 0x5b8dee; // lattice-blue (cost ribbon base)
|
| 58 |
+
|
| 59 |
+
// tunnel geometry
|
| 60 |
+
const N_LAYERS = 7; // stacked model-layer planes
|
| 61 |
+
const LAYER_GAP = 1.4; // world-units between layers along z
|
| 62 |
+
const LAYER_W = 3.2; // plane width/height
|
| 63 |
+
|
| 64 |
+
let _stage = null, _THREE = null, _ctx = null, _group = null, _overlay = null;
|
| 65 |
+
let _frameReg = false, _polls = [], _el = {}, _badge = null, _plain = false;
|
| 66 |
+
|
| 67 |
+
// geometry handles
|
| 68 |
+
let _layers = []; // Array<THREE.Mesh> — stacked layer planes (prover -> verifier)
|
| 69 |
+
let _packet = null; // THREE.Mesh — traveling proof packet
|
| 70 |
+
let _verifier = null; // THREE.Mesh — verifier glyph (collapses proof to a small object)
|
| 71 |
+
let _ribbon = null; // THREE.Mesh — cost-frontier surface
|
| 72 |
+
let _pillars = []; // Array<{ mesh, node }> — trust-base contrast pillars
|
| 73 |
+
let _floor = null;
|
| 74 |
+
let _pulseT = -1; // >=0 while a roundtrip pulse is animating
|
| 75 |
+
|
| 76 |
+
// live state (all read from JSON; nothing invented)
|
| 77 |
+
const S = {
|
| 78 |
+
label: null, // top honesty label VERBATIM (MODELED)
|
| 79 |
+
notVerified: null,
|
| 80 |
+
microLabel: null, // MEASURED | HONEST-STUB
|
| 81 |
+
verifyOk: null,
|
| 82 |
+
proofKb: null, // modeled proof size (kB)
|
| 83 |
+
anchorTime: null, // zkLLM anchor prover time (s)
|
| 84 |
+
trustCeil: null,
|
| 85 |
+
lambda: null,
|
| 86 |
+
grid: null, // prover_time_grid_s rows
|
| 87 |
+
seqAxis: null,
|
| 88 |
+
paramsAxis: null,
|
| 89 |
+
cryptoTCB: null, // trusted_hardware_in_TCB for crypto branch (false)
|
| 90 |
+
teeTCB: null, // trusted_hardware_in_TCB for TEE branch (true)
|
| 91 |
+
state: "init",
|
| 92 |
+
};
|
| 93 |
+
|
| 94 |
+
// =============================================================================
|
| 95 |
+
// mount(ctx)
|
| 96 |
+
// =============================================================================
|
| 97 |
+
export function mount(ctx) {
|
| 98 |
+
_ctx = ctx; _stage = ctx.stage; _THREE = ctx.THREE;
|
| 99 |
+
_group = new _THREE.Group();
|
| 100 |
+
_stage.scene.add(_group);
|
| 101 |
+
_stage.camera.position.set(9, 6, 15);
|
| 102 |
+
try { if (_stage.controls && _stage.controls.target) { _stage.controls.target.set(0, 1.5, 0); _stage.controls.update(); } } catch (_) {}
|
| 103 |
+
try { _stage.setBloom(true); } catch (_) {}
|
| 104 |
+
|
| 105 |
+
_buildFloor();
|
| 106 |
+
_buildTunnel();
|
| 107 |
+
_buildRibbon();
|
| 108 |
+
_buildPillars();
|
| 109 |
+
|
| 110 |
+
if (!_frameReg) { _stage.onFrame(_onFrame); _frameReg = true; }
|
| 111 |
+
|
| 112 |
+
_badge = ctx.live.createBadge();
|
| 113 |
+
_polls.push(ctx.live.poll(EP, 6000, _onData, {
|
| 114 |
+
badge: _badge, onState: (m) => { S.state = m.state; _paintOverlay(); },
|
| 115 |
+
}));
|
| 116 |
+
|
| 117 |
+
_buildOverlay();
|
| 118 |
+
return { id: ID, started: true };
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
// =============================================================================
|
| 122 |
+
// builders
|
| 123 |
+
// =============================================================================
|
| 124 |
+
function _buildFloor() {
|
| 125 |
+
const THREE = _THREE;
|
| 126 |
+
const grid = new THREE.GridHelper(40, 40, C_GRID, 0x0f2027);
|
| 127 |
+
grid.material.opacity = 0.16; grid.material.transparent = true; grid.position.y = -0.01;
|
| 128 |
+
_group.add(grid);
|
| 129 |
+
_floor = grid;
|
| 130 |
+
}
|
| 131 |
+
|
| 132 |
+
// Prover (z-) -> Verifier (z+): stacked translucent model-layer planes forming a tunnel,
|
| 133 |
+
// plus a traveling proof packet and the collapsing verifier glyph.
|
| 134 |
+
function _buildTunnel() {
|
| 135 |
+
const THREE = _THREE;
|
| 136 |
+
const planeGeo = new THREE.PlaneGeometry(LAYER_W, LAYER_W);
|
| 137 |
+
const z0 = -((N_LAYERS - 1) * LAYER_GAP) / 2;
|
| 138 |
+
|
| 139 |
+
for (let i = 0; i < N_LAYERS; i++) {
|
| 140 |
+
const mat = new THREE.MeshStandardMaterial({
|
| 141 |
+
color: C_LAYER, emissive: C_LAYER, emissiveIntensity: 0.12,
|
| 142 |
+
transparent: true, opacity: 0.16, side: THREE.DoubleSide, wireframe: false,
|
| 143 |
+
});
|
| 144 |
+
const mesh = new THREE.Mesh(planeGeo, mat);
|
| 145 |
+
mesh.position.set(-6, 1.6, z0 + i * LAYER_GAP);
|
| 146 |
+
_group.add(mesh);
|
| 147 |
+
// frame outline (wire) so layers read as discrete stages
|
| 148 |
+
const wire = new THREE.Mesh(planeGeo, new THREE.MeshBasicMaterial({
|
| 149 |
+
color: C_LAYER, transparent: true, opacity: 0.28, wireframe: true, side: THREE.DoubleSide,
|
| 150 |
+
}));
|
| 151 |
+
wire.position.copy(mesh.position);
|
| 152 |
+
_group.add(wire);
|
| 153 |
+
_layers.push(mesh);
|
| 154 |
+
}
|
| 155 |
+
|
| 156 |
+
// proof packet — small proof-teal octahedron traveling prover->verifier
|
| 157 |
+
_packet = new THREE.Mesh(
|
| 158 |
+
new THREE.OctahedronGeometry(0.28, 0),
|
| 159 |
+
new THREE.MeshStandardMaterial({ color: C_PACKET, emissive: C_PACKET, emissiveIntensity: 0.6, transparent: true, opacity: 0.95 }),
|
| 160 |
+
);
|
| 161 |
+
_packet.position.set(-6, 1.6, z0);
|
| 162 |
+
_group.add(_packet);
|
| 163 |
+
|
| 164 |
+
// verifier glyph — small violet-blue icosahedron at the +z end; its scale reflects the
|
| 165 |
+
// MODELED proof size (succinct => small). Starts modest; updated from live data.
|
| 166 |
+
_verifier = new THREE.Mesh(
|
| 167 |
+
new THREE.IcosahedronGeometry(0.5, 0),
|
| 168 |
+
new THREE.MeshStandardMaterial({ color: C_MARKER, emissive: C_MARKER, emissiveIntensity: 0.35, transparent: true, opacity: 0.9, wireframe: true }),
|
| 169 |
+
);
|
| 170 |
+
_verifier.position.set(-6, 1.6, z0 + (N_LAYERS - 1) * LAYER_GAP + 1.4);
|
| 171 |
+
_group.add(_verifier);
|
| 172 |
+
}
|
| 173 |
+
|
| 174 |
+
// Cost-frontier ribbon: a plane whose vertices are displaced in Y by MODELED prover time
|
| 175 |
+
// over (model size × sequence length). Colored lattice-blue at low cost -> proof-teal high.
|
| 176 |
+
function _buildRibbon() {
|
| 177 |
+
const THREE = _THREE;
|
| 178 |
+
const segX = 5, segZ = 4; // default until live grid arrives (6 params × 5 seq)
|
| 179 |
+
const geo = new THREE.PlaneGeometry(7, 6, segX, segZ);
|
| 180 |
+
geo.rotateX(-Math.PI / 2);
|
| 181 |
+
const mat = new THREE.MeshStandardMaterial({
|
| 182 |
+
color: C_RIBBON, emissive: C_RIBBON, emissiveIntensity: 0.18,
|
| 183 |
+
transparent: true, opacity: 0.55, side: THREE.DoubleSide,
|
| 184 |
+
wireframe: false, flatShading: true,
|
| 185 |
+
vertexColors: true,
|
| 186 |
+
});
|
| 187 |
+
_ribbon = new THREE.Mesh(geo, mat);
|
| 188 |
+
_ribbon.position.set(6.5, 1.2, 0);
|
| 189 |
+
_group.add(_ribbon);
|
| 190 |
+
|
| 191 |
+
// baseline vertex colors (lattice-blue); recolored when live grid arrives.
|
| 192 |
+
const cnt = geo.attributes.position.count;
|
| 193 |
+
const colors = new Float32Array(cnt * 3);
|
| 194 |
+
const base = new THREE.Color(C_RIBBON);
|
| 195 |
+
for (let i = 0; i < cnt; i++) { colors[i * 3] = base.r; colors[i * 3 + 1] = base.g; colors[i * 3 + 2] = base.b; }
|
| 196 |
+
geo.setAttribute("color", new THREE.BufferAttribute(colors, 3));
|
| 197 |
+
}
|
| 198 |
+
|
| 199 |
+
// Trust-base contrast pillars: crypto (this surface) vs TEE (ccattest). The crypto pillar's
|
| 200 |
+
// silicon-vendor node is greyed-out to show it is OUTSIDE the trust base.
|
| 201 |
+
function _buildPillars() {
|
| 202 |
+
const THREE = _THREE;
|
| 203 |
+
const pillarGeo = new THREE.CylinderGeometry(0.55, 0.55, 3.4, 20, 1, true);
|
| 204 |
+
const nodeGeo = new THREE.SphereGeometry(0.32, 16, 12);
|
| 205 |
+
|
| 206 |
+
const specs = [
|
| 207 |
+
{ x: -1.4, color: C_PACKET, vendorGrey: true, name: "crypto" }, // this surface
|
| 208 |
+
{ x: 1.4, color: C_LAYER, vendorGrey: false, name: "tee" }, // ccattest
|
| 209 |
+
];
|
| 210 |
+
for (const sp of specs) {
|
| 211 |
+
const mesh = new THREE.Mesh(pillarGeo, new THREE.MeshStandardMaterial({
|
| 212 |
+
color: sp.color, emissive: sp.color, emissiveIntensity: 0.14,
|
| 213 |
+
transparent: true, opacity: 0.28, side: THREE.DoubleSide, wireframe: true,
|
| 214 |
+
}));
|
| 215 |
+
mesh.position.set(sp.x, 1.9, 7.5);
|
| 216 |
+
_group.add(mesh);
|
| 217 |
+
// "silicon-vendor node" at pillar top — greyed on the crypto pillar (not in TCB).
|
| 218 |
+
const nodeColor = sp.vendorGrey ? C_DIM : C_MARKER;
|
| 219 |
+
const node = new THREE.Mesh(nodeGeo, new THREE.MeshStandardMaterial({
|
| 220 |
+
color: nodeColor, emissive: nodeColor,
|
| 221 |
+
emissiveIntensity: sp.vendorGrey ? 0.08 : 0.4,
|
| 222 |
+
transparent: true, opacity: sp.vendorGrey ? 0.35 : 0.9,
|
| 223 |
+
}));
|
| 224 |
+
node.position.set(sp.x, 3.9, 7.5);
|
| 225 |
+
_group.add(node);
|
| 226 |
+
_pillars.push({ mesh, node });
|
| 227 |
+
}
|
| 228 |
+
}
|
| 229 |
+
|
| 230 |
+
// =============================================================================
|
| 231 |
+
// live data handler — read VERBATIM, never upgrade
|
| 232 |
+
// =============================================================================
|
| 233 |
+
function _onData(j) {
|
| 234 |
+
S.label = (j.label || "MODELED").toUpperCase();
|
| 235 |
+
S.notVerified = j.not_verified === true;
|
| 236 |
+
|
| 237 |
+
const pcm = j.proof_cost_model || {};
|
| 238 |
+
const cf = pcm.cost_frontier || {};
|
| 239 |
+
S.grid = Array.isArray(cf.prover_time_grid_s) ? cf.prover_time_grid_s : null;
|
| 240 |
+
S.seqAxis = cf.axes && Array.isArray(cf.axes.seq_len) ? cf.axes.seq_len : null;
|
| 241 |
+
S.paramsAxis = cf.axes && Array.isArray(cf.axes.params_b) ? cf.axes.params_b : null;
|
| 242 |
+
S.proofKb = cf.proof_size_kb_modeled && typeof cf.proof_size_kb_modeled.value === "number"
|
| 243 |
+
? cf.proof_size_kb_modeled.value : null;
|
| 244 |
+
S.anchorTime = cf.anchor && typeof cf.anchor.prover_time_s === "number"
|
| 245 |
+
? cf.anchor.prover_time_s : null;
|
| 246 |
+
|
| 247 |
+
const ma = j.micro_artifact || {};
|
| 248 |
+
S.microLabel = typeof ma.label === "string" ? ma.label.toUpperCase() : null;
|
| 249 |
+
S.verifyOk = typeof ma.verify_ok === "boolean" ? ma.verify_ok : null;
|
| 250 |
+
|
| 251 |
+
const d = j.doctrine || {};
|
| 252 |
+
S.trustCeil = typeof d.trust_ceiling === "number" ? d.trust_ceiling : null;
|
| 253 |
+
S.lambda = typeof d.lambda === "string" ? d.lambda : null;
|
| 254 |
+
|
| 255 |
+
const br = (j.trust_model_matrix || {}).branches || {};
|
| 256 |
+
const crypto = br["cryptographic_zkml (this surface)"] || {};
|
| 257 |
+
const tee = br["tee_attestation (ccattest)"] || {};
|
| 258 |
+
S.cryptoTCB = typeof crypto.trusted_hardware_in_TCB === "boolean" ? crypto.trusted_hardware_in_TCB : null;
|
| 259 |
+
S.teeTCB = typeof tee.trusted_hardware_in_TCB === "boolean" ? tee.trusted_hardware_in_TCB : null;
|
| 260 |
+
|
| 261 |
+
_updateVerifier();
|
| 262 |
+
_updateRibbon();
|
| 263 |
+
_updatePillars();
|
| 264 |
+
// fire a roundtrip pulse only when the real micro-artifact actually reconciled.
|
| 265 |
+
if (S.microLabel === "MEASURED" && S.verifyOk === true) _pulseT = 0;
|
| 266 |
+
_paintOverlay();
|
| 267 |
+
}
|
| 268 |
+
|
| 269 |
+
// verifier glyph scale reflects MODELED proof size (succinct => small).
|
| 270 |
+
function _updateVerifier() {
|
| 271 |
+
if (!_verifier) return;
|
| 272 |
+
const live = S.state === "live";
|
| 273 |
+
if (live && S.proofKb != null) {
|
| 274 |
+
// map ~200 kB -> small glyph; keep it visibly "succinct".
|
| 275 |
+
const s = Math.max(0.3, Math.min(0.9, 0.3 + (S.proofKb / 200) * 0.4));
|
| 276 |
+
_verifier.scale.setScalar(s);
|
| 277 |
+
_verifier.material.color.setHex(C_MARKER);
|
| 278 |
+
_verifier.material.emissive.setHex(C_MARKER);
|
| 279 |
+
_verifier.material.opacity = 0.9;
|
| 280 |
+
} else {
|
| 281 |
+
_verifier.scale.setScalar(0.5);
|
| 282 |
+
_verifier.material.color.setHex(C_DIM);
|
| 283 |
+
_verifier.material.emissive.setHex(C_DIM);
|
| 284 |
+
_verifier.material.opacity = 0.3;
|
| 285 |
+
}
|
| 286 |
+
}
|
| 287 |
+
|
| 288 |
+
// recolor + displace the ribbon from the live MODELED prover-time grid.
|
| 289 |
+
function _updateRibbon() {
|
| 290 |
+
if (!_ribbon || !_ribbon.geometry) return;
|
| 291 |
+
const THREE = _THREE;
|
| 292 |
+
const geo = _ribbon.geometry;
|
| 293 |
+
const pos = geo.attributes.position;
|
| 294 |
+
const col = geo.attributes.color;
|
| 295 |
+
const live = S.state === "live" && S.grid && S.grid.length;
|
| 296 |
+
|
| 297 |
+
if (!live) {
|
| 298 |
+
// flat + dim grey when no live data
|
| 299 |
+
for (let i = 0; i < pos.count; i++) {
|
| 300 |
+
pos.setY(i, 0);
|
| 301 |
+
col.setXYZ(i, 0.26, 0.31, 0.36);
|
| 302 |
+
}
|
| 303 |
+
pos.needsUpdate = true; col.needsUpdate = true; geo.computeVertexNormals();
|
| 304 |
+
return;
|
| 305 |
+
}
|
| 306 |
+
|
| 307 |
+
// grid rows = params (X), cols = seq (Z). PlaneGeometry has (segX+1)*(segZ+1) verts.
|
| 308 |
+
const rows = S.grid; // [{params_b, prover_time_s:[...]}]
|
| 309 |
+
const nX = rows.length; // params count
|
| 310 |
+
const nZ = rows[0].prover_time_s.length; // seq count
|
| 311 |
+
// find max for normalization
|
| 312 |
+
let mx = 1;
|
| 313 |
+
for (const r of rows) for (const v of r.prover_time_s) if (v > mx) mx = v;
|
| 314 |
+
|
| 315 |
+
const lo = new THREE.Color(C_RIBBON); // lattice-blue (low cost)
|
| 316 |
+
const hi = new THREE.Color(C_PACKET); // proof-teal (high cost)
|
| 317 |
+
const segX = geo.parameters.widthSegments;
|
| 318 |
+
const segZ = geo.parameters.heightSegments;
|
| 319 |
+
|
| 320 |
+
for (let ix = 0; ix <= segX; ix++) {
|
| 321 |
+
for (let iz = 0; iz <= segZ; iz++) {
|
| 322 |
+
const vi = ix * (segZ + 1) + iz;
|
| 323 |
+
const gx = Math.min(nX - 1, Math.round((ix / segX) * (nX - 1)));
|
| 324 |
+
const gz = Math.min(nZ - 1, Math.round((iz / segZ) * (nZ - 1)));
|
| 325 |
+
const t = rows[gx].prover_time_s[gz] / mx; // 0..1 normalized cost
|
| 326 |
+
pos.setY(vi, t * 2.4); // z = prover time (height)
|
| 327 |
+
const c = lo.clone().lerp(hi, t);
|
| 328 |
+
col.setXYZ(vi, c.r, c.g, c.b);
|
| 329 |
+
}
|
| 330 |
+
}
|
| 331 |
+
pos.needsUpdate = true; col.needsUpdate = true; geo.computeVertexNormals();
|
| 332 |
+
}
|
| 333 |
+
|
| 334 |
+
function _updatePillars() {
|
| 335 |
+
if (_pillars.length < 2) return;
|
| 336 |
+
const live = S.state === "live";
|
| 337 |
+
// crypto pillar[0]: vendor node greyed iff crypto TCB has NO trusted hardware (expected).
|
| 338 |
+
const cryptoGrey = S.cryptoTCB === false || S.cryptoTCB == null;
|
| 339 |
+
const cNode = _pillars[0].node;
|
| 340 |
+
cNode.material.color.setHex(cryptoGrey ? C_DIM : C_MARKER);
|
| 341 |
+
cNode.material.emissive.setHex(cryptoGrey ? C_DIM : C_MARKER);
|
| 342 |
+
cNode.material.emissiveIntensity = cryptoGrey ? 0.08 : 0.4;
|
| 343 |
+
cNode.material.opacity = cryptoGrey ? 0.35 : 0.9;
|
| 344 |
+
// TEE pillar[1]: vendor node lit iff TEE TCB includes trusted hardware (expected true).
|
| 345 |
+
const teeLit = S.teeTCB === true;
|
| 346 |
+
const tNode = _pillars[1].node;
|
| 347 |
+
tNode.material.color.setHex(teeLit ? C_MARKER : C_DIM);
|
| 348 |
+
tNode.material.emissive.setHex(teeLit ? C_MARKER : C_DIM);
|
| 349 |
+
tNode.material.emissiveIntensity = teeLit ? 0.4 : 0.1;
|
| 350 |
+
tNode.material.opacity = teeLit ? 0.9 : 0.4;
|
| 351 |
+
if (!live) {
|
| 352 |
+
_pillars.forEach((p) => { p.mesh.material.opacity = 0.14; });
|
| 353 |
+
} else {
|
| 354 |
+
_pillars.forEach((p) => { p.mesh.material.opacity = 0.28; });
|
| 355 |
+
}
|
| 356 |
+
}
|
| 357 |
+
|
| 358 |
+
// =============================================================================
|
| 359 |
+
// per-frame animation
|
| 360 |
+
// =============================================================================
|
| 361 |
+
function _onFrame() {
|
| 362 |
+
const t = performance.now();
|
| 363 |
+
if (_group) _group.rotation.y = Math.sin(t * 0.00007) * 0.10;
|
| 364 |
+
if (_verifier) { _verifier.rotation.y += 0.02; _verifier.rotation.x += 0.006; }
|
| 365 |
+
|
| 366 |
+
// proof packet travels prover -> verifier along the tunnel, looping.
|
| 367 |
+
if (_packet && _layers.length) {
|
| 368 |
+
const z0 = _layers[0].position.z;
|
| 369 |
+
const z1 = _verifier ? _verifier.position.z : _layers[_layers.length - 1].position.z;
|
| 370 |
+
const phase = (t * 0.00035) % 1;
|
| 371 |
+
_packet.position.z = z0 + (z1 - z0) * phase;
|
| 372 |
+
_packet.rotation.y += 0.05;
|
| 373 |
+
const live = S.state === "live";
|
| 374 |
+
_packet.material.color.setHex(live ? C_PACKET : C_DIM);
|
| 375 |
+
_packet.material.emissive.setHex(live ? C_PACKET : C_DIM);
|
| 376 |
+
_packet.material.opacity = live ? 0.95 : 0.35;
|
| 377 |
+
// light the layer the packet is currently passing through
|
| 378 |
+
for (let i = 0; i < _layers.length; i++) {
|
| 379 |
+
const near = Math.abs(_layers[i].position.z - _packet.position.z) < LAYER_GAP * 0.6;
|
| 380 |
+
_layers[i].material.opacity = live ? (near ? 0.4 : 0.16) : 0.1;
|
| 381 |
+
}
|
| 382 |
+
}
|
| 383 |
+
|
| 384 |
+
// live roundtrip pulse: a single proof-teal (MEASURED) or dim-grey (STUB) surge on the
|
| 385 |
+
// verifier glyph when the real micro-artifact returns. NEVER a green/1.0 state.
|
| 386 |
+
if (_pulseT >= 0 && _verifier) {
|
| 387 |
+
_pulseT += 0.02;
|
| 388 |
+
const measured = S.microLabel === "MEASURED" && S.verifyOk === true;
|
| 389 |
+
const c = measured ? C_PACKET : C_DIM;
|
| 390 |
+
_verifier.material.emissive.setHex(c);
|
| 391 |
+
_verifier.material.emissiveIntensity = 0.35 + 0.5 * Math.max(0, Math.sin(_pulseT * Math.PI));
|
| 392 |
+
if (_pulseT >= 1) { _pulseT = -1; _verifier.material.emissiveIntensity = 0.35; }
|
| 393 |
+
}
|
| 394 |
+
}
|
| 395 |
+
|
| 396 |
+
// =============================================================================
|
| 397 |
+
// overlay (HUD)
|
| 398 |
+
// =============================================================================
|
| 399 |
+
function _buildOverlay() {
|
| 400 |
+
const ctx = _ctx;
|
| 401 |
+
_overlay = document.createElement("div");
|
| 402 |
+
Object.assign(_overlay.style, {
|
| 403 |
+
position: "absolute", left: "14px", top: "14px", zIndex: "6",
|
| 404 |
+
display: "flex", flexDirection: "column", gap: "8px",
|
| 405 |
+
maxWidth: "min(94%,460px)",
|
| 406 |
+
font: "12px ui-sans-serif,system-ui,Segoe UI,Roboto,Arial", color: "#eef3f6",
|
| 407 |
+
});
|
| 408 |
+
|
| 409 |
+
const h = document.createElement("div");
|
| 410 |
+
h.style.cssText = "font:600 13px ui-sans-serif,system-ui;letter-spacing:.4px";
|
| 411 |
+
h.textContent = TITLE;
|
| 412 |
+
_overlay.appendChild(h);
|
| 413 |
+
|
| 414 |
+
const sub = document.createElement("div");
|
| 415 |
+
sub.style.cssText = "color:#9fb1bf;font-size:11px;line-height:1.55";
|
| 416 |
+
sub.innerHTML =
|
| 417 |
+
'The <b>cryptographic-proof</b> trust branch of verifiable inference: a succinct ' +
|
| 418 |
+
'<b>zero-knowledge</b> argument that a <b>committed</b> model produced a specific output, ' +
|
| 419 |
+
'checkable against only a public weight commitment — <b>no trusted hardware, no ' +
|
| 420 |
+
'vendor in the trust base</b>. Orthogonal to the estate’s TEE branch (ccattest). ' +
|
| 421 |
+
'Honesty label <b>MODELED</b> — literature-parameterized cost model, explicitly ' +
|
| 422 |
+
'<b>NOT VERIFIED</b>; no live LLM-scale proof is produced. 0 runtime CDN.';
|
| 423 |
+
_overlay.appendChild(sub);
|
| 424 |
+
|
| 425 |
+
const brow = document.createElement("div");
|
| 426 |
+
brow.style.cssText = "display:flex;gap:8px;align-items:center;flex-wrap:wrap";
|
| 427 |
+
if (_badge && _badge.el) brow.appendChild(_badge.el);
|
| 428 |
+
_overlay.appendChild(brow);
|
| 429 |
+
|
| 430 |
+
const card = document.createElement("div");
|
| 431 |
+
card.style.cssText = "background:#0a1117;border:1px solid #1d2a36;border-radius:9px;padding:9px 10px;display:flex;flex-direction:column;gap:6px";
|
| 432 |
+
|
| 433 |
+
const chead = document.createElement("div");
|
| 434 |
+
chead.style.cssText = "display:flex;align-items:center;gap:8px;flex-wrap:wrap";
|
| 435 |
+
const dot = document.createElement("span");
|
| 436 |
+
dot.style.cssText = "width:9px;height:9px;border-radius:50%;background:#5b8dee;box-shadow:0 0 7px #5b8dee";
|
| 437 |
+
const nm = document.createElement("b");
|
| 438 |
+
nm.style.cssText = "font-size:12px;color:#5b8dee;letter-spacing:.3px";
|
| 439 |
+
nm.textContent = "zkinfer";
|
| 440 |
+
chead.appendChild(dot); chead.appendChild(nm);
|
| 441 |
+
card.appendChild(chead);
|
| 442 |
+
|
| 443 |
+
const grid = document.createElement("div");
|
| 444 |
+
grid.style.cssText = "display:grid;grid-template-columns:1fr;gap:4px";
|
| 445 |
+
function kpiRow(id, label) {
|
| 446 |
+
const r = document.createElement("div");
|
| 447 |
+
r.style.cssText = "display:flex;justify-content:space-between;gap:10px;font-size:11px";
|
| 448 |
+
const l = document.createElement("span"); l.style.cssText = "color:#9fb1bf"; l.textContent = label;
|
| 449 |
+
const v = document.createElement("b");
|
| 450 |
+
v.id = id;
|
| 451 |
+
v.style.cssText = "font-variant-numeric:tabular-nums;color:#eef3f6;text-align:right;max-width:62%;overflow-wrap:anywhere";
|
| 452 |
+
v.textContent = "—";
|
| 453 |
+
_el[id] = v;
|
| 454 |
+
r.appendChild(l); r.appendChild(v); return r;
|
| 455 |
+
}
|
| 456 |
+
grid.appendChild(kpiRow("zk-label", "honesty label (top)"));
|
| 457 |
+
grid.appendChild(kpiRow("zk-anchor", "prover time · zkLLM 13B (MODELED)"));
|
| 458 |
+
grid.appendChild(kpiRow("zk-proof", "proof size (MODELED, succinct)"));
|
| 459 |
+
grid.appendChild(kpiRow("zk-micro", "commit→verify roundtrip"));
|
| 460 |
+
grid.appendChild(kpiRow("zk-tcb", "trusted hardware in TCB (crypto)"));
|
| 461 |
+
grid.appendChild(kpiRow("zk-trust", "trust ceiling"));
|
| 462 |
+
grid.appendChild(kpiRow("zk-lambda", "Λ"));
|
| 463 |
+
card.appendChild(grid);
|
| 464 |
+
|
| 465 |
+
const fn = document.createElement("div");
|
| 466 |
+
fn.style.cssText = "font-size:9.5px;color:#6b7a86;line-height:1.5";
|
| 467 |
+
fn.textContent =
|
| 468 |
+
"Sources: zkLLM arXiv:2404.16109 (CCS’24) · Kang et al. arXiv:2210.08674 · " +
|
| 469 |
+
"ZKML EuroSys’24 DOI 10.1145/3627703.3650088 · South et al. arXiv:2402.02675 · " +
|
| 470 |
+
"Peng et al. survey arXiv:2502.18535. MODELED · not verified.";
|
| 471 |
+
card.appendChild(fn);
|
| 472 |
+
_overlay.appendChild(card);
|
| 473 |
+
|
| 474 |
+
const pl = document.createElement("button");
|
| 475 |
+
pl.textContent = "◑ what this means";
|
| 476 |
+
pl.title = "Toggle plain-language explanation for investors & consumers.";
|
| 477 |
+
pl.style.cssText = "font:11px ui-monospace,monospace;padding:5px 11px;border-radius:7px;border:1px solid #3af4c8;background:#08140f;color:#3af4c8;cursor:pointer;width:fit-content";
|
| 478 |
+
pl.addEventListener("click", () => {
|
| 479 |
+
_plain = !_plain;
|
| 480 |
+
pl.style.background = _plain ? "#0f2a20" : "#08140f";
|
| 481 |
+
_applyPlain();
|
| 482 |
+
});
|
| 483 |
+
_overlay.appendChild(pl);
|
| 484 |
+
|
| 485 |
+
const pd = document.createElement("div");
|
| 486 |
+
pd.id = "zk-plain";
|
| 487 |
+
pd.style.cssText = "font-size:10.5px;color:#c9d6df;line-height:1.55;border:1px dashed #26333f;border-radius:7px;padding:7px 9px;display:none";
|
| 488 |
+
_el["plain"] = pd;
|
| 489 |
+
_overlay.appendChild(pd);
|
| 490 |
+
|
| 491 |
+
(ctx.container || document.body).appendChild(_overlay);
|
| 492 |
+
_paintOverlay();
|
| 493 |
+
}
|
| 494 |
+
|
| 495 |
+
function _applyPlain() {
|
| 496 |
+
const pd = _el["plain"];
|
| 497 |
+
if (!pd) return;
|
| 498 |
+
pd.style.display = _plain ? "block" : "none";
|
| 499 |
+
if (!_plain) return;
|
| 500 |
+
const micro = S.microLabel === "MEASURED" && S.verifyOk === true
|
| 501 |
+
? "really ran and reconciled just now"
|
| 502 |
+
: (S.microLabel === "HONEST-STUB" ? "is an honest stub (did not run)" : "loading…");
|
| 503 |
+
pd.innerHTML =
|
| 504 |
+
"<b>What this means:</b> zkML lets a model host prove — with a small math object " +
|
| 505 |
+
"anyone can check — that a <b>specific committed model</b> produced a given output, " +
|
| 506 |
+
"<b>without revealing the weights</b> and <b>without the checker re-running the model</b>. " +
|
| 507 |
+
"That is the cryptographic cousin of a hardware attestation (the estate’s ccattest " +
|
| 508 |
+
"tab): instead of trusting a chip vendor, you trust <b>standard math assumptions</b>. " +
|
| 509 |
+
"This tab shows <b>MODELED</b> costs read from five real papers (prover time, proof size, " +
|
| 510 |
+
"verify time) — it is <b>NOT a live proof</b> and never shows a “verified/1.0” " +
|
| 511 |
+
"state. The one genuinely-run piece is a tiny <b>commit→prove→verify roundtrip</b> " +
|
| 512 |
+
"computed on the server (it " + micro + "); it proves the <b>plumbing</b> is real, not " +
|
| 513 |
+
"that it scales to an LLM. Plain: honest cost map + trust contrast + one real toy check, " +
|
| 514 |
+
"clearly labeled, no overclaim.";
|
| 515 |
+
}
|
| 516 |
+
|
| 517 |
+
function _tok(s) {
|
| 518 |
+
if (s === "live") return null;
|
| 519 |
+
if (s === "missing") return "NO-LIVE-DATA";
|
| 520 |
+
if (s === "degraded") return "DEGRADED";
|
| 521 |
+
if (s === "error") return "OFFLINE";
|
| 522 |
+
return "…";
|
| 523 |
+
}
|
| 524 |
+
function _set(id, v) { if (_el[id]) _el[id].textContent = v; }
|
| 525 |
+
function _fmtTime(s) { return s == null ? "—" : (s >= 60 ? (s / 60).toFixed(1) + " min" : s + " s"); }
|
| 526 |
+
|
| 527 |
+
function _paintOverlay() {
|
| 528 |
+
const t = _tok(S.state);
|
| 529 |
+
_set("zk-label", t || (S.label || "MODELED"));
|
| 530 |
+
_set("zk-anchor", t || (S.anchorTime != null ? "< " + _fmtTime(S.anchorTime) : "—"));
|
| 531 |
+
_set("zk-proof", t || (S.proofKb != null ? "< " + S.proofKb + " kB" : "—"));
|
| 532 |
+
_set("zk-micro", t || (S.microLabel ? (S.microLabel + (S.verifyOk === true ? " · verify_ok" : "")) : "—"));
|
| 533 |
+
_set("zk-tcb", t || (S.cryptoTCB === false ? "false (none)" : (S.cryptoTCB === true ? "true" : "—")));
|
| 534 |
+
_set("zk-trust", t || (S.trustCeil != null ? String(S.trustCeil) : "—"));
|
| 535 |
+
_set("zk-lambda", t || (S.lambda || "—"));
|
| 536 |
+
if (_plain) _applyPlain();
|
| 537 |
+
}
|
| 538 |
+
|
| 539 |
+
// =============================================================================
|
| 540 |
+
// unmount — dispose everything; must not affect other organs
|
| 541 |
+
// =============================================================================
|
| 542 |
+
export function unmount() {
|
| 543 |
+
_polls.forEach((p) => { try { p.stop(); } catch (_) {} }); _polls = [];
|
| 544 |
+
try { if (_overlay && _overlay.parentNode) _overlay.parentNode.removeChild(_overlay); } catch (_) {}
|
| 545 |
+
try {
|
| 546 |
+
if (_group && _stage) {
|
| 547 |
+
_group.traverse((o) => {
|
| 548 |
+
if (o.geometry && o.geometry.dispose) o.geometry.dispose();
|
| 549 |
+
if (o.material) {
|
| 550 |
+
const ms = Array.isArray(o.material) ? o.material : [o.material];
|
| 551 |
+
ms.forEach((mm) => { if (mm.dispose) mm.dispose(); });
|
| 552 |
+
}
|
| 553 |
+
});
|
| 554 |
+
_stage.scene.remove(_group);
|
| 555 |
+
}
|
| 556 |
+
} catch (_) {}
|
| 557 |
+
_group = _overlay = null;
|
| 558 |
+
_layers = []; _packet = null; _verifier = null; _ribbon = null; _pillars = []; _floor = null;
|
| 559 |
+
_el = {}; _badge = null; _plain = false; _frameReg = false; _pulseT = -1;
|
| 560 |
+
_stage = _THREE = _ctx = null;
|
| 561 |
+
S.label = S.notVerified = S.microLabel = S.verifyOk = S.proofKb = S.anchorTime = null;
|
| 562 |
+
S.trustCeil = S.lambda = S.grid = S.seqAxis = S.paramsAxis = S.cryptoTCB = S.teeTCB = null;
|
| 563 |
+
S.state = "init";
|
| 564 |
+
}
|
| 565 |
+
|
| 566 |
+
export default { id: ID, title: TITLE, endpoints: [EP], mount, unmount };
|