@kya-os/mcp-i-core 1.2.3-canary.6 → 1.3.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/.claude/settings.local.json +9 -0
- package/.turbo/turbo-build.log +4 -0
- package/.turbo/turbo-test$colon$coverage.log +4514 -0
- package/.turbo/turbo-test.log +2973 -0
- package/COMPLIANCE_IMPROVEMENT_REPORT.md +483 -0
- package/Composer 3.md +615 -0
- package/GPT-5.md +1169 -0
- package/OPUS-plan.md +352 -0
- package/PHASE_3_AND_4.1_SUMMARY.md +585 -0
- package/PHASE_3_SUMMARY.md +317 -0
- package/PHASE_4.1.3_SUMMARY.md +428 -0
- package/PHASE_4.1_COMPLETE.md +525 -0
- package/PHASE_4_USER_DID_IDENTITY_LINKING_PLAN.md +1240 -0
- package/SCHEMA_COMPLIANCE_REPORT.md +275 -0
- package/TEST_PLAN.md +571 -0
- package/coverage/coverage-final.json +57 -0
- package/dist/__tests__/utils/mock-providers.d.ts +1 -2
- package/dist/__tests__/utils/mock-providers.d.ts.map +1 -1
- package/dist/__tests__/utils/mock-providers.js.map +1 -1
- package/dist/cache/oauth-config-cache.d.ts +69 -0
- package/dist/cache/oauth-config-cache.d.ts.map +1 -0
- package/dist/cache/oauth-config-cache.js +76 -0
- package/dist/cache/oauth-config-cache.js.map +1 -0
- package/dist/identity/idp-token-resolver.d.ts +53 -0
- package/dist/identity/idp-token-resolver.d.ts.map +1 -0
- package/dist/identity/idp-token-resolver.js +108 -0
- package/dist/identity/idp-token-resolver.js.map +1 -0
- package/dist/identity/idp-token-storage.interface.d.ts +42 -0
- package/dist/identity/idp-token-storage.interface.d.ts.map +1 -0
- package/dist/identity/idp-token-storage.interface.js +12 -0
- package/dist/identity/idp-token-storage.interface.js.map +1 -0
- package/dist/identity/user-did-manager.d.ts +39 -1
- package/dist/identity/user-did-manager.d.ts.map +1 -1
- package/dist/identity/user-did-manager.js +69 -3
- package/dist/identity/user-did-manager.js.map +1 -1
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +39 -1
- package/dist/index.js.map +1 -1
- package/dist/runtime/audit-logger.d.ts +37 -0
- package/dist/runtime/audit-logger.d.ts.map +1 -0
- package/dist/runtime/audit-logger.js +9 -0
- package/dist/runtime/audit-logger.js.map +1 -0
- package/dist/runtime/base.d.ts +58 -2
- package/dist/runtime/base.d.ts.map +1 -1
- package/dist/runtime/base.js +266 -11
- package/dist/runtime/base.js.map +1 -1
- package/dist/services/access-control.service.d.ts.map +1 -1
- package/dist/services/access-control.service.js +200 -35
- package/dist/services/access-control.service.js.map +1 -1
- package/dist/services/authorization/authorization-registry.d.ts +29 -0
- package/dist/services/authorization/authorization-registry.d.ts.map +1 -0
- package/dist/services/authorization/authorization-registry.js +57 -0
- package/dist/services/authorization/authorization-registry.js.map +1 -0
- package/dist/services/authorization/types.d.ts +53 -0
- package/dist/services/authorization/types.d.ts.map +1 -0
- package/dist/services/authorization/types.js +10 -0
- package/dist/services/authorization/types.js.map +1 -0
- package/dist/services/batch-delegation.service.d.ts +53 -0
- package/dist/services/batch-delegation.service.d.ts.map +1 -0
- package/dist/services/batch-delegation.service.js +95 -0
- package/dist/services/batch-delegation.service.js.map +1 -0
- package/dist/services/oauth-config.service.d.ts +53 -0
- package/dist/services/oauth-config.service.d.ts.map +1 -0
- package/dist/services/oauth-config.service.js +117 -0
- package/dist/services/oauth-config.service.js.map +1 -0
- package/dist/services/oauth-provider-registry.d.ts +77 -0
- package/dist/services/oauth-provider-registry.d.ts.map +1 -0
- package/dist/services/oauth-provider-registry.js +112 -0
- package/dist/services/oauth-provider-registry.js.map +1 -0
- package/dist/services/oauth-service.d.ts +77 -0
- package/dist/services/oauth-service.d.ts.map +1 -0
- package/dist/services/oauth-service.js +348 -0
- package/dist/services/oauth-service.js.map +1 -0
- package/dist/services/oauth-token-retrieval.service.d.ts +49 -0
- package/dist/services/oauth-token-retrieval.service.d.ts.map +1 -0
- package/dist/services/oauth-token-retrieval.service.js +150 -0
- package/dist/services/oauth-token-retrieval.service.js.map +1 -0
- package/dist/services/provider-resolver.d.ts +48 -0
- package/dist/services/provider-resolver.d.ts.map +1 -0
- package/dist/services/provider-resolver.js +120 -0
- package/dist/services/provider-resolver.js.map +1 -0
- package/dist/services/provider-validator.d.ts +55 -0
- package/dist/services/provider-validator.d.ts.map +1 -0
- package/dist/services/provider-validator.js +135 -0
- package/dist/services/provider-validator.js.map +1 -0
- package/dist/services/tool-context-builder.d.ts +57 -0
- package/dist/services/tool-context-builder.d.ts.map +1 -0
- package/dist/services/tool-context-builder.js +125 -0
- package/dist/services/tool-context-builder.js.map +1 -0
- package/dist/services/tool-protection.service.d.ts +87 -10
- package/dist/services/tool-protection.service.d.ts.map +1 -1
- package/dist/services/tool-protection.service.js +282 -112
- package/dist/services/tool-protection.service.js.map +1 -1
- package/dist/types/oauth-required-error.d.ts +40 -0
- package/dist/types/oauth-required-error.d.ts.map +1 -0
- package/dist/types/oauth-required-error.js +40 -0
- package/dist/types/oauth-required-error.js.map +1 -0
- package/dist/utils/did-helpers.d.ts +33 -0
- package/dist/utils/did-helpers.d.ts.map +1 -1
- package/dist/utils/did-helpers.js +40 -0
- package/dist/utils/did-helpers.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/docs/API_REFERENCE.md +1362 -0
- package/docs/COMPLIANCE_MATRIX.md +691 -0
- package/docs/STATUSLIST2021_GUIDE.md +696 -0
- package/docs/W3C_VC_DELEGATION_GUIDE.md +710 -0
- package/package.json +24 -50
- package/scripts/audit-compliance.ts +724 -0
- package/src/__tests__/cache/tool-protection-cache.test.ts +640 -0
- package/src/__tests__/config/provider-runtime-config.test.ts +309 -0
- package/src/__tests__/delegation-e2e.test.ts +690 -0
- package/src/__tests__/identity/user-did-manager.test.ts +213 -0
- package/src/__tests__/index.test.ts +56 -0
- package/src/__tests__/integration/full-flow.test.ts +776 -0
- package/src/__tests__/integration.test.ts +281 -0
- package/src/__tests__/providers/base.test.ts +173 -0
- package/src/__tests__/providers/memory.test.ts +319 -0
- package/src/__tests__/regression/phase2-regression.test.ts +427 -0
- package/src/__tests__/runtime/audit-logger.test.ts +154 -0
- package/src/__tests__/runtime/base-extensions.test.ts +593 -0
- package/src/__tests__/runtime/base.test.ts +869 -0
- package/src/__tests__/runtime/delegation-flow.test.ts +164 -0
- package/src/__tests__/runtime/proof-client-did.test.ts +375 -0
- package/src/__tests__/runtime/route-interception.test.ts +686 -0
- package/src/__tests__/runtime/tool-protection-enforcement.test.ts +908 -0
- package/src/__tests__/services/agentshield-integration.test.ts +784 -0
- package/src/__tests__/services/provider-resolver-edge-cases.test.ts +487 -0
- package/src/__tests__/services/tool-protection-oauth-provider.test.ts +480 -0
- package/src/__tests__/services/tool-protection.service.test.ts +1366 -0
- package/src/__tests__/utils/mock-providers.ts +340 -0
- package/src/cache/oauth-config-cache.d.ts +69 -0
- package/src/cache/oauth-config-cache.d.ts.map +1 -0
- package/src/cache/oauth-config-cache.js +71 -0
- package/src/cache/oauth-config-cache.js.map +1 -0
- package/src/cache/oauth-config-cache.ts +123 -0
- package/src/cache/tool-protection-cache.ts +171 -0
- package/src/compliance/EXAMPLE.md +412 -0
- package/src/compliance/__tests__/schema-verifier.test.ts +797 -0
- package/src/compliance/index.ts +8 -0
- package/src/compliance/schema-registry.ts +460 -0
- package/src/compliance/schema-verifier.ts +708 -0
- package/src/config/__tests__/remote-config.spec.ts +268 -0
- package/src/config/remote-config.ts +174 -0
- package/src/config.ts +309 -0
- package/src/delegation/__tests__/audience-validator.test.ts +112 -0
- package/src/delegation/__tests__/bitstring.test.ts +346 -0
- package/src/delegation/__tests__/cascading-revocation.test.ts +628 -0
- package/src/delegation/__tests__/delegation-graph.test.ts +584 -0
- package/src/delegation/__tests__/utils.test.ts +152 -0
- package/src/delegation/__tests__/vc-issuer.test.ts +442 -0
- package/src/delegation/__tests__/vc-verifier.test.ts +922 -0
- package/src/delegation/audience-validator.ts +52 -0
- package/src/delegation/bitstring.ts +278 -0
- package/src/delegation/cascading-revocation.ts +370 -0
- package/src/delegation/delegation-graph.ts +299 -0
- package/src/delegation/index.ts +14 -0
- package/src/delegation/statuslist-manager.ts +353 -0
- package/src/delegation/storage/__tests__/memory-graph-storage.test.ts +366 -0
- package/src/delegation/storage/__tests__/memory-statuslist-storage.test.ts +228 -0
- package/src/delegation/storage/index.ts +9 -0
- package/src/delegation/storage/memory-graph-storage.ts +178 -0
- package/src/delegation/storage/memory-statuslist-storage.ts +77 -0
- package/src/delegation/utils.ts +42 -0
- package/src/delegation/vc-issuer.ts +232 -0
- package/src/delegation/vc-verifier.ts +568 -0
- package/src/identity/idp-token-resolver.ts +147 -0
- package/src/identity/idp-token-storage.interface.ts +59 -0
- package/src/identity/user-did-manager.ts +370 -0
- package/src/index.ts +260 -0
- package/src/providers/base.d.ts +91 -0
- package/src/providers/base.d.ts.map +1 -0
- package/src/providers/base.js +38 -0
- package/src/providers/base.js.map +1 -0
- package/src/providers/base.ts +96 -0
- package/src/providers/memory.ts +142 -0
- package/src/runtime/audit-logger.ts +39 -0
- package/src/runtime/base.ts +1329 -0
- package/src/services/__tests__/access-control.integration.test.ts +443 -0
- package/src/services/__tests__/access-control.proof-response-validation.test.ts +578 -0
- package/src/services/__tests__/access-control.service.test.ts +970 -0
- package/src/services/__tests__/batch-delegation.service.test.ts +351 -0
- package/src/services/__tests__/crypto.service.test.ts +531 -0
- package/src/services/__tests__/oauth-provider-registry.test.ts +142 -0
- package/src/services/__tests__/proof-verifier.integration.test.ts +485 -0
- package/src/services/__tests__/proof-verifier.test.ts +489 -0
- package/src/services/__tests__/provider-resolution.integration.test.ts +198 -0
- package/src/services/__tests__/provider-resolver.test.ts +217 -0
- package/src/services/__tests__/storage.service.test.ts +358 -0
- package/src/services/access-control.service.ts +990 -0
- package/src/services/authorization/authorization-registry.ts +66 -0
- package/src/services/authorization/types.ts +71 -0
- package/src/services/batch-delegation.service.ts +137 -0
- package/src/services/crypto.service.ts +302 -0
- package/src/services/errors.ts +76 -0
- package/src/services/index.ts +9 -0
- package/src/services/oauth-config.service.d.ts +53 -0
- package/src/services/oauth-config.service.d.ts.map +1 -0
- package/src/services/oauth-config.service.js +113 -0
- package/src/services/oauth-config.service.js.map +1 -0
- package/src/services/oauth-config.service.ts +166 -0
- package/src/services/oauth-provider-registry.d.ts +57 -0
- package/src/services/oauth-provider-registry.d.ts.map +1 -0
- package/src/services/oauth-provider-registry.js +73 -0
- package/src/services/oauth-provider-registry.js.map +1 -0
- package/src/services/oauth-provider-registry.ts +123 -0
- package/src/services/oauth-service.ts +510 -0
- package/src/services/oauth-token-retrieval.service.ts +245 -0
- package/src/services/proof-verifier.ts +478 -0
- package/src/services/provider-resolver.d.ts +48 -0
- package/src/services/provider-resolver.d.ts.map +1 -0
- package/src/services/provider-resolver.js +106 -0
- package/src/services/provider-resolver.js.map +1 -0
- package/src/services/provider-resolver.ts +144 -0
- package/src/services/provider-validator.ts +170 -0
- package/src/services/storage.service.ts +566 -0
- package/src/services/tool-context-builder.ts +172 -0
- package/src/services/tool-protection.service.ts +958 -0
- package/src/types/oauth-required-error.ts +63 -0
- package/src/types/tool-protection.ts +155 -0
- package/src/utils/__tests__/did-helpers.test.ts +101 -0
- package/src/utils/base64.ts +148 -0
- package/src/utils/cors.ts +83 -0
- package/src/utils/did-helpers.ts +150 -0
- package/src/utils/index.ts +8 -0
- package/src/utils/storage-keys.ts +278 -0
- package/tsconfig.json +21 -0
- package/vitest.config.ts +56 -0
|
@@ -0,0 +1,696 @@
|
|
|
1
|
+
# StatusList2021 Revocation Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
StatusList2021 is a W3C standard for efficient, privacy-preserving credential revocation. It uses bitstring compression to enable scalable revocation checking with minimal bandwidth and storage requirements.
|
|
6
|
+
|
|
7
|
+
**Key Benefits:**
|
|
8
|
+
- **Efficient**: 131,072 credentials in ~16KB compressed bitstring
|
|
9
|
+
- **Privacy-Preserving**: Correlates less than individual revocation lists
|
|
10
|
+
- **Scalable**: Single HTTP request to check any credential status
|
|
11
|
+
- **Batch Updates**: Update multiple credential statuses atomically
|
|
12
|
+
|
|
13
|
+
## How It Works
|
|
14
|
+
|
|
15
|
+
### Bitstring Compression
|
|
16
|
+
|
|
17
|
+
StatusList2021 uses a compressed bitstring where each credential gets assigned an index:
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
Bit Position: 0 1 2 3 4 5 6 7 ... 131071
|
|
21
|
+
Status: 0 1 0 0 1 0 0 0 ... 1
|
|
22
|
+
↑ ↑ ↑ ↑ ↑
|
|
23
|
+
OK REV OK OK REV
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
- **0** = Credential is valid
|
|
27
|
+
- **1** = Credential is revoked
|
|
28
|
+
|
|
29
|
+
The bitstring is GZIP-compressed and encoded as base64, reducing ~16KB uncompressed to ~2-4KB compressed.
|
|
30
|
+
|
|
31
|
+
### Performance Characteristics
|
|
32
|
+
|
|
33
|
+
| Credential Count | Uncompressed Size | Compressed Size | HTTP Transfer |
|
|
34
|
+
|-----------------|-------------------|-----------------|---------------|
|
|
35
|
+
| 10,000 | ~1.2 KB | ~400 bytes | <1ms |
|
|
36
|
+
| 100,000 | ~12 KB | ~2 KB | ~5ms |
|
|
37
|
+
| 131,072 (max) | ~16 KB | ~4 KB | ~10ms |
|
|
38
|
+
|
|
39
|
+
**Comparison to Individual Revocation Lists:**
|
|
40
|
+
- Individual lists: N credentials = N HTTP requests
|
|
41
|
+
- StatusList2021: N credentials = 1 HTTP request
|
|
42
|
+
|
|
43
|
+
## Architecture
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
47
|
+
│ Issuer System │
|
|
48
|
+
├─────────────────────────────────────────────────────────────┤
|
|
49
|
+
│ │
|
|
50
|
+
│ ┌──────────────┐ ┌─────────────────┐ │
|
|
51
|
+
│ │ Delegation │────────▶│ StatusList2021 │ │
|
|
52
|
+
│ │ Credential │ │ Manager │ │
|
|
53
|
+
│ └──────────────┘ └─────────────────┘ │
|
|
54
|
+
│ │ │ │
|
|
55
|
+
│ │ ▼ │
|
|
56
|
+
│ │ ┌──────────────┐ │
|
|
57
|
+
│ │ │ Bitstring │ │
|
|
58
|
+
│ │ │ Storage │ │
|
|
59
|
+
│ │ │ (Redis/DB) │ │
|
|
60
|
+
│ │ └──────────────┘ │
|
|
61
|
+
│ │ │ │
|
|
62
|
+
│ │ ▼ │
|
|
63
|
+
│ │ ┌──────────────┐ │
|
|
64
|
+
│ │ │ Status List │ │
|
|
65
|
+
│ │ │ VC Document │ │
|
|
66
|
+
│ │ └──────────────┘ │
|
|
67
|
+
│ │ │ │
|
|
68
|
+
│ └──────────────────────────┼─────────────────────────┘
|
|
69
|
+
│ │
|
|
70
|
+
│ ▼
|
|
71
|
+
│ [Public HTTPS URL]
|
|
72
|
+
│ https://issuer.com/status/1
|
|
73
|
+
│ │
|
|
74
|
+
├────────────────────────────────────┼─────────────────────────┐
|
|
75
|
+
│ │ │
|
|
76
|
+
│ Verifier System │ │
|
|
77
|
+
│ ▼ │
|
|
78
|
+
│ ┌──────────────────┐ │
|
|
79
|
+
│ │ StatusList2021 │ │
|
|
80
|
+
│ │ Verifier │ │
|
|
81
|
+
│ └──────────────────┘ │
|
|
82
|
+
│ │ │
|
|
83
|
+
│ ▼ │
|
|
84
|
+
│ [Check Status] │
|
|
85
|
+
│ Valid ✓ or Revoked ✗ │
|
|
86
|
+
└───────────────────────────────────────────────────────────────┘
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Basic Usage
|
|
90
|
+
|
|
91
|
+
### 1. Creating a Status List
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
import { StatusList2021Manager } from '@kya-os/mcp-i-core';
|
|
95
|
+
|
|
96
|
+
// Initialize manager
|
|
97
|
+
const statusListManager = new StatusList2021Manager({
|
|
98
|
+
issuerDid: 'did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK',
|
|
99
|
+
statusListUrl: 'https://issuer.example.com/status/1',
|
|
100
|
+
storage: myStorageProvider, // Redis, DynamoDB, etc.
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// Create a new status list
|
|
104
|
+
const statusListVC = await statusListManager.createStatusList({
|
|
105
|
+
id: 'https://issuer.example.com/status/1',
|
|
106
|
+
purpose: 'revocation',
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
console.log(statusListVC);
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Output:**
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"@context": [
|
|
116
|
+
"https://www.w3.org/2018/credentials/v1",
|
|
117
|
+
"https://w3id.org/vc/status-list/2021/v1"
|
|
118
|
+
],
|
|
119
|
+
"id": "https://issuer.example.com/status/1",
|
|
120
|
+
"type": ["VerifiableCredential", "StatusList2021Credential"],
|
|
121
|
+
"issuer": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
|
|
122
|
+
"issuanceDate": "2025-10-17T12:00:00Z",
|
|
123
|
+
"credentialSubject": {
|
|
124
|
+
"id": "https://issuer.example.com/status/1#list",
|
|
125
|
+
"type": "StatusList2021",
|
|
126
|
+
"statusPurpose": "revocation",
|
|
127
|
+
"encodedList": "H4sIAAAAAAAAA+3BMQEAAADCoPVPbQwfoAAAAAAAAAAAAAAAAAAAAIC3AYbSVKsAQAAA"
|
|
128
|
+
},
|
|
129
|
+
"proof": {
|
|
130
|
+
"type": "Ed25519Signature2020",
|
|
131
|
+
"created": "2025-10-17T12:00:00Z",
|
|
132
|
+
"verificationMethod": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK#z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
|
|
133
|
+
"proofPurpose": "assertionMethod",
|
|
134
|
+
"proofValue": "z58DAdFfa9SkqZMVPxAQpic7ndSayn1PzZs6ZjWp1CktyGesjuTSwRdoWhAfGFCF5bppETSTojQCrfFPP2oumHKtz"
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### 2. Issuing Credentials with Status
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
import { DelegationIssuer } from '@kya-os/mcp-i-core';
|
|
143
|
+
|
|
144
|
+
const issuer = new DelegationIssuer({
|
|
145
|
+
issuerDid: 'did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK',
|
|
146
|
+
privateKeyJwk: issuerPrivateKey,
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// Allocate a status list index for this credential
|
|
150
|
+
const statusListIndex = await statusListManager.allocateIndex();
|
|
151
|
+
|
|
152
|
+
const delegation = await issuer.issue({
|
|
153
|
+
subjectDid: 'did:key:z6MkrWXJPkxPCuQF7RqeKZFdZqBXz3oCG7PUty5dXLKGzELj',
|
|
154
|
+
constraints: {
|
|
155
|
+
scope: {
|
|
156
|
+
allowedTools: ['read_file', 'list_directory'],
|
|
157
|
+
allowedResources: ['/documents/*'],
|
|
158
|
+
},
|
|
159
|
+
time: {
|
|
160
|
+
notBefore: new Date().toISOString(),
|
|
161
|
+
notAfter: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
credentialStatus: {
|
|
165
|
+
id: `https://issuer.example.com/status/1#${statusListIndex}`,
|
|
166
|
+
type: 'StatusList2021Entry',
|
|
167
|
+
statusPurpose: 'revocation',
|
|
168
|
+
statusListIndex: statusListIndex.toString(),
|
|
169
|
+
statusListCredential: 'https://issuer.example.com/status/1',
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
console.log('Issued delegation with status index:', statusListIndex);
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### 3. Revoking a Credential
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
// Revoke a credential by its status list index
|
|
180
|
+
await statusListManager.revokeCredential(statusListIndex);
|
|
181
|
+
|
|
182
|
+
console.log(`Credential at index ${statusListIndex} has been revoked`);
|
|
183
|
+
|
|
184
|
+
// The status list VC is automatically updated and republished
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### 4. Checking Credential Status
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
import { verifyDelegation } from '@kya-os/mcp-i-core';
|
|
191
|
+
|
|
192
|
+
const result = await verifyDelegation({
|
|
193
|
+
credential: delegation,
|
|
194
|
+
expectedAudience: 'https://api.example.com',
|
|
195
|
+
checkStatus: true, // Enable status checking
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
if (!result.verified) {
|
|
199
|
+
console.error('Verification failed:', result.error);
|
|
200
|
+
if (result.statusRevoked) {
|
|
201
|
+
console.error('Credential has been revoked!');
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Integration with Delegation Credentials
|
|
207
|
+
|
|
208
|
+
### Credential Structure
|
|
209
|
+
|
|
210
|
+
When a delegation credential includes status checking, it has a `credentialStatus` field:
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
{
|
|
214
|
+
"@context": [
|
|
215
|
+
"https://www.w3.org/2018/credentials/v1",
|
|
216
|
+
"https://w3id.org/security/suites/ed25519-2020/v1",
|
|
217
|
+
"https://w3id.org/vc/status-list/2021/v1",
|
|
218
|
+
"https://schemas.kya-os.ai/delegation/v1"
|
|
219
|
+
],
|
|
220
|
+
"id": "urn:uuid:12345678-1234-1234-1234-123456789abc",
|
|
221
|
+
"type": ["VerifiableCredential", "DelegationCredential"],
|
|
222
|
+
"issuer": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
|
|
223
|
+
"issuanceDate": "2025-10-17T12:00:00Z",
|
|
224
|
+
"credentialSubject": {
|
|
225
|
+
"id": "did:key:z6MkrWXJPkxPCuQF7RqeKZFdZqBXz3oCG7PUty5dXLKGzELj",
|
|
226
|
+
"constraints": {
|
|
227
|
+
"scope": {
|
|
228
|
+
"allowedTools": ["read_file"],
|
|
229
|
+
"allowedResources": ["/documents/*"]
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
"credentialStatus": {
|
|
234
|
+
"id": "https://issuer.example.com/status/1#42",
|
|
235
|
+
"type": "StatusList2021Entry",
|
|
236
|
+
"statusPurpose": "revocation",
|
|
237
|
+
"statusListIndex": "42",
|
|
238
|
+
"statusListCredential": "https://issuer.example.com/status/1"
|
|
239
|
+
},
|
|
240
|
+
"proof": { ... }
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Verification Flow
|
|
245
|
+
|
|
246
|
+
```
|
|
247
|
+
┌──────────────┐
|
|
248
|
+
│ Verifier │
|
|
249
|
+
│ receives │
|
|
250
|
+
│ delegation │
|
|
251
|
+
└──────┬───────┘
|
|
252
|
+
│
|
|
253
|
+
▼
|
|
254
|
+
┌─────────────────────┐
|
|
255
|
+
│ Parse credential │
|
|
256
|
+
│ status field │
|
|
257
|
+
└─────────┬───────────┘
|
|
258
|
+
│
|
|
259
|
+
▼
|
|
260
|
+
┌─────────────────────────────┐
|
|
261
|
+
│ Fetch StatusList2021 │
|
|
262
|
+
│ from statusListCredential │
|
|
263
|
+
└─────────┬───────────────────┘
|
|
264
|
+
│
|
|
265
|
+
▼
|
|
266
|
+
┌─────────────────────────────┐
|
|
267
|
+
│ Decompress encodedList │
|
|
268
|
+
└─────────┬───────────────────┘
|
|
269
|
+
│
|
|
270
|
+
▼
|
|
271
|
+
┌─────────────────────────────┐
|
|
272
|
+
│ Check bit at │
|
|
273
|
+
│ statusListIndex │
|
|
274
|
+
└─────────┬───────────────────┘
|
|
275
|
+
│
|
|
276
|
+
├──────────┐
|
|
277
|
+
│ │
|
|
278
|
+
▼ ▼
|
|
279
|
+
┌─────┐ ┌─────────┐
|
|
280
|
+
│ 0 │ │ 1 │
|
|
281
|
+
│ ✓ │ │ ✗ │
|
|
282
|
+
└─────┘ └─────────┘
|
|
283
|
+
Valid Revoked
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## Cascading Revocation
|
|
287
|
+
|
|
288
|
+
When you revoke a parent delegation, all child delegations should also be revoked. The framework handles this automatically:
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
import { DelegationGraph } from '@kya-os/mcp-i-core';
|
|
292
|
+
|
|
293
|
+
// Build delegation graph
|
|
294
|
+
const graph = new DelegationGraph();
|
|
295
|
+
await graph.addDelegation(parentDelegation);
|
|
296
|
+
await graph.addDelegation(childDelegation1);
|
|
297
|
+
await graph.addDelegation(childDelegation2);
|
|
298
|
+
|
|
299
|
+
// Revoke parent and all children
|
|
300
|
+
await graph.revokeDelegation(
|
|
301
|
+
parentDelegation.id,
|
|
302
|
+
statusListManager,
|
|
303
|
+
{ cascade: true }
|
|
304
|
+
);
|
|
305
|
+
|
|
306
|
+
console.log('Parent and all children revoked');
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
**Revocation Process:**
|
|
310
|
+
```
|
|
311
|
+
Parent (index: 42)
|
|
312
|
+
├─ Child 1 (index: 100)
|
|
313
|
+
│ └─ Grandchild (index: 200)
|
|
314
|
+
└─ Child 2 (index: 150)
|
|
315
|
+
|
|
316
|
+
Revoke parent → cascade = true
|
|
317
|
+
→ Set bit 42 to 1
|
|
318
|
+
→ Set bit 100 to 1
|
|
319
|
+
→ Set bit 200 to 1
|
|
320
|
+
→ Set bit 150 to 1
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
## Storage Providers
|
|
324
|
+
|
|
325
|
+
### In-Memory Storage (Development)
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
import { InMemoryStatusListStorage } from '@kya-os/mcp-i-core';
|
|
329
|
+
|
|
330
|
+
const storage = new InMemoryStatusListStorage();
|
|
331
|
+
|
|
332
|
+
const manager = new StatusList2021Manager({
|
|
333
|
+
issuerDid: myDid,
|
|
334
|
+
statusListUrl: 'https://issuer.example.com/status/1',
|
|
335
|
+
storage,
|
|
336
|
+
});
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Redis Storage (Production)
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
import { RedisStatusListStorage } from '@kya-os/mcp-i-core';
|
|
343
|
+
import Redis from 'ioredis';
|
|
344
|
+
|
|
345
|
+
const redis = new Redis(process.env.REDIS_URL);
|
|
346
|
+
|
|
347
|
+
const storage = new RedisStatusListStorage({
|
|
348
|
+
client: redis,
|
|
349
|
+
keyPrefix: 'statuslist:',
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
const manager = new StatusList2021Manager({
|
|
353
|
+
issuerDid: myDid,
|
|
354
|
+
statusListUrl: 'https://issuer.example.com/status/1',
|
|
355
|
+
storage,
|
|
356
|
+
});
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
### DynamoDB Storage (AWS)
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
import { DynamoDBStatusListStorage } from '@kya-os/mcp-i-core';
|
|
363
|
+
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
|
|
364
|
+
|
|
365
|
+
const dynamodb = new DynamoDBClient({ region: 'us-east-1' });
|
|
366
|
+
|
|
367
|
+
const storage = new DynamoDBStatusListStorage({
|
|
368
|
+
client: dynamodb,
|
|
369
|
+
tableName: 'StatusLists',
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
const manager = new StatusList2021Manager({
|
|
373
|
+
issuerDid: myDid,
|
|
374
|
+
statusListUrl: 'https://issuer.example.com/status/1',
|
|
375
|
+
storage,
|
|
376
|
+
});
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
## Privacy Considerations
|
|
380
|
+
|
|
381
|
+
### Correlation Attacks
|
|
382
|
+
|
|
383
|
+
**Problem:** If each credential has its own revocation endpoint, tracking which endpoints are checked reveals which credentials are being verified.
|
|
384
|
+
|
|
385
|
+
**Solution:** StatusList2021 groups many credentials into a single list. Verifiers fetch the entire list, making it harder to correlate checks with specific credentials.
|
|
386
|
+
|
|
387
|
+
```
|
|
388
|
+
Bad (Individual Lists):
|
|
389
|
+
- Verifier checks https://issuer.com/revoke/alice-credential
|
|
390
|
+
→ Issuer knows Alice's credential is being used
|
|
391
|
+
|
|
392
|
+
Good (StatusList2021):
|
|
393
|
+
- Verifier checks https://issuer.com/status/1
|
|
394
|
+
→ Issuer knows someone is using a credential from this list (could be any of 100k+)
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
### Herd Privacy
|
|
398
|
+
|
|
399
|
+
The larger the status list, the better the privacy:
|
|
400
|
+
|
|
401
|
+
| List Size | Privacy Level |
|
|
402
|
+
|-----------|----------------------------|
|
|
403
|
+
| 100 | Low (1% of list) |
|
|
404
|
+
| 1,000 | Medium (0.1% of list) |
|
|
405
|
+
| 10,000 | Good (0.01% of list) |
|
|
406
|
+
| 100,000+ | Excellent (0.001% of list) |
|
|
407
|
+
|
|
408
|
+
**Best Practice:** Use large status lists (50k-100k credentials per list) to maximize herd privacy.
|
|
409
|
+
|
|
410
|
+
## Advanced Patterns
|
|
411
|
+
|
|
412
|
+
### Multiple Status Lists
|
|
413
|
+
|
|
414
|
+
For different purposes or to manage scale:
|
|
415
|
+
|
|
416
|
+
```typescript
|
|
417
|
+
// Separate lists by purpose
|
|
418
|
+
const revocationList = await manager.createStatusList({
|
|
419
|
+
id: 'https://issuer.example.com/status/revocation/1',
|
|
420
|
+
purpose: 'revocation',
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
const suspensionList = await manager.createStatusList({
|
|
424
|
+
id: 'https://issuer.example.com/status/suspension/1',
|
|
425
|
+
purpose: 'suspension',
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
// Separate lists by tenant
|
|
429
|
+
const tenantAList = await manager.createStatusList({
|
|
430
|
+
id: 'https://issuer.example.com/status/tenant-a/1',
|
|
431
|
+
purpose: 'revocation',
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
const tenantBList = await manager.createStatusList({
|
|
435
|
+
id: 'https://issuer.example.com/status/tenant-b/1',
|
|
436
|
+
purpose: 'revocation',
|
|
437
|
+
});
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
### Batch Revocation
|
|
441
|
+
|
|
442
|
+
Revoke multiple credentials atomically:
|
|
443
|
+
|
|
444
|
+
```typescript
|
|
445
|
+
await statusListManager.batchRevoke([
|
|
446
|
+
42, // credential 1
|
|
447
|
+
100, // credential 2
|
|
448
|
+
250, // credential 3
|
|
449
|
+
1337, // credential 4
|
|
450
|
+
]);
|
|
451
|
+
|
|
452
|
+
console.log('4 credentials revoked in single atomic update');
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
### Caching Status Lists
|
|
456
|
+
|
|
457
|
+
Verifiers should cache status lists with appropriate TTLs:
|
|
458
|
+
|
|
459
|
+
```typescript
|
|
460
|
+
import { CachedStatusListVerifier } from '@kya-os/mcp-i-core';
|
|
461
|
+
|
|
462
|
+
const verifier = new CachedStatusListVerifier({
|
|
463
|
+
cache: {
|
|
464
|
+
ttl: 300, // 5 minutes
|
|
465
|
+
maxSize: 100, // Cache up to 100 status lists
|
|
466
|
+
},
|
|
467
|
+
httpClient: fetch,
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
// First check: fetches from network
|
|
471
|
+
await verifier.checkStatus(credential1);
|
|
472
|
+
|
|
473
|
+
// Second check within TTL: uses cache
|
|
474
|
+
await verifier.checkStatus(credential2);
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
### Status List Rotation
|
|
478
|
+
|
|
479
|
+
Rotate status lists periodically to limit size:
|
|
480
|
+
|
|
481
|
+
```typescript
|
|
482
|
+
// Create new status list
|
|
483
|
+
const newList = await manager.createStatusList({
|
|
484
|
+
id: 'https://issuer.example.com/status/2',
|
|
485
|
+
purpose: 'revocation',
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
// Migrate new credentials to new list
|
|
489
|
+
const newIndex = await newListManager.allocateIndex();
|
|
490
|
+
|
|
491
|
+
// Archive old list (keep accessible for verification)
|
|
492
|
+
await manager.archiveStatusList('https://issuer.example.com/status/1');
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
## Best Practices
|
|
496
|
+
|
|
497
|
+
### 1. Index Allocation
|
|
498
|
+
|
|
499
|
+
Always allocate indexes sequentially to maximize compression:
|
|
500
|
+
|
|
501
|
+
```typescript
|
|
502
|
+
// Good: Sequential allocation
|
|
503
|
+
const index1 = await manager.allocateIndex(); // 0
|
|
504
|
+
const index2 = await manager.allocateIndex(); // 1
|
|
505
|
+
const index3 = await manager.allocateIndex(); // 2
|
|
506
|
+
|
|
507
|
+
// Bad: Random allocation
|
|
508
|
+
const index = Math.floor(Math.random() * 131072); // Sparse bitstring, poor compression
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
### 2. Status List Size
|
|
512
|
+
|
|
513
|
+
Choose appropriate status list sizes:
|
|
514
|
+
|
|
515
|
+
```typescript
|
|
516
|
+
// Small issuer (<10k credentials): Single list
|
|
517
|
+
const singleList = {
|
|
518
|
+
id: 'https://issuer.example.com/status/1',
|
|
519
|
+
purpose: 'revocation',
|
|
520
|
+
};
|
|
521
|
+
|
|
522
|
+
// Medium issuer (10k-100k): List per purpose
|
|
523
|
+
const revocationList = {
|
|
524
|
+
id: 'https://issuer.example.com/status/revocation/1',
|
|
525
|
+
purpose: 'revocation',
|
|
526
|
+
};
|
|
527
|
+
|
|
528
|
+
// Large issuer (>100k): Sharded lists
|
|
529
|
+
const lists = [
|
|
530
|
+
'https://issuer.example.com/status/1',
|
|
531
|
+
'https://issuer.example.com/status/2',
|
|
532
|
+
'https://issuer.example.com/status/3',
|
|
533
|
+
];
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
### 3. Verification Caching
|
|
537
|
+
|
|
538
|
+
Cache status list fetches to reduce network overhead:
|
|
539
|
+
|
|
540
|
+
```typescript
|
|
541
|
+
const verifier = new CachedStatusListVerifier({
|
|
542
|
+
cache: {
|
|
543
|
+
ttl: 300, // 5 min for high-security
|
|
544
|
+
// ttl: 3600, // 1 hour for lower-security
|
|
545
|
+
maxSize: 100,
|
|
546
|
+
},
|
|
547
|
+
});
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
### 4. Error Handling
|
|
551
|
+
|
|
552
|
+
Handle status checking failures gracefully:
|
|
553
|
+
|
|
554
|
+
```typescript
|
|
555
|
+
try {
|
|
556
|
+
const result = await verifyDelegation({
|
|
557
|
+
credential: delegation,
|
|
558
|
+
checkStatus: true,
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
if (!result.verified) {
|
|
562
|
+
if (result.statusRevoked) {
|
|
563
|
+
throw new Error('Credential revoked');
|
|
564
|
+
}
|
|
565
|
+
throw new Error(`Verification failed: ${result.error}`);
|
|
566
|
+
}
|
|
567
|
+
} catch (error) {
|
|
568
|
+
if (error.code === 'STATUS_LIST_UNAVAILABLE') {
|
|
569
|
+
// Status list endpoint down
|
|
570
|
+
// Decision: Accept credential or reject?
|
|
571
|
+
logger.warn('Status list unavailable, allowing credential');
|
|
572
|
+
} else {
|
|
573
|
+
throw error;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
### 5. Monitoring
|
|
579
|
+
|
|
580
|
+
Monitor status list health:
|
|
581
|
+
|
|
582
|
+
```typescript
|
|
583
|
+
const metrics = await manager.getMetrics();
|
|
584
|
+
|
|
585
|
+
console.log({
|
|
586
|
+
totalCredentials: metrics.allocatedIndexes,
|
|
587
|
+
revokedCredentials: metrics.revokedCount,
|
|
588
|
+
revocationRate: metrics.revokedCount / metrics.allocatedIndexes,
|
|
589
|
+
listSizeBytes: metrics.compressedSize,
|
|
590
|
+
compressionRatio: metrics.uncompressedSize / metrics.compressedSize,
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
// Alert if revocation rate is suspiciously high
|
|
594
|
+
if (metrics.revocationRate > 0.5) {
|
|
595
|
+
logger.alert('High revocation rate detected!');
|
|
596
|
+
}
|
|
597
|
+
```
|
|
598
|
+
|
|
599
|
+
## Complete Working Example
|
|
600
|
+
|
|
601
|
+
```typescript
|
|
602
|
+
import {
|
|
603
|
+
StatusList2021Manager,
|
|
604
|
+
InMemoryStatusListStorage,
|
|
605
|
+
DelegationIssuer,
|
|
606
|
+
verifyDelegation,
|
|
607
|
+
} from '@kya-os/mcp-i-core';
|
|
608
|
+
|
|
609
|
+
async function main() {
|
|
610
|
+
// 1. Setup issuer
|
|
611
|
+
const issuerDid = 'did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK';
|
|
612
|
+
const statusListUrl = 'https://issuer.example.com/status/1';
|
|
613
|
+
|
|
614
|
+
// 2. Create status list manager
|
|
615
|
+
const storage = new InMemoryStatusListStorage();
|
|
616
|
+
const statusListManager = new StatusList2021Manager({
|
|
617
|
+
issuerDid,
|
|
618
|
+
statusListUrl,
|
|
619
|
+
storage,
|
|
620
|
+
});
|
|
621
|
+
|
|
622
|
+
// 3. Create status list
|
|
623
|
+
const statusListVC = await statusListManager.createStatusList({
|
|
624
|
+
id: statusListUrl,
|
|
625
|
+
purpose: 'revocation',
|
|
626
|
+
});
|
|
627
|
+
console.log('✓ Status list created');
|
|
628
|
+
|
|
629
|
+
// 4. Setup delegation issuer
|
|
630
|
+
const issuer = new DelegationIssuer({
|
|
631
|
+
issuerDid,
|
|
632
|
+
privateKeyJwk: issuerPrivateKey,
|
|
633
|
+
});
|
|
634
|
+
|
|
635
|
+
// 5. Issue delegation with status
|
|
636
|
+
const statusListIndex = await statusListManager.allocateIndex();
|
|
637
|
+
const delegation = await issuer.issue({
|
|
638
|
+
subjectDid: 'did:key:z6MkrWXJPkxPCuQF7RqeKZFdZqBXz3oCG7PUty5dXLKGzELj',
|
|
639
|
+
constraints: {
|
|
640
|
+
scope: {
|
|
641
|
+
allowedTools: ['read_file'],
|
|
642
|
+
allowedResources: ['/documents/*'],
|
|
643
|
+
},
|
|
644
|
+
},
|
|
645
|
+
credentialStatus: {
|
|
646
|
+
id: `${statusListUrl}#${statusListIndex}`,
|
|
647
|
+
type: 'StatusList2021Entry',
|
|
648
|
+
statusPurpose: 'revocation',
|
|
649
|
+
statusListIndex: statusListIndex.toString(),
|
|
650
|
+
statusListCredential: statusListUrl,
|
|
651
|
+
},
|
|
652
|
+
});
|
|
653
|
+
console.log('✓ Delegation issued with status index:', statusListIndex);
|
|
654
|
+
|
|
655
|
+
// 6. Verify delegation (should pass)
|
|
656
|
+
let result = await verifyDelegation({
|
|
657
|
+
credential: delegation,
|
|
658
|
+
checkStatus: true,
|
|
659
|
+
statusListFetcher: async (url) => {
|
|
660
|
+
// In production, this would be an HTTP fetch
|
|
661
|
+
return statusListVC;
|
|
662
|
+
},
|
|
663
|
+
});
|
|
664
|
+
console.log('✓ Verification passed:', result.verified);
|
|
665
|
+
|
|
666
|
+
// 7. Revoke credential
|
|
667
|
+
await statusListManager.revokeCredential(statusListIndex);
|
|
668
|
+
console.log('✓ Credential revoked');
|
|
669
|
+
|
|
670
|
+
// 8. Verify again (should fail)
|
|
671
|
+
result = await verifyDelegation({
|
|
672
|
+
credential: delegation,
|
|
673
|
+
checkStatus: true,
|
|
674
|
+
statusListFetcher: async (url) => {
|
|
675
|
+
return await statusListManager.getStatusList(statusListUrl);
|
|
676
|
+
},
|
|
677
|
+
});
|
|
678
|
+
console.log('✗ Verification failed (revoked):', !result.verified);
|
|
679
|
+
console.log(' Status revoked:', result.statusRevoked);
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
main().catch(console.error);
|
|
683
|
+
```
|
|
684
|
+
|
|
685
|
+
## References
|
|
686
|
+
|
|
687
|
+
- [W3C StatusList2021 Specification](https://www.w3.org/TR/vc-status-list-2021/)
|
|
688
|
+
- [Verifiable Credentials Data Model](https://www.w3.org/TR/vc-data-model/)
|
|
689
|
+
- [Privacy Considerations for StatusList2021](https://www.w3.org/TR/vc-status-list-2021/#privacy-considerations)
|
|
690
|
+
- [MCP-I Delegation Guide](./W3C_VC_DELEGATION_GUIDE.md)
|
|
691
|
+
|
|
692
|
+
## Next Steps
|
|
693
|
+
|
|
694
|
+
1. Read the [W3C VC Delegation Guide](./W3C_VC_DELEGATION_GUIDE.md) to understand delegation credentials
|
|
695
|
+
2. Review the [Compliance Matrix](./COMPLIANCE_MATRIX.md) for schema validation
|
|
696
|
+
3. Explore the [API Reference](./API_REFERENCE.md) for detailed API documentation
|