@ucptools/validator 1.0.0 → 1.0.1

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 (236) hide show
  1. package/.claude/settings.local.json +60 -0
  2. package/.vercel/README.txt +11 -0
  3. package/.vercel/project.json +1 -0
  4. package/dist/cli/index.d.ts +6 -0
  5. package/dist/cli/index.d.ts.map +1 -0
  6. package/dist/cli/index.js +279 -0
  7. package/dist/cli/index.js.map +1 -0
  8. package/dist/compliance/compliance-generator.d.ts +34 -0
  9. package/dist/compliance/compliance-generator.d.ts.map +1 -0
  10. package/dist/compliance/compliance-generator.js +320 -0
  11. package/dist/compliance/compliance-generator.js.map +1 -0
  12. package/dist/compliance/index.d.ts +8 -0
  13. package/dist/compliance/index.d.ts.map +1 -0
  14. package/dist/compliance/index.js +17 -0
  15. package/dist/compliance/index.js.map +1 -0
  16. package/dist/compliance/templates.d.ts +34 -0
  17. package/dist/compliance/templates.d.ts.map +1 -0
  18. package/{src/compliance/templates.ts → dist/compliance/templates.js} +117 -155
  19. package/dist/compliance/templates.js.map +1 -0
  20. package/dist/compliance/types.d.ts +64 -0
  21. package/dist/compliance/types.d.ts.map +1 -0
  22. package/dist/compliance/types.js +64 -0
  23. package/dist/compliance/types.js.map +1 -0
  24. package/dist/db/index.d.ts +11 -0
  25. package/dist/db/index.d.ts.map +1 -0
  26. package/dist/db/index.js +63 -0
  27. package/dist/db/index.js.map +1 -0
  28. package/dist/db/schema.d.ts +444 -0
  29. package/dist/db/schema.d.ts.map +1 -0
  30. package/dist/db/schema.js +65 -0
  31. package/dist/db/schema.js.map +1 -0
  32. package/dist/feed-analyzer/feed-analyzer.d.ts +26 -0
  33. package/dist/feed-analyzer/feed-analyzer.d.ts.map +1 -0
  34. package/{src/feed-analyzer/feed-analyzer.ts → dist/feed-analyzer/feed-analyzer.js} +642 -726
  35. package/dist/feed-analyzer/feed-analyzer.js.map +1 -0
  36. package/dist/feed-analyzer/index.d.ts +8 -0
  37. package/dist/feed-analyzer/index.d.ts.map +1 -0
  38. package/dist/feed-analyzer/index.js +19 -0
  39. package/dist/feed-analyzer/index.js.map +1 -0
  40. package/dist/feed-analyzer/types.d.ts +204 -0
  41. package/dist/feed-analyzer/types.d.ts.map +1 -0
  42. package/dist/feed-analyzer/types.js +162 -0
  43. package/dist/feed-analyzer/types.js.map +1 -0
  44. package/{src/generator/index.ts → dist/generator/index.d.ts} +1 -1
  45. package/dist/generator/index.d.ts.map +1 -0
  46. package/dist/generator/index.js +13 -0
  47. package/dist/generator/index.js.map +1 -0
  48. package/dist/generator/key-generator.d.ts +24 -0
  49. package/dist/generator/key-generator.d.ts.map +1 -0
  50. package/dist/generator/key-generator.js +144 -0
  51. package/dist/generator/key-generator.js.map +1 -0
  52. package/dist/generator/profile-builder.d.ts +15 -0
  53. package/dist/generator/profile-builder.d.ts.map +1 -0
  54. package/dist/generator/profile-builder.js +338 -0
  55. package/dist/generator/profile-builder.js.map +1 -0
  56. package/dist/hosting/artifacts-generator.d.ts +10 -0
  57. package/dist/hosting/artifacts-generator.d.ts.map +1 -0
  58. package/{src/hosting/artifacts-generator.ts → dist/hosting/artifacts-generator.js} +191 -241
  59. package/dist/hosting/artifacts-generator.js.map +1 -0
  60. package/{src/hosting/index.ts → dist/hosting/index.d.ts} +1 -1
  61. package/dist/hosting/index.d.ts.map +1 -0
  62. package/dist/hosting/index.js +10 -0
  63. package/dist/hosting/index.js.map +1 -0
  64. package/dist/index.d.ts +18 -0
  65. package/dist/index.d.ts.map +1 -0
  66. package/dist/index.js +78 -0
  67. package/dist/index.js.map +1 -0
  68. package/{src/security/index.ts → dist/security/index.d.ts} +8 -15
  69. package/dist/security/index.d.ts.map +1 -0
  70. package/dist/security/index.js +12 -0
  71. package/dist/security/index.js.map +1 -0
  72. package/dist/security/security-scanner.d.ts +10 -0
  73. package/dist/security/security-scanner.d.ts.map +1 -0
  74. package/dist/security/security-scanner.js +541 -0
  75. package/dist/security/security-scanner.js.map +1 -0
  76. package/dist/security/types.d.ts +48 -0
  77. package/dist/security/types.d.ts.map +1 -0
  78. package/dist/security/types.js +21 -0
  79. package/dist/security/types.js.map +1 -0
  80. package/dist/services/directory.d.ts +104 -0
  81. package/dist/services/directory.d.ts.map +1 -0
  82. package/dist/services/directory.js +333 -0
  83. package/dist/services/directory.js.map +1 -0
  84. package/dist/simulator/agent-simulator.d.ts +69 -0
  85. package/dist/simulator/agent-simulator.d.ts.map +1 -0
  86. package/{src/simulator/agent-simulator.ts → dist/simulator/agent-simulator.js} +650 -941
  87. package/dist/simulator/agent-simulator.js.map +1 -0
  88. package/{src/simulator/index.ts → dist/simulator/index.d.ts} +7 -7
  89. package/dist/simulator/index.d.ts.map +1 -0
  90. package/dist/simulator/index.js +23 -0
  91. package/dist/simulator/index.js.map +1 -0
  92. package/{src/simulator/types.ts → dist/simulator/types.d.ts} +145 -170
  93. package/dist/simulator/types.d.ts.map +1 -0
  94. package/dist/simulator/types.js +18 -0
  95. package/dist/simulator/types.js.map +1 -0
  96. package/dist/types/generator.d.ts +106 -0
  97. package/dist/types/generator.d.ts.map +1 -0
  98. package/dist/types/generator.js +6 -0
  99. package/dist/types/generator.js.map +1 -0
  100. package/{src/types/index.ts → dist/types/index.d.ts} +1 -1
  101. package/dist/types/index.d.ts.map +1 -0
  102. package/dist/types/index.js +23 -0
  103. package/dist/types/index.js.map +1 -0
  104. package/dist/types/ucp-profile.d.ts +103 -0
  105. package/dist/types/ucp-profile.d.ts.map +1 -0
  106. package/dist/types/ucp-profile.js +45 -0
  107. package/dist/types/ucp-profile.js.map +1 -0
  108. package/dist/types/validation.d.ts +68 -0
  109. package/dist/types/validation.d.ts.map +1 -0
  110. package/dist/types/validation.js +32 -0
  111. package/dist/types/validation.js.map +1 -0
  112. package/dist/validator/index.d.ts +26 -0
  113. package/dist/validator/index.d.ts.map +1 -0
  114. package/dist/validator/index.js +161 -0
  115. package/dist/validator/index.js.map +1 -0
  116. package/dist/validator/network-validator.d.ts +28 -0
  117. package/dist/validator/network-validator.d.ts.map +1 -0
  118. package/dist/validator/network-validator.js +319 -0
  119. package/dist/validator/network-validator.js.map +1 -0
  120. package/dist/validator/rules-validator.d.ts +11 -0
  121. package/dist/validator/rules-validator.d.ts.map +1 -0
  122. package/dist/validator/rules-validator.js +257 -0
  123. package/dist/validator/rules-validator.js.map +1 -0
  124. package/dist/validator/sdk-validator.d.ts +58 -0
  125. package/dist/validator/sdk-validator.d.ts.map +1 -0
  126. package/{src/validator/sdk-validator.ts → dist/validator/sdk-validator.js} +273 -330
  127. package/dist/validator/sdk-validator.js.map +1 -0
  128. package/dist/validator/structural-validator.d.ts +11 -0
  129. package/dist/validator/structural-validator.d.ts.map +1 -0
  130. package/dist/validator/structural-validator.js +415 -0
  131. package/dist/validator/structural-validator.js.map +1 -0
  132. package/package.json +1 -1
  133. package/publish-output.txt +0 -0
  134. package/CLAUDE.md +0 -109
  135. package/api/analyze-feed.js +0 -140
  136. package/api/badge.js +0 -185
  137. package/api/benchmark.js +0 -177
  138. package/api/directory-stats.ts +0 -29
  139. package/api/directory.ts +0 -73
  140. package/api/generate-compliance.js +0 -143
  141. package/api/generate-schema.js +0 -457
  142. package/api/generate.js +0 -132
  143. package/api/security-scan.js +0 -133
  144. package/api/simulate.js +0 -187
  145. package/api/tsconfig.json +0 -10
  146. package/api/validate.js +0 -1351
  147. package/apify-actor/.actor/actor.json +0 -68
  148. package/apify-actor/.actor/input_schema.json +0 -32
  149. package/apify-actor/APIFY-STORE-LISTING.md +0 -412
  150. package/apify-actor/Dockerfile +0 -8
  151. package/apify-actor/README.md +0 -166
  152. package/apify-actor/main.ts +0 -111
  153. package/apify-actor/package.json +0 -17
  154. package/apify-actor/src/main.js +0 -199
  155. package/docs/BRAND-IDENTITY.md +0 -238
  156. package/docs/BRAND-STYLE-GUIDE.md +0 -356
  157. package/drizzle/0000_black_king_cobra.sql +0 -39
  158. package/drizzle/meta/0000_snapshot.json +0 -309
  159. package/drizzle/meta/_journal.json +0 -13
  160. package/drizzle.config.ts +0 -10
  161. package/public/.well-known/ucp +0 -25
  162. package/public/android-chrome-192x192.png +0 -0
  163. package/public/android-chrome-512x512.png +0 -0
  164. package/public/apple-touch-icon.png +0 -0
  165. package/public/brand.css +0 -321
  166. package/public/directory.html +0 -701
  167. package/public/favicon-16x16.png +0 -0
  168. package/public/favicon-32x32.png +0 -0
  169. package/public/favicon.ico +0 -0
  170. package/public/guides/bigcommerce.html +0 -743
  171. package/public/guides/fastucp.html +0 -838
  172. package/public/guides/magento.html +0 -779
  173. package/public/guides/shopify.html +0 -726
  174. package/public/guides/squarespace.html +0 -749
  175. package/public/guides/wix.html +0 -747
  176. package/public/guides/woocommerce.html +0 -733
  177. package/public/index.html +0 -3835
  178. package/public/learn.html +0 -396
  179. package/public/logo.jpeg +0 -0
  180. package/public/og-image-icon.png +0 -0
  181. package/public/og-image.png +0 -0
  182. package/public/robots.txt +0 -6
  183. package/public/site.webmanifest +0 -31
  184. package/public/sitemap.xml +0 -69
  185. package/public/social/linkedin-banner-1128x191.png +0 -0
  186. package/public/social/temp.PNG +0 -0
  187. package/public/social/x-header-1500x500.png +0 -0
  188. package/public/verify.html +0 -410
  189. package/scripts/generate-favicons.js +0 -44
  190. package/scripts/generate-ico.js +0 -23
  191. package/scripts/generate-og-image.js +0 -45
  192. package/scripts/reset-db.ts +0 -77
  193. package/scripts/seed-db.ts +0 -71
  194. package/scripts/setup-benchmark-db.js +0 -70
  195. package/src/api/server.ts +0 -266
  196. package/src/cli/index.ts +0 -302
  197. package/src/compliance/compliance-generator.ts +0 -452
  198. package/src/compliance/index.ts +0 -28
  199. package/src/compliance/types.ts +0 -170
  200. package/src/db/index.ts +0 -28
  201. package/src/db/schema.ts +0 -84
  202. package/src/feed-analyzer/index.ts +0 -34
  203. package/src/feed-analyzer/types.ts +0 -354
  204. package/src/generator/key-generator.ts +0 -124
  205. package/src/generator/profile-builder.ts +0 -402
  206. package/src/index.ts +0 -105
  207. package/src/security/security-scanner.ts +0 -604
  208. package/src/security/types.ts +0 -55
  209. package/src/services/directory.ts +0 -434
  210. package/src/types/generator.ts +0 -140
  211. package/src/types/ucp-profile.ts +0 -140
  212. package/src/types/validation.ts +0 -89
  213. package/src/validator/index.ts +0 -194
  214. package/src/validator/network-validator.ts +0 -417
  215. package/src/validator/rules-validator.ts +0 -297
  216. package/src/validator/structural-validator.ts +0 -476
  217. package/tests/fixtures/non-compliant-profile.json +0 -25
  218. package/tests/fixtures/official-sample-profile.json +0 -75
  219. package/tests/integration/benchmark.test.ts +0 -207
  220. package/tests/integration/database.test.ts +0 -163
  221. package/tests/integration/directory-api.test.ts +0 -268
  222. package/tests/integration/simulate-api.test.ts +0 -230
  223. package/tests/integration/validate-api.test.ts +0 -269
  224. package/tests/setup.ts +0 -15
  225. package/tests/unit/agent-simulator.test.ts +0 -575
  226. package/tests/unit/compliance-generator.test.ts +0 -374
  227. package/tests/unit/directory-service.test.ts +0 -272
  228. package/tests/unit/feed-analyzer.test.ts +0 -517
  229. package/tests/unit/lint-suggestions.test.ts +0 -423
  230. package/tests/unit/official-samples.test.ts +0 -211
  231. package/tests/unit/pdf-report.test.ts +0 -390
  232. package/tests/unit/sdk-validator.test.ts +0 -531
  233. package/tests/unit/security-scanner.test.ts +0 -410
  234. package/tests/unit/validation.test.ts +0 -390
  235. package/vercel.json +0 -34
  236. package/vitest.config.ts +0 -22
@@ -1,531 +0,0 @@
1
- /**
2
- * Tests for SDK-based Validator
3
- * Tests validation using the official @ucp-js/sdk Zod schemas
4
- */
5
-
6
- import { describe, it, expect } from 'vitest';
7
- import { readFileSync } from 'fs';
8
- import { join } from 'path';
9
- import {
10
- validateWithSdk,
11
- safeValidateWithSdk,
12
- validateUcpObject,
13
- validateServiceWithSdk,
14
- validateCapabilityWithSdk,
15
- validateSigningKeysWithSdk,
16
- isSdkCompliant,
17
- getSdkVersion,
18
- } from '../../src/validator/sdk-validator.js';
19
-
20
- // Load test fixtures
21
- const fixturesDir = join(process.cwd(), 'tests', 'fixtures');
22
- const officialSampleProfile = JSON.parse(
23
- readFileSync(join(fixturesDir, 'official-sample-profile.json'), 'utf-8')
24
- );
25
- const nonCompliantProfile = JSON.parse(
26
- readFileSync(join(fixturesDir, 'non-compliant-profile.json'), 'utf-8')
27
- );
28
-
29
- describe('SDK Validator', () => {
30
- describe('getSdkVersion', () => {
31
- it('should return the SDK version', () => {
32
- const version = getSdkVersion();
33
- expect(version).toBe('0.1.0');
34
- });
35
- });
36
-
37
- describe('isSdkCompliant', () => {
38
- it('should return true for official sample profile', () => {
39
- expect(isSdkCompliant(officialSampleProfile)).toBe(true);
40
- });
41
-
42
- it('should return false for non-compliant profile', () => {
43
- expect(isSdkCompliant(nonCompliantProfile)).toBe(false);
44
- });
45
-
46
- it('should return false for empty object', () => {
47
- expect(isSdkCompliant({})).toBe(false);
48
- });
49
-
50
- it('should return false for null', () => {
51
- expect(isSdkCompliant(null)).toBe(false);
52
- });
53
- });
54
-
55
- describe('validateWithSdk', () => {
56
- it('should validate official sample profile successfully', () => {
57
- const result = validateWithSdk(officialSampleProfile);
58
-
59
- expect(result.valid).toBe(true);
60
- expect(result.issues).toHaveLength(0);
61
- expect(result.sdkVersion).toBe('0.1.0');
62
- expect(result.parsedProfile).toBeDefined();
63
- });
64
-
65
- it('should return issues for non-compliant profile', () => {
66
- const result = validateWithSdk(nonCompliantProfile);
67
-
68
- expect(result.valid).toBe(false);
69
- expect(result.issues.length).toBeGreaterThan(0);
70
- expect(result.sdkVersion).toBe('0.1.0');
71
- });
72
-
73
- it('should validate profile with all optional fields', () => {
74
- const fullProfile = {
75
- ucp: {
76
- version: '2026-01-15',
77
- services: {
78
- 'dev.ucp.shopping': {
79
- version: '2026-01-15',
80
- spec: 'https://ucp.dev/specs/shopping',
81
- rest: {
82
- endpoint: 'https://example.com/api',
83
- schema: 'https://ucp.dev/schemas/shopping.json',
84
- },
85
- },
86
- },
87
- capabilities: [
88
- {
89
- name: 'dev.ucp.shopping.checkout',
90
- version: '2026-01-15',
91
- spec: 'https://ucp.dev/specs/shopping/checkout',
92
- schema: 'https://ucp.dev/schemas/shopping/checkout.json',
93
- },
94
- ],
95
- },
96
- signing_keys: [
97
- {
98
- kty: 'EC',
99
- kid: 'key-1',
100
- crv: 'P-256',
101
- x: 'test-x',
102
- y: 'test-y',
103
- use: 'sig',
104
- },
105
- ],
106
- };
107
-
108
- const result = validateWithSdk(fullProfile);
109
- expect(result.valid).toBe(true);
110
- });
111
- });
112
-
113
- describe('safeValidateWithSdk', () => {
114
- it('should not throw for invalid input', () => {
115
- expect(() => safeValidateWithSdk(null)).not.toThrow();
116
- expect(() => safeValidateWithSdk(undefined)).not.toThrow();
117
- expect(() => safeValidateWithSdk('string')).not.toThrow();
118
- expect(() => safeValidateWithSdk(123)).not.toThrow();
119
- });
120
-
121
- it('should return valid: false for invalid profiles', () => {
122
- const result = safeValidateWithSdk({ invalid: true });
123
- expect(result.valid).toBe(false);
124
- expect(result.issues.length).toBeGreaterThan(0);
125
- });
126
- });
127
-
128
- describe('validateUcpObject', () => {
129
- it('should validate ucp object from official sample', () => {
130
- const result = validateUcpObject(officialSampleProfile.ucp);
131
- expect(result.valid).toBe(true);
132
- expect(result.issues).toHaveLength(0);
133
- });
134
-
135
- it('should fail for ucp object from non-compliant profile', () => {
136
- const result = validateUcpObject(nonCompliantProfile.ucp);
137
- expect(result.valid).toBe(false);
138
- expect(result.issues.length).toBeGreaterThan(0);
139
- });
140
-
141
- it('should validate minimal ucp object', () => {
142
- const minimalUcp = {
143
- version: '2026-01-15',
144
- services: {
145
- 'dev.ucp.shopping': {
146
- version: '2026-01-15',
147
- spec: 'https://ucp.dev/specs/shopping',
148
- rest: {
149
- endpoint: 'https://example.com/api',
150
- schema: 'https://ucp.dev/schemas/shopping.json',
151
- },
152
- },
153
- },
154
- capabilities: [
155
- {
156
- name: 'dev.ucp.shopping.checkout',
157
- version: '2026-01-15',
158
- spec: 'https://ucp.dev/specs/checkout',
159
- schema: 'https://ucp.dev/schemas/checkout.json',
160
- },
161
- ],
162
- };
163
-
164
- const result = validateUcpObject(minimalUcp);
165
- expect(result.valid).toBe(true);
166
- });
167
- });
168
-
169
- describe('validateServiceWithSdk', () => {
170
- it('should validate a properly structured service', () => {
171
- const service = {
172
- version: '2026-01-15',
173
- spec: 'https://ucp.dev/specs/shopping',
174
- rest: {
175
- endpoint: 'https://example.com/api',
176
- schema: 'https://ucp.dev/schemas/shopping.json',
177
- },
178
- };
179
-
180
- const result = validateServiceWithSdk('dev.ucp.shopping', service);
181
- expect(result.valid).toBe(true);
182
- });
183
-
184
- it('should fail for service missing version', () => {
185
- const service = {
186
- spec: 'https://ucp.dev/specs/shopping',
187
- rest: {
188
- endpoint: 'https://example.com/api',
189
- schema: 'https://ucp.dev/schemas/shopping.json',
190
- },
191
- };
192
-
193
- const result = validateServiceWithSdk('dev.ucp.shopping', service);
194
- expect(result.valid).toBe(false);
195
- expect(result.issues.some(i => i.path.includes('version'))).toBe(true);
196
- });
197
-
198
- it('should fail for service missing spec', () => {
199
- const service = {
200
- version: '2026-01-15',
201
- rest: {
202
- endpoint: 'https://example.com/api',
203
- schema: 'https://ucp.dev/schemas/shopping.json',
204
- },
205
- };
206
-
207
- const result = validateServiceWithSdk('dev.ucp.shopping', service);
208
- expect(result.valid).toBe(false);
209
- expect(result.issues.some(i => i.path.includes('spec'))).toBe(true);
210
- });
211
-
212
- it('should validate service with MCP transport', () => {
213
- const service = {
214
- version: '2026-01-15',
215
- spec: 'https://ucp.dev/specs/shopping',
216
- mcp: {
217
- endpoint: 'https://example.com/mcp',
218
- schema: 'https://ucp.dev/schemas/shopping.json',
219
- },
220
- };
221
-
222
- const result = validateServiceWithSdk('dev.ucp.shopping', service);
223
- expect(result.valid).toBe(true);
224
- });
225
-
226
- it('should validate service with A2A transport', () => {
227
- const service = {
228
- version: '2026-01-15',
229
- spec: 'https://ucp.dev/specs/shopping',
230
- a2a: {
231
- endpoint: 'https://example.com/a2a',
232
- },
233
- };
234
-
235
- const result = validateServiceWithSdk('dev.ucp.shopping', service);
236
- expect(result.valid).toBe(true);
237
- });
238
- });
239
-
240
- describe('validateCapabilityWithSdk', () => {
241
- it('should validate a properly structured capability', () => {
242
- const capability = {
243
- name: 'dev.ucp.shopping.checkout',
244
- version: '2026-01-15',
245
- spec: 'https://ucp.dev/specs/checkout',
246
- schema: 'https://ucp.dev/schemas/checkout.json',
247
- };
248
-
249
- const result = validateCapabilityWithSdk(0, capability);
250
- expect(result.valid).toBe(true);
251
- });
252
-
253
- it('should fail for capability missing name', () => {
254
- const capability = {
255
- version: '2026-01-15',
256
- spec: 'https://ucp.dev/specs/checkout',
257
- schema: 'https://ucp.dev/schemas/checkout.json',
258
- };
259
-
260
- const result = validateCapabilityWithSdk(0, capability);
261
- expect(result.valid).toBe(false);
262
- });
263
-
264
- it('should validate capability with extends field', () => {
265
- const capability = {
266
- name: 'dev.ucp.shopping.fulfillment',
267
- version: '2026-01-15',
268
- spec: 'https://ucp.dev/specs/fulfillment',
269
- schema: 'https://ucp.dev/schemas/fulfillment.json',
270
- extends: 'dev.ucp.shopping.order',
271
- };
272
-
273
- const result = validateCapabilityWithSdk(0, capability);
274
- expect(result.valid).toBe(true);
275
- });
276
-
277
- it('should validate capability with config field', () => {
278
- const capability = {
279
- name: 'dev.ucp.shopping.checkout',
280
- version: '2026-01-15',
281
- spec: 'https://ucp.dev/specs/checkout',
282
- schema: 'https://ucp.dev/schemas/checkout.json',
283
- config: {
284
- supported_currencies: ['USD', 'EUR'],
285
- max_items: 100,
286
- },
287
- };
288
-
289
- const result = validateCapabilityWithSdk(0, capability);
290
- expect(result.valid).toBe(true);
291
- });
292
- });
293
-
294
- describe('validateSigningKeysWithSdk', () => {
295
- it('should validate properly structured signing keys', () => {
296
- const signingKeys = [
297
- {
298
- kty: 'EC',
299
- kid: 'key-1',
300
- crv: 'P-256',
301
- x: 'test-x-coordinate',
302
- y: 'test-y-coordinate',
303
- use: 'sig',
304
- },
305
- ];
306
-
307
- const result = validateSigningKeysWithSdk(signingKeys);
308
- expect(result.valid).toBe(true);
309
- });
310
-
311
- it('should validate RSA signing keys', () => {
312
- const signingKeys = [
313
- {
314
- kty: 'RSA',
315
- kid: 'rsa-key-1',
316
- n: 'test-modulus',
317
- e: 'AQAB',
318
- use: 'sig',
319
- },
320
- ];
321
-
322
- const result = validateSigningKeysWithSdk(signingKeys);
323
- expect(result.valid).toBe(true);
324
- });
325
-
326
- it('should fail for signing keys missing kty', () => {
327
- const signingKeys = [
328
- {
329
- kid: 'key-1',
330
- crv: 'P-256',
331
- x: 'test-x',
332
- y: 'test-y',
333
- },
334
- ];
335
-
336
- const result = validateSigningKeysWithSdk(signingKeys);
337
- expect(result.valid).toBe(false);
338
- });
339
-
340
- it('should fail for signing keys missing kid', () => {
341
- const signingKeys = [
342
- {
343
- kty: 'EC',
344
- crv: 'P-256',
345
- x: 'test-x',
346
- y: 'test-y',
347
- },
348
- ];
349
-
350
- const result = validateSigningKeysWithSdk(signingKeys);
351
- expect(result.valid).toBe(false);
352
- });
353
-
354
- it('should validate empty signing keys array', () => {
355
- const result = validateSigningKeysWithSdk([]);
356
- expect(result.valid).toBe(true);
357
- });
358
-
359
- it('should fail for non-array signing keys', () => {
360
- const result = validateSigningKeysWithSdk({ keys: [] });
361
- expect(result.valid).toBe(false);
362
- });
363
- });
364
-
365
- describe('Error Path Mapping', () => {
366
- it('should correctly map nested paths', () => {
367
- const invalidProfile = {
368
- ucp: {
369
- version: '2026-01-15',
370
- services: {
371
- 'dev.ucp.shopping': {
372
- version: 123, // Should be string
373
- spec: 'https://ucp.dev/specs/shopping',
374
- rest: {
375
- endpoint: 'https://example.com/api',
376
- schema: 'https://ucp.dev/schemas/shopping.json',
377
- },
378
- },
379
- },
380
- capabilities: [
381
- {
382
- name: 'dev.ucp.shopping.checkout',
383
- version: '2026-01-15',
384
- spec: 'https://ucp.dev/specs/checkout',
385
- schema: 'https://ucp.dev/schemas/checkout.json',
386
- },
387
- ],
388
- },
389
- };
390
-
391
- const result = safeValidateWithSdk(invalidProfile);
392
- expect(result.valid).toBe(false);
393
- // Should have path like $.ucp.services.dev.ucp.shopping.version
394
- const versionIssue = result.issues.find(i => i.path.includes('version'));
395
- expect(versionIssue).toBeDefined();
396
- });
397
-
398
- it('should map array paths correctly', () => {
399
- const invalidProfile = {
400
- ucp: {
401
- version: '2026-01-15',
402
- services: {},
403
- capabilities: [
404
- null, // Invalid capability
405
- ],
406
- },
407
- };
408
-
409
- const result = safeValidateWithSdk(invalidProfile);
410
- expect(result.valid).toBe(false);
411
- // Should have path like $.ucp.capabilities[0]
412
- const capIssue = result.issues.find(i => i.path.includes('capabilities'));
413
- expect(capIssue).toBeDefined();
414
- });
415
- });
416
-
417
- describe('SDK Compliant Profile Variations', () => {
418
- it('should validate profile with multiple services', () => {
419
- const profile = {
420
- ucp: {
421
- version: '2026-01-15',
422
- services: {
423
- 'dev.ucp.shopping': {
424
- version: '2026-01-15',
425
- spec: 'https://ucp.dev/specs/shopping',
426
- rest: {
427
- endpoint: 'https://example.com/api/shopping',
428
- schema: 'https://ucp.dev/schemas/shopping.json',
429
- },
430
- },
431
- 'com.example.custom': {
432
- version: '2026-01-15',
433
- spec: 'https://example.com/specs/custom',
434
- rest: {
435
- endpoint: 'https://example.com/api/custom',
436
- schema: 'https://example.com/schemas/custom.json',
437
- },
438
- },
439
- },
440
- capabilities: [
441
- {
442
- name: 'dev.ucp.shopping.checkout',
443
- version: '2026-01-15',
444
- spec: 'https://ucp.dev/specs/checkout',
445
- schema: 'https://ucp.dev/schemas/checkout.json',
446
- },
447
- ],
448
- },
449
- };
450
-
451
- const result = validateWithSdk(profile);
452
- expect(result.valid).toBe(true);
453
- });
454
-
455
- it('should validate profile with multiple transports on same service', () => {
456
- const profile = {
457
- ucp: {
458
- version: '2026-01-15',
459
- services: {
460
- 'dev.ucp.shopping': {
461
- version: '2026-01-15',
462
- spec: 'https://ucp.dev/specs/shopping',
463
- rest: {
464
- endpoint: 'https://example.com/api',
465
- schema: 'https://ucp.dev/schemas/shopping.json',
466
- },
467
- mcp: {
468
- endpoint: 'https://example.com/mcp',
469
- schema: 'https://ucp.dev/schemas/shopping-mcp.json',
470
- },
471
- },
472
- },
473
- capabilities: [
474
- {
475
- name: 'dev.ucp.shopping.checkout',
476
- version: '2026-01-15',
477
- spec: 'https://ucp.dev/specs/checkout',
478
- schema: 'https://ucp.dev/schemas/checkout.json',
479
- },
480
- ],
481
- },
482
- };
483
-
484
- const result = validateWithSdk(profile);
485
- expect(result.valid).toBe(true);
486
- });
487
-
488
- it('should validate profile with capability extension chain', () => {
489
- const profile = {
490
- ucp: {
491
- version: '2026-01-15',
492
- services: {
493
- 'dev.ucp.shopping': {
494
- version: '2026-01-15',
495
- spec: 'https://ucp.dev/specs/shopping',
496
- rest: {
497
- endpoint: 'https://example.com/api',
498
- schema: 'https://ucp.dev/schemas/shopping.json',
499
- },
500
- },
501
- },
502
- capabilities: [
503
- {
504
- name: 'dev.ucp.shopping.checkout',
505
- version: '2026-01-15',
506
- spec: 'https://ucp.dev/specs/checkout',
507
- schema: 'https://ucp.dev/schemas/checkout.json',
508
- },
509
- {
510
- name: 'dev.ucp.shopping.order',
511
- version: '2026-01-15',
512
- spec: 'https://ucp.dev/specs/order',
513
- schema: 'https://ucp.dev/schemas/order.json',
514
- extends: 'dev.ucp.shopping.checkout',
515
- },
516
- {
517
- name: 'dev.ucp.shopping.fulfillment',
518
- version: '2026-01-15',
519
- spec: 'https://ucp.dev/specs/fulfillment',
520
- schema: 'https://ucp.dev/schemas/fulfillment.json',
521
- extends: 'dev.ucp.shopping.order',
522
- },
523
- ],
524
- },
525
- };
526
-
527
- const result = validateWithSdk(profile);
528
- expect(result.valid).toBe(true);
529
- });
530
- });
531
- });