docs+site: CERT-01 web certificate viewer and packaging links

- certificate.html brand kit preview with multihash when present
- PACKAGING.md CERT section residual
This commit is contained in:
George Lambert 2026-10-13 21:50:36 -04:00
commit 5cfb92c82a
7 changed files with 445 additions and 3 deletions

View file

@ -53,7 +53,8 @@ verae-print pending --html # offline queue page
Tray, menu bar, CERT-01 digests, version stamps (`HelperVersion` **0.3.6**), and IPP GET vs POST split:
- [docs/PACKAGING.md](docs/PACKAGING.md) — Windows tray (no elevated MSI), macOS LaunchAgent / unsigned `.app` / notarization (docs only), `pending` / `tray-status` / `menubar`, statuslang notify titles, hold ≠ evidence.
- [docs/PACKAGING.md](docs/PACKAGING.md) — Windows tray (no elevated MSI), macOS LaunchAgent / unsigned `.app` / notarization (docs only), `pending` / `tray-status` / `menubar`, statuslang notify titles, hold ≠ evidence, CERT-01 web viewer.
- [site/printit.verae.ai/certificate.html](site/printit.verae.ai/certificate.html) — CERT-01 branded certificate HTML (plum/gold, multihash when present).
## Contributing

View file

@ -176,6 +176,23 @@ Rules:
final / already-registered states (`statuslang.IsEvidence`). Standing
copy: `statuslang.EvidenceNote`.
### Web certificate viewer (printit.verae.ai)
Site page: [`site/printit.verae.ai/certificate.html`](../site/printit.verae.ai/certificate.html)
| Item | Status |
|------|--------|
| CERT-01 layout | **Shipped** — plum/gold double frame, Fraunces title via Google Fonts, gold rule, final banner, mono digests, digests-only footer |
| Brand kit | Uses `brand/tokens.css`, `verae-ui-kit.css`, `brand/logo/verae-mark.svg` |
| Multihash / BLAKE3 | Shown **only when present** (query, sidecar, or sample); never invented |
| Load paths | Query string (`?sha256=&receipt=&…`), optional `.verae.json` sidecar drop, “Sample data” button |
| Print CSS | Letter page, toolbar hidden, frame colors preserved |
| Live verify | Link to `explorer.verae.ai/time?receipt=&sha256=` (same as `pdfcert.LookupURL`) |
| Residual gap | Full design-file **CERT-01.html** pixel match (embedded Fraunces/Cantarell from design kit, live QR bitmap, Substrate extrinsic polish) is **not** claimed — PDF path (`internal/pdfcert` + `platform/registration-pdf/build.mjs`) remains the issued certificate artifact |
Design source of truth for the paper mock: `verae-2026-design/ui-designs/src/html/CERT-01.html`.
Cross-product siblings (not owned here): Sign `certificate.html` (SG-P1), Verify ZP-V5, MCP Mac export PDF.
## statuslang notify titles
Source: [`internal/statuslang`](../internal/statuslang/status.go). Tray,
@ -253,3 +270,4 @@ tray/menubar assets.
| `platform/macos/menubar/` | Swift menubar + LaunchAgent + `.app` |
| `platform/macos/pkg/build-pkg.sh` | optional signed `.pkg` (certs required) |
| `platform/smoke-packaging-metadata.sh` | A4 packaging smoke |
| `site/printit.verae.ai/certificate.html` | CERT-01 web cert viewer (brand kit) |

View file

@ -3,7 +3,10 @@
Static site served by Caddy on 70.88.205.138 from `/var/www/printit.verae.ai`.
- `index.html` — download page, "How it works" welcome dialog, "Learn more" FAQ.
- `certificate.html` — CERT-01 web certificate viewer (brand tokens, plum/gold frame, multihash/BLAKE3 only when present; query or `.verae.json` sidecar).
- `queue.html` — PT-04 / PT-W4 job queue help page.
- `img/`, `samples/` — screenshots and the sample receipt PDF used by the page.
- `brand/` — tokens + logos (BrandingBook kit).
- `downloads/` is not in git (162 MB of release builds); see `DOWNLOADS-MANIFEST.txt` for the files and checksums that were live.
Deploy: `rsync -a --exclude downloads site/printit.verae.ai/ marchon@70.88.205.138:/var/www/printit.verae.ai/` (back up `index.html` first).

View file

@ -0,0 +1,413 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1"/>
<title>Verae Timestamp Certificate · CERT-01 · PrintIt</title>
<meta name="description" content="CERT-01 branded timestamp certificate viewer for PrintIt. Digests only — final receipt is evidence."/>
<link rel="canonical" href="https://printit.verae.ai/certificate.html"/>
<link rel="stylesheet" href="brand/tokens.css"/>
<link rel="stylesheet" href="verae-ui-kit.css"/>
<link rel="preconnect" href="https://fonts.googleapis.com"/>
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin/>
<link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,600;9..144,700&amp;family=JetBrains+Mono:wght@500&amp;display=swap" rel="stylesheet"/>
<style>
body{margin:0;background:var(--canvas,#E9E6EE);color:var(--ink,#1D1534);font-family:var(--font-sans),system-ui,-apple-system,Segoe UI,sans-serif}
.toolbar{padding:12px 20px;background:var(--card,#fff);border-bottom:1px solid var(--line,#E3DEF0);display:flex;gap:10px;align-items:center;flex-wrap:wrap}
.toolbar b{color:var(--plum,#531B59)}
.toolbar .help{font-size:12px;color:var(--muted,#5E5470)}
.toolbar .spacer{flex:1}
.btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;font-weight:600;font-size:13px;border-radius:8px;padding:0 14px;height:36px;border:1px solid transparent;text-decoration:none;cursor:pointer;font-family:inherit}
.btn.secondary{background:var(--card,#fff);color:var(--plum,#531B59);border-color:#CDBFD4}
.btn.primary{background:var(--plum,#531B59);color:#fff}
.btn.tonal{background:var(--plum-100,#EBD9EE);color:var(--plum-d,#3E1343);border:0}
.wrap{max-width:900px;margin:0 auto;padding:24px 16px 48px}
/* CERT-01 paper sheet — plum outer + gold inner frame */
.sheet{
background:#fff;position:relative;border-radius:4px;
box-shadow:0 12px 40px rgba(30,10,40,.18),0 2px 8px rgba(30,10,40,.08);
padding:48px 56px 56px;min-height:720px;
box-shadow:
0 12px 40px rgba(30,10,40,.18),
inset 0 0 0 1.5px var(--plum,#531B59),
inset 0 0 0 6px #fff,
inset 0 0 0 6.5px var(--gold,#C4A85A);
}
.head{display:flex;justify-content:space-between;align-items:flex-start;gap:16px}
.logo-row{display:flex;align-items:center;gap:10px}
.logo-row img{height:36px;width:auto;display:block}
.mark{width:36px;height:36px;border-radius:9px;background:linear-gradient(140deg,var(--plum,#531B59),var(--violet,#6B3FD6));display:grid;place-items:center;color:#fff;font-weight:800;font-size:13px;flex:none}
.cert-meta{text-align:right;font-size:11px;color:var(--muted,#5E5470);line-height:1.45}
.title{
text-align:center;margin:28px 0 0;
font-family:var(--font-serif),Fraunces,Georgia,serif;
font-weight:700;font-size:clamp(22px,3.2vw,26px);line-height:1.25;letter-spacing:-0.01em;color:var(--ink,#1D1534);
}
.subtitle{text-align:center;font-size:12.5px;color:var(--muted,#5E5470);margin:8px auto 0;max-width:34rem;line-height:1.45}
.rule{height:2px;background:var(--gold,#C4A85A);width:120px;margin:14px auto 0;border:0}
.banner{
margin-top:20px;border:2px solid var(--ok,#0E6B3A);background:var(--ok-bg,#E3F5EA);
border-radius:10px;padding:12px 16px;display:flex;gap:12px;align-items:center;
}
.banner.provisional{border-color:var(--pend-bd,#D5DAE1);background:var(--pend-bg,#EEF0F3)}
.banner .check{font-size:28px;line-height:1;color:var(--ok,#0E6B3A);font-weight:700}
.banner.provisional .check{color:var(--pend,#475467)}
.banner .bt{font:700 15px/1.3 var(--font-sans),system-ui;color:var(--ok,#0E6B3A)}
.banner.provisional .bt{color:var(--pend,#475467)}
.banner .bs{font-size:12px;color:#1D4D33;margin-top:2px}
.banner.provisional .bs{color:var(--muted,#5E5470)}
.kv{display:grid;grid-template-columns:150px 1fr;gap:10px 16px;margin-top:22px;font-size:13px}
.kv dt{color:var(--muted,#5E5470);font-weight:600;font-size:12px;padding-top:2px}
.kv dd{margin:0;word-break:break-all;line-height:1.45}
.mono{font-family:var(--font-mono),'JetBrains Mono',ui-monospace,SF Mono,Menlo,monospace;font-size:11px;letter-spacing:-0.01em}
.mh{display:inline-flex;align-items:flex-start;gap:4px;flex-wrap:wrap;background:var(--surface-2,#F4F1F8);border:1px solid var(--line,#E3DEF0);border-radius:6px;padding:4px 8px}
.mh .pfx{color:var(--plum,#531B59);font-weight:600}
.verify-box{
display:flex;gap:18px;align-items:flex-start;margin-top:24px;padding:16px;
border:1px solid var(--line,#E3DEF0);border-radius:10px;background:var(--bg,#FBFAFD);
}
.qr{
width:112px;height:112px;flex:none;border:2px solid var(--ink,#1D1534);border-radius:8px;
background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 29 29'%3E%3Cpath fill='%231D1534' d='M1 1h7v7H1zm2 2v3h3V3zm10 0h7v7h-7zm2 2v3h3V3zM1 13h7v7H1zm2 2v3h3v-3zm18-14h7v7h-7zm2 2v3h3V3zm0 10h3v2h-3zm-4 0h2v2h-2zm4 4h3v3h-3zm-4 2h2v3h-2zm-2-4h2v2h-2zm6 6h3v2h-3zm-8 0h2v2h-2zm4-2h2v4h-2zm-6 0h2v2h-2z'/%3E%3C/svg%3E") center/72% no-repeat;
position:relative;
}
.qr span{position:absolute;inset:auto;left:50%;top:50%;transform:translate(-50%,-50%);background:#fff;padding:2px 5px;font:700 10px system-ui;color:var(--plum,#531B59)}
.verify-box ol{margin:6px 0 0 16px;padding:0;line-height:1.6;color:var(--ink-soft,#3B3250);font-size:12.5px}
.verify-box a{color:var(--info,#3B2A8C);font-size:10px;word-break:break-all}
.foot{
margin-top:28px;padding-top:14px;border-top:1px solid var(--line,#E3DEF0);
font-size:10px;color:var(--muted,#5E5470);line-height:1.5;
}
.load{margin-top:18px;padding:14px 16px;background:var(--card,#fff);border:1px solid var(--line,#E3DEF0);border-radius:12px}
.load label{display:block;font-size:12px;font-weight:600;color:var(--muted,#5E5470);margin-bottom:6px}
.load input[type=file]{font-size:13px}
.note{font-size:12px;color:var(--muted,#5E5470);margin:8px 0 0;line-height:1.4}
.hidden{display:none!important}
@media print{
.toolbar,.load,.no-print{display:none!important}
html,body{background:#fff!important;margin:0;padding:0}
.wrap{padding:0;max-width:none}
.sheet{
box-shadow:none!important;
border:2px solid #531B59;
outline:1px solid #C4A85A;outline-offset:-5px;
margin:0;border-radius:0;min-height:0;padding:28px 36px 36px;
-webkit-print-color-adjust:exact;print-color-adjust:exact;
}
.rule,.banner,.mh,.qr{ -webkit-print-color-adjust:exact;print-color-adjust:exact }
.rule{background:#C4A85A!important}
a{color:inherit;text-decoration:none}
}
@page{size:letter;margin:12mm}
</style>
</head>
<body>
<div class="toolbar no-print">
<b>CERT-01</b>
<span class="help">PrintIt · Verae Timestamp Certificate (web preview)</span>
<span class="spacer"></span>
<button class="btn secondary" type="button" id="btn-sample">Sample data</button>
<button class="btn primary" type="button" onclick="window.print()">Print</button>
<a class="btn secondary" href="index.html">printit.verae.ai</a>
<a class="btn secondary" href="queue.html">Queue</a>
</div>
<div class="wrap">
<article class="sheet" id="cert" aria-label="Verae Timestamp Certificate">
<div class="head">
<div class="logo-row">
<img src="brand/logo/verae-mark.svg" alt="Verae" width="36" height="36"
onerror="this.style.display='none';this.nextElementSibling.style.display='grid'"/>
<span class="mark" style="display:none" aria-hidden="true">V</span>
<span style="font-weight:700;font-size:14px;color:var(--plum,#531B59)">Verae</span>
</div>
<div class="cert-meta">
<div id="cert-no">Certificate preview</div>
<div>verify.verae.ai · explorer.verae.ai/time</div>
</div>
</div>
<h1 class="title">Verae Timestamp Certificate</h1>
<p class="subtitle">Proof that this exact document existed at the time below, recorded on the Verae Substrate blockchain</p>
<hr class="rule"/>
<div class="banner" id="banner" role="status">
<div class="check" aria-hidden="true">✓</div>
<div>
<div class="bt" id="banner-title">FINAL — Substrate block finalized</div>
<div class="bs" id="banner-sub">GRANDPA-finalized on VeraeNet · digests only</div>
</div>
</div>
<dl class="kv" id="fields">
<dt>Document</dt>
<dd id="f-doc">—</dd>
<dt id="l-mh">Content multihash</dt>
<dd id="f-mh"><span class="mono">—</span></dd>
<dt>SHA-256 (hex)</dt>
<dd id="f-sha"><span class="mono">—</span></dd>
<dt id="l-b3" class="hidden">BLAKE3 (hex)</dt>
<dd id="f-b3" class="hidden">—</dd>
<dt id="l-b3mh" class="hidden">BLAKE3 multihash</dt>
<dd id="f-b3mh" class="hidden">—</dd>
<dt>Server time</dt>
<dd id="f-time">—</dd>
<dt>VeraeTime receipt</dt>
<dd id="f-receipt"><span class="mono">—</span></dd>
<dt>Ledger / merkle</dt>
<dd id="f-merkle">—</dd>
<dt>Issued by</dt>
<dd id="f-issued">Verae Print Stamp (printit)</dd>
</dl>
<div class="verify-box">
<div class="qr" aria-hidden="true"><span>Verae</span></div>
<div>
<b style="font-size:12.5px">Verify this certificate</b>
<ol>
<li>Open the explorer link (or scan the QR on a printed PDF).</li>
<li>Compare the local file’s SHA-256 to the multihash below — file never uploaded.</li>
<li>Only a <b>final</b> / already-registered receipt is evidence. Hold ids are not proof.</li>
</ol>
<div style="margin-top:8px"><a id="verify-link" href="https://explorer.verae.ai/time" target="_blank" rel="noopener">https://explorer.verae.ai/time</a></div>
</div>
</div>
<p class="foot" id="footer-note">
Only the document’s SHA-256 digest was submitted; the file was not uploaded.
Hashes are multihash (sha2-256, code 0x12, length 0x20 → <span class="mono">f1220</span>…).
Hold / pending / jobId values are never evidence.
Verae LLC · verae.ai · explorer.verae.ai
</p>
</article>
<div class="load no-print">
<label for="sidecar">Load a PrintIt <code>.verae.json</code> sidecar (optional)</label>
<input type="file" id="sidecar" accept=".json,application/json"/>
<p class="note">
Query params also work:
<span class="mono">?document=&amp;sha256=&amp;receipt=&amp;created_at=&amp;merkle=&amp;blake3=&amp;block=&amp;helper_version=</span>
Multihash / BLAKE3 lines appear <b>only when data is present</b> — never invented.
Full CERT-01.html Fraunces pixel match is still a design residual; this page uses brand tokens + plum/gold frame.
</p>
</div>
</div>
<script>
(function () {
var SAMPLE = {
document_name: 'Purchase-Order-7781.pdf',
sha256: '20515740e1051f69c552b83ff1a919398feca768090930a4a502f9335273f279',
multihash: 'f122020515740e1051f69c552b83ff1a919398feca768090930a4a502f9335273f279',
receipt_id: 'bafkreihq3examplev7xq',
created_at: '2026-10-09T05:20:28Z',
merkle: 'Block #1,284,530 · extrinsic 1284530-1',
block: '1284530',
helper_version: '0.3.6',
status: 'final',
byte_length: 184220
};
function $(id) { return document.getElementById(id); }
function isHex64(s) {
return typeof s === 'string' && /^[0-9a-fA-F]{64}$/.test(s.replace(/^0x/i, ''));
}
function cleanHex(s) {
if (!s) return '';
s = String(s).trim().replace(/^0x/i, '').toLowerCase();
return isHex64(s) ? s : '';
}
function contentMultihash(sha) {
var h = cleanHex(sha);
return h ? 'f1220' + h : '';
}
function blake3Multihash(b3) {
var h = cleanHex(b3);
return h ? 'f1e20' + h : '';
}
function fmtBytes(n) {
if (n == null || n === '' || isNaN(Number(n))) return '';
n = Number(n);
return n.toLocaleString('en-US') + ' bytes';
}
function fmtBlock(n) {
if (n == null || n === '') return '';
var s = String(n).replace(/,/g, '');
if (!/^\d+$/.test(s)) return String(n);
return Number(s).toLocaleString('en-US');
}
function setRow(labelId, valueId, show, html) {
var l = labelId ? $(labelId) : null;
var v = $(valueId);
if (!v) return;
if (show) {
if (l) l.classList.remove('hidden');
v.classList.remove('hidden');
v.innerHTML = html;
} else {
if (l) l.classList.add('hidden');
v.classList.add('hidden');
v.textContent = '';
}
}
function mhSpan(full) {
if (!full) return '—';
var pfx = full.slice(0, 5);
var rest = full.slice(5);
return '<span class="mh mono"><span class="pfx">' + escapeHtml(pfx) + '</span> ' + escapeHtml(rest) + '</span>';
}
function escapeHtml(s) {
return String(s).replace(/[&<>"']/g, function (c) {
return ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' })[c];
});
}
function lookupURL(sha, receipt) {
var u = 'https://explorer.verae.ai/time';
var sep = '?';
if (receipt) { u += sep + 'receipt=' + encodeURIComponent(receipt); sep = '&'; }
if (sha) { u += sep + 'sha256=' + encodeURIComponent(sha); }
return u;
}
function apply(data) {
data = data || {};
var doc = data.document_name || data.document || data.file || '';
var sha = cleanHex(data.sha256 || data.hash || '');
var mh = (data.multihash || data.content_multihash || '').trim() || contentMultihash(sha);
if (mh && !/^f1220/i.test(mh) && isHex64(mh)) mh = 'f1220' + mh.toLowerCase();
var b3 = cleanHex(data.blake3 || '');
var b3mh = (data.blake3_multihash || '').trim() || blake3Multihash(b3);
var receipt = (data.receipt_id || data.receipt || data.certificate || '').trim();
var created = (data.created_at || data.timestamp || data.server_time || '').trim();
var merkle = (data.merkle || data.ledger || '').trim();
var block = data.block || data.block_number || data.blockNumber || '';
var helper = data.helper_version || data.helperVersion || '';
var bytes = data.byte_length || data.bytes || data.size_bytes;
var status = (data.status || data.state || 'final').toLowerCase();
var evidence = status === 'final' || status === 'existing' || status === 'completed' || status === 'ok';
var docLine = doc || '(digest only)';
if (bytes) docLine += ' · ' + fmtBytes(bytes);
$('f-doc').textContent = docLine;
setRow('l-mh', 'f-mh', !!mh, mhSpan(mh));
$('f-sha').innerHTML = sha
? '<span class="mono">' + escapeHtml(sha) + '</span>'
: '<span class="mono">—</span>';
setRow('l-b3', 'f-b3', !!b3, '<span class="mono">' + escapeHtml(b3) + '</span>');
setRow('l-b3mh', 'f-b3mh', !!b3mh, mhSpan(b3mh));
if (created) {
$('f-time').textContent = created + ' (VeraeTime) — never the local clock';
} else {
$('f-time').textContent = '— (server time only; never invent local clock)';
}
$('f-receipt').innerHTML = receipt
? '<span class="mono">' + escapeHtml(receipt) + '</span>'
: '<span class="mono">—</span>';
var merkleLine = merkle || (block ? ('Block #' + fmtBlock(block)) : '—');
$('f-merkle').textContent = merkleLine;
var issued = 'Verae Print Stamp';
if (helper) issued += ' ' + helper;
issued += ' (printit)';
$('f-issued').textContent = issued;
var banner = $('banner');
if (evidence) {
banner.classList.remove('provisional');
var blk = fmtBlock(block);
$('banner-title').textContent = blk
? ('FINAL — Substrate block #' + blk + ', finalized')
: (status === 'existing' ? 'Already registered — final evidence' : 'FINAL — Substrate block finalized');
$('banner-sub').textContent = 'GRANDPA-finalized on VeraeNet (rpc.verae.ai)' +
(created ? (' · ' + created) : '');
} else {
banner.classList.add('provisional');
$('banner-title').textContent = 'Not a certificate yet — pending finality';
$('banner-sub').textContent = 'Hold / pending / included states are not evidence. statuslang: only final & already registered.';
}
$('cert-no').textContent = receipt
? ('Receipt ' + (receipt.length > 28 ? receipt.slice(0, 12) + '…' + receipt.slice(-8) : receipt))
: 'Certificate preview';
var url = lookupURL(sha, receipt);
var a = $('verify-link');
a.href = url;
a.textContent = url;
}
function fromQuery() {
var q = new URLSearchParams(location.search);
if (![...q.keys()].length) return null;
return {
document_name: q.get('document') || q.get('file') || '',
sha256: q.get('sha256') || q.get('hash') || '',
multihash: q.get('multihash') || '',
blake3: q.get('blake3') || '',
blake3_multihash: q.get('blake3_multihash') || '',
receipt_id: q.get('receipt') || q.get('receipt_id') || q.get('certificate') || '',
created_at: q.get('created_at') || q.get('timestamp') || '',
merkle: q.get('merkle') || '',
block: q.get('block') || q.get('block_number') || '',
helper_version: q.get('helper_version') || '',
byte_length: q.get('bytes') || q.get('byte_length') || '',
status: q.get('status') || 'final'
};
}
function normalizeSidecar(j) {
return {
document_name: j.document_name || j.document || j.file || j.original_file || '',
sha256: j.sha256 || j.hash || '',
multihash: j.multihash || j.content_multihash || '',
blake3: j.blake3 || '',
blake3_multihash: j.blake3_multihash || '',
receipt_id: j.receipt_id || j.receipt || j.certificate || '',
created_at: j.created_at || j.timestamp || '',
merkle: j.merkle || '',
block: j.block_number || j.block || (j.chain && j.chain.block) || '',
helper_version: j.helper_version || '',
byte_length: j.byte_length || j.size_bytes || '',
status: j.status || 'final'
};
}
var q = fromQuery();
apply(q || SAMPLE);
$('btn-sample').addEventListener('click', function () {
history.replaceState(null, '', location.pathname);
apply(SAMPLE);
});
$('sidecar').addEventListener('change', function (ev) {
var f = ev.target.files && ev.target.files[0];
if (!f) return;
var r = new FileReader();
r.onload = function () {
try {
var j = JSON.parse(r.result);
apply(normalizeSidecar(j));
} catch (e) {
alert('Could not parse JSON sidecar: ' + e.message);
}
};
r.readAsText(f);
});
})();
</script>
</body>
</html>

View file

@ -256,6 +256,7 @@
<p class="hash">sha256 001ba8b3e94aaa3af8730343a821727b354b8545fb19b908bb2b6f1e4350678f</p>
<a class="btn btn-primary" href="https://explorer.verae.ai/time?sha256=001ba8b3e94aaa3af8730343a821727b354b8545fb19b908bb2b6f1e4350678f&amp;receipt=QmQWBx6jo8gkgAVdkAr48AxQgvgqsrTyfyHKn7RiDGWsJA" target="_blank" rel="noopener">Open the sample verification</a>
<a class="btn btn-secondary" href="/samples/verae-receipt-sample.pdf" target="_blank" rel="noopener">View the sample receipt</a>
<a class="btn btn-secondary" href="certificate.html?sha256=001ba8b3e94aaa3af8730343a821727b354b8545fb19b908bb2b6f1e4350678f&amp;receipt=QmQWBx6jo8gkgAVdkAr48AxQgvgqsrTyfyHKn7RiDGWsJA&amp;document=verae-receipt-sample.pdf&amp;status=final">CERT-01 certificate preview</a>
</details>
</section>
@ -277,7 +278,11 @@
· <a href="https://customer.verae.ai/portal/">Customer portal</a>
· <a href="https://explorer.verae.ai/time">VeraeTime explorer</a>
· <a href="https://zap.verae.ai/portal/">Zapier portal</a>
<p><a class="inline" href="queue.html">Job queue (PT-04)</a></p>
<p>
<a class="inline" href="queue.html">Job queue (PT-04)</a>
· <a class="inline" href="certificate.html">Certificate (CERT-01)</a>
· <a class="inline" href="samples/verae-receipt-sample.pdf" target="_blank" rel="noopener">Sample receipt PDF</a>
</p>
</footer>
</main>

View file

@ -75,7 +75,7 @@ http://127.0.0.1:8631/status</pre>
<li><b>Final receipt ready</b> — stamp succeeded; open certificate from Verae Timestamps</li>
<li><b>Failed – retrying</b> — non-auth error; job may retry later</li>
</ul>
<p class="help" style="margin-top:12px;margin-bottom:0"><a href="index.html">← printit.verae.ai</a></p>
<p class="help" style="margin-top:12px;margin-bottom:0"><a href="index.html">← printit.verae.ai</a> · <a href="certificate.html">Certificate (CERT-01)</a></p>
</div>
</main>
</body>

View file

@ -1,4 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url><loc>https://printit.verae.ai/</loc></url>
<url><loc>https://printit.verae.ai/certificate.html</loc></url>
<url><loc>https://printit.verae.ai/queue.html</loc></url>
</urlset>