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 repr and JavaScript's Number.toString do), 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.