Preview: the CLI and API are not released yet.
Euthyne
Verification spec (draft)

Action receipt

Draft. The DSSE envelope, the in-toto Statement and the predicate fields.

An action receipt is a DSSE envelope. Its payload is an in-toto Statement v1.

Envelope

{
  "payloadType": "application/vnd.in-toto+json",
  "payload": "<base64 of the Statement bytes>",
  "signatures": [
    { "keyid": "<session key ID>", "sig": "<base64 Ed25519 signature>" }
  ]
}

The signature covers the DSSE pre-authentication encoding (PAE) of the payload type and the raw payload bytes:

PAE(type, body) = "DSSEv1" SP LEN(type) SP type SP LEN(body) SP body

SP is one space and LEN is the length in bytes as ASCII decimal. The signature covers bytes, so there is no JSON canonicalization step.

Statement

{
  "_type": "https://in-toto.io/Statement/v1",
  "subject": [
    { "name": "tool_input", "digest": { "sha256": "<commitment>" } }
  ],
  "predicateType": "https://euthyne.com/attestation/action/v1",
  "predicate": { }
}

subject lists the content commitments, one entry per committed field. The name is the field, for example tool_input. The digest is the commitment, not a plain hash of the value. See Commitments.

Predicate

Everything in the predicate is in clear.

FieldContent
idReceipt ID, with the rcpt_ prefix
tDevice time, in milliseconds since the Unix epoch
orgOrganization ID
deviceFingerprint of the device key
humanForge account of the human, for example github:12345
harnessHarness name and version
modelModel ID, with source: hook, transcript or unknown
sessionid, seq, and prev, the digest of the previous receipt in the session
eventHook event name, for example PostToolUse
toolTool name, use_id, outcome (ok, error or denied) and duration
repoRemote, branch and HEAD
filesPaths, each with its git blob SHA after the action
commitThe new commit SHA, after a git commit
salt_keyID and epoch of the commitment key used for the salts

The nested structure of each field is not final.

Receipt digest

The digest of a receipt is the SHA-256 of its envelope. It is the value used in prev, in the log leaf and in change receipts.

Hook events

These Claude Code hook events produce receipts or receipt data:

EventRecorded
SessionStartSession open, repository, HEAD, model if present
UserPromptSubmitPrompt commitment
PostToolUseThe action receipt
PostToolUseFailure, PermissionDeniedOutcome error or denied
SubagentStart, SubagentStopSubagent attribution
PostModelSwitchModel change
StopTurn end: HEAD and blob SHAs of touched files
SessionEndLocal queue write only

Codex uses the same event names. Its tool hooks cover shell commands, apply_patch, MCP tools and local function tools. They do not cover tools hosted by the provider, such as web search.

Keys

  • Device key. Ed25519, one per device per organization, kept in the OS keychain. A W3C Verifiable Credential 2.0 (vc+jwt), issued by Euthyne, binds it to a human and an organization.
  • Session key. Certified by the device key when a session starts, valid for 24 hours at most. It signs the receipts of that session.
  • Key events. Binding, rotating and revoking a device key are log entries too. So "revoked at log index N" can be proven.

Log leaf

leaf = type_byte || SHA-256(envelope)

The leaf holds no organization ID. The type byte values are not final.

Change receipt

A change receipt uses the same envelope and Statement format. Euthyne signs it with its service key.

  • subject: { "digest": { "gitCommit": "<final SHA>" } }
  • predicateType: https://euthyne.com/attestation/change/v1
  • Predicate: repository, pull request number, head and final SHA, merge method, author, merged by, merged at; sessions[] with link method and the Merkle root of their receipt digests; approvals[] with the reviewed SHA and the author and launcher checks; CI; coverage; observed agent_markers.

The full field list is not specified yet.

On this page