@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.
- package/.claude/settings.local.json +60 -0
- package/.vercel/README.txt +11 -0
- package/.vercel/project.json +1 -0
- package/dist/cli/index.d.ts +6 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +279 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/compliance/compliance-generator.d.ts +34 -0
- package/dist/compliance/compliance-generator.d.ts.map +1 -0
- package/dist/compliance/compliance-generator.js +320 -0
- package/dist/compliance/compliance-generator.js.map +1 -0
- package/dist/compliance/index.d.ts +8 -0
- package/dist/compliance/index.d.ts.map +1 -0
- package/dist/compliance/index.js +17 -0
- package/dist/compliance/index.js.map +1 -0
- package/dist/compliance/templates.d.ts +34 -0
- package/dist/compliance/templates.d.ts.map +1 -0
- package/{src/compliance/templates.ts → dist/compliance/templates.js} +117 -155
- package/dist/compliance/templates.js.map +1 -0
- package/dist/compliance/types.d.ts +64 -0
- package/dist/compliance/types.d.ts.map +1 -0
- package/dist/compliance/types.js +64 -0
- package/dist/compliance/types.js.map +1 -0
- package/dist/db/index.d.ts +11 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +63 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/schema.d.ts +444 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +65 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/feed-analyzer/feed-analyzer.d.ts +26 -0
- package/dist/feed-analyzer/feed-analyzer.d.ts.map +1 -0
- package/{src/feed-analyzer/feed-analyzer.ts → dist/feed-analyzer/feed-analyzer.js} +642 -726
- package/dist/feed-analyzer/feed-analyzer.js.map +1 -0
- package/dist/feed-analyzer/index.d.ts +8 -0
- package/dist/feed-analyzer/index.d.ts.map +1 -0
- package/dist/feed-analyzer/index.js +19 -0
- package/dist/feed-analyzer/index.js.map +1 -0
- package/dist/feed-analyzer/types.d.ts +204 -0
- package/dist/feed-analyzer/types.d.ts.map +1 -0
- package/dist/feed-analyzer/types.js +162 -0
- package/dist/feed-analyzer/types.js.map +1 -0
- package/{src/generator/index.ts → dist/generator/index.d.ts} +1 -1
- package/dist/generator/index.d.ts.map +1 -0
- package/dist/generator/index.js +13 -0
- package/dist/generator/index.js.map +1 -0
- package/dist/generator/key-generator.d.ts +24 -0
- package/dist/generator/key-generator.d.ts.map +1 -0
- package/dist/generator/key-generator.js +144 -0
- package/dist/generator/key-generator.js.map +1 -0
- package/dist/generator/profile-builder.d.ts +15 -0
- package/dist/generator/profile-builder.d.ts.map +1 -0
- package/dist/generator/profile-builder.js +338 -0
- package/dist/generator/profile-builder.js.map +1 -0
- package/dist/hosting/artifacts-generator.d.ts +10 -0
- package/dist/hosting/artifacts-generator.d.ts.map +1 -0
- package/{src/hosting/artifacts-generator.ts → dist/hosting/artifacts-generator.js} +191 -241
- package/dist/hosting/artifacts-generator.js.map +1 -0
- package/{src/hosting/index.ts → dist/hosting/index.d.ts} +1 -1
- package/dist/hosting/index.d.ts.map +1 -0
- package/dist/hosting/index.js +10 -0
- package/dist/hosting/index.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +78 -0
- package/dist/index.js.map +1 -0
- package/{src/security/index.ts → dist/security/index.d.ts} +8 -15
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +12 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/security-scanner.d.ts +10 -0
- package/dist/security/security-scanner.d.ts.map +1 -0
- package/dist/security/security-scanner.js +541 -0
- package/dist/security/security-scanner.js.map +1 -0
- package/dist/security/types.d.ts +48 -0
- package/dist/security/types.d.ts.map +1 -0
- package/dist/security/types.js +21 -0
- package/dist/security/types.js.map +1 -0
- package/dist/services/directory.d.ts +104 -0
- package/dist/services/directory.d.ts.map +1 -0
- package/dist/services/directory.js +333 -0
- package/dist/services/directory.js.map +1 -0
- package/dist/simulator/agent-simulator.d.ts +69 -0
- package/dist/simulator/agent-simulator.d.ts.map +1 -0
- package/{src/simulator/agent-simulator.ts → dist/simulator/agent-simulator.js} +650 -941
- package/dist/simulator/agent-simulator.js.map +1 -0
- package/{src/simulator/index.ts → dist/simulator/index.d.ts} +7 -7
- package/dist/simulator/index.d.ts.map +1 -0
- package/dist/simulator/index.js +23 -0
- package/dist/simulator/index.js.map +1 -0
- package/{src/simulator/types.ts → dist/simulator/types.d.ts} +145 -170
- package/dist/simulator/types.d.ts.map +1 -0
- package/dist/simulator/types.js +18 -0
- package/dist/simulator/types.js.map +1 -0
- package/dist/types/generator.d.ts +106 -0
- package/dist/types/generator.d.ts.map +1 -0
- package/dist/types/generator.js +6 -0
- package/dist/types/generator.js.map +1 -0
- package/{src/types/index.ts → dist/types/index.d.ts} +1 -1
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +23 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/ucp-profile.d.ts +103 -0
- package/dist/types/ucp-profile.d.ts.map +1 -0
- package/dist/types/ucp-profile.js +45 -0
- package/dist/types/ucp-profile.js.map +1 -0
- package/dist/types/validation.d.ts +68 -0
- package/dist/types/validation.d.ts.map +1 -0
- package/dist/types/validation.js +32 -0
- package/dist/types/validation.js.map +1 -0
- package/dist/validator/index.d.ts +26 -0
- package/dist/validator/index.d.ts.map +1 -0
- package/dist/validator/index.js +161 -0
- package/dist/validator/index.js.map +1 -0
- package/dist/validator/network-validator.d.ts +28 -0
- package/dist/validator/network-validator.d.ts.map +1 -0
- package/dist/validator/network-validator.js +319 -0
- package/dist/validator/network-validator.js.map +1 -0
- package/dist/validator/rules-validator.d.ts +11 -0
- package/dist/validator/rules-validator.d.ts.map +1 -0
- package/dist/validator/rules-validator.js +257 -0
- package/dist/validator/rules-validator.js.map +1 -0
- package/dist/validator/sdk-validator.d.ts +58 -0
- package/dist/validator/sdk-validator.d.ts.map +1 -0
- package/{src/validator/sdk-validator.ts → dist/validator/sdk-validator.js} +273 -330
- package/dist/validator/sdk-validator.js.map +1 -0
- package/dist/validator/structural-validator.d.ts +11 -0
- package/dist/validator/structural-validator.d.ts.map +1 -0
- package/dist/validator/structural-validator.js +415 -0
- package/dist/validator/structural-validator.js.map +1 -0
- package/package.json +1 -1
- package/publish-output.txt +0 -0
- package/CLAUDE.md +0 -109
- package/api/analyze-feed.js +0 -140
- package/api/badge.js +0 -185
- package/api/benchmark.js +0 -177
- package/api/directory-stats.ts +0 -29
- package/api/directory.ts +0 -73
- package/api/generate-compliance.js +0 -143
- package/api/generate-schema.js +0 -457
- package/api/generate.js +0 -132
- package/api/security-scan.js +0 -133
- package/api/simulate.js +0 -187
- package/api/tsconfig.json +0 -10
- package/api/validate.js +0 -1351
- package/apify-actor/.actor/actor.json +0 -68
- package/apify-actor/.actor/input_schema.json +0 -32
- package/apify-actor/APIFY-STORE-LISTING.md +0 -412
- package/apify-actor/Dockerfile +0 -8
- package/apify-actor/README.md +0 -166
- package/apify-actor/main.ts +0 -111
- package/apify-actor/package.json +0 -17
- package/apify-actor/src/main.js +0 -199
- package/docs/BRAND-IDENTITY.md +0 -238
- package/docs/BRAND-STYLE-GUIDE.md +0 -356
- package/drizzle/0000_black_king_cobra.sql +0 -39
- package/drizzle/meta/0000_snapshot.json +0 -309
- package/drizzle/meta/_journal.json +0 -13
- package/drizzle.config.ts +0 -10
- package/public/.well-known/ucp +0 -25
- package/public/android-chrome-192x192.png +0 -0
- package/public/android-chrome-512x512.png +0 -0
- package/public/apple-touch-icon.png +0 -0
- package/public/brand.css +0 -321
- package/public/directory.html +0 -701
- package/public/favicon-16x16.png +0 -0
- package/public/favicon-32x32.png +0 -0
- package/public/favicon.ico +0 -0
- package/public/guides/bigcommerce.html +0 -743
- package/public/guides/fastucp.html +0 -838
- package/public/guides/magento.html +0 -779
- package/public/guides/shopify.html +0 -726
- package/public/guides/squarespace.html +0 -749
- package/public/guides/wix.html +0 -747
- package/public/guides/woocommerce.html +0 -733
- package/public/index.html +0 -3835
- package/public/learn.html +0 -396
- package/public/logo.jpeg +0 -0
- package/public/og-image-icon.png +0 -0
- package/public/og-image.png +0 -0
- package/public/robots.txt +0 -6
- package/public/site.webmanifest +0 -31
- package/public/sitemap.xml +0 -69
- package/public/social/linkedin-banner-1128x191.png +0 -0
- package/public/social/temp.PNG +0 -0
- package/public/social/x-header-1500x500.png +0 -0
- package/public/verify.html +0 -410
- package/scripts/generate-favicons.js +0 -44
- package/scripts/generate-ico.js +0 -23
- package/scripts/generate-og-image.js +0 -45
- package/scripts/reset-db.ts +0 -77
- package/scripts/seed-db.ts +0 -71
- package/scripts/setup-benchmark-db.js +0 -70
- package/src/api/server.ts +0 -266
- package/src/cli/index.ts +0 -302
- package/src/compliance/compliance-generator.ts +0 -452
- package/src/compliance/index.ts +0 -28
- package/src/compliance/types.ts +0 -170
- package/src/db/index.ts +0 -28
- package/src/db/schema.ts +0 -84
- package/src/feed-analyzer/index.ts +0 -34
- package/src/feed-analyzer/types.ts +0 -354
- package/src/generator/key-generator.ts +0 -124
- package/src/generator/profile-builder.ts +0 -402
- package/src/index.ts +0 -105
- package/src/security/security-scanner.ts +0 -604
- package/src/security/types.ts +0 -55
- package/src/services/directory.ts +0 -434
- package/src/types/generator.ts +0 -140
- package/src/types/ucp-profile.ts +0 -140
- package/src/types/validation.ts +0 -89
- package/src/validator/index.ts +0 -194
- package/src/validator/network-validator.ts +0 -417
- package/src/validator/rules-validator.ts +0 -297
- package/src/validator/structural-validator.ts +0 -476
- package/tests/fixtures/non-compliant-profile.json +0 -25
- package/tests/fixtures/official-sample-profile.json +0 -75
- package/tests/integration/benchmark.test.ts +0 -207
- package/tests/integration/database.test.ts +0 -163
- package/tests/integration/directory-api.test.ts +0 -268
- package/tests/integration/simulate-api.test.ts +0 -230
- package/tests/integration/validate-api.test.ts +0 -269
- package/tests/setup.ts +0 -15
- package/tests/unit/agent-simulator.test.ts +0 -575
- package/tests/unit/compliance-generator.test.ts +0 -374
- package/tests/unit/directory-service.test.ts +0 -272
- package/tests/unit/feed-analyzer.test.ts +0 -517
- package/tests/unit/lint-suggestions.test.ts +0 -423
- package/tests/unit/official-samples.test.ts +0 -211
- package/tests/unit/pdf-report.test.ts +0 -390
- package/tests/unit/sdk-validator.test.ts +0 -531
- package/tests/unit/security-scanner.test.ts +0 -410
- package/tests/unit/validation.test.ts +0 -390
- package/vercel.json +0 -34
- package/vitest.config.ts +0 -22
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Structural Validator
|
|
4
|
+
* Validates UCP Profile JSON structure (no network calls)
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.validateStructure = validateStructure;
|
|
8
|
+
const validation_js_1 = require("../types/validation.js");
|
|
9
|
+
/**
|
|
10
|
+
* Version format regex (YYYY-MM-DD)
|
|
11
|
+
*/
|
|
12
|
+
const VERSION_REGEX = /^\d{4}-\d{2}-\d{2}$/;
|
|
13
|
+
/**
|
|
14
|
+
* Validate the structural integrity of a UCP profile
|
|
15
|
+
* Returns an array of validation issues
|
|
16
|
+
*/
|
|
17
|
+
function validateStructure(profile) {
|
|
18
|
+
const issues = [];
|
|
19
|
+
// Check if it's an object
|
|
20
|
+
if (!profile || typeof profile !== 'object') {
|
|
21
|
+
issues.push({
|
|
22
|
+
severity: 'error',
|
|
23
|
+
code: validation_js_1.ValidationErrorCodes.MISSING_UCP_OBJECT,
|
|
24
|
+
path: '$',
|
|
25
|
+
message: 'Profile must be a JSON object',
|
|
26
|
+
hint: 'Ensure your profile is valid JSON and contains a root object',
|
|
27
|
+
});
|
|
28
|
+
return issues;
|
|
29
|
+
}
|
|
30
|
+
const profileObj = profile;
|
|
31
|
+
// Check for ucp root object
|
|
32
|
+
if (!profileObj.ucp || typeof profileObj.ucp !== 'object') {
|
|
33
|
+
issues.push({
|
|
34
|
+
severity: 'error',
|
|
35
|
+
code: validation_js_1.ValidationErrorCodes.MISSING_UCP_OBJECT,
|
|
36
|
+
path: '$.ucp',
|
|
37
|
+
message: 'Missing required "ucp" object at root level',
|
|
38
|
+
hint: 'Add a "ucp" object containing version, services, and capabilities',
|
|
39
|
+
});
|
|
40
|
+
return issues;
|
|
41
|
+
}
|
|
42
|
+
const ucp = profileObj.ucp;
|
|
43
|
+
// Validate version
|
|
44
|
+
issues.push(...validateVersion(ucp));
|
|
45
|
+
// Validate services
|
|
46
|
+
issues.push(...validateServices(ucp));
|
|
47
|
+
// Validate capabilities
|
|
48
|
+
issues.push(...validateCapabilities(ucp));
|
|
49
|
+
// Validate signing_keys if present
|
|
50
|
+
if (profileObj.signing_keys !== undefined) {
|
|
51
|
+
issues.push(...validateSigningKeys(profileObj.signing_keys));
|
|
52
|
+
}
|
|
53
|
+
return issues;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Validate UCP version field
|
|
57
|
+
*/
|
|
58
|
+
function validateVersion(ucp) {
|
|
59
|
+
const issues = [];
|
|
60
|
+
if (!ucp.version) {
|
|
61
|
+
issues.push({
|
|
62
|
+
severity: 'error',
|
|
63
|
+
code: validation_js_1.ValidationErrorCodes.MISSING_VERSION,
|
|
64
|
+
path: '$.ucp.version',
|
|
65
|
+
message: 'Missing required "version" field in ucp object',
|
|
66
|
+
hint: 'Add version field with format "YYYY-MM-DD" (e.g., "2026-01-11")',
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
else if (typeof ucp.version !== 'string') {
|
|
70
|
+
issues.push({
|
|
71
|
+
severity: 'error',
|
|
72
|
+
code: validation_js_1.ValidationErrorCodes.INVALID_VERSION_FORMAT,
|
|
73
|
+
path: '$.ucp.version',
|
|
74
|
+
message: 'Version must be a string',
|
|
75
|
+
hint: 'Use format "YYYY-MM-DD" (e.g., "2026-01-11")',
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
else if (!VERSION_REGEX.test(ucp.version)) {
|
|
79
|
+
issues.push({
|
|
80
|
+
severity: 'error',
|
|
81
|
+
code: validation_js_1.ValidationErrorCodes.INVALID_VERSION_FORMAT,
|
|
82
|
+
path: '$.ucp.version',
|
|
83
|
+
message: `Invalid version format: "${ucp.version}"`,
|
|
84
|
+
hint: 'Use format "YYYY-MM-DD" (e.g., "2026-01-11")',
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return issues;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Validate services object
|
|
91
|
+
*/
|
|
92
|
+
function validateServices(ucp) {
|
|
93
|
+
const issues = [];
|
|
94
|
+
if (!ucp.services) {
|
|
95
|
+
issues.push({
|
|
96
|
+
severity: 'error',
|
|
97
|
+
code: validation_js_1.ValidationErrorCodes.MISSING_SERVICES,
|
|
98
|
+
path: '$.ucp.services',
|
|
99
|
+
message: 'Missing required "services" field in ucp object',
|
|
100
|
+
hint: 'Add a services object with at least one service definition',
|
|
101
|
+
});
|
|
102
|
+
return issues;
|
|
103
|
+
}
|
|
104
|
+
if (typeof ucp.services !== 'object' || Array.isArray(ucp.services)) {
|
|
105
|
+
issues.push({
|
|
106
|
+
severity: 'error',
|
|
107
|
+
code: validation_js_1.ValidationErrorCodes.INVALID_SERVICE_STRUCTURE,
|
|
108
|
+
path: '$.ucp.services',
|
|
109
|
+
message: 'Services must be an object (not an array)',
|
|
110
|
+
hint: 'Use format: { "dev.ucp.shopping": { ... } }',
|
|
111
|
+
});
|
|
112
|
+
return issues;
|
|
113
|
+
}
|
|
114
|
+
const services = ucp.services;
|
|
115
|
+
// Check for at least one service
|
|
116
|
+
if (Object.keys(services).length === 0) {
|
|
117
|
+
issues.push({
|
|
118
|
+
severity: 'warn',
|
|
119
|
+
code: validation_js_1.ValidationErrorCodes.MISSING_SERVICES,
|
|
120
|
+
path: '$.ucp.services',
|
|
121
|
+
message: 'Services object is empty',
|
|
122
|
+
hint: 'Add at least one service (e.g., "dev.ucp.shopping")',
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
// Validate each service
|
|
126
|
+
for (const [serviceName, service] of Object.entries(services)) {
|
|
127
|
+
issues.push(...validateService(serviceName, service));
|
|
128
|
+
}
|
|
129
|
+
return issues;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Validate individual service definition
|
|
133
|
+
*/
|
|
134
|
+
function validateService(name, service) {
|
|
135
|
+
const issues = [];
|
|
136
|
+
const path = `$.ucp.services["${name}"]`;
|
|
137
|
+
if (!service || typeof service !== 'object') {
|
|
138
|
+
issues.push({
|
|
139
|
+
severity: 'error',
|
|
140
|
+
code: validation_js_1.ValidationErrorCodes.INVALID_SERVICE_STRUCTURE,
|
|
141
|
+
path,
|
|
142
|
+
message: `Service "${name}" must be an object`,
|
|
143
|
+
});
|
|
144
|
+
return issues;
|
|
145
|
+
}
|
|
146
|
+
const svc = service;
|
|
147
|
+
// Check required version
|
|
148
|
+
if (!svc.version) {
|
|
149
|
+
issues.push({
|
|
150
|
+
severity: 'error',
|
|
151
|
+
code: validation_js_1.ValidationErrorCodes.INVALID_SERVICE_STRUCTURE,
|
|
152
|
+
path: `${path}.version`,
|
|
153
|
+
message: `Service "${name}" missing required "version" field`,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
else if (typeof svc.version === 'string' && !VERSION_REGEX.test(svc.version)) {
|
|
157
|
+
issues.push({
|
|
158
|
+
severity: 'error',
|
|
159
|
+
code: validation_js_1.ValidationErrorCodes.INVALID_VERSION_FORMAT,
|
|
160
|
+
path: `${path}.version`,
|
|
161
|
+
message: `Invalid version format in service "${name}"`,
|
|
162
|
+
hint: 'Use format "YYYY-MM-DD"',
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
// Check required spec
|
|
166
|
+
if (!svc.spec) {
|
|
167
|
+
issues.push({
|
|
168
|
+
severity: 'error',
|
|
169
|
+
code: validation_js_1.ValidationErrorCodes.INVALID_SERVICE_STRUCTURE,
|
|
170
|
+
path: `${path}.spec`,
|
|
171
|
+
message: `Service "${name}" missing required "spec" field`,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
// Check for at least one transport
|
|
175
|
+
const hasTransport = svc.rest || svc.mcp || svc.a2a || svc.embedded;
|
|
176
|
+
if (!hasTransport) {
|
|
177
|
+
issues.push({
|
|
178
|
+
severity: 'warn',
|
|
179
|
+
code: validation_js_1.ValidationErrorCodes.INVALID_SERVICE_STRUCTURE,
|
|
180
|
+
path,
|
|
181
|
+
message: `Service "${name}" has no transport bindings`,
|
|
182
|
+
hint: 'Add at least one transport: rest, mcp, a2a, or embedded',
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
// Validate REST transport if present
|
|
186
|
+
if (svc.rest) {
|
|
187
|
+
issues.push(...validateRestTransport(svc.rest, `${path}.rest`));
|
|
188
|
+
}
|
|
189
|
+
// Validate MCP transport if present
|
|
190
|
+
if (svc.mcp) {
|
|
191
|
+
issues.push(...validateMcpTransport(svc.mcp, `${path}.mcp`));
|
|
192
|
+
}
|
|
193
|
+
return issues;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Validate REST transport binding
|
|
197
|
+
*/
|
|
198
|
+
function validateRestTransport(transport, path) {
|
|
199
|
+
const issues = [];
|
|
200
|
+
if (!transport || typeof transport !== 'object') {
|
|
201
|
+
issues.push({
|
|
202
|
+
severity: 'error',
|
|
203
|
+
code: validation_js_1.ValidationErrorCodes.INVALID_SERVICE_STRUCTURE,
|
|
204
|
+
path,
|
|
205
|
+
message: 'REST transport must be an object',
|
|
206
|
+
});
|
|
207
|
+
return issues;
|
|
208
|
+
}
|
|
209
|
+
const rest = transport;
|
|
210
|
+
if (!rest.schema) {
|
|
211
|
+
issues.push({
|
|
212
|
+
severity: 'error',
|
|
213
|
+
code: validation_js_1.ValidationErrorCodes.INVALID_SERVICE_STRUCTURE,
|
|
214
|
+
path: `${path}.schema`,
|
|
215
|
+
message: 'REST transport missing required "schema" field',
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
if (!rest.endpoint) {
|
|
219
|
+
issues.push({
|
|
220
|
+
severity: 'error',
|
|
221
|
+
code: validation_js_1.ValidationErrorCodes.INVALID_SERVICE_STRUCTURE,
|
|
222
|
+
path: `${path}.endpoint`,
|
|
223
|
+
message: 'REST transport missing required "endpoint" field',
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
return issues;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Validate MCP transport binding
|
|
230
|
+
*/
|
|
231
|
+
function validateMcpTransport(transport, path) {
|
|
232
|
+
const issues = [];
|
|
233
|
+
if (!transport || typeof transport !== 'object') {
|
|
234
|
+
issues.push({
|
|
235
|
+
severity: 'error',
|
|
236
|
+
code: validation_js_1.ValidationErrorCodes.INVALID_SERVICE_STRUCTURE,
|
|
237
|
+
path,
|
|
238
|
+
message: 'MCP transport must be an object',
|
|
239
|
+
});
|
|
240
|
+
return issues;
|
|
241
|
+
}
|
|
242
|
+
const mcp = transport;
|
|
243
|
+
if (!mcp.schema) {
|
|
244
|
+
issues.push({
|
|
245
|
+
severity: 'error',
|
|
246
|
+
code: validation_js_1.ValidationErrorCodes.INVALID_SERVICE_STRUCTURE,
|
|
247
|
+
path: `${path}.schema`,
|
|
248
|
+
message: 'MCP transport missing required "schema" field',
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
if (!mcp.endpoint) {
|
|
252
|
+
issues.push({
|
|
253
|
+
severity: 'error',
|
|
254
|
+
code: validation_js_1.ValidationErrorCodes.INVALID_SERVICE_STRUCTURE,
|
|
255
|
+
path: `${path}.endpoint`,
|
|
256
|
+
message: 'MCP transport missing required "endpoint" field',
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
return issues;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Validate capabilities array
|
|
263
|
+
*/
|
|
264
|
+
function validateCapabilities(ucp) {
|
|
265
|
+
const issues = [];
|
|
266
|
+
if (!ucp.capabilities) {
|
|
267
|
+
issues.push({
|
|
268
|
+
severity: 'error',
|
|
269
|
+
code: validation_js_1.ValidationErrorCodes.MISSING_CAPABILITIES,
|
|
270
|
+
path: '$.ucp.capabilities',
|
|
271
|
+
message: 'Missing required "capabilities" field in ucp object',
|
|
272
|
+
hint: 'Add a capabilities array with at least one capability',
|
|
273
|
+
});
|
|
274
|
+
return issues;
|
|
275
|
+
}
|
|
276
|
+
if (!Array.isArray(ucp.capabilities)) {
|
|
277
|
+
issues.push({
|
|
278
|
+
severity: 'error',
|
|
279
|
+
code: validation_js_1.ValidationErrorCodes.INVALID_CAPABILITY_STRUCTURE,
|
|
280
|
+
path: '$.ucp.capabilities',
|
|
281
|
+
message: 'Capabilities must be an array',
|
|
282
|
+
});
|
|
283
|
+
return issues;
|
|
284
|
+
}
|
|
285
|
+
if (ucp.capabilities.length === 0) {
|
|
286
|
+
issues.push({
|
|
287
|
+
severity: 'warn',
|
|
288
|
+
code: validation_js_1.ValidationErrorCodes.MISSING_CAPABILITIES,
|
|
289
|
+
path: '$.ucp.capabilities',
|
|
290
|
+
message: 'Capabilities array is empty',
|
|
291
|
+
hint: 'Add at least one capability (e.g., dev.ucp.shopping.checkout)',
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
// Validate each capability
|
|
295
|
+
for (let i = 0; i < ucp.capabilities.length; i++) {
|
|
296
|
+
issues.push(...validateCapability(ucp.capabilities[i], i));
|
|
297
|
+
}
|
|
298
|
+
return issues;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Validate individual capability
|
|
302
|
+
*/
|
|
303
|
+
function validateCapability(capability, index) {
|
|
304
|
+
const issues = [];
|
|
305
|
+
const path = `$.ucp.capabilities[${index}]`;
|
|
306
|
+
if (!capability || typeof capability !== 'object') {
|
|
307
|
+
issues.push({
|
|
308
|
+
severity: 'error',
|
|
309
|
+
code: validation_js_1.ValidationErrorCodes.INVALID_CAPABILITY_STRUCTURE,
|
|
310
|
+
path,
|
|
311
|
+
message: `Capability at index ${index} must be an object`,
|
|
312
|
+
});
|
|
313
|
+
return issues;
|
|
314
|
+
}
|
|
315
|
+
const cap = capability;
|
|
316
|
+
// Check required fields
|
|
317
|
+
if (!cap.name) {
|
|
318
|
+
issues.push({
|
|
319
|
+
severity: 'error',
|
|
320
|
+
code: validation_js_1.ValidationErrorCodes.INVALID_CAPABILITY_STRUCTURE,
|
|
321
|
+
path: `${path}.name`,
|
|
322
|
+
message: 'Capability missing required "name" field',
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
if (!cap.version) {
|
|
326
|
+
issues.push({
|
|
327
|
+
severity: 'error',
|
|
328
|
+
code: validation_js_1.ValidationErrorCodes.INVALID_CAPABILITY_STRUCTURE,
|
|
329
|
+
path: `${path}.version`,
|
|
330
|
+
message: 'Capability missing required "version" field',
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
else if (typeof cap.version === 'string' && !VERSION_REGEX.test(cap.version)) {
|
|
334
|
+
issues.push({
|
|
335
|
+
severity: 'error',
|
|
336
|
+
code: validation_js_1.ValidationErrorCodes.INVALID_VERSION_FORMAT,
|
|
337
|
+
path: `${path}.version`,
|
|
338
|
+
message: `Invalid version format: "${cap.version}"`,
|
|
339
|
+
hint: 'Use format "YYYY-MM-DD"',
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
if (!cap.spec) {
|
|
343
|
+
issues.push({
|
|
344
|
+
severity: 'error',
|
|
345
|
+
code: validation_js_1.ValidationErrorCodes.INVALID_CAPABILITY_STRUCTURE,
|
|
346
|
+
path: `${path}.spec`,
|
|
347
|
+
message: 'Capability missing required "spec" field',
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
if (!cap.schema) {
|
|
351
|
+
issues.push({
|
|
352
|
+
severity: 'error',
|
|
353
|
+
code: validation_js_1.ValidationErrorCodes.INVALID_CAPABILITY_STRUCTURE,
|
|
354
|
+
path: `${path}.schema`,
|
|
355
|
+
message: 'Capability missing required "schema" field',
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
return issues;
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Validate signing_keys structure
|
|
362
|
+
* Accepts signing_keys as a direct array of JWKs (official UCP format)
|
|
363
|
+
*/
|
|
364
|
+
function validateSigningKeys(signingKeys) {
|
|
365
|
+
const issues = [];
|
|
366
|
+
const path = '$.signing_keys';
|
|
367
|
+
// signing_keys should be an array of JWKs
|
|
368
|
+
if (!Array.isArray(signingKeys)) {
|
|
369
|
+
issues.push({
|
|
370
|
+
severity: 'error',
|
|
371
|
+
code: validation_js_1.ValidationErrorCodes.INVALID_SIGNING_KEY,
|
|
372
|
+
path,
|
|
373
|
+
message: 'signing_keys must be an array of JWK objects',
|
|
374
|
+
});
|
|
375
|
+
return issues;
|
|
376
|
+
}
|
|
377
|
+
for (let i = 0; i < signingKeys.length; i++) {
|
|
378
|
+
issues.push(...validateJwk(signingKeys[i], `${path}[${i}]`));
|
|
379
|
+
}
|
|
380
|
+
return issues;
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Validate JWK structure
|
|
384
|
+
*/
|
|
385
|
+
function validateJwk(jwk, path) {
|
|
386
|
+
const issues = [];
|
|
387
|
+
if (!jwk || typeof jwk !== 'object') {
|
|
388
|
+
issues.push({
|
|
389
|
+
severity: 'error',
|
|
390
|
+
code: validation_js_1.ValidationErrorCodes.INVALID_SIGNING_KEY,
|
|
391
|
+
path,
|
|
392
|
+
message: 'JWK must be an object',
|
|
393
|
+
});
|
|
394
|
+
return issues;
|
|
395
|
+
}
|
|
396
|
+
const key = jwk;
|
|
397
|
+
if (!key.kty) {
|
|
398
|
+
issues.push({
|
|
399
|
+
severity: 'error',
|
|
400
|
+
code: validation_js_1.ValidationErrorCodes.INVALID_SIGNING_KEY,
|
|
401
|
+
path: `${path}.kty`,
|
|
402
|
+
message: 'JWK missing required "kty" field',
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
if (!key.kid) {
|
|
406
|
+
issues.push({
|
|
407
|
+
severity: 'error',
|
|
408
|
+
code: validation_js_1.ValidationErrorCodes.INVALID_SIGNING_KEY,
|
|
409
|
+
path: `${path}.kid`,
|
|
410
|
+
message: 'JWK missing required "kid" field',
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
return issues;
|
|
414
|
+
}
|
|
415
|
+
//# sourceMappingURL=structural-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structural-validator.js","sourceRoot":"","sources":["../../src/validator/structural-validator.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
File without changes
|
package/CLAUDE.md
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
# CLAUDE.md
|
|
2
|
-
|
|
3
|
-
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
-
|
|
5
|
-
## Project Overview
|
|
6
|
-
|
|
7
|
-
UCP Profile Manager is a toolkit for validating and generating UCP (Universal Commerce Protocol) Business Profiles - an open standard enabling AI agents to discover, browse, and complete purchases on UCP-enabled merchants. The project includes a core library, REST API, CLI tools, web UI, and Apify actor integration.
|
|
8
|
-
|
|
9
|
-
**Live deployment:** https://ucptools.dev
|
|
10
|
-
|
|
11
|
-
## Commands
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
# Development
|
|
15
|
-
npm run dev # Watch mode Express server (tsx watch src/api/server.ts)
|
|
16
|
-
npm run build # TypeScript compilation
|
|
17
|
-
npm start # Production server (node dist/api/server.js)
|
|
18
|
-
|
|
19
|
-
# Testing
|
|
20
|
-
npm test # Vitest tests (30s timeout, v8 coverage)
|
|
21
|
-
|
|
22
|
-
# Linting
|
|
23
|
-
npm run lint # ESLint on src/**/*.ts
|
|
24
|
-
|
|
25
|
-
# CLI tools
|
|
26
|
-
npm run validate # Run validator CLI (tsx src/cli/index.ts)
|
|
27
|
-
npm run generate # Run generator CLI (tsx src/cli/generate.ts)
|
|
28
|
-
|
|
29
|
-
# Database (Drizzle + PostgreSQL)
|
|
30
|
-
npm run db:generate # Generate Drizzle schema
|
|
31
|
-
npm run db:migrate # Apply migrations
|
|
32
|
-
npm run db:push # Push schema to DB
|
|
33
|
-
npm run db:studio # Open Drizzle Studio
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
## Architecture
|
|
37
|
-
|
|
38
|
-
### Core Library (`/src/`)
|
|
39
|
-
|
|
40
|
-
**Validator (`/src/validator/`)** - Four validation levels:
|
|
41
|
-
- `structural-validator.ts` - JSON structure, required fields, version format (YYYY-MM-DD)
|
|
42
|
-
- `rules-validator.ts` - UCP compliance (namespace/origin binding, extension chains, HTTPS endpoints, signing keys)
|
|
43
|
-
- `network-validator.ts` - Remote schema fetching/verification, self-describing schema validation
|
|
44
|
-
- `sdk-validator.ts` - Integration with @ucp-js/sdk for official UCP compliance
|
|
45
|
-
- `index.ts` - Orchestrator exposing `validateProfile()`, `validateRemote()`, `validateQuick()`, `validateJsonString()`
|
|
46
|
-
|
|
47
|
-
**Generator (`/src/generator/`)** - Profile generation:
|
|
48
|
-
- `profile-builder.ts` - `buildProfile()` for full profiles, `generateMinimalProfile()` for checkout-only
|
|
49
|
-
- `key-generator.ts` - Ed25519/ES256 signing key generation (`generateSigningKeyPair()`)
|
|
50
|
-
|
|
51
|
-
**Simulator (`/src/simulator/`)** - AI agent interaction simulation:
|
|
52
|
-
- `agent-simulator.ts` - Tests real-world functionality: discovery flow, capability inspection, checkout simulation
|
|
53
|
-
- Not just spec compliance - simulates actual agent workflows
|
|
54
|
-
|
|
55
|
-
**Hosting (`/src/hosting/`)** - Platform-specific deployment configs:
|
|
56
|
-
- `artifacts-generator.ts` - Generates installation artifacts for Nginx, Apache, Vercel, Netlify, Cloudflare Workers, S3+CloudFront
|
|
57
|
-
|
|
58
|
-
### API & Deployment
|
|
59
|
-
|
|
60
|
-
**Express API (`/src/api/server.ts`)** - REST endpoints:
|
|
61
|
-
- `POST /v1/profiles/validate`, `/validate-quick`, `/validate-remote`, `/validate-json`
|
|
62
|
-
- `POST /v1/profiles/generate`, `/generate-minimal`
|
|
63
|
-
- `POST /v1/hosting/artifacts`
|
|
64
|
-
|
|
65
|
-
**Vercel Serverless (`/api/`)** - Edge functions for ucptools.dev
|
|
66
|
-
|
|
67
|
-
**Database (`/src/db/`)** - Drizzle ORM with PostgreSQL (Neon):
|
|
68
|
-
- Schema: merchants (directory), benchmarkStats, benchmarkSummary
|
|
69
|
-
- Service: `/src/services/directory.ts` - merchant CRUD, filtering, stats
|
|
70
|
-
|
|
71
|
-
### Types (`/src/types/`)
|
|
72
|
-
- `ucp-profile.ts` - UCP specification types
|
|
73
|
-
- `validation.ts` - ValidationReport, ValidationIssue interfaces
|
|
74
|
-
- `generator.ts` - Generator input/output types
|
|
75
|
-
|
|
76
|
-
## Key Patterns
|
|
77
|
-
|
|
78
|
-
**Validation Issue Structure:**
|
|
79
|
-
```typescript
|
|
80
|
-
{
|
|
81
|
-
severity: 'error' | 'warn' | 'info',
|
|
82
|
-
code: string, // e.g., 'UCP_NS_ORIGIN_MISMATCH'
|
|
83
|
-
path: string, // JSON path, e.g., '$.ucp.capabilities[0]'
|
|
84
|
-
message: string,
|
|
85
|
-
hint?: string // Fix suggestion
|
|
86
|
-
}
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
**Error Codes:** `UCP_MISSING_ROOT`, `UCP_MISSING_VERSION`, `UCP_INVALID_VERSION_FORMAT`, `UCP_NS_ORIGIN_MISMATCH`, `UCP_ORPHANED_EXTENSION`, `UCP_ENDPOINT_NOT_HTTPS`, `UCP_ENDPOINT_TRAILING_SLASH`, `UCP_MISSING_SIGNING_KEYS`, `UCP_SCHEMA_FETCH_FAILED`
|
|
90
|
-
|
|
91
|
-
## Environment Variables
|
|
92
|
-
|
|
93
|
-
```
|
|
94
|
-
DATABASE_URL # PostgreSQL connection string (Neon)
|
|
95
|
-
NODE_ENV # development | production
|
|
96
|
-
PORT # API port (default: 3000)
|
|
97
|
-
LOG_LEVEL # Pino log level (default: info)
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
## Tech Stack
|
|
101
|
-
|
|
102
|
-
- **Runtime:** Node.js 20+, TypeScript 5.6, ES2022 target
|
|
103
|
-
- **API:** Express 4.21
|
|
104
|
-
- **Database:** PostgreSQL via @neondatabase/serverless, Drizzle ORM
|
|
105
|
-
- **Validation:** AJV 8.17 (JSON Schema), Zod 3.23, @ucp-js/sdk 0.1
|
|
106
|
-
- **Crypto:** jose (JWT/JWK), Ed25519 signing
|
|
107
|
-
- **CLI:** Commander 12, Chalk 5
|
|
108
|
-
- **Testing:** Vitest
|
|
109
|
-
- **Deployment:** Vercel
|