@kya-os/mcp-i-core 1.2.3-canary.7 → 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.
Files changed (231) hide show
  1. package/.claude/settings.local.json +9 -0
  2. package/.turbo/turbo-build.log +4 -0
  3. package/.turbo/turbo-test$colon$coverage.log +4514 -0
  4. package/.turbo/turbo-test.log +2973 -0
  5. package/COMPLIANCE_IMPROVEMENT_REPORT.md +483 -0
  6. package/Composer 3.md +615 -0
  7. package/GPT-5.md +1169 -0
  8. package/OPUS-plan.md +352 -0
  9. package/PHASE_3_AND_4.1_SUMMARY.md +585 -0
  10. package/PHASE_3_SUMMARY.md +317 -0
  11. package/PHASE_4.1.3_SUMMARY.md +428 -0
  12. package/PHASE_4.1_COMPLETE.md +525 -0
  13. package/PHASE_4_USER_DID_IDENTITY_LINKING_PLAN.md +1240 -0
  14. package/SCHEMA_COMPLIANCE_REPORT.md +275 -0
  15. package/TEST_PLAN.md +571 -0
  16. package/coverage/coverage-final.json +57 -0
  17. package/dist/__tests__/utils/mock-providers.d.ts +1 -2
  18. package/dist/__tests__/utils/mock-providers.d.ts.map +1 -1
  19. package/dist/__tests__/utils/mock-providers.js.map +1 -1
  20. package/dist/cache/oauth-config-cache.d.ts +69 -0
  21. package/dist/cache/oauth-config-cache.d.ts.map +1 -0
  22. package/dist/cache/oauth-config-cache.js +76 -0
  23. package/dist/cache/oauth-config-cache.js.map +1 -0
  24. package/dist/identity/idp-token-resolver.d.ts +53 -0
  25. package/dist/identity/idp-token-resolver.d.ts.map +1 -0
  26. package/dist/identity/idp-token-resolver.js +108 -0
  27. package/dist/identity/idp-token-resolver.js.map +1 -0
  28. package/dist/identity/idp-token-storage.interface.d.ts +42 -0
  29. package/dist/identity/idp-token-storage.interface.d.ts.map +1 -0
  30. package/dist/identity/idp-token-storage.interface.js +12 -0
  31. package/dist/identity/idp-token-storage.interface.js.map +1 -0
  32. package/dist/identity/user-did-manager.d.ts +39 -1
  33. package/dist/identity/user-did-manager.d.ts.map +1 -1
  34. package/dist/identity/user-did-manager.js +69 -3
  35. package/dist/identity/user-did-manager.js.map +1 -1
  36. package/dist/index.d.ts +22 -0
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +39 -1
  39. package/dist/index.js.map +1 -1
  40. package/dist/runtime/audit-logger.d.ts +37 -0
  41. package/dist/runtime/audit-logger.d.ts.map +1 -0
  42. package/dist/runtime/audit-logger.js +9 -0
  43. package/dist/runtime/audit-logger.js.map +1 -0
  44. package/dist/runtime/base.d.ts +58 -2
  45. package/dist/runtime/base.d.ts.map +1 -1
  46. package/dist/runtime/base.js +266 -11
  47. package/dist/runtime/base.js.map +1 -1
  48. package/dist/services/access-control.service.d.ts.map +1 -1
  49. package/dist/services/access-control.service.js +200 -35
  50. package/dist/services/access-control.service.js.map +1 -1
  51. package/dist/services/authorization/authorization-registry.d.ts +29 -0
  52. package/dist/services/authorization/authorization-registry.d.ts.map +1 -0
  53. package/dist/services/authorization/authorization-registry.js +57 -0
  54. package/dist/services/authorization/authorization-registry.js.map +1 -0
  55. package/dist/services/authorization/types.d.ts +53 -0
  56. package/dist/services/authorization/types.d.ts.map +1 -0
  57. package/dist/services/authorization/types.js +10 -0
  58. package/dist/services/authorization/types.js.map +1 -0
  59. package/dist/services/batch-delegation.service.d.ts +53 -0
  60. package/dist/services/batch-delegation.service.d.ts.map +1 -0
  61. package/dist/services/batch-delegation.service.js +95 -0
  62. package/dist/services/batch-delegation.service.js.map +1 -0
  63. package/dist/services/oauth-config.service.d.ts +53 -0
  64. package/dist/services/oauth-config.service.d.ts.map +1 -0
  65. package/dist/services/oauth-config.service.js +117 -0
  66. package/dist/services/oauth-config.service.js.map +1 -0
  67. package/dist/services/oauth-provider-registry.d.ts +77 -0
  68. package/dist/services/oauth-provider-registry.d.ts.map +1 -0
  69. package/dist/services/oauth-provider-registry.js +112 -0
  70. package/dist/services/oauth-provider-registry.js.map +1 -0
  71. package/dist/services/oauth-service.d.ts +77 -0
  72. package/dist/services/oauth-service.d.ts.map +1 -0
  73. package/dist/services/oauth-service.js +348 -0
  74. package/dist/services/oauth-service.js.map +1 -0
  75. package/dist/services/oauth-token-retrieval.service.d.ts +49 -0
  76. package/dist/services/oauth-token-retrieval.service.d.ts.map +1 -0
  77. package/dist/services/oauth-token-retrieval.service.js +150 -0
  78. package/dist/services/oauth-token-retrieval.service.js.map +1 -0
  79. package/dist/services/provider-resolver.d.ts +48 -0
  80. package/dist/services/provider-resolver.d.ts.map +1 -0
  81. package/dist/services/provider-resolver.js +120 -0
  82. package/dist/services/provider-resolver.js.map +1 -0
  83. package/dist/services/provider-validator.d.ts +55 -0
  84. package/dist/services/provider-validator.d.ts.map +1 -0
  85. package/dist/services/provider-validator.js +135 -0
  86. package/dist/services/provider-validator.js.map +1 -0
  87. package/dist/services/tool-context-builder.d.ts +57 -0
  88. package/dist/services/tool-context-builder.d.ts.map +1 -0
  89. package/dist/services/tool-context-builder.js +125 -0
  90. package/dist/services/tool-context-builder.js.map +1 -0
  91. package/dist/services/tool-protection.service.d.ts +87 -10
  92. package/dist/services/tool-protection.service.d.ts.map +1 -1
  93. package/dist/services/tool-protection.service.js +282 -112
  94. package/dist/services/tool-protection.service.js.map +1 -1
  95. package/dist/types/oauth-required-error.d.ts +40 -0
  96. package/dist/types/oauth-required-error.d.ts.map +1 -0
  97. package/dist/types/oauth-required-error.js +40 -0
  98. package/dist/types/oauth-required-error.js.map +1 -0
  99. package/dist/utils/did-helpers.d.ts +33 -0
  100. package/dist/utils/did-helpers.d.ts.map +1 -1
  101. package/dist/utils/did-helpers.js +40 -0
  102. package/dist/utils/did-helpers.js.map +1 -1
  103. package/dist/utils/index.d.ts +1 -0
  104. package/dist/utils/index.d.ts.map +1 -1
  105. package/dist/utils/index.js +1 -0
  106. package/dist/utils/index.js.map +1 -1
  107. package/docs/API_REFERENCE.md +1362 -0
  108. package/docs/COMPLIANCE_MATRIX.md +691 -0
  109. package/docs/STATUSLIST2021_GUIDE.md +696 -0
  110. package/docs/W3C_VC_DELEGATION_GUIDE.md +710 -0
  111. package/package.json +24 -50
  112. package/scripts/audit-compliance.ts +724 -0
  113. package/src/__tests__/cache/tool-protection-cache.test.ts +640 -0
  114. package/src/__tests__/config/provider-runtime-config.test.ts +309 -0
  115. package/src/__tests__/delegation-e2e.test.ts +690 -0
  116. package/src/__tests__/identity/user-did-manager.test.ts +213 -0
  117. package/src/__tests__/index.test.ts +56 -0
  118. package/src/__tests__/integration/full-flow.test.ts +776 -0
  119. package/src/__tests__/integration.test.ts +281 -0
  120. package/src/__tests__/providers/base.test.ts +173 -0
  121. package/src/__tests__/providers/memory.test.ts +319 -0
  122. package/src/__tests__/regression/phase2-regression.test.ts +427 -0
  123. package/src/__tests__/runtime/audit-logger.test.ts +154 -0
  124. package/src/__tests__/runtime/base-extensions.test.ts +593 -0
  125. package/src/__tests__/runtime/base.test.ts +869 -0
  126. package/src/__tests__/runtime/delegation-flow.test.ts +164 -0
  127. package/src/__tests__/runtime/proof-client-did.test.ts +375 -0
  128. package/src/__tests__/runtime/route-interception.test.ts +686 -0
  129. package/src/__tests__/runtime/tool-protection-enforcement.test.ts +908 -0
  130. package/src/__tests__/services/agentshield-integration.test.ts +784 -0
  131. package/src/__tests__/services/provider-resolver-edge-cases.test.ts +487 -0
  132. package/src/__tests__/services/tool-protection-oauth-provider.test.ts +480 -0
  133. package/src/__tests__/services/tool-protection.service.test.ts +1366 -0
  134. package/src/__tests__/utils/mock-providers.ts +340 -0
  135. package/src/cache/oauth-config-cache.d.ts +69 -0
  136. package/src/cache/oauth-config-cache.d.ts.map +1 -0
  137. package/src/cache/oauth-config-cache.js +71 -0
  138. package/src/cache/oauth-config-cache.js.map +1 -0
  139. package/src/cache/oauth-config-cache.ts +123 -0
  140. package/src/cache/tool-protection-cache.ts +171 -0
  141. package/src/compliance/EXAMPLE.md +412 -0
  142. package/src/compliance/__tests__/schema-verifier.test.ts +797 -0
  143. package/src/compliance/index.ts +8 -0
  144. package/src/compliance/schema-registry.ts +460 -0
  145. package/src/compliance/schema-verifier.ts +708 -0
  146. package/src/config/__tests__/remote-config.spec.ts +268 -0
  147. package/src/config/remote-config.ts +174 -0
  148. package/src/config.ts +309 -0
  149. package/src/delegation/__tests__/audience-validator.test.ts +112 -0
  150. package/src/delegation/__tests__/bitstring.test.ts +346 -0
  151. package/src/delegation/__tests__/cascading-revocation.test.ts +628 -0
  152. package/src/delegation/__tests__/delegation-graph.test.ts +584 -0
  153. package/src/delegation/__tests__/utils.test.ts +152 -0
  154. package/src/delegation/__tests__/vc-issuer.test.ts +442 -0
  155. package/src/delegation/__tests__/vc-verifier.test.ts +922 -0
  156. package/src/delegation/audience-validator.ts +52 -0
  157. package/src/delegation/bitstring.ts +278 -0
  158. package/src/delegation/cascading-revocation.ts +370 -0
  159. package/src/delegation/delegation-graph.ts +299 -0
  160. package/src/delegation/index.ts +14 -0
  161. package/src/delegation/statuslist-manager.ts +353 -0
  162. package/src/delegation/storage/__tests__/memory-graph-storage.test.ts +366 -0
  163. package/src/delegation/storage/__tests__/memory-statuslist-storage.test.ts +228 -0
  164. package/src/delegation/storage/index.ts +9 -0
  165. package/src/delegation/storage/memory-graph-storage.ts +178 -0
  166. package/src/delegation/storage/memory-statuslist-storage.ts +77 -0
  167. package/src/delegation/utils.ts +42 -0
  168. package/src/delegation/vc-issuer.ts +232 -0
  169. package/src/delegation/vc-verifier.ts +568 -0
  170. package/src/identity/idp-token-resolver.ts +147 -0
  171. package/src/identity/idp-token-storage.interface.ts +59 -0
  172. package/src/identity/user-did-manager.ts +370 -0
  173. package/src/index.ts +260 -0
  174. package/src/providers/base.d.ts +91 -0
  175. package/src/providers/base.d.ts.map +1 -0
  176. package/src/providers/base.js +38 -0
  177. package/src/providers/base.js.map +1 -0
  178. package/src/providers/base.ts +96 -0
  179. package/src/providers/memory.ts +142 -0
  180. package/src/runtime/audit-logger.ts +39 -0
  181. package/src/runtime/base.ts +1329 -0
  182. package/src/services/__tests__/access-control.integration.test.ts +443 -0
  183. package/src/services/__tests__/access-control.proof-response-validation.test.ts +578 -0
  184. package/src/services/__tests__/access-control.service.test.ts +970 -0
  185. package/src/services/__tests__/batch-delegation.service.test.ts +351 -0
  186. package/src/services/__tests__/crypto.service.test.ts +531 -0
  187. package/src/services/__tests__/oauth-provider-registry.test.ts +142 -0
  188. package/src/services/__tests__/proof-verifier.integration.test.ts +485 -0
  189. package/src/services/__tests__/proof-verifier.test.ts +489 -0
  190. package/src/services/__tests__/provider-resolution.integration.test.ts +198 -0
  191. package/src/services/__tests__/provider-resolver.test.ts +217 -0
  192. package/src/services/__tests__/storage.service.test.ts +358 -0
  193. package/src/services/access-control.service.ts +990 -0
  194. package/src/services/authorization/authorization-registry.ts +66 -0
  195. package/src/services/authorization/types.ts +71 -0
  196. package/src/services/batch-delegation.service.ts +137 -0
  197. package/src/services/crypto.service.ts +302 -0
  198. package/src/services/errors.ts +76 -0
  199. package/src/services/index.ts +9 -0
  200. package/src/services/oauth-config.service.d.ts +53 -0
  201. package/src/services/oauth-config.service.d.ts.map +1 -0
  202. package/src/services/oauth-config.service.js +113 -0
  203. package/src/services/oauth-config.service.js.map +1 -0
  204. package/src/services/oauth-config.service.ts +166 -0
  205. package/src/services/oauth-provider-registry.d.ts +57 -0
  206. package/src/services/oauth-provider-registry.d.ts.map +1 -0
  207. package/src/services/oauth-provider-registry.js +73 -0
  208. package/src/services/oauth-provider-registry.js.map +1 -0
  209. package/src/services/oauth-provider-registry.ts +123 -0
  210. package/src/services/oauth-service.ts +510 -0
  211. package/src/services/oauth-token-retrieval.service.ts +245 -0
  212. package/src/services/proof-verifier.ts +478 -0
  213. package/src/services/provider-resolver.d.ts +48 -0
  214. package/src/services/provider-resolver.d.ts.map +1 -0
  215. package/src/services/provider-resolver.js +106 -0
  216. package/src/services/provider-resolver.js.map +1 -0
  217. package/src/services/provider-resolver.ts +144 -0
  218. package/src/services/provider-validator.ts +170 -0
  219. package/src/services/storage.service.ts +566 -0
  220. package/src/services/tool-context-builder.ts +172 -0
  221. package/src/services/tool-protection.service.ts +958 -0
  222. package/src/types/oauth-required-error.ts +63 -0
  223. package/src/types/tool-protection.ts +155 -0
  224. package/src/utils/__tests__/did-helpers.test.ts +101 -0
  225. package/src/utils/base64.ts +148 -0
  226. package/src/utils/cors.ts +83 -0
  227. package/src/utils/did-helpers.ts +150 -0
  228. package/src/utils/index.ts +8 -0
  229. package/src/utils/storage-keys.ts +278 -0
  230. package/tsconfig.json +21 -0
  231. 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
+ }