Evaluation documents
Generated from the model types in crates/canon/src/model. canon evaluate reads a compiled protocol, one case snapshot, a set of evidence records and, optionally, a list of authority decisions and a list of explicit decisions, and writes a decision. canon check reads a protocol and, optionally, the properties declared beside it. Every key is listed; a key Canon does not know is refused.
canon-case/1
Read by canon evaluate. The JSON Schema is generated from the same types.
Case
A canon-case/1 case snapshot as written.
| Key | Value | Required | Meaning |
|---|---|---|---|
format | text | required | The document format; the evaluator accepts only canon-case/1. |
id | identifier (CaseId) | required | — |
protocol | identifier (ProtocolId) | required | The protocol that governs the case. |
artifacts | map from identifier (ArtifactId) to CaseArtifact | required | The current revision of each declared artifact, keyed by artifact id. |
termination | identifier (OutcomeId) | optional | The outcome the case terminated through; absent while the case is open. Whether the protocol declares it is checked by the outcomes section (story:outcomes). |
revision | identifier (Revision) | optional | The case's own current revision. An explicit decision applies only while its case_revision is this one; a snapshot without one has no explicit decision applying. |
inputs | map from identifier (InputId) to identifier (InputValue) | optional | The value of each case input, keyed by input id, fixed when the case opens. Left out by a case of a protocol that declares no input. |
independence | map from identifier (Principal) to list of identifier (IndependenceDimensionId) | optional | The dimensions on which each producer is independent of the case's work, keyed by producer, as the trusted context that writes the case resolved them. A producer absent from it, or listed with [], is independent on no dimension. |
More columns: swipe horizontally, or focus the table and use the arrow keys.
CaseArtifact
One declared artifact as the case snapshot records it.
| Key | Value | Required | Meaning |
|---|---|---|---|
revision | identifier (Revision) | required | The artifact's current revision. |
More columns: swipe horizontally, or focus the table and use the arrow keys.
canon-evidence/1
Read by canon evaluate. The JSON Schema is generated from the same types.
EvidenceRecord
One canon-evidence/1 record as written. subject and subject_revision bind it: the
evaluator refuses a record whose subject the protocol does not declare, and applies a record
only while its subject revision is the case's current revision of that subject.
| Key | Value | Required | Meaning |
|---|---|---|---|
format | text | required | The document format; the evaluator accepts only canon-evidence/1. |
id | identifier (EvidenceId) | required | — |
kind | identifier (EvidenceKindId) | required | The evidence kind, which the protocol declares. |
result | text | optional | What the observation found; a record without one matches only an evidence match that names no result. |
subject | identifier (ArtifactId) | required | The artifact the record is about. |
subject_revision | identifier (Revision) | required | The revision of that artifact the record is about. |
observed_at | text (Instant) | optional | When the observation was made; its age at the evaluation instant is measured from here. A record without it never expires. |
upstream_revisions | map from identifier (ArtifactId) to identifier (Revision) | optional | The revision of each upstream artifact the observation was made against, keyed by artifact. A record without it is never invalidated. |
producer | identifier (Principal) | optional | Who produced the record, recorded as given: Canon does not prove it. A record without one is of no evidence match that demands independence. |
child_case | identifier (CaseId) | optional | The child case a case_outcome record is about (story:case-composition): one record per child case, its result the child's outcome, open while the child runs. Written only on a case_outcome record, which must name its child and give an outcome. |
More columns: swipe horizontally, or focus the table and use the arrow keys.
canon-decision/1
Written by canon evaluate.
Decision
A canon-decision/1 document. A section slot that is None is not serialized.
| Key | Value | Present | Meaning |
|---|---|---|---|
format | text | always | Always canon-decision/1. |
case | identifier (CaseId) | always | — |
protocol | identifier (ProtocolId) | always | — |
protocol_revision | integer, 0 or more | always | The revision of the compiled protocol that applied. |
claims | map from identifier (ClaimId) to ClaimDecision | always | Every declared claim, in identifier order. |
obligations | any JSON value | when present | Each declared obligation, in identifier order, with its ObligationStatus; written when the protocol declares an obligation. Its shape is fixed by CANON-OBLIGATION-001 and, for an obligation with an applicability predicate, CANON-INPUT-001. |
actions | any JSON value | when present | Each declared action, admissible, approval-required or blocked, with the reasons for a status other than admissible; written when the protocol declares an action. Its shape is fixed by CANON-AUTHORITY-001. |
outcomes | any JSON value | when present | Each declared outcome, legitimate or blocked, with the reasons it is blocked; written when the protocol declares an outcome. Its shape is fixed by CANON-OUTCOME-001 and, for an outcome that requires an explicit decision, by CANON-OUTCOME-002: a legitimate one records decided_by ({"decision": <name>, "principals": [...]}), and a blocked one gives the reason {"decision": <name>, "present": false}. |
explanation | any JSON value | when present | Why each claim that is not true, each open obligation, each action that is not admissible and each blocked outcome has its status, traced to the evidence records that applied or were excluded, and what the decision was computed from (computed_from); the evaluator writes it on every decision. Its shape is fixed by CANON-EXPLAIN-001. |
More columns: swipe horizontally, or focus the table and use the arrow keys.
ClaimDecision
One claim's entry in a decision.
| Key | Value | Present | Meaning |
|---|---|---|---|
value | Truth | always | — |
excluded_evidence | list of EvidenceExclusion | when not empty | The evidence an exclusion stage kept from this claim, in evidence-id order. Empty unless a stage excluded something; an empty list is not serialized. |
More columns: swipe horizontally, or focus the table and use the arrow keys.
EvidenceExclusion
One evidence record an exclusion stage kept from a claim, and why.
| Key | Value | Present | Meaning |
|---|---|---|---|
| evidence | identifier (EvidenceId) | always | — |
reason | ExclusionReason | always | — |
More columns: swipe horizontally, or focus the table and use the arrow keys.
ExclusionReason
Why evidence was excluded: before claims were evaluated, or, for NotIndependent, from the
evidence matches that demand an independence its producer lacks.
| Value | Meaning |
|---|---|
revision_mismatch | Bound to a revision of its subject that is not the current one. |
expired | Older than its kind allows at the evaluation instant. |
invalidated | Invalidated by an invalidation rule. |
not_independent | Produced by a producer the case does not list as independent on every dimension an evidence match demands. |
More columns: swipe horizontally, or focus the table and use the arrow keys.
canon-authority/1
Read by canon evaluate --authority: a list of AuthorityDecision entries; an empty list is allowed. A capability decided twice is refused, whatever the decision; the JSON Schema cannot express that, and refuses only an entry repeated exactly. The JSON Schema is generated from the same types.
AuthorityDecision
One entry of a canon-authority/1 document: a capability and whether it is granted.
| Key | Value | Required | Meaning |
|---|---|---|---|
capability | identifier (CapabilityId) | required | The capability decided, an identifier an action's requires may name. |
decision | Grant | required | Whether it is granted. |
More columns: swipe horizontally, or focus the table and use the arrow keys.
Grant
An authority decision on one capability. With its precondition true, an action is
admissible when every capability it requires is granted, blocked when one is denied, and
approval-required when none is denied and one is not decided.
| Value | Meaning |
|---|---|
granted | The capability is granted. |
denied | The capability is denied; asking again would not change it. |
More columns: swipe horizontally, or focus the table and use the arrow keys.
canon-decisions/1
Read by canon evaluate --decisions: a list of ExplicitDecision entries; an empty list is allowed. An entry given twice, every key equal, is refused. The JSON Schema is generated from the same types.
ExplicitDecision
One entry of a canon-decisions/1 document. It applies to outcome when the outcome requires
a decision named decision and case_revision is the case snapshot's revision.
| Key | Value | Required | Meaning |
|---|---|---|---|
decision | identifier (DecisionName) | required | Which decision was taken. |
| outcome | identifier (OutcomeId) | required | The outcome it was taken for. |
principal | identifier (Principal) | required | Who took it. |
case_revision | identifier (Revision) | required | The case revision it was taken at. |
More columns: swipe horizontally, or focus the table and use the arrow keys.
canon-properties/1
Read by canon check --properties. The JSON Schema is generated from the same types.
Properties
A canon-properties/1 document as written.
| Key | Value | Required | Meaning |
|---|---|---|---|
format | text | required | The document format; canon check accepts only canon-properties/1. |
protocol | identifier (ProtocolId) | required | The id of the protocol the properties are about; canon check refuses another. |
properties | map from identifier (PropertyId) to Property | optional | The properties, keyed by identifier. A property declared twice is refused. |
More columns: swipe horizontally, or focus the table and use the arrow keys.
Property
One property: its subject's status is the same in every two states that agree on everything
except the evidence the independent_of claim reads.
| Key | Value | Required | Meaning |
|---|---|---|---|
description | text | optional | — |
subject | PropertySubject | required | The action or outcome whose status the property is about. |
independent_of | PropertyDependency | required | What the subject's status must not depend on. |
More columns: swipe horizontally, or focus the table and use the arrow keys.
PropertySubject
What a property is about. Written as a map with exactly one of the keys action or outcome.
| Key | Value | Meaning |
|---|---|---|
| action | identifier (ActionId) | The action's status: admissible, approval-required or blocked. |
| outcome | identifier (OutcomeId) | The outcome's status: legitimate or blocked. |
More columns: swipe horizontally, or focus the table and use the arrow keys.
PropertyDependency
What a property's subject must not depend on. Written as a map with the one key claim.
| Key | Value | Meaning |
|---|---|---|
| claim | identifier (ClaimId) | The claim, standing for the evidence it reads, by kind and subject, directly or through the claims it tests. |
More columns: swipe horizontally, or focus the table and use the arrow keys.
Identifiers
An identifier is text. A well-formed identifier is not empty, and without whitespace, control characters or Unicode format characters (general category Cf). Each kind of identifier is its own type, so one cannot stand in for another. These are the kinds these documents use:
| Type | Identifies |
|---|---|
ProtocolId | Identifies a protocol, independently of its revision. |
CaseId | Identifies one case governed by a protocol. |
ArtifactId | Identifies an artifact a protocol declares. |
Revision | Identifies one revision of an artifact, or of the case itself: the case snapshot's own revision, and the case revision an explicit decision was taken at. |
ClaimId | Identifies a claim a protocol declares. |
EvidenceId | Identifies one evidence record. |
EvidenceKindId | Identifies a kind of evidence a protocol declares. |
ActionId | Identifies an action a protocol declares. |
OutcomeId | Identifies an outcome a protocol declares. |
CapabilityId | Names a capability an action requires authority for. |
DecisionName | Names an explicit decision an outcome may require (explicitly_inconclusive). |
Principal | Who took an explicit decision, or who produced an evidence record, recorded as given: Canon resolves no identity and proves no production. |
IndependenceDimensionId | Identifies an independence dimension a protocol declares (different_principal). Canon gives no dimension a meaning; the trusted context that writes the case resolves it. |
InputId | Identifies a case input a protocol declares. |
InputValue | One value a case input may take: an identifier its input declares. Read from any scalar, alike in the protocol and in the case: values: [true, false] declares the values true and false, and a case gives one as flag: true. |
PropertyId | Identifies one property of a canon-properties/1 document. |
More columns: swipe horizontally, or focus the table and use the arrow keys.
Text formats
These values are text in a fixed form, not identifiers. Canon refuses text that does not match its pattern, and also checks what the pattern cannot:
| Type | Written as | Pattern |
|---|---|---|
Instant | An instant written YYYY-MM-DDTHH:MM:SSZ in UTC, or with a fraction of one to nine digits after the seconds, YYYY-MM-DDTHH:MM:SS.fffZ; uppercase T and Z, no leap second (2026-10-04T12:00:00Z, 2026-10-04T12:00:00.400Z): when evidence was observed, and the evaluation instant. Order forms compare every instant of one evaluation at one resolution, the coarsest precision written among its records, dropping finer digits (12:00:00.4Z beside 12:00:00Z reads as 12:00:00Z); expiry reads the whole seconds and ignores the fraction. Calendar validity is checked by Canon, not by the pattern: the date must exist (leap years included) and the time be at most 23:59:59. | ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]{1,9})?Z$ |
More columns: swipe horizontally, or focus the table and use the arrow keys.