KYA verification profile 1.0
How KYA verifies – not how evidence is issued. The profile defines rules, its own container formats and the report, and binds other vendors' formats such as Verifiable Intent to the same ten checks. Licensed under CC BY 4.0.
In short
The KYA verification profile 1.0 defines how verification works: claims profile, receipt chain kya-chain/1, evidence pack kya-pack/1, timestamp binding, report – and the mapping of other formats such as Verifiable Intent onto the ten checks.
Scope
This specification defines a claims profile for mandates and decisions, two container formats and the verification report. For signatures, selective disclosure, status lists and timestamps it refers to existing standards: JWS, SD-JWT VC, IETF Token Status List and RFC 3161. Canonical JSON follows RFC 8785 in the subset described here.
The normative source is the engine @knowyouragent/verify-core; this page is reconciled against it on every build.
Claims profile 1.0
Mandates and decisions are mapped onto a normalized view. The aliases let existing implementations keep their field names. New aliases are only added with a test vector.
| Normalized field | Accepted claims |
|---|---|
| Agent | sub, agent, agent_id, agentId |
| Principal | principal, principal_id, mandant, on_behalf_of |
| Scope (action types) | scope, actions, allowed_actions, action_types, actionTypes |
| Amount limit per action | max_amount, amount_max, limits.amount_max, limits.max_amount, amount_limit, maxAmount |
| Currency | currency, limits.currency |
| Counterparties | counterparties, allowed_counterparties, merchants, counterparty |
| Period limit (reported only) | amountLimitPerMonth, limits.amount_per_period, limits.per_month, frequency_limit, frequencyLimit |
| Mandate reference in decision | mandate_id, mandateId, mid, mandate |
| Decision | decision, dec, result |
| Action | action, act |
| Receipt reference | receipt_id, receiptId |
Action types in the scope may end in .*, for example purchase.*. Period limits cannot be checked offline and are reported as present, not as complied with.
Receipt chain kya-chain/1
{
"kind": "kya-chain/1",
"entries": [{
"seq": 1,
"ts": "2026-10-01T08:00:02Z",
"receipt_id": "rcpt-0001",
"decision_jti": "dec-2026-10-01-0001",
"mandate_id": "urn:uuid:…",
"agent": "did:key:z6Mk…",
"action": { "type": "purchase.goods", "amount": 4, "currency": "CHF" },
"result": "executed",
"prev_hash": null,
"entry_hash": "9f2c…",
"timestamp": "MIIL…"
}]
}
entry_hashis the hexadecimal SHA-256 over the entry's canonical JSON withoutentry_hashand withouttimestamp.prev_hashisnullor 64 zeros for the first entry, then the predecessor'sentry_hash.seqis optional and, if present, gapless.timestampis optional: an RFC 3161 token in Base64 whose messageImprint is the 32 bytes ofentry_hash.
Evidence pack kya-pack/1
{
"kind": "kya-pack/1",
"created": "2026-10-12T10:00:00Z",
"parts": {
"mandate": "<SD-JWT VC>",
"passport": "<SD-JWT VC, optional>",
"decision": "<JWS>",
"chain": { "kind": "kya-chain/1", "entries": [ … ] },
"status_lists": [ "<status list JWT>" ],
"keys": [ { "kty": "EC", "kid": "…" } ]
},
"manifest": { "alg": "sha-256", "digest": "<hex>" },
"timestamps": [ { "target": "manifest", "token": "<Base64>" } ]
}
manifest.digestis the SHA-256 over the canonical JSON ofparts.- Bundled keys count as self-asserted. They prove integrity, never the issuer.
timestamps[].targetismanifest,chain-head,entry:Nordecision.
Timestamp binding
- The messageImprint must use SHA-256 and contain exactly the bytes of the target: manifest digest, chain head, entry hash or the SHA-256 of the decision token.
- The timestamp authority's certificate must carry the extended key usage timeStamping and be valid at the time of the stamp.
- Trust only arises through an anchor of the verifying party. Certificates in the token serve as intermediates, not as anchors.
Status lists
Mandates reference a status list per IETF Token Status List through status.status_list.idx and .uri. The list must be signed by the mandate's issuer. Values: 0 valid, 1 revoked, 2 suspended; anything else is unknown. Verification does not fetch lists; the verifying party provides them.
Verification report kya-report/1
{
"kind": "kya-report/1",
"verifier": { "name": "@knowyouragent/verify-core", "version": "1.2.0" },
"policy": "kya-policy/1.0",
"checkedAt": "2026-10-12T10:00:00.000Z",
"input": { "sha256": "…", "bytes": 5321, "format": "kya-pack/1" },
"verdict": "VALID",
"assurance": "KYA-A4",
"checks": [ { "id": "parse_schema", "status": "VALID" }, … ],
"facts": [ { "k": "agent", "v": "did:key:z6Mk…" }, … ],
"options": { "trustedKeys": 0, "statusLists": 0, "tsaAnchors": 1, "digest": "…" },
"reportDigest": "…"
}Versioning
Formats carry their version in the kind field. The policy version sets the rules for verdict and levels. Backwards-incompatible changes get a new major version; older reports keep their version.