@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,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-Memory Delegation Graph Storage Provider
|
|
3
|
+
*
|
|
4
|
+
* Memory-based implementation for testing and development.
|
|
5
|
+
* NOT suitable for production (no persistence).
|
|
6
|
+
*
|
|
7
|
+
* SOLID: Implements DelegationGraphStorageProvider interface
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type {
|
|
11
|
+
DelegationGraphStorageProvider,
|
|
12
|
+
DelegationNode,
|
|
13
|
+
} from '../delegation-graph';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Memory-based Delegation Graph storage
|
|
17
|
+
*
|
|
18
|
+
* Stores delegation nodes in memory with efficient graph queries.
|
|
19
|
+
* Useful for:
|
|
20
|
+
* - Unit tests
|
|
21
|
+
* - Integration tests
|
|
22
|
+
* - Development/debugging
|
|
23
|
+
* - Examples
|
|
24
|
+
*/
|
|
25
|
+
export class MemoryDelegationGraphStorage
|
|
26
|
+
implements DelegationGraphStorageProvider
|
|
27
|
+
{
|
|
28
|
+
private nodes = new Map<string, DelegationNode>();
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Get a delegation node by ID
|
|
32
|
+
*/
|
|
33
|
+
async getNode(delegationId: string): Promise<DelegationNode | null> {
|
|
34
|
+
return this.nodes.get(delegationId) || null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Save a delegation node
|
|
39
|
+
*/
|
|
40
|
+
async setNode(node: DelegationNode): Promise<void> {
|
|
41
|
+
this.nodes.set(node.id, node);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get all children of a delegation
|
|
46
|
+
*/
|
|
47
|
+
async getChildren(delegationId: string): Promise<DelegationNode[]> {
|
|
48
|
+
const parent = this.nodes.get(delegationId);
|
|
49
|
+
if (!parent) return [];
|
|
50
|
+
|
|
51
|
+
return parent.children
|
|
52
|
+
.map((childId) => this.nodes.get(childId))
|
|
53
|
+
.filter((node): node is DelegationNode => node !== undefined);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Get the full chain from root to this delegation
|
|
58
|
+
*/
|
|
59
|
+
async getChain(delegationId: string): Promise<DelegationNode[]> {
|
|
60
|
+
const chain: DelegationNode[] = [];
|
|
61
|
+
let currentId: string | null = delegationId;
|
|
62
|
+
|
|
63
|
+
// Walk up the tree to root
|
|
64
|
+
while (currentId) {
|
|
65
|
+
const node = this.nodes.get(currentId);
|
|
66
|
+
if (!node) break;
|
|
67
|
+
|
|
68
|
+
chain.unshift(node); // Add to front (root first)
|
|
69
|
+
currentId = node.parentId;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return chain;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Get all descendants (children, grandchildren, etc.)
|
|
77
|
+
*
|
|
78
|
+
* Uses BFS for efficiency.
|
|
79
|
+
*/
|
|
80
|
+
async getDescendants(delegationId: string): Promise<DelegationNode[]> {
|
|
81
|
+
const descendants: DelegationNode[] = [];
|
|
82
|
+
const queue: string[] = [delegationId];
|
|
83
|
+
const visited = new Set<string>();
|
|
84
|
+
|
|
85
|
+
while (queue.length > 0) {
|
|
86
|
+
const currentId = queue.shift()!;
|
|
87
|
+
|
|
88
|
+
// Skip if already visited (prevent infinite loops)
|
|
89
|
+
if (visited.has(currentId)) continue;
|
|
90
|
+
visited.add(currentId);
|
|
91
|
+
|
|
92
|
+
const node = this.nodes.get(currentId);
|
|
93
|
+
if (!node) continue;
|
|
94
|
+
|
|
95
|
+
// Add children to queue
|
|
96
|
+
for (const childId of node.children) {
|
|
97
|
+
if (!visited.has(childId)) {
|
|
98
|
+
queue.push(childId);
|
|
99
|
+
|
|
100
|
+
const childNode = this.nodes.get(childId);
|
|
101
|
+
if (childNode) {
|
|
102
|
+
descendants.push(childNode);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return descendants;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Delete a node
|
|
113
|
+
*/
|
|
114
|
+
async deleteNode(delegationId: string): Promise<void> {
|
|
115
|
+
this.nodes.delete(delegationId);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Clear all data (for testing)
|
|
120
|
+
*/
|
|
121
|
+
clear(): void {
|
|
122
|
+
this.nodes.clear();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Get all node IDs (for testing)
|
|
127
|
+
*/
|
|
128
|
+
getAllNodeIds(): string[] {
|
|
129
|
+
return Array.from(this.nodes.keys());
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Get graph statistics (for testing/debugging)
|
|
134
|
+
*/
|
|
135
|
+
getStats(): {
|
|
136
|
+
totalNodes: number;
|
|
137
|
+
rootNodes: number;
|
|
138
|
+
leafNodes: number;
|
|
139
|
+
maxDepth: number;
|
|
140
|
+
} {
|
|
141
|
+
const nodes = Array.from(this.nodes.values());
|
|
142
|
+
|
|
143
|
+
const rootNodes = nodes.filter((n) => n.parentId === null).length;
|
|
144
|
+
const leafNodes = nodes.filter((n) => n.children.length === 0).length;
|
|
145
|
+
|
|
146
|
+
// Calculate max depth
|
|
147
|
+
let maxDepth = 0;
|
|
148
|
+
for (const node of nodes) {
|
|
149
|
+
const chain = this.getChainSync(node.id);
|
|
150
|
+
maxDepth = Math.max(maxDepth, chain.length - 1);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return {
|
|
154
|
+
totalNodes: nodes.length,
|
|
155
|
+
rootNodes,
|
|
156
|
+
leafNodes,
|
|
157
|
+
maxDepth,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Synchronous chain retrieval (for stats)
|
|
163
|
+
*/
|
|
164
|
+
private getChainSync(delegationId: string): DelegationNode[] {
|
|
165
|
+
const chain: DelegationNode[] = [];
|
|
166
|
+
let currentId: string | null = delegationId;
|
|
167
|
+
|
|
168
|
+
while (currentId) {
|
|
169
|
+
const node = this.nodes.get(currentId);
|
|
170
|
+
if (!node) break;
|
|
171
|
+
|
|
172
|
+
chain.unshift(node);
|
|
173
|
+
currentId = node.parentId;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return chain;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-Memory StatusList Storage Provider
|
|
3
|
+
*
|
|
4
|
+
* Memory-based implementation for testing and development.
|
|
5
|
+
* NOT suitable for production (no persistence).
|
|
6
|
+
*
|
|
7
|
+
* SOLID: Implements StatusListStorageProvider interface
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { StatusList2021Credential } from '@kya-os/contracts';
|
|
11
|
+
import type { StatusListStorageProvider } from '../statuslist-manager';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Memory-based StatusList storage
|
|
15
|
+
*
|
|
16
|
+
* Stores status lists in memory. Thread-safe index allocation.
|
|
17
|
+
* Useful for:
|
|
18
|
+
* - Unit tests
|
|
19
|
+
* - Integration tests
|
|
20
|
+
* - Development/debugging
|
|
21
|
+
* - Examples
|
|
22
|
+
*/
|
|
23
|
+
export class MemoryStatusListStorage implements StatusListStorageProvider {
|
|
24
|
+
private statusLists = new Map<string, StatusList2021Credential>();
|
|
25
|
+
private indexCounters = new Map<string, number>();
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Get a status list credential by ID
|
|
29
|
+
*/
|
|
30
|
+
async getStatusList(
|
|
31
|
+
statusListId: string
|
|
32
|
+
): Promise<StatusList2021Credential | null> {
|
|
33
|
+
return this.statusLists.get(statusListId) || null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Save a status list credential
|
|
38
|
+
*/
|
|
39
|
+
async setStatusList(
|
|
40
|
+
statusListId: string,
|
|
41
|
+
credential: StatusList2021Credential
|
|
42
|
+
): Promise<void> {
|
|
43
|
+
this.statusLists.set(statusListId, credential);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Allocate a new index (thread-safe)
|
|
48
|
+
*/
|
|
49
|
+
async allocateIndex(statusListId: string): Promise<number> {
|
|
50
|
+
const current = this.indexCounters.get(statusListId) || 0;
|
|
51
|
+
const allocated = current;
|
|
52
|
+
this.indexCounters.set(statusListId, current + 1);
|
|
53
|
+
return allocated;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Get current index count (for testing)
|
|
58
|
+
*/
|
|
59
|
+
getIndexCount(statusListId: string): number {
|
|
60
|
+
return this.indexCounters.get(statusListId) || 0;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Clear all data (for testing)
|
|
65
|
+
*/
|
|
66
|
+
clear(): void {
|
|
67
|
+
this.statusLists.clear();
|
|
68
|
+
this.indexCounters.clear();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Get all status list IDs (for testing)
|
|
73
|
+
*/
|
|
74
|
+
getAllStatusListIds(): string[] {
|
|
75
|
+
return Array.from(this.statusLists.keys());
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delegation Utilities
|
|
3
|
+
*
|
|
4
|
+
* Shared utility functions for delegation credential operations.
|
|
5
|
+
* Following DRY (Don't Repeat Yourself) principle.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* JSON canonicalization (RFC 8785)
|
|
10
|
+
*
|
|
11
|
+
* Creates a deterministic representation of JSON for signing.
|
|
12
|
+
* Per W3C VC spec, canonicalization ensures identical VCs produce identical signatures.
|
|
13
|
+
*
|
|
14
|
+
* DRY: Single implementation shared across vc-issuer and statuslist-manager.
|
|
15
|
+
*
|
|
16
|
+
* @param obj - The object to canonicalize
|
|
17
|
+
* @returns Canonical JSON string
|
|
18
|
+
*/
|
|
19
|
+
export function canonicalizeJSON(obj: any): string {
|
|
20
|
+
if (obj === null) return 'null';
|
|
21
|
+
if (typeof obj === 'boolean') return obj.toString();
|
|
22
|
+
if (typeof obj === 'number') {
|
|
23
|
+
if (!isFinite(obj)) {
|
|
24
|
+
throw new Error('Cannot canonicalize non-finite number');
|
|
25
|
+
}
|
|
26
|
+
return JSON.stringify(obj);
|
|
27
|
+
}
|
|
28
|
+
if (typeof obj === 'string') return JSON.stringify(obj);
|
|
29
|
+
if (Array.isArray(obj)) {
|
|
30
|
+
const elements = obj.map((item) => canonicalizeJSON(item));
|
|
31
|
+
return '[' + elements.join(',') + ']';
|
|
32
|
+
}
|
|
33
|
+
if (typeof obj === 'object') {
|
|
34
|
+
const keys = Object.keys(obj).sort();
|
|
35
|
+
const pairs = keys.map((key) => {
|
|
36
|
+
const value = canonicalizeJSON(obj[key]);
|
|
37
|
+
return JSON.stringify(key) + ':' + value;
|
|
38
|
+
});
|
|
39
|
+
return '{' + pairs.join(',') + '}';
|
|
40
|
+
}
|
|
41
|
+
throw new Error(`Cannot canonicalize type: ${typeof obj}`);
|
|
42
|
+
}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delegation Credential Issuer (Platform-Agnostic)
|
|
3
|
+
*
|
|
4
|
+
* Issues W3C Verifiable Credentials for delegations with Ed25519 signatures.
|
|
5
|
+
* Follows the Python POC design (Delegation-Service.md:136-163) where
|
|
6
|
+
* delegations are issued AS W3C VCs.
|
|
7
|
+
*
|
|
8
|
+
* Related Spec: MCP-I §4.1, §4.2, W3C VC Data Model 1.1
|
|
9
|
+
* Python Reference: Delegation-Service.md
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type {
|
|
13
|
+
DelegationCredential,
|
|
14
|
+
DelegationRecord,
|
|
15
|
+
CredentialStatus,
|
|
16
|
+
Proof,
|
|
17
|
+
} from '@kya-os/contracts';
|
|
18
|
+
import { wrapDelegationAsVC } from '@kya-os/contracts';
|
|
19
|
+
import { canonicalizeJSON } from './utils';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Options for issuing a delegation credential
|
|
23
|
+
*/
|
|
24
|
+
export interface IssueDelegationOptions {
|
|
25
|
+
/** VC ID (optional, will be generated if not provided) */
|
|
26
|
+
id?: string;
|
|
27
|
+
|
|
28
|
+
/** Issuance date (optional, defaults to now) */
|
|
29
|
+
issuanceDate?: string;
|
|
30
|
+
|
|
31
|
+
/** Expiration date (optional, derived from constraints if not provided) */
|
|
32
|
+
expirationDate?: string;
|
|
33
|
+
|
|
34
|
+
/** Credential status for StatusList2021 (optional) */
|
|
35
|
+
credentialStatus?: CredentialStatus;
|
|
36
|
+
|
|
37
|
+
/** Additional context URIs (optional) */
|
|
38
|
+
additionalContexts?: string[];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Signing function interface
|
|
43
|
+
*
|
|
44
|
+
* Platform-specific implementations provide this function to sign VCs.
|
|
45
|
+
* For example:
|
|
46
|
+
* - Node.js: Uses jose library with importPKCS8
|
|
47
|
+
* - Cloudflare: Uses Web Crypto API
|
|
48
|
+
*/
|
|
49
|
+
export interface VCSigningFunction {
|
|
50
|
+
/**
|
|
51
|
+
* Sign a canonicalized VC
|
|
52
|
+
*
|
|
53
|
+
* @param canonicalVC - The canonical JSON string to sign
|
|
54
|
+
* @param issuerDid - The DID of the issuer
|
|
55
|
+
* @param kid - The key ID
|
|
56
|
+
* @returns Ed25519Signature2020 proof
|
|
57
|
+
*/
|
|
58
|
+
(canonicalVC: string, issuerDid: string, kid: string): Promise<Proof>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Identity provider interface
|
|
63
|
+
*
|
|
64
|
+
* Platform-specific implementations provide identity details.
|
|
65
|
+
*/
|
|
66
|
+
export interface IdentityProvider {
|
|
67
|
+
/** Get the DID of this identity */
|
|
68
|
+
getDid(): string;
|
|
69
|
+
|
|
70
|
+
/** Get the key ID of this identity */
|
|
71
|
+
getKeyId(): string;
|
|
72
|
+
|
|
73
|
+
/** Get the private key (base64 encoded) */
|
|
74
|
+
getPrivateKey(): string;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Delegation Credential Issuer (Platform-Agnostic)
|
|
79
|
+
*
|
|
80
|
+
* Issues W3C Verifiable Credentials for delegations.
|
|
81
|
+
* Per Python POC (Delegation-Service.md:136-146):
|
|
82
|
+
* - Every delegation MUST be issued as a VC
|
|
83
|
+
* - VC is signed with Ed25519 (Ed25519Signature2020)
|
|
84
|
+
* - StatusList2021 support for efficient revocation
|
|
85
|
+
*/
|
|
86
|
+
export class DelegationCredentialIssuer {
|
|
87
|
+
constructor(
|
|
88
|
+
private identity: IdentityProvider,
|
|
89
|
+
private signingFunction: VCSigningFunction
|
|
90
|
+
) {}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Issue a delegation credential
|
|
94
|
+
*
|
|
95
|
+
* Creates a W3C Verifiable Credential from a delegation record.
|
|
96
|
+
* Signs it with Ed25519 and returns the complete DelegationCredential.
|
|
97
|
+
*
|
|
98
|
+
* @param delegation - The delegation record to issue as a VC
|
|
99
|
+
* @param options - Issuance options
|
|
100
|
+
* @returns Signed DelegationCredential
|
|
101
|
+
*/
|
|
102
|
+
async issueDelegationCredential(
|
|
103
|
+
delegation: DelegationRecord,
|
|
104
|
+
options: IssueDelegationOptions = {}
|
|
105
|
+
): Promise<DelegationCredential> {
|
|
106
|
+
// Step 1: Create unsigned VC
|
|
107
|
+
let unsignedVC = wrapDelegationAsVC(delegation, {
|
|
108
|
+
id: options.id,
|
|
109
|
+
issuanceDate: options.issuanceDate,
|
|
110
|
+
expirationDate: options.expirationDate,
|
|
111
|
+
credentialStatus: options.credentialStatus,
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// Add additional contexts if provided
|
|
115
|
+
if (options.additionalContexts && options.additionalContexts.length > 0) {
|
|
116
|
+
const existingContexts = unsignedVC['@context'] as Array<
|
|
117
|
+
string | Record<string, any>
|
|
118
|
+
>;
|
|
119
|
+
unsignedVC = {
|
|
120
|
+
...unsignedVC,
|
|
121
|
+
'@context': [...existingContexts, ...options.additionalContexts],
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Step 2: Canonicalize VC (for signing)
|
|
126
|
+
const canonicalVC = this.canonicalizeVC(unsignedVC);
|
|
127
|
+
|
|
128
|
+
// Step 3: Sign with Ed25519 using platform-specific signing function
|
|
129
|
+
const proof = await this.signingFunction(
|
|
130
|
+
canonicalVC,
|
|
131
|
+
this.identity.getDid(),
|
|
132
|
+
this.identity.getKeyId()
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
// Step 4: Return signed VC
|
|
136
|
+
return {
|
|
137
|
+
...unsignedVC,
|
|
138
|
+
proof,
|
|
139
|
+
} as DelegationCredential;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Create a delegation record and issue it as a VC in one step
|
|
144
|
+
*
|
|
145
|
+
* Convenience method for creating a new delegation from scratch.
|
|
146
|
+
*
|
|
147
|
+
* @param params - Delegation parameters
|
|
148
|
+
* @param options - Issuance options
|
|
149
|
+
* @returns Signed DelegationCredential
|
|
150
|
+
*/
|
|
151
|
+
async createAndIssueDelegation(
|
|
152
|
+
params: {
|
|
153
|
+
id: string;
|
|
154
|
+
issuerDid: string;
|
|
155
|
+
subjectDid: string;
|
|
156
|
+
controller?: string;
|
|
157
|
+
parentId?: string;
|
|
158
|
+
constraints: DelegationRecord['constraints'];
|
|
159
|
+
status?: DelegationRecord['status'];
|
|
160
|
+
metadata?: Record<string, any>;
|
|
161
|
+
},
|
|
162
|
+
options: IssueDelegationOptions = {}
|
|
163
|
+
): Promise<DelegationCredential> {
|
|
164
|
+
const now = Date.now();
|
|
165
|
+
|
|
166
|
+
// Create delegation record
|
|
167
|
+
const delegation: DelegationRecord = {
|
|
168
|
+
id: params.id,
|
|
169
|
+
issuerDid: params.issuerDid,
|
|
170
|
+
subjectDid: params.subjectDid,
|
|
171
|
+
controller: params.controller,
|
|
172
|
+
vcId: options.id || `urn:uuid:${params.id}`,
|
|
173
|
+
parentId: params.parentId,
|
|
174
|
+
constraints: params.constraints,
|
|
175
|
+
signature: '', // Will be filled by VC proof
|
|
176
|
+
status: params.status || 'active',
|
|
177
|
+
createdAt: now,
|
|
178
|
+
metadata: params.metadata,
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
// Issue as VC
|
|
182
|
+
return this.issueDelegationCredential(delegation, options);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Canonicalize VC for signing
|
|
187
|
+
*
|
|
188
|
+
* Uses JCS (JSON Canonicalization Scheme, RFC 8785) to create
|
|
189
|
+
* a deterministic representation of the VC.
|
|
190
|
+
*
|
|
191
|
+
* @param vc - The unsigned VC
|
|
192
|
+
* @returns Canonical JSON string
|
|
193
|
+
*/
|
|
194
|
+
private canonicalizeVC(vc: Omit<DelegationCredential, 'proof'>): string {
|
|
195
|
+
// DRY: Use shared canonicalization utility
|
|
196
|
+
return canonicalizeJSON(vc);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Get issuer DID
|
|
201
|
+
*
|
|
202
|
+
* @returns The DID of this issuer
|
|
203
|
+
*/
|
|
204
|
+
getIssuerDid(): string {
|
|
205
|
+
return this.identity.getDid();
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Get issuer key ID
|
|
210
|
+
*
|
|
211
|
+
* @returns The key ID of this issuer
|
|
212
|
+
*/
|
|
213
|
+
getIssuerKeyId(): string {
|
|
214
|
+
return this.identity.getKeyId();
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Create a delegation credential issuer
|
|
220
|
+
*
|
|
221
|
+
* Convenience factory function.
|
|
222
|
+
*
|
|
223
|
+
* @param identity - Identity provider
|
|
224
|
+
* @param signingFunction - Platform-specific signing function
|
|
225
|
+
* @returns DelegationCredentialIssuer instance
|
|
226
|
+
*/
|
|
227
|
+
export function createDelegationIssuer(
|
|
228
|
+
identity: IdentityProvider,
|
|
229
|
+
signingFunction: VCSigningFunction
|
|
230
|
+
): DelegationCredentialIssuer {
|
|
231
|
+
return new DelegationCredentialIssuer(identity, signingFunction);
|
|
232
|
+
}
|