Signed verdicts
Every result is a signed record of exactly what was checked, how, and what was found, so a verdict can be shown to a client or an auditor and checked by anyone.
signed has four fields: record, signature, kid (which key signed it) and alg (always EdDSA). The signature covers record only.
record holds:
| Field | Contents |
|---|---|
id, created_at |
The check. |
inputs |
kind, mode, and files: each file's name, size in bytes and SHA-256 fingerprint (never the file itself). Also spec (size and fps, if you sent them) and prompt_sha256 for pre-flights. |
engine |
version, the SHA-256 of every model used, and the settings that decide a verdict. |
result |
The findings, exactly as returned. |
check_seconds |
How long it took. |
test |
true for test-mode checks. |
signature is an Ed25519 signature over the record serialised canonically:
- JSON with object keys sorted, at every level.
- No whitespace:
,and:as separators. - Non-ASCII characters written as UTF-8, not escaped (
"Zoë", not"Zo\u00eb"). - Numbers written the shortest way that reads back as the same double (as Python's
reprand JavaScript'sNumber.toStringdo), e.g.0.970673145319531. - The whole thing encoded as UTF-8 bytes.
signature is base64url without padding.
Verify offline
raccord.verify(check) # fetches the public key from /v1/signing-keys and checks the signature
Or by hand, in Python:
import base64, json, httpx
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
def b64(s):
return base64.urlsafe_b64decode(s + "=" * (-len(s) % 4)) # unpadded base64url
keys = httpx.get("https://api.kolamlabs.ai/v1/signing-keys").json()["keys"] # a JWK Set
jwk = next(k for k in keys if k["kid"] == check["signed"]["kid"])
body = json.dumps(check["signed"]["record"], sort_keys=True, separators=(",", ":"), ensure_ascii=False).encode()
Ed25519PublicKey.from_public_bytes(b64(jwk["x"])).verify(b64(check["signed"]["signature"]), body) # raises if invalid
GET /v1/signing-keys returns a JWK Set: {"keys": [{"kty": "OKP", "crv": "Ed25519", "kid": …, "x": …}]}. Pick the key whose kid matches; x is the raw public key, base64url without padding. To ask the server instead: POST /v1/verify with {"record", "signature"}.
Re-run
POST /v1/checks/{id}/rerun runs the check again and compares. The response is {"identical": true, "differences": []} when the inputs, engine and findings match, and the re-run is signed like any check.
- If your account keeps media, nothing needs re-sending.
- Otherwise, send the same files. They're matched to the record by fingerprint; different files are refused.
Re-runs are charged like a new check. The same files, engine and settings give the same findings.