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

#CheckQuestionArea
1Format and schema
parse_schema
core check
Is the format recognized, are required fields present, is the version supported?Authenticity
2Cryptographic integrity
cryptographic_integrity
core check
Are signatures, disclosures, hash chains and manifest unchanged?Authenticity
3Issuer
issuer_resolution
Is the key bound to the issuer – through a DID or because the verifying party trusts it?Authenticity
4Agent and principal
subject_agent_binding
core check
Do all parts name the same agent, is the principal named, does the agent hold the bound key?Identity and principal
5Mandate validity
mandate_validity
core check
Was the mandate valid at the time of the action?Authority
6Scope of the action
intent_scope
Is the action within the mandate's action type, amount limit, currency and counterparty?Authority
7Delegation chain
delegation_provenance
Is every hop signed, connected without gaps and no broader than the previous one?Identity and principal
8Revocation
revocation
core check
Is the mandate neither revoked nor suspended according to the status list?Authority
9Execution receipt
execution_binding
Does the receipt reference exactly this decision and this mandate?Proof
10Timestamp
timestamp_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

StatusLabelMeaning
VALIDprovenChecked and proven.
INVALIDdisprovenChecked and disproven.
NOT_CHECKEDnot checkedNot performed because a prerequisite is missing.
NOT_PRESENTnot presentThe evidence does not contain the element.
UNKNOWNunknownPerformed, but without a reliable result.
RECOGNIZEDrecognizedFormat 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

VerdictLabelCondition
INVALIDInvalidAt least one check is disproven.
INDETERMINATEIndeterminateNothing is disproven, but the core statement is not fully proven or a check is unknown.
VALIDValidAll 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

SourceMeaningProves the issuer
didfrom the issuer DIDyes
trustedfrom the verifying partyyes
embeddedin the token itself (self-asserted)no
bundledbundled 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.

CodeMeaning
format_unknownThe format is not known.
format_recognized_not_supportedThe format is recognized but not checked in this version.
not_evidence_key_materialThis is key material, not evidence. Paste it under “Trust of the verifying party”.
malformedThe input is structurally defective.
required_claim_missingA required field is missing.
format_not_supportedNot checked because the format is not supported.
signature_invalidThe signature does not match the content.
no_keyNo key available. Add the issuer's key under “Trust of the verifying party”.
unsupported_algThe signature algorithm is not available in this environment. Update your browser (Chrome or Edge 137+, Firefox 129+, Safari 17+).
disclosure_digest_mismatchA disclosure does not match its hash.
disclosure_unreferencedA disclosure is not referenced in the signed content.
disclosure_duplicateA disclosure appears twice.
kb_jwt_invalidThe key binding JWT is invalid: the presenter does not demonstrably hold the bound key.
chain_hash_mismatchA receipt was changed after it was chained.
chain_link_brokenThe receipt chain has a gap or a wrong order.
binding_mismatchA layer is not bound to the previous one: the hash binding does not match.
manifest_mismatchThe pack content does not match the manifest.
no_crypto_materialThe evidence contains no cryptographic material.
tsa_signature_invalidThe timestamp signature is invalid.
issuer_key_not_trustedThe key comes from the evidence itself and is not bound to the issuer.
kid_issuer_mismatchThe key identifier points to a different identity than the issuer.
no_signed_artifactNo signed artifact present.
agent_mismatchThe parts of the evidence name different agents.
principal_missingThe principal is not named.
agent_missingThe agent is not named.
no_credentialNo mandate and no agent passport present.
credential_is_not_a_mandateThe presented credential is not a mandate.
expiredExpired at the time of evaluation.
not_yet_validNot yet valid at the time of evaluation.
mandate_not_includedThe mandate is not included.
action_not_in_scopeThe action type is outside the mandate.
amount_exceeds_limitThe amount exceeds the mandate's limit.
currency_mismatchThe currency differs from the mandate.
counterparty_not_allowedThe counterparty is not permitted by the mandate.
mandate_without_scopeThe mandate has no scope. An unlimited authority cannot be checked.
constraint_not_supportedA mandate constraint cannot be checked automatically without further input, for example without the merchant's key.
no_actionNo action in the evidence.
no_delegationNo delegation chain: the principal mandated directly.
delegation_brokenThe delegation chain is broken or expired.
delegation_scope_widenedA delegation hop widens the scope.
delegation_key_missingA bound key is missing for a delegation hop.
revokedThe mandate is revoked.
suspendedThe mandate is suspended.
status_value_unknownThe status list reports an unknown value.
status_list_not_providedNo matching status list was provided.
status_list_unverifiedThe status list is not demonstrably from the issuer.
status_list_invalidThe status list is defective.
no_status_referenceThe mandate names no revocation mechanism.
receipt_decision_mismatchThe receipt references a different decision.
receipt_mandate_mismatchThe receipt references a different mandate.
no_receiptNo execution receipt present.
no_decision_referenceThe receipt names no decision.
tsa_malformedThe timestamp cannot be read.
tsa_imprint_mismatchThe timestamp covers different content.
tsa_anchor_not_providedNo timestamp anchor provided. Add it under “Trust of the verifying party”.
tsa_not_trustedThe timestamp does not lead to any of the provided anchors.
tsa_target_unknownIt is unclear which content the timestamp covers.
no_timestampNo timestamp present.
prerequisite_failedNot 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.