Verify a pack without calling us.
Prove an evidence pack is byte-identical to what the platform generated — offline, with openssl and the public key served from this domain.
Three steps, no account, no vendor in the loop.
- 1
Receive
Two files arrive with every signed export
The PDF, and a JSON sidecar built from the X-Evidence-* headers served with it. The signature is computed as Ed25519(sha256(pdf bytes)), so the hash and the signature check independently.
- 2
Fetch
Get the public key from this domain
It returns the Ed25519 public key (PEM) and its keyId — confirm the keyId matches the sidecar. Pin the key out-of-band on first use, e.g. in your engagement file.
- 3
Verify
Re-hash, then check the signature
Any changed byte changes the SHA-256 and verification fails. Prefer offline verification; the online endpoint below is a convenience, not the authority.
evidence-pack.pdf.sig.json
sidecar{
"signature": "<base64 Ed25519 signature>",
"sha256": "<hex digest of the PDF bytes>",
"keyId": "<16-hex-char key identifier>",
"algorithm": "Ed25519",
"signedAt": "2026-08-05T09:14:22.000Z"
}verify a pack offline
openssl# 1. The PDF's hash must equal the sidecar's sha256 field
shasum -a 256 report.pdf
# 2. Verify the signature over that digest
echo -n "<sha256 hex>" | xxd -r -p > digest.bin
echo "<signature base64>" | base64 -d > sig.bin
curl -s https://<domain>/.well-known/assetops-signing-key \
| jq -r .publicKeyPem > pub.pem
openssl pkeyutl -verify -pubin -inkey pub.pem \
-rawin -in digest.bin -sigfile sig.bin
# -> "Signature Verified Successfully"Online convenience check: POST /api/evidence/verify with the PDF and the sidecar's signature returns { valid: true | false }. Offline verification is authoritative.
What the platform guarantees internally.
The pack is the last link. The record it summarises has its own tamper evidence.
Append-only audit log
Postgres triggers reject UPDATE and DELETE on the audit table — enforcement sits under the application.
Per-workspace hash chain
Every row carries the hash of the row before it; re-walking the chain detects out-of-band edits or deletions.
Content-hashed files
Evidence files store a SHA-256 at upload; the file served back later can be re-hashed against it.
For chain-of-custody questions, ask the operator for the audit-log extract for the relevant resource — each entry carries actor, timestamp, IP, and before/after values.
Limitations — stated plainly
What a signature proves, and what it doesn't.
Signing proves the artifact left the platform and was not modified since. It does not by itself prove the truth of field data — sensor readings and photos carry their own trail: ingest timestamps, monotonic sequence numbers, device identity, and the audit chain.
A verified signature means: this exact file, from this platform, unmodified. Check the keyId against the published key before relying on it.
A deployment without a signing key stamps this banner on the pack's first page and serves no signature headers. Do not accept such a pack as evidence — it says so itself.
Hand this page to whoever has to sign off.
The procedure works on any signed pack, from any workspace, on any deployment of the platform.
Canonical raw document: auditor-verification-guide.md · Key endpoint: /.well-known/assetops-signing-key