<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE rfc [
  <!ENTITY nbsp "&#160;">
]>
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" category="exp" docName="draft-wright-verdict-record-00" ipr="trust200902" submissionType="IETF" consensus="false" version="3" xml:lang="en" tocInclude="true" sortRefs="true" symRefs="true">
  <front>
    <title abbrev="Verdict Records">Verdict Records: Results on Claims that Cite Receipts as Evidence</title>
    <seriesInfo name="Internet-Draft" value="draft-wright-verdict-record-00"/>
    <author fullname="Darren Wright" initials="D." surname="Wright">
      <organization>Sencor AI S.L.</organization>
      <address>
        <postal><country>Spain</country></postal>
        <email>darren@sencor.ai</email>
      </address>
    </author>
    <date/>
    <keyword>verdict</keyword><keyword>claim</keyword><keyword>receipt</keyword><keyword>evidence</keyword>
    <abstract>
      <t>This document defines a verdict record: a statement, bound to its issuer, of a result reached on a claim, together with the evidence the result relies on and the rule by which the result can be re-derived. Evidence is cited by digest and can be a receipt or record in any format, such as a SCITT Receipt or an Agent Action Capsule. The document defines how a checker checks a verdict record and what such a check does and does not show. It defines no receipt format and changes none.</t>
    </abstract>
  </front>
  <middle>
    <section anchor="intro">
      <name>Introduction</name>
      <t>Several formats record that something happened or that something was said. A SCITT Signed Statement, registered on a Transparency Service, yields a Receipt <xref target="RFC9943"/>. An Agent Action Capsule records one agent action and its disposition <xref target="I-D.mih-scitt-agent-action-capsule"/>. A Signed Evaluation Receipt records one evaluation result <xref target="I-D.gruszka-signed-evaluation-receipts"/>. Each records an act or a statement; a Receipt is issued by the Transparency Service on which the statement is registered.</t>
      <t>This document defines a companion to those formats: a verdict record, which states a result reached on a claim and cites such receipts and records as its evidence. It does not define how evidence is captured, and it does not replace any receipt format.</t>
      <t>A verdict record names the rule that produced its result. Where the rule is mechanical, any checker that holds the evidence can re-run it and compare. Where no mechanical rule can re-derive the result, the record says so, and a check then shows only what the result was based on, and when.</t>
      <t>A check of a verdict record never shows that a claim is true. It shows that the issuer asserted the result, on the stated evidence, under the stated rule.</t>
      <section anchor="reqlang">
        <name>Requirements Language</name>
        <t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they appear in all capitals, as shown here.</t>
      </section>
      <section anchor="terms">
        <name>Terminology</name>
        <dl newline="false" spacing="normal">
          <dt>Claim:</dt>
          <dd>A statement whose support is in question. A claim can be carried by a record or receipt in any format, or stated as text.</dd>
          <dt>Evidence item:</dt>
          <dd>A sequence of bytes, such as a receipt, a signed statement or a record, that a verdict record cites by its digest.</dd>
          <dt>Issuer:</dt>
          <dd>The party whose key binds a verdict record. The record names it in its <tt>writer</tt> member.</dd>
          <dt>Checker:</dt>
          <dd>Whoever runs the checks of <xref target="checking"/>. A checker needs no access to the issuer's systems.</dd>
          <dt>Presenter:</dt>
          <dd>Whoever hands the checker a verdict record and its evidence items. That can be the issuer, a party that relies on the record, or anyone.</dd>
          <dt>Rule:</dt>
          <dd>A named, specified procedure that re-derives a result from the body of a record. The name <tt>judgement</tt> means that no mechanical rule can re-derive the result.</dd>
        </dl>
      </section>
    </section>
    <section anchor="record">
      <name>The Verdict Record</name>
      <section anchor="encoding">
        <name>Encoding and Digests</name>
        <t>A verdict record is a JSON object <xref target="RFC8259"/> in canonical form. In canonical form, object members are sorted by name, compared as sequences of Unicode code points; there is no whitespace outside strings; strings escape only the quotation mark, the reverse solidus and control characters, and write every other character as its UTF-8 bytes; numbers are integers; and arrays keep their order. Re-serializing the parsed record MUST give the same bytes.</t>
        <t>A verdict record MUST be strict JSON: valid UTF-8 that does not start with a byte-order mark, in which no object at any depth has the same member name twice and no escape forms a lone surrogate. A checker MUST refuse JSON nested deeper than 32 levels at any point.</t>
        <t>An integer is written as an optional minus sign and digits only, with no leading zero, no fraction and no exponent, and lies between -(2^53 - 1) and 2^53 - 1. A time is UTC, written YYYY-MM-DDTHH:MM:SS.ffffffZ with exactly six fraction digits. Hex is lowercase, two characters per byte, with no prefix. A member of the wrong JSON type is refused at the step that reads it.</t>
        <t>The digest of a verdict record, and of an evidence item, is the SHA-256 hash <xref target="FIPS180-4"/> of its exact bytes, written in hex. This document defines no salted or hiding form of digest.</t>
      </section>
      <section anchor="members">
        <name>Members</name>
        <t>A verdict record has exactly the members below. No other member is allowed. The members <tt>v</tt>, <tt>kind</tt>, <tt>key</tt>, <tt>version</tt>, <tt>writer</tt> and <tt>body</tt> MUST be present. A record without <tt>evidence</tt> or <tt>check</tt> can be parsed, but fails step 1 or step 2 of <xref target="steps"/>.</t>
        <dl newline="false" spacing="normal">
          <dt><tt>v</tt>:</dt>
          <dd>A string. This document defines the value "verdict-record/1".</dd>
          <dt><tt>kind</tt>:</dt>
          <dd>A string: the record kind. This document defines two kinds: "check-run", a run of a rule whose body holds the values the rule reads, and "model-decision", a decision made by an AI model. A kind starting with "x-" is private.</dd>
          <dt><tt>key</tt>:</dt>
          <dd>A non-empty string: the record's key within its kind, chosen by the issuer. It MUST be opaque.</dd>
          <dt><tt>version</tt>:</dt>
          <dd>An integer of 1 or more: the version of this record for this key.</dd>
          <dt><tt>supersedes</tt>:</dt>
          <dd>Null for version 1; for a later version, the digest of the previous version.</dd>
          <dt><tt>writer</tt>:</dt>
          <dd>A non-empty string: the issuer, the party whose key binds the record.</dd>
          <dt><tt>actor</tt>:</dt>
          <dd>An object: who reached the result. Its members are <tt>type</tt> ("person" or "system") and <tt>id</tt>, and for a system also <tt>model</tt> and <tt>model_version</tt>.</dd>
          <dt><tt>act_time</tt>:</dt>
          <dd>A time: when the result was reached, by the issuer's statement.</dd>
          <dt><tt>evidence</tt>:</dt>
          <dd>An array of the evidence items this record relies on. Each entry is an object with exactly two members: <tt>sha256</tt>, the digest of the item (<xref target="encoding"/>), and <tt>format</tt>, a string that names the format by whose rules the item is verified (<xref target="formats"/>).</dd>
          <dt><tt>check</tt>:</dt>
          <dd>An object with the members <tt>rule</tt> (a string, the name of the rule), <tt>inputs</tt> (an object, optional, naming members of <tt>body</tt> that the rule reads) and <tt>result</tt> (the result the rule gave).</dd>
          <dt><tt>body</tt>:</dt>
          <dd>An object: the content of the record. Its members depend on <tt>kind</tt>. It holds the claim (<xref target="claim"/>) and the values the rule reads.</dd>
        </dl>
      </section>
      <section anchor="claim">
        <name>The Claim</name>
        <t>The member <tt>body.claim</tt> names the claim the verdict is about. It is an object with exactly one of two members: <tt>text</tt>, a string that states the claim, or <tt>ref</tt>, an evidence entry (as in <tt>evidence</tt>) for the record or receipt that carries the claim. When <tt>ref</tt> is used, the same entry MUST also appear in <tt>evidence</tt>.</t>
      </section>
    </section>
    <section anchor="carriage">
      <name>Carrying a Verdict Record</name>
      <t>This document does not define how a verdict record is signed, time-stamped or made available. From the container that carries the record, a checker needs three things: the exact bytes of the record; a key that bound those bytes, shown to belong to the party the record names in <tt>writer</tt>; and an upper time bound, a time no later than which the record existed, which the checker establishes itself.</t>
      <t>A SCITT Signed Statement whose payload is the verdict record, registered on a Transparency Service whose Receipt the checker verifies, is one such container <xref target="RFC9943"/>.</t>
      <t>If the container does not show the record, the state is held, with the reason (<xref target="state"/>).</t>
    </section>
    <section anchor="checking">
      <name>Checking a Verdict Record</name>
      <section anchor="results">
        <name>Results of a Step</name>
        <dl newline="false" spacing="normal">
          <dt>PASS:</dt>
          <dd>the step ran and its condition holds.</dd>
          <dt>FAIL:</dt>
          <dd>the step ran and its condition does not hold. The result names the step.</dd>
          <dt>NOT RUN:</dt>
          <dd>an input the step needs is missing, or is not shown to come from outside the issuer's reach (<xref target="inputs"/>). The result names the step and the input it needs.</dd>
        </dl>
        <t>When a step cannot run, the check goes on with its other steps. If a later step FAILs, the check FAILs at that step. Otherwise it is NOT RUN at the first step that could not run.</t>
        <t>Two checkers that implement this document and hold the same inputs MUST give the same result and name the same step. No step reads the checker's clock.</t>
      </section>
      <section anchor="inputs">
        <name>Inputs</name>
        <t>Every input that a step relies on MUST come from outside the issuer's reach. In this document an input is outside the issuer's reach in two ways only: the checker computes it from bytes it holds (a digest, a signature, or the re-run of a rule), or it is the checker's own input (its policy (<xref target="policy"/>), its trust anchors, this document, and the rule specifications it holds). A checker MUST NOT take its own inputs from the record or from the issuer.</t>
        <t>A statement made by the issuer alone, such as the content of the record, can be reported. It MUST NOT make a step PASS that would otherwise not pass.</t>
        <t>A step MUST NOT rely on the absence of a statement that the issuer or the presenter could withhold.</t>
      </section>
      <section anchor="steps">
        <name>Steps</name>
        <t>Step 1. The member <tt>check</tt> MUST be present. It MUST name a rule and give a result. The rule <tt>judgement</tt> is allowed only for kinds that the checker's policy lists.</t>
        <t>Step 2. The member <tt>evidence</tt> MUST be an array of entries as in <xref target="members"/>. For each entry, the checker MUST hold an item whose digest equals the entry's <tt>sha256</tt>; if it does not, step 2 is NOT RUN, naming the entry.</t>
        <t>Each item is verified by the rules of the format its entry names. An item that does not verify, or whose format the checker's policy does not list, is not relied on: step 2 is then NOT RUN, naming it.</t>
        <t>An item that is itself a verdict record is checked by this section, as a record of its own. Where an item's verification gives it an upper time bound, that bound MUST NOT be later than the upper time bound of the record that cites it; if it is later, step 2 is NOT RUN. The checker's policy sets how deep such citations are followed; beyond that depth, step 2 is NOT RUN.</t>
        <t>Step 3. If the rule is not <tt>judgement</tt>, the checker MUST hold the rule's specification. It re-runs the rule on <tt>body</tt>, reading the members that <tt>check.inputs</tt> names. A rule input of the wrong JSON type is a FAIL of this step, not a result of the rule. The result MUST equal <tt>check.result</tt>; if it does not, step 3 FAILs.</t>
        <t>The check passes when steps 1 to 3 PASS.</t>
      </section>
      <section anchor="state">
        <name>State and Report</name>
        <t>A checker reports the record's state: released, when steps 1 to 3 PASS; held, when no step FAILs and at least one is NOT RUN; refused, when a step FAILs; or no verdict, when the checker's own policy is invalid. With the state it reports each step's result and, for each step that FAILed or did not run, the step and the input it needed.</t>
        <t>A checker MUST NOT report any word or member that speaks for the whole record and that a reader could take as "this is true", such as verified, valid, true, trusted, correct, proven, confirmed or OK. A summary line, where one is printed, names the state and every step's result.</t>
        <t>A state speaks as of the record's upper time bound. The report states that time, and the SHA-256 digest of the checker's policy and of each set of trust anchors it used, so that another checker can see what the state rests on.</t>
      </section>
      <section anchor="policy">
        <name>Checker Policy</name>
        <t>A checker's policy is its own input. It lists the kinds for which <tt>judgement</tt> is allowed, the evidence formats the checker can verify, and the depth of citation it follows. A checker whose policy is invalid gives no verdict.</t>
      </section>
    </section>
    <section anchor="shows">
      <name>What a Check Shows and Does Not Show</name>
      <t>A released verdict record shows that its issuer asserted the result, on the stated evidence, under the stated rule, no later than its upper time bound. It never shows that the claim is true.</t>
      <t>For the rule <tt>judgement</tt>, a check shows only what the result was based on, and when. It does not show that the judgement is correct.</t>
      <t>The values in <tt>body</tt> that a rule reads are the issuer's statement. A check does not show that they are true.</t>
      <t>A check does not show that the issuer kept its key secret, or that no other version of the record exists beyond those the checker holds.</t>
    </section>
    <section anchor="formats">
      <name>Relation to Receipt Formats</name>
      <t>Receipts and records made by other formats, such as SCITT Signed Statements and Receipts <xref target="RFC9943"/>, Agent Action Capsules <xref target="I-D.mih-scitt-agent-action-capsule"/> and Signed Evaluation Receipts <xref target="I-D.gruszka-signed-evaluation-receipts"/>, enter a verdict record as evidence items. A verdict record adds no property to them and requires none of them.</t>
      <t>The <tt>format</tt> member of an evidence entry is a media type <xref target="RFC6838"/> where one is registered for the item, and otherwise a URI that names the specification of the item's format. For an item that is itself a verdict record, the format is the string "verdict-record/1". A checker verifies an item only by the specification so named.</t>
    </section>
    <section anchor="security">
      <name>Security Considerations</name>
      <t>A verdict record is its issuer's statement. Its result can be wrong, and a mechanical rule can be re-run correctly on values that are false. A released state is a statement about what was asserted and on what evidence, not about the claim.</t>
      <t>A presenter can withhold evidence items or later versions of a record. Because no step relies on the absence of a statement that could be withheld (<xref target="inputs"/>), withholding can leave a step NOT RUN but cannot make a step PASS.</t>
      <t>The rule <tt>judgement</tt> admits any result. A checker's policy limits it to the kinds for which the checker accepts a result that no rule re-derives.</t>
      <t>The check is deterministic and reads no clock (<xref target="results"/>), so two checkers holding the same inputs report the same state.</t>
      <t>Every evidence item is given to the checker in full. An issuer ought to consider, before citing an item, whether it is fit to pass to every party that may check the record.</t>
      <t>Key compromise, revocation and the trustworthiness of time sources are properties of the container (<xref target="carriage"/>) and are outside the scope of this document.</t>
    </section>
    <section anchor="iana">
      <name>IANA Considerations</name>
      <t>This document has no IANA actions. A later version may ask IANA for registries of record kinds, rule names and evidence format names, which this version lists in <xref target="members"/>, <xref target="steps"/> and <xref target="formats"/>.</t>
    </section>
  </middle>
  <back>
    <references anchor="sec-references">
      <name>References</name>
      <references anchor="sec-normative-references">
        <name>Normative References</name>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8259.xml"/>
        <reference anchor="FIPS180-4" target="https://doi.org/10.6028/NIST.FIPS.180-4">
  <front><title>Secure Hash Standard (SHS)</title>
    <author><organization>National Institute of Standards and Technology</organization></author>
    <date year="2015" month="August"/></front>
  <seriesInfo name="FIPS PUB" value="180-4"/>
  <seriesInfo name="DOI" value="10.6028/NIST.FIPS.180-4"/>
</reference>
      </references>
      <references anchor="sec-informative-references">
        <name>Informative References</name>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.6838.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8792.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9943.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml3/reference.I-D.mih-scitt-agent-action-capsule.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml3/reference.I-D.gruszka-signed-evaluation-receipts.xml"/>
      </references>
    </references>
    <section anchor="example">
      <name>Example</name>
      <t>The record below is a decision by a model on a claim carried by another record. Its rule is <tt>judgement</tt>, so a checker re-runs no rule; it holds both evidence items, verifies each by its own format, and reports the state. Long lines are folded for display as described in <xref target="RFC8792"/>; the record itself has no whitespace and no line breaks.</t>
      <t>The claim record cited by both <tt>body.claim.ref</tt> and the first evidence entry is these bytes:</t>
      <artwork type="ascii-art"><![CDATA[
=============== NOTE: '\' line wrapping per RFC 8792 ================

{"made_by":"builder.example","statement":"Release 2.1 of example-ser\
vice passed its acceptance suite."}
]]></artwork>
      <t>The verdict record, with whitespace added for display:</t>
      <sourcecode type="json"><![CDATA[
=============== NOTE: '\' line wrapping per RFC 8792 ================

{
  "act_time": "2026-10-23T10:00:00.000000Z",
  "actor": {
    "id": "checker-7",
    "model": "example-model",
    "model_version": "1",
    "type": "system"
  },
  "body": {
    "claim": {
      "ref": {
        "format": "application/json",
        "sha256": "f4747f1fa1ad63eaad90e41b587794f8f5c82f9215b9a8e23\
a6c204edabc7d48"
      }
    }
  },
  "check": {
    "result": "supported",
    "rule": "judgement"
  },
  "evidence": [
    {
      "format": "application/json",
      "sha256": "f4747f1fa1ad63eaad90e41b587794f8f5c82f9215b9a8e23a6\
c204edabc7d48"
    },
    {
      "format": "https://datatracker.ietf.org/doc/draft-gruszka-sign\
ed-evaluation-receipts/",
      "sha256": "0c964f45c450a0253fc09eb2316e6ad271944be201c46ebf2c5\
d40e529f35306"
    }
  ],
  "key": "verdict-0001",
  "kind": "model-decision",
  "supersedes": null,
  "v": "verdict-record/1",
  "version": 1,
  "writer": "verifier.example"
}
]]></sourcecode>
      <t>Its digest, over its canonical bytes, is:</t>
      <artwork type="ascii-art"><![CDATA[
2a85c94e39c56f50185b3b69b8f56026946364631799774a83b4f93399841c45
]]></artwork>
    </section>
  </back>
</rfc>
