Verification model
Verify, don't rate. Every check has a fixed question, every status a fixed meaning, every failure a reason.
In short
Ten fixed checks with one question each. Every check returns one of six statuses, every failure carries a reason code.
The ten checks
| # | Check | Question | Area |
|---|---|---|---|
| 1 | Format and schemaparse_schemacore check | Is the format recognized, are required fields present, is the version supported? | Authenticity |
| 2 | Cryptographic integritycryptographic_integritycore check | Are signatures, disclosures, hash chains and manifest unchanged? | Authenticity |
| 3 | Issuerissuer_resolution | Is the key bound to the issuer – through a DID or because the verifying party trusts it? | Authenticity |
| 4 | Agent and principalsubject_agent_bindingcore check | Do all parts name the same agent, is the principal named, does the agent hold the bound key? | Identity and principal |
| 5 | Mandate validitymandate_validitycore check | Was the mandate valid at the time of the action? | Authority |
| 6 | Scope of the actionintent_scope | Is the action within the mandate's action type, amount limit, currency and counterparty? | Authority |
| 7 | Delegation chaindelegation_provenance | Is every hop signed, connected without gaps and no broader than the previous one? | Identity and principal |
| 8 | Revocationrevocationcore check | Is the mandate neither revoked nor suspended according to the status list? | Authority |
| 9 | Execution receiptexecution_binding | Does the receipt reference exactly this decision and this mandate? | Proof |
| 10 | Timestamptimestamp_assurance | Is the RFC 3161 timestamp valid, bound to the content and traceable to an anchor of the verifying party? | Proof |
The five core checks form the core statement. Without them no overall verdict of “valid” is possible. Revocation is part of it because the question is whether an action was permitted – not merely whether the mandate was once issued.
Six statuses
| Status | Label | Meaning |
|---|---|---|
VALID | proven | Checked and proven. |
INVALID | disproven | Checked and disproven. |
NOT_CHECKED | not checked | Not performed because a prerequisite is missing. |
NOT_PRESENT | not present | The evidence does not contain the element. |
UNKNOWN | unknown | Performed, but without a reliable result. |
RECOGNIZED | recognized | Format recognized, deliberately not fully checked. |
There is no implicit success. A check that was not performed has not passed, and every status other than “proven” carries a reason code.
Three verdicts
| Verdict | Label | Condition |
|---|---|---|
INVALID | Invalid | At least one check is disproven. |
INDETERMINATE | Indeterminate | Nothing is disproven, but the core statement is not fully proven or a check is unknown. |
VALID | Valid | All core checks are proven and no check is unknown. |
The difference between “invalid” and “indeterminate” is the most important statement of the model: disproven and not verifiable are different things and never coincide.
Time basis
If the evidence contains a decision with an issuance time, the mandate's validity is assessed at that time – the moment of the action. Without a decision, the time of verification applies. The report always states which time basis was used. A tolerance of 60 seconds absorbs clock drift, nothing more.
Status lists reflect the state at the time they were issued. A revocation after the action does not retroactively make an action that was permitted at the time impermissible; the report therefore also states when the list was issued.
Key provenance
| Source | Meaning | Proves the issuer |
|---|---|---|
did | from the issuer DID | yes |
trusted | from the verifying party | yes |
embedded | in the token itself (self-asserted) | no |
bundled | bundled with the pack (self-asserted) | no |
Only “from the issuer DID” and “from the verifying party” prove the issuer. The other two sources prove integrity, but not who issued.
Reason codes
Every code is stable and defined identically in both languages. It appears in the machine-readable report and is translated in the interface.
| Code | Meaning |
|---|---|
format_unknown | The format is not known. |
format_recognized_not_supported | The format is recognized but not checked in this version. |
not_evidence_key_material | This is key material, not evidence. Paste it under “Trust of the verifying party”. |
malformed | The input is structurally defective. |
required_claim_missing | A required field is missing. |
format_not_supported | Not checked because the format is not supported. |
signature_invalid | The signature does not match the content. |
no_key | No key available. Add the issuer's key under “Trust of the verifying party”. |
unsupported_alg | The signature algorithm is not available in this environment. Update your browser (Chrome or Edge 137+, Firefox 129+, Safari 17+). |
disclosure_digest_mismatch | A disclosure does not match its hash. |
disclosure_unreferenced | A disclosure is not referenced in the signed content. |
disclosure_duplicate | A disclosure appears twice. |
kb_jwt_invalid | The key binding JWT is invalid: the presenter does not demonstrably hold the bound key. |
chain_hash_mismatch | A receipt was changed after it was chained. |
chain_link_broken | The receipt chain has a gap or a wrong order. |
binding_mismatch | A layer is not bound to the previous one: the hash binding does not match. |
manifest_mismatch | The pack content does not match the manifest. |
no_crypto_material | The evidence contains no cryptographic material. |
tsa_signature_invalid | The timestamp signature is invalid. |
issuer_key_not_trusted | The key comes from the evidence itself and is not bound to the issuer. |
kid_issuer_mismatch | The key identifier points to a different identity than the issuer. |
no_signed_artifact | No signed artifact present. |
agent_mismatch | The parts of the evidence name different agents. |
principal_missing | The principal is not named. |
agent_missing | The agent is not named. |
no_credential | No mandate and no agent passport present. |
credential_is_not_a_mandate | The presented credential is not a mandate. |
expired | Expired at the time of evaluation. |
not_yet_valid | Not yet valid at the time of evaluation. |
mandate_not_included | The mandate is not included. |
action_not_in_scope | The action type is outside the mandate. |
amount_exceeds_limit | The amount exceeds the mandate's limit. |
currency_mismatch | The currency differs from the mandate. |
counterparty_not_allowed | The counterparty is not permitted by the mandate. |
mandate_without_scope | The mandate has no scope. An unlimited authority cannot be checked. |
constraint_not_supported | A mandate constraint cannot be checked automatically without further input, for example without the merchant's key. |
no_action | No action in the evidence. |
no_delegation | No delegation chain: the principal mandated directly. |
delegation_broken | The delegation chain is broken or expired. |
delegation_scope_widened | A delegation hop widens the scope. |
delegation_key_missing | A bound key is missing for a delegation hop. |
revoked | The mandate is revoked. |
suspended | The mandate is suspended. |
status_value_unknown | The status list reports an unknown value. |
status_list_not_provided | No matching status list was provided. |
status_list_unverified | The status list is not demonstrably from the issuer. |
status_list_invalid | The status list is defective. |
no_status_reference | The mandate names no revocation mechanism. |
receipt_decision_mismatch | The receipt references a different decision. |
receipt_mandate_mismatch | The receipt references a different mandate. |
no_receipt | No execution receipt present. |
no_decision_reference | The receipt names no decision. |
tsa_malformed | The timestamp cannot be read. |
tsa_imprint_mismatch | The timestamp covers different content. |
tsa_anchor_not_provided | No timestamp anchor provided. Add it under “Trust of the verifying party”. |
tsa_not_trusted | The timestamp does not lead to any of the provided anchors. |
tsa_target_unknown | It is unclear which content the timestamp covers. |
no_timestamp | No timestamp present. |
prerequisite_failed | Not checked because an earlier check failed. |
Determinism
The report kya-report/1 contains the input hash, an options digest, the verification time, the engine version and the policy version. Its reportDigest is the SHA-256 over the report's canonical JSON. The same input, the same options and the same verification time produce the same digest – in the browser, on the command line and in CI.