KYA-Prüfprofil 1.0

Wie KYA prüft – nicht, wie ausgestellt wird. Das Profil legt Regeln, eigene Containerformate und den Prüfbericht fest und bindet Formate anderer Anbieter wie Verifiable Intent an dieselben zehn Prüfschritte. Lizenziert unter CC BY 4.0.

Kurz gesagt

Das KYA-Prüfprofil 1.0 legt fest, wie geprüft wird: Claims-Profil, Beleg-Kette kya-chain/1, Nachweispaket kya-pack/1, Zeitstempel-Bindung, Prüfbericht – und die Abbildung fremder Formate wie Verifiable Intent auf die zehn Prüfschritte.

Geltungsbereich

Diese Spezifikation definiert ein Claims-Profil für Mandate und Entscheide, zwei Containerformate und den Prüfbericht. Für Signaturen, selektive Offenlegung, Statuslisten und Zeitstempel verweist sie auf bestehende Standards: JWS, SD-JWT VC, IETF Token Status List und RFC 3161. Kanonisches JSON folgt RFC 8785 in der hier beschriebenen Teilmenge.

Normative Quelle ist der Prüfkern @knowyouragent/verify-core; diese Seite wird bei jedem Build gegen ihn abgeglichen.

Claims-Profil 1.0

Mandate und Entscheide werden auf eine normalisierte Sicht abgebildet. Die Aliasse erlauben bestehenden Implementierungen, ihre Feldnamen beizubehalten. Neue Aliasse werden nur mit Testvektor aufgenommen.

Normiertes FeldAkzeptierte Claims
Agentsub, agent, agent_id, agentId
Auftraggeberprincipal, principal_id, mandant, on_behalf_of
Umfang (Handlungstypen)scope, actions, allowed_actions, action_types, actionTypes
Betragsgrenze je Handlungmax_amount, amount_max, limits.amount_max, limits.max_amount, amount_limit, maxAmount
Währungcurrency, limits.currency
Gegenparteiencounterparties, allowed_counterparties, merchants, counterparty
Periodenlimit (nur ausgewiesen)amountLimitPerMonth, limits.amount_per_period, limits.per_month, frequency_limit, frequencyLimit
Mandatsbezug im Entscheidmandate_id, mandateId, mid, mandate
Entscheiddecision, dec, result
Handlungaction, act
Belegbezugreceipt_id, receiptId

Handlungstypen im Umfang dürfen mit .* enden, zum Beispiel purchase.*. Periodenlimits sind offline nicht prüfbar und werden als vorhanden ausgewiesen, nicht als eingehalten.

Beleg-Kette 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_hash ist der hexadezimale SHA-256 über das kanonische JSON des Eintrags ohne entry_hash und ohne timestamp.
  • prev_hash ist beim ersten Eintrag null oder 64 Nullen, danach der entry_hash des Vorgängers.
  • seq ist optional und, falls vorhanden, lückenlos.
  • timestamp ist optional: ein RFC-3161-Token in Base64, dessen messageImprint die 32 Bytes von entry_hash sind.

Nachweispaket 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": [ "<Statuslisten-JWT>" ],
    "keys": [ { "kty": "EC", "kid": "…" } ]
  },
  "manifest": { "alg": "sha-256", "digest": "<hex>" },
  "timestamps": [ { "target": "manifest", "token": "<Base64>" } ]
}
  • manifest.digest ist der SHA-256 über das kanonische JSON von parts.
  • Beigelegte Schlüssel gelten als selbst behauptet. Sie belegen Integrität, nie den Aussteller.
  • timestamps[].target ist manifest, chain-head, entry:N oder decision.

Zeitstempel-Bindung

  • Der messageImprint muss SHA-256 verwenden und genau die Bytes des Ziels enthalten: Manifest-Digest, Kettenkopf, Eintragshash oder den SHA-256 des Entscheid-Tokens.
  • Das Zertifikat der Zeitstempelstelle muss den erweiterten Verwendungszweck timeStamping tragen und zum Zeitpunkt des Stempels gültig sein.
  • Vertrauen entsteht nur über einen Anker der prüfenden Stelle. Zertifikate im Token dienen als Zwischenglieder, nicht als Anker.

Statuslisten

Mandate verweisen mit status.status_list.idx und .uri auf eine Statusliste nach IETF Token Status List. Die Liste muss vom Aussteller des Mandats signiert sein. Werte: 0 gültig, 1 widerrufen, 2 suspendiert; alles andere ist unbestimmt. Die Prüfung lädt keine Listen; die prüfende Stelle legt sie vor.

Prüfbericht 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": "…"
}

Versionierung

Formate tragen ihre Version im Feld kind. Die Policy-Version legt die Regeln für Urteil und Stufen fest. Rückwärtsinkompatible Änderungen erhalten eine neue Hauptversion; ältere Berichte behalten ihre Version.