zero-trust-physics / index.html
spiderpilot89's picture
Plain words; path to the offer and the free sample
92ffa15 verified
Raw History Blame Contribute Delete
20.3 kB
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Zero-Trust Physics</title>
<meta name="description" content="A deterministic physics runtime. Every answer comes with a cryptographic proof.">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400..700&family=JetBrains+Mono:wght@400;500&family=Libre+Franklin:wght@400;500;600&family=Newsreader:opsz,wght@6..72,400..600&display=swap">
<style>
:root{
--paper:#FAF8F5; --ink:#1C1C1E; --ink-2:#56514A; --hair:#D3CCBF; --plate:#FFFFFF;
--red:#C0392B; --green:#27AE60;
--display:"Fraunces","Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
--text:"Newsreader","Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
--sans:"Libre Franklin","Franklin Gothic Medium","Helvetica Neue",Arial,sans-serif;
--mono:"JetBrains Mono",ui-monospace,"SF Mono",Menlo,Consolas,monospace;
--eight:linear-gradient(90deg,#C0392B 0 12.5%,#E67E22 12.5% 25%,#F1C40F 25% 37.5%,#27AE60 37.5% 50%,#1F6FB2 50% 62.5%,#6C3FAF 62.5% 75%,#6B4423 75% 87.5%,#1a1a1a 87.5% 100%);
}
@media (prefers-color-scheme: dark){
:root{ --paper:#050505; --ink:#F5F5F5; --ink-2:#B8B4AD; --hair:#34332F; --plate:#121211; }
}
*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{margin:0;background:var(--paper);color:var(--ink);font-family:var(--text);font-size:1.16rem;line-height:1.5}
.stripe{height:6px;background:var(--eight)}
main{max-width:720px;margin:0 auto;padding:2.2rem 16px 3rem}
h1,h2,h3{font-family:var(--display);font-weight:600;letter-spacing:-.01em;line-height:1.12;margin:0}
h1{font-size:clamp(2.2rem,7vw,3.1rem)}
h2{font-size:clamp(1.5rem,4.6vw,1.9rem);margin-top:2.6rem}
h3{font-size:1.3rem;margin-top:1.2rem}
p{margin:.8rem 0 0}
.lede{font-size:1.24rem;margin-top:1rem}
section{border-top:1px solid var(--hair);margin-top:2.6rem}
section h2{margin-top:1.6rem}
.plate{background:var(--plate);border:1px solid var(--hair);padding:.8rem .9rem;margin-top:.9rem;display:flex;gap:.8rem;align-items:flex-start;justify-content:space-between}
.plate code{font-family:var(--mono);font-size:.9rem;line-height:1.5;overflow-wrap:anywhere;white-space:pre-wrap}
label{display:block;font-family:var(--sans);font-size:.82rem;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-2);margin-top:1.1rem}
input{display:block;width:100%;margin-top:.4rem;padding:.7rem .8rem;font-family:var(--text);font-size:1.16rem;color:var(--ink);background:var(--plate);border:1px solid var(--hair);border-radius:0}
input[type=number]{font-family:var(--mono);font-size:1.05rem;max-width:12rem}
input:focus-visible,button:focus-visible,a:focus-visible{outline:2px solid #1F6FB2;outline-offset:2px}
button{font-family:var(--sans);font-size:.95rem;font-weight:600;padding:.7rem 1.1rem;border:1px solid var(--ink);border-radius:0;cursor:pointer;background:var(--ink);color:var(--paper);margin-top:.9rem}
button.quiet{background:transparent;color:var(--ink)}
button.copy{margin:0;padding:.3rem .6rem;font-size:.78rem;flex:none}
button[disabled]{opacity:.55;cursor:default}
.out{margin-top:1rem}
.out:empty{display:none}
.out h3:first-child{margin-top:0}
.out ul{margin:.5rem 0 0;padding-left:1.2rem}
.out li{margin-top:.3rem}
.out blockquote{margin:.8rem 0 0;padding-left:.9rem;border-left:3px solid var(--hair);color:var(--ink-2)}
.out code{font-family:var(--mono);font-size:.88rem}
.proof{font-family:var(--mono);font-size:.9rem;line-height:1.5;overflow-wrap:anywhere;background:var(--plate);border:1px solid var(--hair);padding:.7rem .9rem;margin-top:.6rem}
.holds{border-left:4px solid var(--green);padding-left:.9rem}
.stops{border-left:4px solid var(--red);padding-left:.9rem}
.foot{font-family:var(--sans);font-size:.92rem;color:var(--ink-2);border-top:1px solid var(--hair);margin-top:2.6rem;padding-top:.6rem}
a{color:inherit;text-underline-offset:.16em}
</style>
</head>
<body>
<div class="stripe" aria-hidden="true"></div>
<main>
<h1>Zero-Trust Physics</h1>
<p class="lede">Zero-Trust Physics is a deterministic physics runtime for agents and RL rollouts. An agent asks about real hardware, and every answer comes with a SHA-384 proof, so any agent can run it again and get the same thing. Every answer the address computes is also signed ML-DSA-87. Past what a model was compared with, it keeps going with the same equations and flags every step, and each flag carries the limit, the value reached and the extent past it. It stops only at a physical limit, or where its equations, constants or tables no longer hold, and it names the reason.</p>
<p>Engine 0.15.2: 61 models, one for each real object, 46 of them compared with measurement. Each states its spec sheet in numbers: what it computes, its range, what it was fitted on, what it was compared with and within what, its gap, and what it refuses.</p>
<section>
<h2>Hand it to your agent.</h2>
<div class="plate"><code id="address">https://mcp.zerotrustphysics.com/mcp</code><button class="copy quiet" data-copy="address">Copy</button></div>
<p>Open to any agent. Something to paste:</p>
<div class="plate"><code id="paste">Connect to https://mcp.zerotrustphysics.com/mcp and read what is there. Then tell me what it is, and why it might matter to me.</code><button class="copy quiet" data-copy="paste">Copy</button></div>
</section>
<section>
<h2>What do you have?</h2>
<p>Describe a real thing in a sentence, and see which model fits it, what it was fitted on, and how close it came to the measurements other people made.</p>
<form id="find-form">
<label for="thing">A real thing, in a sentence</label>
<input id="thing" type="text" placeholder="a lithium cell discharging in the cold" autocomplete="off">
<button id="find-button" type="submit">Find the model</button>
</form>
<div class="out" id="found" aria-live="polite"></div>
</section>
<section>
<h2>Watch one answer arrive</h2>
<p>An agent asked how hard a battery pack could be pushed for ten minutes. A hundredth of an amp separates the run that holds from the run that stops. Try 71.44, then 71.45, then a number of your own.</p>
<form id="run-form">
<label for="amps">Current, in amps</label>
<input id="amps" type="number" step="0.01" value="71.44" inputmode="decimal">
<button id="run-button" type="submit">Ask the verifier</button>
</form>
<div class="out" id="ran" aria-live="polite"></div>
</section>
<section>
<h2>Run it again</h2>
<p>Does the same question arrive at the same cryptographic proof a second time? That is what makes an answer something your agent can pass on.</p>
<button id="confirm-button" class="quiet" type="button">Confirm the proof</button>
<div class="out" id="confirmed" aria-live="polite"></div>
</section>
<div class="foot">
<p>The pack is a company specimen: a 12-cell lithium-ion pack of 22 Ah, 50.4 V full and 36.0 V empty, every constant stated in its description. The models of real things, each with the people who measured them, are on the site.</p>
<p><a href="https://zerotrustphysics.com">The site</a> · <a href="https://doi.org/10.5281/zenodo.23517223">The paper</a> · <a href="https://github.com/johnkruze/zero-trust-physics">Confirm a proof and its signature with no engine, on GitHub</a> · <a href="https://github.com/johnkruze/zero-trust-physics-engine">The engine's source, tagged v0.15.2</a></p>
<p>This page holds no physics of its own. Your browser asks the address above, and every answer is shown as it arrived.</p>
<p>Reaching John Kruze: kruze@zerotrustphysics.com</p>
<p><a href="https://zerotrustphysics.com/offers/fast-start/">Paid air-gapped rollout packs</a> · <a href="https://huggingface.co/datasets/zero-trust-physics/zero-trust-physics-sample-group-1">A free 5-task sample</a></p>
<p>By Protocol Company.</p>
</div>
</main>
<script>
const ADDRESS = "https://mcp.zerotrustphysics.com/mcp";
const TIMEOUT_MS = 75000; // the address itself waits 60 seconds for an answer
const TRIES = 3; // when the address is busy it says so at once; ask again
const BUSY = "Too many concurrent physics tasks.";
const AWAY = "The verifier could not be reached from here just now. Please try again in a moment.";
const STILL_BUSY = "The verifier is busy with other questions just now. Please try again in a moment.";
const UNREADABLE = "An answer arrived that could not be read. Please try again in a moment.";
class Unanswered extends Error {}
const sleep = (ms) => new Promise((done) => setTimeout(done, ms));
// The one place a request leaves this page.
async function ask(tool, args) {
const body = JSON.stringify({jsonrpc: "2.0", id: 1, method: "tools/call", params: {name: tool, arguments: args}});
let wait = 1500;
for (let attempt = 0; attempt < TRIES; attempt++) {
const last = attempt + 1 === TRIES;
const stop = new AbortController();
const timer = setTimeout(() => stop.abort(), TIMEOUT_MS);
let response, text;
try {
response = await fetch(ADDRESS, {
method: "POST", body, signal: stop.signal,
headers: {"Content-Type": "application/json", "Accept": "application/json, text/event-stream"},
});
text = await response.text();
} catch (error) {
throw new Unanswered(AWAY);
} finally {
clearTimeout(timer);
}
if (response.status === 429) {
if (last) throw new Unanswered(STILL_BUSY);
await sleep(wait); wait *= 2; continue;
}
if (!response.ok) {
throw new Unanswered(`The verifier answered with HTTP status ${response.status} and no result. Please try again in a moment.`);
}
let said, stopped;
try {
// An answer may arrive as plain JSON or as one event of a stream.
const events = text.split(/\r?\n/).filter((line) => line.startsWith("data:")).map((line) => line.slice(5));
const message = JSON.parse(events.length ? events[events.length - 1] : text);
if (message.error) {
said = String(message.error.message || ""); stopped = true;
} else {
said = (message.result.content || []).map((part) => part.text || "").join("");
stopped = Boolean(message.result.isError);
}
} catch (error) {
throw new Unanswered(UNREADABLE);
}
if (stopped && said.includes(BUSY)) {
if (last) throw new Unanswered(STILL_BUSY);
await sleep(wait); wait *= 2; continue;
}
if (stopped) throw new Unanswered("The verifier stopped this request and said why: " + (said || "no reason came with it."));
return said;
}
throw new Unanswered(STILL_BUSY);
}
// Everything shown is placed as text, never as markup.
function el(tag, text, cls) {
const node = document.createElement(tag);
if (text !== undefined) node.textContent = text;
if (cls) node.className = cls;
return node;
}
function show(out, ...nodes) { out.replaceChildren(...nodes); }
function say(out, sentence) { show(out, el("p", sentence)); }
async function pressing(button, during, work) {
const was = button.textContent;
button.disabled = true; button.textContent = during;
try { await work(); } finally { button.disabled = false; button.textContent = was; }
}
function named(row) {
return row.solver ? row.solver : `${row.domain || ""} / ${row.card || ""}`;
}
function point(lead, text, code) {
const li = el("li", lead);
li.append(code ? el("code", text) : document.createTextNode(text));
return li;
}
const found = document.getElementById("found");
document.getElementById("find-form").addEventListener("submit", (event) => {
event.preventDefault();
const described = document.getElementById("thing").value.trim();
if (!described) { say(found, "Describe a real thing in a sentence first, such as a lithium cell discharging in the cold."); return; }
pressing(document.getElementById("find-button"), "Finding…", async () => {
let matches, nearest;
try {
const answer = JSON.parse(await ask("find_model", {description: described, limit: 3}));
matches = (answer.matches || []).filter((row) => row && typeof row === "object");
nearest = (answer.nearest_by_words || []).filter((row) => row && typeof row === "object");
} catch (error) {
say(found, error instanceof Unanswered ? error.message : UNREADABLE); return;
}
const nodes = [];
if (matches.length) {
nodes.push(el("p", matches.length === 1 ? "This is what fits." : "These fit, the closest first."));
for (const row of matches) {
nodes.push(el("h3", row.model_of || "A served model"));
const list = el("ul");
list.append(point("Its name at the address: ", named(row), true));
if (row.fit) list.append(point("Why it fits: ", `it ${row.fit}.`));
if (row.compared_with) list.append(point("What stands behind it: ", String(row.compared_with)));
if (row.accuracy_against_measurement) list.append(point("Against measurement: ", String(row.accuracy_against_measurement)));
nodes.push(list);
}
nodes.push(el("p", "Your agent can read the full description, run it and cite the people whose measurements it stands on, by that name, at the address."));
} else {
nodes.push(el("p", "Nothing served fits that description. Each model is of one named real thing, made from open measurements of it. To ask for a model of yours, write to John Kruze at kruze@zerotrustphysics.com and name an open dataset of the thing."));
if (nearest.length) {
nodes.push(el("p", "The nearest by words, none of them a model of what you described:"));
const list = el("ul");
for (const row of nearest) {
const li = el("li", `${row.model_of || "A served model"} `);
li.append(el("code", named(row)));
if (row.not_a_match) li.append(document.createTextNode(` (${row.not_a_match})`));
list.append(li);
}
nodes.push(list);
}
}
show(found, ...nodes);
});
});
// 600 -> 10:00 and 599.8 -> 9:59.8, as the front page writes a run's reach.
function clock(seconds) {
const tenths = Math.round(seconds * 10);
const minutes = Math.floor(tenths / 600), rest = tenths % 600;
const whole = Math.floor(rest / 10), tenth = rest % 10;
return `${minutes}:${String(whole).padStart(2, "0")}` + (tenth ? `.${tenth}` : "");
}
let kept = null; // the last question asked and the proof that came back
const ran = document.getElementById("ran");
const confirmed = document.getElementById("confirmed");
document.getElementById("run-form").addEventListener("submit", (event) => {
event.preventDefault();
const amps = Number(document.getElementById("amps").value);
if (document.getElementById("amps").value.trim() === "" || !Number.isFinite(amps)) {
kept = null; show(confirmed); say(ran, "Enter the current as a number of amps first, such as 71.44."); return;
}
pressing(document.getElementById("run-button"), "Asking…", async () => {
const request = {
domain: "energy", card: "battery_sag", initial: {soc: 1.0}, dt_s: 0.1,
segments: [{steps: 6000, load: {current_a: amps}}], record_every: 6000,
};
let answer, proof, state, reached;
try {
answer = JSON.parse(await ask("run_trajectory", request));
proof = answer.run_seal;
state = answer.final_state || {};
reached = Number(state.t_s || 0);
if (typeof proof !== "string" || !Number.isFinite(reached)) throw new Error("unreadable");
} catch (error) {
kept = null; show(confirmed); say(ran, error instanceof Unanswered ? error.message : UNREADABLE); return;
}
const block = el("div");
if (answer.outcome === "completed") {
block.className = "holds";
block.append(el("h3", "Holds the ten minutes."));
let said = `At ${amps} amps the pack reached ${clock(reached)}`;
if (typeof state.terminal_v === "number") said += ` and ended at ${state.terminal_v.toFixed(4)} volts`;
if (typeof state.cutoff_margin_v === "number") said += `, ${state.cutoff_margin_v.toFixed(4)} volts above where it would stop`;
block.append(el("p", said + "."));
} else {
block.className = "stops";
block.append(el("h3", `Stops at ${clock(reached)}.`));
block.append(el("p", `At ${amps} amps the model stopped before the ten minutes were up, and said why.`));
if (answer.reject_detail) {
block.append(el("p", "Its reply, exactly as it came:"));
block.append(el("blockquote", String(answer.reject_detail)));
}
}
// Each flag the run carries: the limit, the value reached and the extent past it.
for (const flag of Array.isArray(answer.exceedance_extremes) ? answer.exceedance_extremes : []) {
if (!flag || typeof flag.limit !== "number" || typeof flag.value !== "number" || typeof flag.extent !== "number") continue;
const unit = flag.unit ? ` ${flag.unit}` : "";
let line = `Flagged${flag.flag ? ` (${flag.flag})` : ""}: ${flag.quantity || "a value"} went ${flag.side || "past"} its limit of ${flag.limit}${unit}`;
if (typeof flag.steps === "number") line += ` on ${flag.steps.toLocaleString("en")} steps`;
line += `; at its furthest ${flag.value.toFixed(4)}${unit}, ${flag.extent.toFixed(4)}${unit} past the limit`;
if (typeof flag.largest_at_step === "number") line += ` (step ${flag.largest_at_step.toLocaleString("en")})`;
block.append(el("p", line + "."));
}
kept = {request: answer.inputs || request, run_seal: proof, amps};
show(confirmed);
const nodes = [block,
el("p", "The proof of this answer (SHA-384, seal rule v2):"),
el("div", proof, "proof")];
const signed = answer.signature;
if (signed && typeof signed === "object" && signed.alg && signed.key_id) {
nodes.push(el("p", `Signed ${signed.alg} by the address${signed.issued_at ? ` at ${signed.issued_at}` : ""}${signed.expires_at ? `, expiring ${signed.expires_at}` : ""}, with the key whose fingerprint is:`));
nodes.push(el("div", String(signed.key_id), "proof"));
}
nodes.push(el("p", "Any agent that asks the same question gets the same proof. The signature is new on every answer. Press the button below to see the proof come back."));
show(ran, ...nodes);
});
});
document.getElementById("confirm-button").addEventListener("click", () => {
if (!kept) { say(confirmed, "Ask the verifier a question first. The proof that comes back is what gets confirmed here."); return; }
const asked = kept;
pressing(document.getElementById("confirm-button"), "Running it again…", async () => {
let holds, second;
try {
const again = JSON.parse(await ask("verify_tape", {request: asked.request, run_seal: asked.run_seal}));
holds = again.holds === true;
second = again.recomputed_run_seal;
} catch (error) {
say(confirmed, error instanceof Unanswered ? error.message : UNREADABLE); return;
}
if (holds && second === asked.run_seal) {
show(confirmed,
el("h3", "It came back the same."),
el("p", `The verifier ran the ${asked.amps} amp question a second time, from the start, and arrived at the same cryptographic proof:`),
el("div", second, "proof"),
el("p", "The programs at github.com/johnkruze/zero-trust-physics confirm a proof like this one with no engine at all, and verify its signature against the key at the address's /answer-key."));
} else {
show(confirmed,
el("h3", "It did not come back the same."),
el("p", "The verifier ran the question a second time and did not arrive at the same cryptographic proof. Ask the question again, then confirm the proof that comes back."));
}
});
});
for (const button of document.querySelectorAll("button.copy")) {
button.addEventListener("click", async () => {
try {
await navigator.clipboard.writeText(document.getElementById(button.dataset.copy).textContent);
button.textContent = "Copied";
} catch (error) {
button.textContent = "Select and copy";
}
setTimeout(() => { button.textContent = "Copy"; }, 1600);
});
}
</script>
</body>
</html>