open-standards/wai/wai-quantum-py/python/wai_quantum/static/receipt.js
Transaction Science 22fdc7a3cb wai-quantum-py: WAI Quantum in Python and notebooks, in-process
A new crate, wai/wai-quantum-py, built by maturin 1.15.0 into one abi3 wheel
per platform (pyo3 0.29.3, Python 3.9 on), module wai_quantum. Its extension
module wraps the shared job engine and nothing else: run, plan, lint, draw
(text and the engine SVG), layout, critique, improve, shortcuts,
equivalent, verify, seal, canonical, digest, methods, accuracy_classes and
history, values crossing one to one with JSON (NaN, integers past 64 bits
and non-string keys refused). A job is the service form as a plain dict
with helpers (counts, probabilities, expectations, amplitudes, method,
accuracy, receipt); Key reads and writes the command line key files and
finds the same user key; bloch gives each qubit reduced state from the
engine expectation values. A refusal raises EngineError with the engine
message, its line, and a code slot for the engine diagnostic codes.

Service is a client in the standard library alone for the job service
(submit, status, result, cancel, run), naming itself
wai-quantum-python/<version>, its receipts checked here offline.

Widgets (the widgets extra): Circuit (the engine drawing, gates clickable,
authorship marks from a history), Result, Receipt (the engine verdict) and
Bloch (drag to turn), each a plain ES module, each with static HTML (and
SVG) fallbacks that render without the widget library.

Five doc notebooks run in CI and are held to their stored outputs.
ci/check.sh is the whole check; 62 pytest tests hold the package to the
command line (same results, plans, lints, critiques, drawings, methods,
equivalence verdicts; receipts verified both ways; the same user key; the
digest recomputed from Python canonical bytes), to the service run locally,
and run the front ends under node on the payloads; Python 3.9 smoke with
the wheel alone. Workflow wai-quantum-py.yml runs it on linux and macos.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-27 19:51:08 -04:00

47 lines
1.9 KiB
JavaScript

// The Receipt widget: who signed a job's result, the digest and the signature, and
// whether the receipt seals the request and the result. That verdict is the
// engine's, checked in Python when the widget was made; this page only shows it.
function el(tag, attrs = {}, ...kids) {
const e = document.createElement(tag);
for (const [k, v] of Object.entries(attrs)) {
if (k === 'text') e.textContent = v;
else if (v != null) e.setAttribute(k, String(v));
}
for (const k of kids) if (k != null) e.append(k);
return e;
}
const short = (s, keep) => (!s ? '' : s.length <= 2 * keep + 1 ? s : `${s.slice(0, keep)}…${s.slice(-keep)}`);
function render({ model, el: host }) {
const root = el('div', { class: 'wq wq-receipt-widget' });
host.append(root);
function draw() {
const d = model.get('data') || {};
const ok = d.valid === true;
const rows = [
['signer', d.signer || '—'],
['key', d.key || '—'],
['digest', d.digest || '—'],
['signature', short(d.signature, 16) || '—'],
['form', `${d.alg || '?'} over ${d.canon || 'the first form'} canonical JSON`],
];
const t = el('table', { class: 'wq-table' });
for (const [k, v] of rows) t.append(el('tr', {}, el('td', { class: 'wq-muted', text: k }), el('td', { class: 'wq-mono wq-break', text: v })));
const parts = [
el('div', {}, 'receipt ', el('span', { class: `wq-badge ${ok ? 'wq-good' : 'wq-bad'}`, text: ok ? 'verified' : 'INVALID' }),
' ', el('span', { class: 'wq-muted', text: `checked here, binding ${d.binds || 'the request and the result as given'}` })),
t,
];
if (d.demo) parts.push(el('div', { class: 'wq-muted', text: 'Signed with the published demo key: it shows the result is unaltered, not who signed it.' }));
root.replaceChildren(...parts);
}
draw();
model.on('change:data', draw);
return () => model.off('change:data', draw);
}
export default { render };