Skip to content

Security

Evidence specification

An open description of the evidence Immiscible keeps (records, checkpoints and bundles) so anyone can check it without us.

An open description of the evidence Immiscible keeps, so anyone can check it without us. The reference verifier is scripts/verify-evidence.mjs: one file, no dependencies, short enough to read before running. Step by step use is in verifying offline.

#Why it exists

Logs written by the system they describe are hard to trust: the same system that made a decision can rewrite the record of it. Immiscible’s evidence is built so that a rewrite shows:

  1. Every record names the hash of the record before it, so changing, removing or reordering one breaks the chain at that point.
  2. At intervals, and whenever someone asks, the head of the chain is signed with Ed25519 into a checkpoint. A customer who keeps a checkpoint can later prove that the history up to it is the history they were shown, even if every copy we hold had been rewritten.
  3. The bundle carries every public key that ever signed a checkpoint, including retired ones, so a checkpoint from years ago still verifies after its key was rotated.

#Records

A record is a JSON object:

FieldMeaning
schemaassay.evidence.v1
seqposition in the chain, from 0, with no gaps
ida random id
atISO 8601 time it was written
prevthe hash of the record before it; 64 zeros for the first
kindwhat happened, for example agent_decision, agent_tier, policy_action
payloadthe details, with digests and pseudonyms in place of personal data
hashSHA-256, hex, of the canonical form of every other field

The canonical form is JSON with object keys sorted, no whitespace, arrays in order. Payloads are stored exactly as hashed.

#Checkpoints

A checkpoint is a compact JWS with header {"alg":"EdDSA","typ":"immiscible-checkpoint+jwt","kid":...} and claims:

ClaimMeaning
typimmiscible.checkpoint.v1
widthe workspace
seqcheckpoint number, from 1
recordshow many records the chain had
headthe hash of record records - 1
prevthe head signed by the previous checkpoint, or null
iatwhen it was signed, in seconds

A checkpoint holds if its signature verifies against the key named by kid and record records - 1 in the chain still has hash head.

#Bundle

GET /api/w/:wid/evidence/bundle returns:

JSON
{
  "format": "immiscible.evidence-bundle.v1",
  "workspace": "…",
  "generatedAt": "…",
  "records": [ … ],
  "checkpoints": [ { "seq": 1, "head": "…", "records": 42, "token": "…", "kid": "…", "at": "…" } ],
  "keys": [ { "kty": "OKP", "crv": "Ed25519", "x": "…", "kid": "…", "alg": "EdDSA" } ]
}

Verify it:

Shell
node scripts/verify-evidence.mjs bundle.json
node scripts/verify-evidence.mjs bundle.json --checkpoint <a checkpoint you kept>
node scripts/verify-evidence.mjs bundle.json --keys keys-you-kept.json

#Trusting the keys

A bundle carries its own public keys, so on its own it proves only that it is consistent with itself: whoever produced it could, in principle, rewrite history, mint a new key and re-sign every checkpoint. Two things close that gap, and an auditor should use at least one:

  • Keep the keys. Fetch /.well-known/immiscible-keys.json (also served at /.well-known/assay-keys.json, its path before the rename) when you start relying on the evidence, keep the file, and pass it with --keys. Only those keys are then trusted.
  • Keep checkpoints. A checkpoint you saved when it was issued is checked against the chain with --checkpoint; no key change can make old history match it.

#Checkpoints as a sequence

Checkpoints are numbered from 1 with no gaps, and each names the head the one before it signed. The verifier reports a gap or a broken link, so removing a checkpoint is as visible as changing a record.

#Obligations

The bundle lists, under obligations, the published record-keeping obligations this evidence supports (for example EU AI Act Art. 12 and Art. 26(6)). Each scorecard control carries the same kind of map. These are references for the people who write the compliance file, not claims of compliance.

Exit code 0 means everything verified. Otherwise the report names the first record that broke and every checkpoint that no longer holds.

#What this is not

It proves the record was not changed after it was written and signed. It does not, on its own, prove that a decision was right, and it does not make anyone compliant with anything: it is evidence a compliance process can rely on.