CEL/1.0, PUBLIC VERIFICATION
Verify a NEXPEC evidence pack.
Drag the pack onto the area below. Your browser recomputes every SHA-256 hash against the canonical-JSON serialisation of each artifact and checks the chain-of-custody. Nothing leaves your machine. NEXPEC does not see the file.
Drop your NEXPEC evidence pack here
or click to browse. The file is processed entirely in your browser, nothing is uploaded.
EXPECTED, .JSON, NEXPEC EVIDENCE PACK v1.0
VERIFICATION PROTOCOL
What this page proves
- 1
Canonical JSON
Each artifact (job, parties, contracts, approvals, invoices, audit_events, …) is re-serialised with object keys sorted lexicographically and whitespace stripped. This produces the same byte stream NEXPEC produced at export time.
- 2
SHA-256 per artifact
Your browser computes SHA-256 over the canonical bytes via SubtleCrypto. The result is compared to the hash declared in the pack's manifest. Any single byte difference flips this hash.
- 3
Root hash
The manifest's artifacts array is itself canonicalised and hashed. The root hash is one number that summarises the entire pack, if any per-artifact hash changes, the root hash changes.
- 4
Verdict
If every per-artifact hash matches AND the recomputed root matches the declared root, the pack is verifiably unmodified since NEXPEC issued it. If anything mismatches, the page reports TAMPERED with the specific artifact that failed.
GUARANTEES
What this page does not require
No NEXPEC account
Auditors verify without onboarding.
No server roundtrip
Pure browser. The file never leaves your machine.
No trust assumption
The algorithm is the proof, not our reputation.
CANONICAL-JSON REFERENCE
The serialisation algorithm fits in about 50 lines of pure TypeScript. Auditors are welcome to read it and re-implement independently in their tooling.
function canonicalJson(v) {
if (v === null) return 'null';
if (typeof v === 'boolean') return v ? 'true' : 'false';
if (typeof v === 'number') return Number.isFinite(v) ? JSON.stringify(v) : 'null';
if (typeof v === 'string') return JSON.stringify(v);
if (Array.isArray(v)) {
return '[' + v.map(canonicalJson).join(',') + ']';
}
if (typeof v === 'object') {
const keys = Object.keys(v).sort();
return '{' + keys.filter(k => v[k] !== undefined)
.map(k => JSON.stringify(k) + ':' + canonicalJson(v[k]))
.join(',') + '}';
}
return 'null';
}Hash: SHA-256, Encoding: UTF-8, Output: lowercase hex.