@kya-os/mcp 1.10.1 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AUDITABILITY.md +441 -0
- package/CHANGELOG.md +88 -0
- package/CONFORMANCE.md +598 -0
- package/README.md +67 -4
- package/SPEC.md +1827 -0
- package/dist/audit/adapters/legacy-audit-log.d.ts +20 -0
- package/dist/audit/adapters/legacy-audit-log.d.ts.map +1 -0
- package/dist/audit/adapters/legacy-audit-log.js +56 -0
- package/dist/audit/adapters/legacy-audit-log.js.map +1 -0
- package/dist/audit/adapters/mcp.d.ts +105 -0
- package/dist/audit/adapters/mcp.d.ts.map +1 -0
- package/dist/audit/adapters/mcp.js +213 -0
- package/dist/audit/adapters/mcp.js.map +1 -0
- package/dist/audit/assurance.d.ts +22 -0
- package/dist/audit/assurance.d.ts.map +1 -0
- package/dist/audit/assurance.js +39 -0
- package/dist/audit/assurance.js.map +1 -0
- package/dist/audit/checkpoint-coordinator.d.ts +51 -0
- package/dist/audit/checkpoint-coordinator.d.ts.map +1 -0
- package/dist/audit/checkpoint-coordinator.js +112 -0
- package/dist/audit/checkpoint-coordinator.js.map +1 -0
- package/dist/audit/checkpoint.d.ts +59 -0
- package/dist/audit/checkpoint.d.ts.map +1 -0
- package/dist/audit/checkpoint.js +219 -0
- package/dist/audit/checkpoint.js.map +1 -0
- package/dist/audit/cli.d.ts +8 -0
- package/dist/audit/cli.d.ts.map +1 -0
- package/dist/audit/cli.js +85 -0
- package/dist/audit/cli.js.map +1 -0
- package/dist/audit/crypto.d.ts +37 -0
- package/dist/audit/crypto.d.ts.map +1 -0
- package/dist/audit/crypto.js +68 -0
- package/dist/audit/crypto.js.map +1 -0
- package/dist/audit/errors.d.ts +29 -0
- package/dist/audit/errors.d.ts.map +1 -0
- package/dist/audit/errors.js +33 -0
- package/dist/audit/errors.js.map +1 -0
- package/dist/audit/evidence.d.ts +45 -0
- package/dist/audit/evidence.d.ts.map +1 -0
- package/dist/audit/evidence.js +151 -0
- package/dist/audit/evidence.js.map +1 -0
- package/dist/audit/index.d.ts +27 -0
- package/dist/audit/index.d.ts.map +1 -0
- package/dist/audit/index.js +27 -0
- package/dist/audit/index.js.map +1 -0
- package/dist/audit/integrity.d.ts +19 -0
- package/dist/audit/integrity.d.ts.map +1 -0
- package/dist/audit/integrity.js +64 -0
- package/dist/audit/integrity.js.map +1 -0
- package/dist/audit/merkle.d.ts +31 -0
- package/dist/audit/merkle.d.ts.map +1 -0
- package/dist/audit/merkle.js +195 -0
- package/dist/audit/merkle.js.map +1 -0
- package/dist/audit/mirror-service.d.ts +19 -0
- package/dist/audit/mirror-service.d.ts.map +1 -0
- package/dist/audit/mirror-service.js +54 -0
- package/dist/audit/mirror-service.js.map +1 -0
- package/dist/audit/projection.d.ts +90 -0
- package/dist/audit/projection.d.ts.map +1 -0
- package/dist/audit/projection.js +142 -0
- package/dist/audit/projection.js.map +1 -0
- package/dist/audit/providers/anchor.d.ts +23 -0
- package/dist/audit/providers/anchor.d.ts.map +1 -0
- package/dist/audit/providers/anchor.js +25 -0
- package/dist/audit/providers/anchor.js.map +1 -0
- package/dist/audit/providers/evidence.d.ts +36 -0
- package/dist/audit/providers/evidence.d.ts.map +1 -0
- package/dist/audit/providers/evidence.js +2 -0
- package/dist/audit/providers/evidence.js.map +1 -0
- package/dist/audit/providers/journal.d.ts +35 -0
- package/dist/audit/providers/journal.d.ts.map +1 -0
- package/dist/audit/providers/journal.js +2 -0
- package/dist/audit/providers/journal.js.map +1 -0
- package/dist/audit/providers/memory-journal.d.ts +24 -0
- package/dist/audit/providers/memory-journal.d.ts.map +1 -0
- package/dist/audit/providers/memory-journal.js +73 -0
- package/dist/audit/providers/memory-journal.js.map +1 -0
- package/dist/audit/providers/observer.d.ts +30 -0
- package/dist/audit/providers/observer.d.ts.map +1 -0
- package/dist/audit/providers/observer.js +100 -0
- package/dist/audit/providers/observer.js.map +1 -0
- package/dist/audit/providers/outbox.d.ts +37 -0
- package/dist/audit/providers/outbox.d.ts.map +1 -0
- package/dist/audit/providers/outbox.js +52 -0
- package/dist/audit/providers/outbox.js.map +1 -0
- package/dist/audit/providers/recorder-client.d.ts +22 -0
- package/dist/audit/providers/recorder-client.d.ts.map +1 -0
- package/dist/audit/providers/recorder-client.js +17 -0
- package/dist/audit/providers/recorder-client.js.map +1 -0
- package/dist/audit/providers/source-state.d.ts +37 -0
- package/dist/audit/providers/source-state.d.ts.map +1 -0
- package/dist/audit/providers/source-state.js +94 -0
- package/dist/audit/providers/source-state.js.map +1 -0
- package/dist/audit/recorder-service.d.ts +78 -0
- package/dist/audit/recorder-service.d.ts.map +1 -0
- package/dist/audit/recorder-service.js +331 -0
- package/dist/audit/recorder-service.js.map +1 -0
- package/dist/audit/replay-bundle.d.ts +52 -0
- package/dist/audit/replay-bundle.d.ts.map +1 -0
- package/dist/audit/replay-bundle.js +551 -0
- package/dist/audit/replay-bundle.js.map +1 -0
- package/dist/audit/schemas.d.ts +1144 -0
- package/dist/audit/schemas.d.ts.map +1 -0
- package/dist/audit/schemas.js +483 -0
- package/dist/audit/schemas.js.map +1 -0
- package/dist/audit/service.d.ts +91 -0
- package/dist/audit/service.d.ts.map +1 -0
- package/dist/audit/service.js +222 -0
- package/dist/audit/service.js.map +1 -0
- package/dist/audit/testing/index.d.ts +2 -0
- package/dist/audit/testing/index.d.ts.map +1 -0
- package/dist/audit/testing/index.js +2 -0
- package/dist/audit/testing/index.js.map +1 -0
- package/dist/audit/testing/provider-contracts.d.ts +51 -0
- package/dist/audit/testing/provider-contracts.d.ts.map +1 -0
- package/dist/audit/testing/provider-contracts.js +391 -0
- package/dist/audit/testing/provider-contracts.js.map +1 -0
- package/dist/audit/types.d.ts +356 -0
- package/dist/audit/types.d.ts.map +1 -0
- package/dist/audit/types.js +49 -0
- package/dist/audit/types.js.map +1 -0
- package/dist/audit/verifier.d.ts +73 -0
- package/dist/audit/verifier.d.ts.map +1 -0
- package/dist/audit/verifier.js +322 -0
- package/dist/audit/verifier.js.map +1 -0
- package/dist/card/proof/canonical.d.ts.map +1 -1
- package/dist/card/proof/canonical.js +19 -1
- package/dist/card/proof/canonical.js.map +1 -1
- package/dist/delegation/delegation-graph.d.ts +4 -0
- package/dist/delegation/delegation-graph.d.ts.map +1 -1
- package/dist/delegation/delegation-graph.js +28 -2
- package/dist/delegation/delegation-graph.js.map +1 -1
- package/dist/delegation/statuslist-manager.d.ts +5 -0
- package/dist/delegation/statuslist-manager.d.ts.map +1 -1
- package/dist/delegation/statuslist-manager.js.map +1 -1
- package/dist/delegation/storage/memory-graph-storage.d.ts +4 -2
- package/dist/delegation/storage/memory-graph-storage.d.ts.map +1 -1
- package/dist/delegation/storage/memory-graph-storage.js +18 -0
- package/dist/delegation/storage/memory-graph-storage.js.map +1 -1
- package/dist/delegation/storage/memory-statuslist-storage.d.ts +5 -2
- package/dist/delegation/storage/memory-statuslist-storage.d.ts.map +1 -1
- package/dist/delegation/storage/memory-statuslist-storage.js +21 -2
- package/dist/delegation/storage/memory-statuslist-storage.js.map +1 -1
- package/dist/delegation/utils.d.ts.map +1 -1
- package/dist/delegation/utils.js +2 -42
- package/dist/delegation/utils.js.map +1 -1
- package/dist/delegation/vc-verifier.d.ts +4 -0
- package/dist/delegation/vc-verifier.d.ts.map +1 -1
- package/dist/delegation/vc-verifier.js +44 -13
- package/dist/delegation/vc-verifier.js.map +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.js +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/middleware/kya-os-transport.d.ts.map +1 -1
- package/dist/middleware/kya-os-transport.js +10 -3
- package/dist/middleware/kya-os-transport.js.map +1 -1
- package/dist/middleware/with-kya-os-server.d.ts +6 -0
- package/dist/middleware/with-kya-os-server.d.ts.map +1 -1
- package/dist/middleware/with-kya-os-server.js +2 -0
- package/dist/middleware/with-kya-os-server.js.map +1 -1
- package/dist/middleware/with-kya-os.config-types.d.ts +15 -0
- package/dist/middleware/with-kya-os.config-types.d.ts.map +1 -1
- package/dist/middleware/with-kya-os.config-types.js.map +1 -1
- package/dist/middleware/with-kya-os.d.ts.map +1 -1
- package/dist/middleware/with-kya-os.delegation-gate.d.ts.map +1 -1
- package/dist/middleware/with-kya-os.delegation-gate.js +96 -3
- package/dist/middleware/with-kya-os.delegation-gate.js.map +1 -1
- package/dist/middleware/with-kya-os.deps.d.ts +2 -0
- package/dist/middleware/with-kya-os.deps.d.ts.map +1 -1
- package/dist/middleware/with-kya-os.js +23 -0
- package/dist/middleware/with-kya-os.js.map +1 -1
- package/dist/middleware/with-kya-os.policy-gate.d.ts.map +1 -1
- package/dist/middleware/with-kya-os.policy-gate.js +29 -4
- package/dist/middleware/with-kya-os.policy-gate.js.map +1 -1
- package/dist/middleware/with-kya-os.protocol.d.ts.map +1 -1
- package/dist/middleware/with-kya-os.protocol.js +10 -0
- package/dist/middleware/with-kya-os.protocol.js.map +1 -1
- package/dist/middleware/with-kya-os.session.d.ts.map +1 -1
- package/dist/middleware/with-kya-os.session.js +208 -2
- package/dist/middleware/with-kya-os.session.js.map +1 -1
- package/dist/middleware/with-kya-os.types.d.ts +6 -0
- package/dist/middleware/with-kya-os.types.d.ts.map +1 -1
- package/dist/middleware/with-kya-os.types.js.map +1 -1
- package/dist/proof/generator.d.ts.map +1 -1
- package/dist/proof/generator.js +6 -5
- package/dist/proof/generator.js.map +1 -1
- package/dist/proof/verifier.d.ts +12 -0
- package/dist/proof/verifier.d.ts.map +1 -1
- package/dist/proof/verifier.js +35 -4
- package/dist/proof/verifier.js.map +1 -1
- package/dist/session/manager.js +1 -1
- package/dist/session/manager.js.map +1 -1
- package/dist/utils/canonical-json.d.ts +15 -0
- package/dist/utils/canonical-json.d.ts.map +1 -0
- package/dist/utils/canonical-json.js +109 -0
- package/dist/utils/canonical-json.js.map +1 -0
- package/dist/utils/crypto-service.d.ts.map +1 -1
- package/dist/utils/crypto-service.js +5 -0
- package/dist/utils/crypto-service.js.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/package.json +29 -11
- package/schemas/README.md +27 -1
- package/schemas/audit-anchor-receipt.schema.json +16 -0
- package/schemas/audit-bundle-manifest.schema.json +71 -0
- package/schemas/audit-checkpoint.schema.json +37 -0
- package/schemas/audit-consistency-proof.schema.json +17 -0
- package/schemas/audit-entry.schema.json +33 -0
- package/schemas/audit-event.schema.json +168 -0
- package/schemas/audit-inclusion-proof.schema.json +17 -0
- package/schemas/audit-observation.schema.json +40 -0
- package/schemas/audit-receipt.schema.json +32 -0
- package/schemas/audit-verification-policy.schema.json +71 -0
- package/schemas/audit-verification-report.schema.json +29 -0
- package/schemas/well-known-mcpi.json +17 -0
package/CONFORMANCE.md
ADDED
|
@@ -0,0 +1,598 @@
|
|
|
1
|
+
# KYA-OS Conformance Requirements
|
|
2
|
+
|
|
3
|
+
**Compliance levels for KYA-OS implementations**
|
|
4
|
+
|
|
5
|
+
Version: 1.0.0
|
|
6
|
+
Status: Stable
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
This document defines three compliance levels for KYA-OS implementations. Each level builds on the previous, with increasing capability requirements. Implementations MUST pass all tests for a given level to claim conformance at that level.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Level 1 — Core Crypto
|
|
17
|
+
|
|
18
|
+
Level 1 establishes the cryptographic foundation. An implementation at this level can generate identities, sign data, verify signatures, and expose discovery metadata.
|
|
19
|
+
|
|
20
|
+
### Requirements
|
|
21
|
+
|
|
22
|
+
| ID | Requirement | Test File | Test Name |
|
|
23
|
+
|----|-------------|-----------|-----------|
|
|
24
|
+
| L1.1 | Generate Ed25519 key pair and derive a `did:key` DID | `src/utils/__tests__/did-helpers.test.ts` | `generateDidKeyFromBytes` / `generateDidKeyFromBase64` |
|
|
25
|
+
| L1.2 | Implement SHA-256 hashing of canonicalized JSON (RFC 8785 JCS) | `src/proof/__tests__/proof-generator.test.ts` | `Canonical Hash Generation > should generate SHA-256 hashes with correct format` |
|
|
26
|
+
| L1.3 | Sign data with EdDSA (JWS compact serialization) | `src/proof/__tests__/proof-generator.test.ts` | `JWS Generation > should generate compact JWS in correct format` |
|
|
27
|
+
| L1.4 | Verify EdDSA signatures | `src/proof/__tests__/proof-generator.test.ts` | `Proof Verification > should verify valid proof structure` |
|
|
28
|
+
| L1.5 | Use EdDSA algorithm identifier in JWS header | `src/proof/__tests__/proof-generator.test.ts` | `JWS Generation > should use EdDSA algorithm` |
|
|
29
|
+
| L1.6 | Resolve `did:key` DIDs to DID Documents | `src/delegation/__tests__/did-key-resolver.test.ts` | `createDidKeyResolver > should resolve Ed25519 did:key to DID Document` |
|
|
30
|
+
| L1.7 | Extract Ed25519 public key from `did:key` | `src/delegation/__tests__/did-key-resolver.test.ts` | `extractPublicKeyFromDidKey > should extract public key bytes from valid did:key` |
|
|
31
|
+
| L1.8 | Convert public key bytes to JWK format | `src/delegation/__tests__/did-key-resolver.test.ts` | `publicKeyToJwk > should convert public key bytes to JWK format` |
|
|
32
|
+
| L1.9 | Implement base58btc encoding/decoding | `src/delegation/__tests__/did-key-resolver.test.ts` | `Base58 Utilities` (all tests) |
|
|
33
|
+
| L1.10 | Expose `/.well-known/mcp` endpoint (recommended) | — | Implementation-specific |
|
|
34
|
+
| L1.11 | Audit logging MAY be implemented | — | Implementation-specific |
|
|
35
|
+
|
|
36
|
+
### Detailed Requirements
|
|
37
|
+
|
|
38
|
+
#### L1.1 — Ed25519 Key Generation
|
|
39
|
+
|
|
40
|
+
Implementation MUST:
|
|
41
|
+
- Generate cryptographically secure random 32-byte private seed
|
|
42
|
+
- Derive 32-byte public key from seed
|
|
43
|
+
- Derive `did:key` DID from public key using multicodec prefix `0xed01` and base58btc encoding
|
|
44
|
+
- Key ID format: `<did>#keys-1`
|
|
45
|
+
|
|
46
|
+
#### L1.2 — SHA-256 Hashing
|
|
47
|
+
|
|
48
|
+
Implementation MUST:
|
|
49
|
+
- Accept arbitrary JSON input
|
|
50
|
+
- Canonicalize according to RFC 8785 (JCS): sorted keys, no whitespace, specific escaping
|
|
51
|
+
- Compute SHA-256 hash of UTF-8 encoded canonical JSON
|
|
52
|
+
- Return hash in format: `sha256:<64-char-lowercase-hex>`
|
|
53
|
+
|
|
54
|
+
#### L1.3 — EdDSA Signing
|
|
55
|
+
|
|
56
|
+
Implementation MUST:
|
|
57
|
+
- Accept data bytes and Ed25519 private key
|
|
58
|
+
- Produce JWS compact serialization: `<header>.<payload>.<signature>`
|
|
59
|
+
- Header MUST include `"alg": "EdDSA"` and `"kid": "<key-id>"`
|
|
60
|
+
- Signature MUST be 64 bytes, base64url-encoded
|
|
61
|
+
|
|
62
|
+
#### L1.4 — EdDSA Verification
|
|
63
|
+
|
|
64
|
+
Implementation MUST:
|
|
65
|
+
- Accept JWS compact string and public key (JWK format)
|
|
66
|
+
- Verify signature against payload
|
|
67
|
+
- Verify `kid` in header matches expected key
|
|
68
|
+
- Return boolean result
|
|
69
|
+
|
|
70
|
+
#### L1.11 — Audit Logging
|
|
71
|
+
|
|
72
|
+
Audit logging MAY be implemented at Level 1. If implemented, it SHOULD capture key generation events and signature operations.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Level 2 — Full Session
|
|
77
|
+
|
|
78
|
+
Level 2 adds session management with replay prevention and proof generation. An implementation at this level can establish secure sessions and generate non-repudiation proofs.
|
|
79
|
+
|
|
80
|
+
### Requirements
|
|
81
|
+
|
|
82
|
+
All Level 1 requirements, plus:
|
|
83
|
+
|
|
84
|
+
| ID | Requirement | Test File | Test Name |
|
|
85
|
+
|----|-------------|-----------|-----------|
|
|
86
|
+
| L2.1 | Implement handshake request validation | `src/session/__tests__/session-manager.test.ts` | `Handshake validation > should create a valid session on correct handshake` |
|
|
87
|
+
| L2.2 | Validate nonce format (base64url, 22+ chars) | `src/session/__tests__/session-manager.test.ts` | `Nonce format > should generate nonce as base64url string` |
|
|
88
|
+
| L2.3 | Enforce timestamp skew ≤120 seconds (default) | `src/session/__tests__/session-manager.test.ts` | `Handshake validation > should reject request with stale timestamp` |
|
|
89
|
+
| L2.4 | Accept requests within timestamp skew | `src/session/__tests__/session-manager.test.ts` | `Handshake validation > should accept request within timestamp skew` |
|
|
90
|
+
| L2.5 | Enforce nonce uniqueness (replay prevention) | `src/session/__tests__/session-manager.test.ts` | `Handshake validation > should reject replayed nonce` |
|
|
91
|
+
| L2.6 | Generate unique nonces | `src/session/__tests__/session-manager.test.ts` | `Nonce format > should generate unique nonces` |
|
|
92
|
+
| L2.7 | Generate session IDs with `kyaos_` prefix | `src/session/__tests__/session-manager.test.ts` | `Handshake validation > should return session ID with kyaos_ prefix` |
|
|
93
|
+
| L2.8 | Maintain session TTL | `src/session/__tests__/session-manager.test.ts` | `Session expiry — TTL behaviour > should expire idle sessions after TTL` |
|
|
94
|
+
| L2.9 | Support configurable timestamp skew | `src/session/__tests__/session-manager.test.ts` | `Custom timestamp skew > should use custom timestampSkewSeconds when provided` |
|
|
95
|
+
| L2.10 | Update session `lastActivity` on access | `src/session/__tests__/session-manager.test.ts` | `Session lookup — getSession > should update lastActivity on each getSession call` |
|
|
96
|
+
| L2.11 | Generate detached proof with request/response hashes | `src/proof/__tests__/proof-generator.test.ts` | `Proof Metadata > should include all required metadata fields` |
|
|
97
|
+
| L2.12 | Include session context in proof metadata | `src/proof/__tests__/proof-generator.test.ts` | `Proof Metadata > should include all required metadata fields` |
|
|
98
|
+
| L2.13 | Verify proof against request/response | `src/proof/__tests__/proof-generator.test.ts` | `Proof Verification > should reject proof with mismatched request` |
|
|
99
|
+
| L2.14 | Validate handshake request format | `src/session/__tests__/session-manager.test.ts` | `validateHandshakeFormat` (all tests) |
|
|
100
|
+
| L2.15 | Create handshake request with current timestamp | `src/session/__tests__/session-manager.test.ts` | `createHandshakeRequest > should use current timestamp` |
|
|
101
|
+
| L2.16 | Audit logging SHOULD be implemented | — | Implementation-specific |
|
|
102
|
+
| L2.17 | Process only the KYA-OS proof `_meta` key; ignore (do not reject) reserved keys | — | Spec-defined behavior (SPEC §7.6) |
|
|
103
|
+
|
|
104
|
+
### Detailed Requirements
|
|
105
|
+
|
|
106
|
+
#### L2.1 — Handshake Validation
|
|
107
|
+
|
|
108
|
+
Implementation MUST validate:
|
|
109
|
+
- `nonce`: Non-empty string, base64url format, minimum 16 bytes entropy
|
|
110
|
+
- `audience`: Non-empty string matching server identity
|
|
111
|
+
- `timestamp`: Positive integer, within skew tolerance of server time
|
|
112
|
+
- `agentDid` (optional): Valid DID format if present
|
|
113
|
+
|
|
114
|
+
#### L2.5 — Nonce Replay Prevention
|
|
115
|
+
|
|
116
|
+
Implementation MUST:
|
|
117
|
+
- Store (nonce, agentDid) tuples for at least `sessionTtlMinutes + 1 minute`
|
|
118
|
+
- Reject any request with a previously-seen nonce for the same agentDid
|
|
119
|
+
- Support cleanup of expired nonces
|
|
120
|
+
|
|
121
|
+
#### L2.16 — Audit Logging
|
|
122
|
+
|
|
123
|
+
Audit logging SHOULD be implemented at Level 2. Implementations SHOULD record session lifecycle events (handshake, expiry, replay rejection) and proof generation events with enough detail to reconstruct the sequence of operations for a given session.
|
|
124
|
+
|
|
125
|
+
#### L2.11 — Detached Proof Generation
|
|
126
|
+
|
|
127
|
+
Proof metadata MUST include:
|
|
128
|
+
- `did`: Signer's DID
|
|
129
|
+
- `kid`: Key ID used for signing
|
|
130
|
+
- `ts`: Unix epoch seconds
|
|
131
|
+
- `nonce`: Session nonce
|
|
132
|
+
- `audience`: Session audience
|
|
133
|
+
- `sessionId`: Session identifier
|
|
134
|
+
- `requestHash`: SHA-256 of canonicalized request (`sha256:<hex>`)
|
|
135
|
+
|
|
136
|
+
`responseHash` (SHA-256 of the canonicalized response, `sha256:<hex>`) MUST be
|
|
137
|
+
present on proofs that carry a response body — success proofs and
|
|
138
|
+
`needs_authorization` challenges — and is ABSENT on `denied` / `step_up_required`
|
|
139
|
+
proofs (which have no response body). See SPEC §7.2 / §7.4 and the
|
|
140
|
+
`detached-proof` schema (`responseHash` is intentionally not in `required`).
|
|
141
|
+
|
|
142
|
+
A verifier that acts on a `needs_authorization` `authorizationUrl` — or
|
|
143
|
+
otherwise relies on the response body — MUST recompute `responseHash` over the
|
|
144
|
+
response it actually received and compare it to the bound value BEFORE trusting
|
|
145
|
+
it. The signature alone proves the proof is authentic, not that the received
|
|
146
|
+
content matches what was signed: an in-path intermediary can leave the signature
|
|
147
|
+
intact while swapping the `authorizationUrl`, and only the recompute detects it.
|
|
148
|
+
|
|
149
|
+
#### L2.17 — `_meta` Namespacing Tolerance
|
|
150
|
+
|
|
151
|
+
`_meta` is the MCP per-request metadata channel and is shared with reserved
|
|
152
|
+
reverse-DNS keys. A conformant verifier MUST:
|
|
153
|
+
- Read the KYA-OS proof from `org.kya-os/proof` and, for backward compatibility,
|
|
154
|
+
from the legacy bare `proof` key.
|
|
155
|
+
- Process **only** the KYA-OS proof key; ignore every other `_meta` key (never
|
|
156
|
+
hash it, never trust it).
|
|
157
|
+
- **Never reject** a response merely because `_meta` also carries non-KYA-OS
|
|
158
|
+
keys, including the MCP-reserved `io.modelcontextprotocol/*` and the W3C Trace
|
|
159
|
+
Context keys `traceparent` / `tracestate` / `baggage`.
|
|
160
|
+
|
|
161
|
+
This holds under the default `strict` `metaPolicy`; `allow-extensions` shares the
|
|
162
|
+
same trust boundary but additionally surfaces non-KYA-OS keys to the application
|
|
163
|
+
layer. See SPEC §7.6.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Level 3 — Full Delegation
|
|
168
|
+
|
|
169
|
+
Level 3 adds W3C Verifiable Credential-based delegation with revocation support. An implementation at this level can issue, verify, and revoke delegations, and propagate delegation context on outbound calls.
|
|
170
|
+
|
|
171
|
+
### Requirements
|
|
172
|
+
|
|
173
|
+
All Level 2 requirements, plus:
|
|
174
|
+
|
|
175
|
+
| ID | Requirement | Test File | Test Name |
|
|
176
|
+
|----|-------------|-----------|-----------|
|
|
177
|
+
| L3.1 | Issue W3C DelegationCredentials | `src/delegation/__tests__/vc-issuer.test.ts` | `issueDelegationCredential > should issue a signed delegation credential` |
|
|
178
|
+
| L3.2 | Wrap DelegationRecord in VC structure | `src/delegation/__tests__/vc-issuer.test.ts` | `issueDelegationCredential > should call wrapDelegationAsVC with delegation record` |
|
|
179
|
+
| L3.3 | Support issuance options (id, dates, status) | `src/delegation/__tests__/vc-issuer.test.ts` | `issueDelegationCredential > should pass options to wrapDelegationAsVC` |
|
|
180
|
+
| L3.4 | Canonicalize VC before signing | `src/delegation/__tests__/vc-issuer.test.ts` | `issueDelegationCredential > should canonicalize VC before signing` |
|
|
181
|
+
| L3.5 | Verify DelegationCredential basic properties | `src/delegation/__tests__/vc-verifier.test.ts` | `verifyDelegationCredential - Basic Validation Stage` (all tests) |
|
|
182
|
+
| L3.5a | Reject claim-contaminated `credentialSubject` (only `id` + `delegation`) | `src/delegation/__tests__/vc-verifier.test.ts` | `Subject Shape (claim contamination) > rejects a credentialSubject carrying non-delegation (claim) fields` |
|
|
183
|
+
| L3.6 | Reject expired credentials | `src/delegation/__tests__/vc-verifier.test.ts` | `Basic Validation Stage > should reject expired credentials` |
|
|
184
|
+
| L3.7 | Reject not-yet-valid credentials | `src/delegation/__tests__/vc-verifier.test.ts` | `Basic Validation Stage > should reject not-yet-valid credentials` |
|
|
185
|
+
| L3.8 | Reject revoked credentials (status field) | `src/delegation/__tests__/vc-verifier.test.ts` | `Basic Validation Stage > should reject revoked credentials` |
|
|
186
|
+
| L3.9 | Verify credential signature | `src/delegation/__tests__/vc-verifier.test.ts` | `Signature Verification > should succeed when signature verification passes` |
|
|
187
|
+
| L3.10 | Resolve issuer DID for signature verification | `src/delegation/__tests__/vc-verifier.test.ts` | `Signature Verification > should fail when DID resolution fails` |
|
|
188
|
+
| L3.11 | Check credential status via StatusList2021 | `src/delegation/__tests__/vc-verifier.test.ts` | `Status Checking > should fail when credential is revoked` |
|
|
189
|
+
| L3.12 | Cache verification results | `src/delegation/__tests__/vc-verifier.test.ts` | `Caching > should return cached result when available` |
|
|
190
|
+
| L3.13 | Enforce CRISP scope constraints | `src/delegation/__tests__/audience-validator.test.ts` | All tests |
|
|
191
|
+
| L3.14 | Register delegation in graph | `src/delegation/__tests__/delegation-graph.test.ts` | `registerDelegation > should register a root delegation` |
|
|
192
|
+
| L3.15 | Link child to parent in delegation graph | `src/delegation/__tests__/delegation-graph.test.ts` | `registerDelegation > should register a child delegation and link to parent` |
|
|
193
|
+
| L3.16 | Validate delegation chain (issuer/subject continuity) | `src/delegation/__tests__/delegation-graph.test.ts` | `validateChain > should validate correct chain` |
|
|
194
|
+
| L3.17 | Detect chain with mismatched issuer/subject | `src/delegation/__tests__/delegation-graph.test.ts` | `validateChain > should invalidate chain with mismatched issuer/subject` |
|
|
195
|
+
| L3.18 | Get delegation chain from leaf to root | `src/delegation/__tests__/delegation-graph.test.ts` | `getChain > should return chain from root to node` |
|
|
196
|
+
| L3.19 | Get all descendants of a delegation | `src/delegation/__tests__/delegation-graph.test.ts` | `getDescendants > should return all descendants recursively` |
|
|
197
|
+
| L3.20 | Create StatusList2021 credential | `src/delegation/__tests__/statuslist-manager.test.ts` | (StatusList2021Manager tests) |
|
|
198
|
+
| L3.21 | Set/check revocation status by index | `src/delegation/__tests__/bitstring.test.ts` | All tests |
|
|
199
|
+
| L3.22 | Cascading revocation of descendant delegations | `src/delegation/__tests__/cascading-revocation.test.ts` | All tests |
|
|
200
|
+
| L3.23 | Build delegation proof JWT for outbound calls | `src/delegation/__tests__/outbound-proof.test.ts` | All tests |
|
|
201
|
+
| L3.24 | Build delegation chain string | `src/delegation/__tests__/outbound-proof.test.ts` | `buildChainString` tests |
|
|
202
|
+
| L3.25 | Return `needs_authorization` hints | Implementation-specific | — |
|
|
203
|
+
| L3.26 | Audit logging MUST be implemented | — | Implementation-specific |
|
|
204
|
+
| L3.27 | Derive authorization from the VC; treat L2 chain/scope headers as advisory | — | Spec-defined behavior (SPEC §8.1) |
|
|
205
|
+
|
|
206
|
+
### Detailed Requirements
|
|
207
|
+
|
|
208
|
+
#### L3.1 — VC Issuance
|
|
209
|
+
|
|
210
|
+
Implementation MUST:
|
|
211
|
+
- Produce valid W3C Verifiable Credential structure
|
|
212
|
+
- Include `@context` with VC v1 and KYA-OS delegation context
|
|
213
|
+
- Include `type` array with `VerifiableCredential` and `DelegationCredential`
|
|
214
|
+
- Include `issuer` as DID string or object with `id`
|
|
215
|
+
- Include `issuanceDate` in ISO 8601 format
|
|
216
|
+
- Include `credentialSubject` with delegation details
|
|
217
|
+
- Include `proof` with Ed25519Signature2020 or equivalent
|
|
218
|
+
|
|
219
|
+
#### L3.5 — VC Verification
|
|
220
|
+
|
|
221
|
+
Implementation MUST validate:
|
|
222
|
+
- `@context` starts with W3C VC v1 context
|
|
223
|
+
- `type` includes required types
|
|
224
|
+
- `issuer` is present and valid
|
|
225
|
+
- `issuanceDate` is present and in the past
|
|
226
|
+
- `expirationDate` (if present) is in the future
|
|
227
|
+
- `credentialSubject.delegation` has required fields
|
|
228
|
+
- `proof` is present
|
|
229
|
+
|
|
230
|
+
#### L3.11 — StatusList2021 Checking
|
|
231
|
+
|
|
232
|
+
Implementation MUST:
|
|
233
|
+
- Fetch StatusList2021 credential from `credentialStatus.statusListCredential`
|
|
234
|
+
- Decompress and decode the bitstring
|
|
235
|
+
- Check bit at `statusListIndex`
|
|
236
|
+
- Return revoked status if bit is 1
|
|
237
|
+
|
|
238
|
+
#### L3.22 — Cascading Revocation
|
|
239
|
+
|
|
240
|
+
When revoking a delegation, implementation MUST:
|
|
241
|
+
- Mark the target delegation as revoked
|
|
242
|
+
- Recursively mark all descendants as revoked
|
|
243
|
+
- Update StatusList2021 for each revoked delegation
|
|
244
|
+
- Emit revocation events (implementation-specific)
|
|
245
|
+
|
|
246
|
+
#### L3.26 — Audit Logging
|
|
247
|
+
|
|
248
|
+
Audit logging MUST be implemented at Level 3. Implementations MUST record:
|
|
249
|
+
- Delegation issuance and revocation events (including cascading revocations), with issuer DID, subject DID, credential ID, and timestamp
|
|
250
|
+
- Delegation verification outcomes (pass/fail), including chain validation results
|
|
251
|
+
- Outbound delegation proof attachments, including the chain string and target audience
|
|
252
|
+
- Any `needs_authorization` hints returned to callers
|
|
253
|
+
|
|
254
|
+
A conformant implementation MAY satisfy part of this requirement using the
|
|
255
|
+
signed detached-JWS proof attached to each outcome: `denied`, `step_up_required`,
|
|
256
|
+
and `needs_authorization` responses carry a proof whose `meta.outcome` records
|
|
257
|
+
the authorization decision (success proofs omit `outcome`, implying `allowed`).
|
|
258
|
+
Such proofs are themselves tamper-evident signed records.
|
|
259
|
+
|
|
260
|
+
Audit records MUST be tamper-evident (e.g., append-only log, signed entries, or equivalent) and MUST be retained for at least the duration of the longest-lived delegation in the system.
|
|
261
|
+
|
|
262
|
+
> **Note:** Revocation is verifier-local (checked against the verifier's local list or cache). L1 implementations MAY use simple local checks; higher levels MAY use StatusList2021.
|
|
263
|
+
|
|
264
|
+
#### L3.27 — VC-Authoritative Layer-2 Headers
|
|
265
|
+
|
|
266
|
+
The Verifiable Credential is authoritative for granted authority. A conformant
|
|
267
|
+
verifier MUST:
|
|
268
|
+
- Derive granted scopes and the delegation chain from `KYA-OS-Delegation-Credential`
|
|
269
|
+
(the VC-JWT) — its embedded scopes, its chain to a trusted root, and its
|
|
270
|
+
StatusList revocation state — together with the `KYA-OS-Delegation-Proof` JWT.
|
|
271
|
+
- Check that `KYA-OS-Agent-DID` equals the Layer-1 signature's resolved DID.
|
|
272
|
+
- **NOT** use `KYA-OS-Delegation-Chain` or `KYA-OS-Granted-Scopes` for any
|
|
273
|
+
authorization decision; these are OPTIONAL advisory transport hints and MUST be
|
|
274
|
+
ignored when they disagree with the credential.
|
|
275
|
+
|
|
276
|
+
Because authority is derived only from signed artifacts (the VC and the proof
|
|
277
|
+
JWT), the Layer-2 headers are NOT required to be RFC 9421 covered components; a
|
|
278
|
+
tampered advisory header is ignored, not a vulnerability. See SPEC §8.1.
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## Running Conformance Tests
|
|
283
|
+
|
|
284
|
+
### Prerequisites
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
# Install dependencies
|
|
288
|
+
pnpm install
|
|
289
|
+
|
|
290
|
+
# Or with npm
|
|
291
|
+
npm install
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Running All Tests
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
# Run all tests
|
|
298
|
+
pnpm test
|
|
299
|
+
|
|
300
|
+
# Or with npx
|
|
301
|
+
npx vitest run
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### Running Specific Test Files
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
# Level 1 - Core Crypto
|
|
308
|
+
npx vitest run src/delegation/__tests__/did-key-resolver.test.ts
|
|
309
|
+
npx vitest run src/utils/__tests__/did-helpers.test.ts
|
|
310
|
+
npx vitest run src/utils/__tests__/base58.test.ts
|
|
311
|
+
|
|
312
|
+
# Level 2 - Session
|
|
313
|
+
npx vitest run src/session/__tests__/session-manager.test.ts
|
|
314
|
+
npx vitest run src/proof/__tests__/proof-generator.test.ts
|
|
315
|
+
|
|
316
|
+
# Level 3 - Delegation
|
|
317
|
+
npx vitest run src/delegation/__tests__/vc-issuer.test.ts
|
|
318
|
+
npx vitest run src/delegation/__tests__/vc-verifier.test.ts
|
|
319
|
+
npx vitest run src/delegation/__tests__/delegation-graph.test.ts
|
|
320
|
+
npx vitest run src/delegation/__tests__/cascading-revocation.test.ts
|
|
321
|
+
npx vitest run src/delegation/__tests__/statuslist-manager.test.ts
|
|
322
|
+
npx vitest run src/delegation/__tests__/bitstring.test.ts
|
|
323
|
+
npx vitest run src/delegation/__tests__/outbound-proof.test.ts
|
|
324
|
+
npx vitest run src/delegation/__tests__/audience-validator.test.ts
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Test Coverage
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
# Run tests with coverage
|
|
331
|
+
pnpm test:coverage
|
|
332
|
+
|
|
333
|
+
# Or
|
|
334
|
+
npx vitest run --coverage
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
## Submitting Conformance Results
|
|
340
|
+
|
|
341
|
+
To submit conformance results for your implementation:
|
|
342
|
+
|
|
343
|
+
1. Fork the `kya-os-mcp` repository
|
|
344
|
+
2. Run the test suite against your implementation
|
|
345
|
+
3. Capture test output and coverage report
|
|
346
|
+
4. Open a GitHub issue at https://github.com/decentralized-identity/kya-os-mcp/issues with:
|
|
347
|
+
- Implementation name and version
|
|
348
|
+
- Target conformance level (1, 2, or 3)
|
|
349
|
+
- Test results (pass/fail counts)
|
|
350
|
+
- Coverage report
|
|
351
|
+
- Platform/runtime information
|
|
352
|
+
- Any deviations or extensions
|
|
353
|
+
|
|
354
|
+
### Issue Template
|
|
355
|
+
|
|
356
|
+
```markdown
|
|
357
|
+
## KYA-OS Conformance Submission
|
|
358
|
+
|
|
359
|
+
**Implementation**: [Name] v[Version]
|
|
360
|
+
**Conformance Level**: [1 | 2 | 3]
|
|
361
|
+
**Platform**: [Node.js 20.x | Cloudflare Workers | etc.]
|
|
362
|
+
|
|
363
|
+
### Test Results
|
|
364
|
+
|
|
365
|
+
- Total Tests: X
|
|
366
|
+
- Passed: X
|
|
367
|
+
- Failed: X
|
|
368
|
+
- Skipped: X
|
|
369
|
+
|
|
370
|
+
### Coverage
|
|
371
|
+
|
|
372
|
+
[Attach or link coverage report]
|
|
373
|
+
|
|
374
|
+
### Deviations
|
|
375
|
+
|
|
376
|
+
[List any deviations from the specification]
|
|
377
|
+
|
|
378
|
+
### Extensions
|
|
379
|
+
|
|
380
|
+
[List any extensions beyond the specification]
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
## Conformance Badges
|
|
386
|
+
|
|
387
|
+
Implementations that pass conformance testing may display badges:
|
|
388
|
+
|
|
389
|
+
- **KYA-OS Level 1 Conformant** — Core cryptographic operations
|
|
390
|
+
- **KYA-OS Level 2 Conformant** — Session management and proofs
|
|
391
|
+
- **KYA-OS Level 3 Conformant** — Full delegation support
|
|
392
|
+
|
|
393
|
+
Badge assets will be provided upon successful conformance submission.
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
397
|
+
## Independent Conformance Harness
|
|
398
|
+
|
|
399
|
+
The `conformance/` directory contains an **implementation-agnostic** test harness:
|
|
400
|
+
a set of versioned, pre-signed test vectors plus a runner that asserts a verifier
|
|
401
|
+
ACCEPTS every positive vector and REJECTS every negative one. It exercises the
|
|
402
|
+
protocol's **public** verify primitives — it does not fork verification logic — so
|
|
403
|
+
the reference implementation and any third-party implementation are held to the
|
|
404
|
+
exact same evidence.
|
|
405
|
+
|
|
406
|
+
### What it covers
|
|
407
|
+
|
|
408
|
+
Each vector is a self-contained JSON object — `{ id, category, description, input,
|
|
409
|
+
expected: "pass" | "fail", reason }` — and carries fully-formed signed artifacts
|
|
410
|
+
so it is reproducible against any implementation without re-signing.
|
|
411
|
+
|
|
412
|
+
| File | Category | Positive | Negative |
|
|
413
|
+
|------|----------|----------|----------|
|
|
414
|
+
| `vectors/signed-proof.json` | Detached proof verification | valid signature + in-window ts | tampered signature, tampered meta, wrong key, timestamp skew exceeded |
|
|
415
|
+
| `vectors/delegation-chain.json` | Delegation chain verification | single-hop, two-hop attenuated | broken issuer↔subject linkage, scope widening, tampered signature, audience mismatch |
|
|
416
|
+
| `vectors/status-list.json` | StatusList2021 revocation | active (bit unset) | revoked (bit set) |
|
|
417
|
+
| `vectors/did-key-resolution.json` | did:key resolution | valid Ed25519 | malformed multibase, wrong method |
|
|
418
|
+
| `vectors/did-web-resolution.json` | did:web resolution | well-formed id-matched document | document id mismatch, not found |
|
|
419
|
+
| `vectors/card-proof.json` | `org.kya-os/proof@1` holder-of-key proof | valid signed proof, in-window, audience-bound | tampered body, tampered signature, wrong audience, expired, kid⇄did forgery |
|
|
420
|
+
| `vectors/entity-card.json` | Entity Card `parseCard` + `verifyCard` | golden card per `entityType`, accountable agent | malformed (unknown field), broken accountability JOIN |
|
|
421
|
+
| `vectors/audit-integrity.json` | Audit JCS + domain-separated hashing + RFC 9162 | fixed Unicode event, leaf/root, inclusion and consistency paths | mutated event/proof relationships are exercised by the audit unit suites |
|
|
422
|
+
|
|
423
|
+
The first five categories exercise the **legacy** session-bound primitives; the
|
|
424
|
+
next two exercise the **Entity Card** layer (see the dedicated section below),
|
|
425
|
+
and `audit-integrity` provides language-neutral bytes and hashes for the audit
|
|
426
|
+
protocol.
|
|
427
|
+
|
|
428
|
+
A `fail` vector passes the suite only when the implementation correctly **rejects**
|
|
429
|
+
it. The runner exits non-zero on any mismatch.
|
|
430
|
+
|
|
431
|
+
### Running the reference implementation
|
|
432
|
+
|
|
433
|
+
```bash
|
|
434
|
+
pnpm install
|
|
435
|
+
pnpm run conformance # run all vectors, exit non-zero on any mismatch
|
|
436
|
+
pnpm run conformance -- --category signed-proof # one category
|
|
437
|
+
pnpm run conformance -- --json # machine-readable report
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
CI runs this on every push/PR (the **Protocol Conformance Harness** job).
|
|
441
|
+
|
|
442
|
+
### Regenerating the vectors
|
|
443
|
+
|
|
444
|
+
The committed JSON is produced from the reference primitives:
|
|
445
|
+
|
|
446
|
+
```bash
|
|
447
|
+
pnpm run conformance:generate
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
Re-running mints fresh keys but preserves every positive/negative relationship by
|
|
451
|
+
construction.
|
|
452
|
+
|
|
453
|
+
### Running the harness against YOUR implementation
|
|
454
|
+
|
|
455
|
+
The harness is decoupled from `@kya-os/mcp` through a single documented port,
|
|
456
|
+
`ConformanceAdapter` (`conformance/types.ts`). Implement its methods over your own
|
|
457
|
+
verifier and feed it the same vectors:
|
|
458
|
+
|
|
459
|
+
```ts
|
|
460
|
+
import { loadVectors } from "./conformance/loader.js";
|
|
461
|
+
import { runConformance, formatReport } from "./conformance/runner.js";
|
|
462
|
+
import type { ConformanceAdapter } from "./conformance/types.js";
|
|
463
|
+
|
|
464
|
+
const myAdapter: ConformanceAdapter = {
|
|
465
|
+
name: "my-implementation",
|
|
466
|
+
async verifySignedProof(input) { /* return { outcome: "pass" | "fail" } */ },
|
|
467
|
+
async verifyDelegationChain(input) { /* ... */ },
|
|
468
|
+
async verifyStatusList(input) { /* ... */ },
|
|
469
|
+
async resolveDidKey(input) { /* ... */ },
|
|
470
|
+
async resolveDidWeb(input) { /* ... */ },
|
|
471
|
+
async verifyCardProof(input) { /* org.kya-os/proof@1 holder-of-key proof */ },
|
|
472
|
+
async verifyEntityCard(input) { /* parseCard + verifyCard */ },
|
|
473
|
+
async verifyAuditIntegrity(input) { /* JCS event digest + RFC 9162 proofs */ },
|
|
474
|
+
};
|
|
475
|
+
|
|
476
|
+
const report = await runConformance(myAdapter, loadVectors());
|
|
477
|
+
console.log(formatReport(report));
|
|
478
|
+
process.exit(report.allMatched ? 0 : 1);
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
**Adapter contract.** Every method takes a vector's `input` and returns
|
|
482
|
+
`{ outcome: "pass" | "fail", detail? }`, where `pass` means your implementation
|
|
483
|
+
ACCEPTED the artifact and `fail` means it REJECTED it. Methods MUST be
|
|
484
|
+
**fail-closed**: any error, malformed input, or unmet security property maps to
|
|
485
|
+
`{ outcome: "fail" }` — never throw. The runner records a thrown error as a
|
|
486
|
+
harness failure, not a rejection. The reference adapter
|
|
487
|
+
(`conformance/reference-adapter.ts`) is the worked example wiring these methods to
|
|
488
|
+
the public `@kya-os/mcp` primitives.
|
|
489
|
+
|
|
490
|
+
### Audit Assurance Profile conformance
|
|
491
|
+
|
|
492
|
+
An AAP claim is broader than a single vector result. An implementation MUST pass
|
|
493
|
+
all lower profiles and MUST truthfully advertise only mechanics its configured
|
|
494
|
+
providers can supply:
|
|
495
|
+
|
|
496
|
+
| Profile | Required executable evidence |
|
|
497
|
+
|---------|------------------------------|
|
|
498
|
+
| AAP-0 | No auditability claim. |
|
|
499
|
+
| AAP-1 Recorded | Strict event schemas and typed lifecycle capture for the declared instrumentation surface. |
|
|
500
|
+
| AAP-2 Chained | AAP-1 plus durable non-best-effort delivery and the journal provider contract, including atomic stale-head rejection, global idempotency, and ordered snapshot reads. |
|
|
501
|
+
| AAP-3 Transparent | AAP-2 plus durable source reconciliation, checkpoint signing, RFC 9162 inclusion/consistency vectors, epoch continuity, and historical verification. |
|
|
502
|
+
| AAP-4 Observed | AAP-3 plus the observer provider contract, independent administration, checkpoint view comparison/fork detection, and authenticated supporting-anchor verification where claimed. |
|
|
503
|
+
|
|
504
|
+
Reference adapter authors can run the framework-neutral suites exported by
|
|
505
|
+
`@kya-os/mcp/audit/testing`. Passing the in-memory reference suite demonstrates
|
|
506
|
+
the contract; it is not evidence that a production datastore, KMS, or observer
|
|
507
|
+
deployment satisfies its operational durability or independence claims.
|
|
508
|
+
|
|
509
|
+
---
|
|
510
|
+
|
|
511
|
+
## Entity Card Conformance
|
|
512
|
+
|
|
513
|
+
The Entity Card is a **distinct, newer layer** on top of the Level 1–3 ladder above:
|
|
514
|
+
a typed, DID-anchored card plus a stateless, sender-constrained per-request proof.
|
|
515
|
+
It is orthogonal to the legacy session-bound proof — the two coexist, each under
|
|
516
|
+
its OWN distinct `_meta` key (`_meta['org.kya-os/proof']` for the legacy
|
|
517
|
+
session-bound proof, `_meta['org.kya-os/proof@1']` for the stateless card proof),
|
|
518
|
+
and each verifier reads its own key and ignores the other. Its
|
|
519
|
+
conformance vectors live in the SAME harness under two categories, wired to the two
|
|
520
|
+
adapter methods `verifyCardProof` and `verifyEntityCard`.
|
|
521
|
+
|
|
522
|
+
### `card-proof` — the `org.kya-os/proof@1` holder-of-key proof
|
|
523
|
+
|
|
524
|
+
`vectors/card-proof.json` carries fully-formed, pre-signed proofs. Each vector's
|
|
525
|
+
`input` is self-contained: the proof object, the `request` it binds, the DID-keyed
|
|
526
|
+
`jwks` the signing key resolves from, the verifier's `expectedAudience`, and a
|
|
527
|
+
pinned `nowMs`/`skewSeconds` window. A conformant `verifyCardProof` MUST recompute
|
|
528
|
+
**every** binding and fail closed on the first that does not hold:
|
|
529
|
+
|
|
530
|
+
| Vector | Expected | Property under test |
|
|
531
|
+
|--------|----------|---------------------|
|
|
532
|
+
| `card-proof/valid` | pass | signature + `requestHash` + `audience` + nonce + window + `kid`⇄`did` all hold |
|
|
533
|
+
| `card-proof/tampered-body` | fail | `requestHash` no longer recomputes to the signed value |
|
|
534
|
+
| `card-proof/tampered-signature` | fail | mutated detached-JWS signature fails EdDSA verification |
|
|
535
|
+
| `card-proof/wrong-audience` | fail | `audience` ≠ the verifier (anti-relay / confused-deputy) |
|
|
536
|
+
| `card-proof/expired` | fail | evaluated outside `created`/`expires` (±skew) — replay guard |
|
|
537
|
+
| `card-proof/kid-did-forgery` | fail | `kid.split('#')[0] !== did` — the forgeable-principal gap |
|
|
538
|
+
|
|
539
|
+
### `entity-card` — the typed card (`parseCard` + `verifyCard`)
|
|
540
|
+
|
|
541
|
+
`vectors/entity-card.json` ships the golden `parseCard`-valid card for each
|
|
542
|
+
`entityType` (`mcp` \| `agent` \| `client` \| `verifier` \| `human`), the accountable
|
|
543
|
+
agent card (whose `responsibleParty === issuer(rootVC)` and leaf-invoker === proof
|
|
544
|
+
`did` recompute over an embedded multi-hop VC 2.0 + ZCAP-LD chain), and negatives:
|
|
545
|
+
a malformed card (unknown top-level property → the strict schema rejects) and a
|
|
546
|
+
broken accountability JOIN (leaf-invoker ≠ the asserted proof `did`). A conformant
|
|
547
|
+
`verifyEntityCard` MUST reject a malformed card and MUST NOT trust the card's
|
|
548
|
+
self-declared `conformanceLevel` — it recomputes it.
|
|
549
|
+
|
|
550
|
+
### Card conformance ↔ the L1/L2/L3 ladder
|
|
551
|
+
|
|
552
|
+
The card's conformance level is **recomputed**, never trusted from the card. It maps
|
|
553
|
+
onto the same ladder:
|
|
554
|
+
|
|
555
|
+
- **L1** — the card parses (`parseCard`) and its DID + key are well-formed; capabilities
|
|
556
|
+
are self-declared (bare strings). The CIMD on-ramp (`client_id` ⇄ `did:web`) sits here.
|
|
557
|
+
- **L2** — every declared capability is attested (a verified `CapabilityAttestation`),
|
|
558
|
+
and, for a card carrying `responsibleParty`, the delegation/accountability edge verifies
|
|
559
|
+
offline (`responsibleParty === issuer(rootVC)`).
|
|
560
|
+
- **L3** — L2 **plus** a valid live holder-of-key proof (a passing `card-proof` vector)
|
|
561
|
+
bound to the request, fused with the token's RFC 9449 `cnf.jkt` (`L3`) or standalone
|
|
562
|
+
(`L3-minus`), and a fresh (live) revocation status. Any missing/expired/revoked artifact
|
|
563
|
+
demotes L3 → L2 → L1, fail-closed.
|
|
564
|
+
|
|
565
|
+
### Cross-language reference (`conformance/verify.py`)
|
|
566
|
+
|
|
567
|
+
`conformance/verify.py` is the **second-language complement** to the adapter contract:
|
|
568
|
+
a pure-Python-stdlib re-implementation that shares no code with the TypeScript
|
|
569
|
+
reference. It verifies the positive `org.kya-os/proof@1` vector and independently
|
|
570
|
+
re-derives the audit event's RFC 8785 bytes, domain-separated digest, RFC 9162
|
|
571
|
+
root, inclusion path, and consistency path. Ed25519 uses the RFC 8032 reference
|
|
572
|
+
without `pip install`.
|
|
573
|
+
|
|
574
|
+
```bash
|
|
575
|
+
python3 conformance/verify.py # npm run conformance:verify:crosslang
|
|
576
|
+
npm run conformance:generate:card # deterministically regenerate the card vectors
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
Expected output:
|
|
580
|
+
|
|
581
|
+
```
|
|
582
|
+
KYA-OS cross-language verifier (Python 3.x, stdlib-only)
|
|
583
|
+
proof: org.kya-os/proof@1 did: did:web:example.com:agents:acme-pay
|
|
584
|
+
[PASS] requestHash JCS+SHA-256 recompute
|
|
585
|
+
[PASS] detached EdDSA JWS over JCS(coveredClaims)
|
|
586
|
+
[PASS] RFC 9421 httpSig over the signature base
|
|
587
|
+
[PASS] RFC 7638 cnf.jkt thumbprint fusion
|
|
588
|
+
[PASS] audit event JCS canonical bytes
|
|
589
|
+
[PASS] domain-separated audit event digest
|
|
590
|
+
[PASS] RFC 9162 audit Merkle root
|
|
591
|
+
[PASS] RFC 9162 audit inclusion proof
|
|
592
|
+
[PASS] RFC 9162 audit consistency proof
|
|
593
|
+
RESULT: PASS — cross-language JCS + Ed25519 parity confirmed
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
---
|
|
597
|
+
|
|
598
|
+
*End of Conformance Requirements*
|