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]>
47 lines
1.9 KiB
JavaScript
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 };
|