@ucptools/validator 1.0.0 → 1.1.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 (330) hide show
  1. package/dist/auth/config.d.ts +20 -0
  2. package/dist/auth/config.d.ts.map +1 -0
  3. package/dist/auth/config.js +114 -0
  4. package/dist/auth/config.js.map +1 -0
  5. package/dist/auth/index.d.ts +5 -0
  6. package/dist/auth/index.d.ts.map +1 -0
  7. package/dist/auth/index.js +17 -0
  8. package/dist/auth/index.js.map +1 -0
  9. package/dist/auth/middleware.d.ts +45 -0
  10. package/dist/auth/middleware.d.ts.map +1 -0
  11. package/dist/auth/middleware.js +170 -0
  12. package/dist/auth/middleware.js.map +1 -0
  13. package/dist/auth/service.d.ts +80 -0
  14. package/dist/auth/service.d.ts.map +1 -0
  15. package/dist/auth/service.js +298 -0
  16. package/dist/auth/service.js.map +1 -0
  17. package/dist/cli/index.d.ts +6 -0
  18. package/dist/cli/index.d.ts.map +1 -0
  19. package/dist/cli/index.js +375 -0
  20. package/dist/cli/index.js.map +1 -0
  21. package/dist/cli/mock-server.d.ts +20 -0
  22. package/dist/cli/mock-server.d.ts.map +1 -0
  23. package/dist/cli/mock-server.js +261 -0
  24. package/dist/cli/mock-server.js.map +1 -0
  25. package/dist/compliance/compliance-generator.d.ts +34 -0
  26. package/dist/compliance/compliance-generator.d.ts.map +1 -0
  27. package/dist/compliance/compliance-generator.js +320 -0
  28. package/dist/compliance/compliance-generator.js.map +1 -0
  29. package/dist/compliance/index.d.ts +8 -0
  30. package/dist/compliance/index.d.ts.map +1 -0
  31. package/dist/compliance/index.js +17 -0
  32. package/dist/compliance/index.js.map +1 -0
  33. package/dist/compliance/templates.d.ts +34 -0
  34. package/dist/compliance/templates.d.ts.map +1 -0
  35. package/{src/compliance/templates.ts → dist/compliance/templates.js} +117 -155
  36. package/dist/compliance/templates.js.map +1 -0
  37. package/dist/compliance/types.d.ts +64 -0
  38. package/dist/compliance/types.d.ts.map +1 -0
  39. package/dist/compliance/types.js +64 -0
  40. package/dist/compliance/types.js.map +1 -0
  41. package/dist/db/index.d.ts +17 -0
  42. package/dist/db/index.d.ts.map +1 -0
  43. package/dist/db/index.js +80 -0
  44. package/dist/db/index.js.map +1 -0
  45. package/dist/db/schema.d.ts +3886 -0
  46. package/dist/db/schema.d.ts.map +1 -0
  47. package/dist/db/schema.js +425 -0
  48. package/dist/db/schema.js.map +1 -0
  49. package/dist/db/utils.d.ts +252 -0
  50. package/dist/db/utils.d.ts.map +1 -0
  51. package/dist/db/utils.js +295 -0
  52. package/dist/db/utils.js.map +1 -0
  53. package/dist/feed-analyzer/feed-analyzer.d.ts +26 -0
  54. package/dist/feed-analyzer/feed-analyzer.d.ts.map +1 -0
  55. package/{src/feed-analyzer/feed-analyzer.ts → dist/feed-analyzer/feed-analyzer.js} +856 -726
  56. package/dist/feed-analyzer/feed-analyzer.js.map +1 -0
  57. package/dist/feed-analyzer/index.d.ts +8 -0
  58. package/dist/feed-analyzer/index.d.ts.map +1 -0
  59. package/dist/feed-analyzer/index.js +19 -0
  60. package/dist/feed-analyzer/index.js.map +1 -0
  61. package/dist/feed-analyzer/types.d.ts +285 -0
  62. package/dist/feed-analyzer/types.d.ts.map +1 -0
  63. package/dist/feed-analyzer/types.js +175 -0
  64. package/dist/feed-analyzer/types.js.map +1 -0
  65. package/{src/generator/index.ts → dist/generator/index.d.ts} +1 -1
  66. package/dist/generator/index.d.ts.map +1 -0
  67. package/dist/generator/index.js +13 -0
  68. package/dist/generator/index.js.map +1 -0
  69. package/dist/generator/key-generator.d.ts +24 -0
  70. package/dist/generator/key-generator.d.ts.map +1 -0
  71. package/dist/generator/key-generator.js +144 -0
  72. package/dist/generator/key-generator.js.map +1 -0
  73. package/dist/generator/profile-builder.d.ts +15 -0
  74. package/dist/generator/profile-builder.d.ts.map +1 -0
  75. package/dist/generator/profile-builder.js +338 -0
  76. package/dist/generator/profile-builder.js.map +1 -0
  77. package/dist/hosting/artifacts-generator.d.ts +10 -0
  78. package/dist/hosting/artifacts-generator.d.ts.map +1 -0
  79. package/{src/hosting/artifacts-generator.ts → dist/hosting/artifacts-generator.js} +191 -241
  80. package/dist/hosting/artifacts-generator.js.map +1 -0
  81. package/{src/hosting/index.ts → dist/hosting/index.d.ts} +1 -1
  82. package/dist/hosting/index.d.ts.map +1 -0
  83. package/dist/hosting/index.js +10 -0
  84. package/dist/hosting/index.js.map +1 -0
  85. package/dist/index.d.ts +18 -0
  86. package/dist/index.d.ts.map +1 -0
  87. package/dist/index.js +78 -0
  88. package/dist/index.js.map +1 -0
  89. package/dist/lib/analytics.d.ts +337 -0
  90. package/dist/lib/analytics.d.ts.map +1 -0
  91. package/dist/lib/analytics.js +188 -0
  92. package/dist/lib/analytics.js.map +1 -0
  93. package/{src/security/index.ts → dist/security/index.d.ts} +8 -15
  94. package/dist/security/index.d.ts.map +1 -0
  95. package/dist/security/index.js +12 -0
  96. package/dist/security/index.js.map +1 -0
  97. package/dist/security/security-scanner.d.ts +10 -0
  98. package/dist/security/security-scanner.d.ts.map +1 -0
  99. package/dist/security/security-scanner.js +669 -0
  100. package/dist/security/security-scanner.js.map +1 -0
  101. package/dist/security/types.d.ts +80 -0
  102. package/dist/security/types.d.ts.map +1 -0
  103. package/dist/security/types.js +21 -0
  104. package/dist/security/types.js.map +1 -0
  105. package/dist/services/analytics.d.ts +114 -0
  106. package/dist/services/analytics.d.ts.map +1 -0
  107. package/dist/services/analytics.js +862 -0
  108. package/dist/services/analytics.js.map +1 -0
  109. package/dist/services/badge.d.ts +31 -0
  110. package/dist/services/badge.d.ts.map +1 -0
  111. package/dist/services/badge.js +152 -0
  112. package/dist/services/badge.js.map +1 -0
  113. package/dist/services/cron.d.ts +125 -0
  114. package/dist/services/cron.d.ts.map +1 -0
  115. package/dist/services/cron.js +613 -0
  116. package/dist/services/cron.js.map +1 -0
  117. package/dist/services/directory.d.ts +106 -0
  118. package/dist/services/directory.d.ts.map +1 -0
  119. package/dist/services/directory.js +351 -0
  120. package/dist/services/directory.js.map +1 -0
  121. package/dist/services/email.d.ts +112 -0
  122. package/dist/services/email.d.ts.map +1 -0
  123. package/dist/services/email.js +772 -0
  124. package/dist/services/email.js.map +1 -0
  125. package/dist/services/hosted-profiles.d.ts +77 -0
  126. package/dist/services/hosted-profiles.d.ts.map +1 -0
  127. package/dist/services/hosted-profiles.js +433 -0
  128. package/dist/services/hosted-profiles.js.map +1 -0
  129. package/dist/services/latency.d.ts +67 -0
  130. package/dist/services/latency.d.ts.map +1 -0
  131. package/dist/services/latency.js +274 -0
  132. package/dist/services/latency.js.map +1 -0
  133. package/dist/services/manifest-compliance.d.ts +64 -0
  134. package/dist/services/manifest-compliance.d.ts.map +1 -0
  135. package/dist/services/manifest-compliance.js +271 -0
  136. package/dist/services/manifest-compliance.js.map +1 -0
  137. package/dist/services/monitoring-diff.d.ts +31 -0
  138. package/dist/services/monitoring-diff.d.ts.map +1 -0
  139. package/dist/services/monitoring-diff.js +189 -0
  140. package/dist/services/monitoring-diff.js.map +1 -0
  141. package/dist/services/notifications.d.ts +46 -0
  142. package/dist/services/notifications.d.ts.map +1 -0
  143. package/dist/services/notifications.js +88 -0
  144. package/dist/services/notifications.js.map +1 -0
  145. package/dist/services/stripe.d.ts +93 -0
  146. package/dist/services/stripe.d.ts.map +1 -0
  147. package/dist/services/stripe.js +490 -0
  148. package/dist/services/stripe.js.map +1 -0
  149. package/dist/services/validation-history.d.ts +99 -0
  150. package/dist/services/validation-history.d.ts.map +1 -0
  151. package/dist/services/validation-history.js +344 -0
  152. package/dist/services/validation-history.js.map +1 -0
  153. package/dist/services/validation-logging.d.ts +103 -0
  154. package/dist/services/validation-logging.d.ts.map +1 -0
  155. package/dist/services/validation-logging.js +210 -0
  156. package/dist/services/validation-logging.js.map +1 -0
  157. package/dist/services/validation.d.ts +119 -0
  158. package/dist/services/validation.d.ts.map +1 -0
  159. package/dist/services/validation.js +1185 -0
  160. package/dist/services/validation.js.map +1 -0
  161. package/dist/simulator/agent-simulator.d.ts +69 -0
  162. package/dist/simulator/agent-simulator.d.ts.map +1 -0
  163. package/dist/simulator/agent-simulator.js +870 -0
  164. package/dist/simulator/agent-simulator.js.map +1 -0
  165. package/{src/simulator/index.ts → dist/simulator/index.d.ts} +7 -7
  166. package/dist/simulator/index.d.ts.map +1 -0
  167. package/dist/simulator/index.js +23 -0
  168. package/dist/simulator/index.js.map +1 -0
  169. package/{src/simulator/types.ts → dist/simulator/types.d.ts} +171 -170
  170. package/dist/simulator/types.d.ts.map +1 -0
  171. package/dist/simulator/types.js +18 -0
  172. package/dist/simulator/types.js.map +1 -0
  173. package/dist/types/acp-validation.d.ts +87 -0
  174. package/dist/types/acp-validation.d.ts.map +1 -0
  175. package/dist/types/acp-validation.js +40 -0
  176. package/dist/types/acp-validation.js.map +1 -0
  177. package/dist/types/analytics.d.ts +182 -0
  178. package/dist/types/analytics.d.ts.map +1 -0
  179. package/dist/types/analytics.js +7 -0
  180. package/dist/types/analytics.js.map +1 -0
  181. package/dist/types/generator.d.ts +106 -0
  182. package/dist/types/generator.d.ts.map +1 -0
  183. package/dist/types/generator.js +6 -0
  184. package/dist/types/generator.js.map +1 -0
  185. package/{src/types/index.ts → dist/types/index.d.ts} +1 -1
  186. package/dist/types/index.d.ts.map +1 -0
  187. package/dist/types/index.js +23 -0
  188. package/dist/types/index.js.map +1 -0
  189. package/dist/types/ucp-profile.d.ts +111 -0
  190. package/dist/types/ucp-profile.d.ts.map +1 -0
  191. package/dist/types/ucp-profile.js +45 -0
  192. package/dist/types/ucp-profile.js.map +1 -0
  193. package/dist/types/validation.d.ts +76 -0
  194. package/dist/types/validation.d.ts.map +1 -0
  195. package/dist/types/validation.js +42 -0
  196. package/dist/types/validation.js.map +1 -0
  197. package/dist/validator/acp/index.d.ts +31 -0
  198. package/dist/validator/acp/index.d.ts.map +1 -0
  199. package/dist/validator/acp/index.js +574 -0
  200. package/dist/validator/acp/index.js.map +1 -0
  201. package/dist/validator/index.d.ts +26 -0
  202. package/dist/validator/index.d.ts.map +1 -0
  203. package/dist/validator/index.js +161 -0
  204. package/dist/validator/index.js.map +1 -0
  205. package/dist/validator/network-validator.d.ts +28 -0
  206. package/dist/validator/network-validator.d.ts.map +1 -0
  207. package/dist/validator/network-validator.js +319 -0
  208. package/dist/validator/network-validator.js.map +1 -0
  209. package/dist/validator/rules-validator.d.ts +19 -0
  210. package/dist/validator/rules-validator.d.ts.map +1 -0
  211. package/dist/validator/rules-validator.js +306 -0
  212. package/dist/validator/rules-validator.js.map +1 -0
  213. package/dist/validator/sdk-validator.d.ts +58 -0
  214. package/dist/validator/sdk-validator.d.ts.map +1 -0
  215. package/{src/validator/sdk-validator.ts → dist/validator/sdk-validator.js} +273 -330
  216. package/dist/validator/sdk-validator.js.map +1 -0
  217. package/dist/validator/structural-validator.d.ts +11 -0
  218. package/dist/validator/structural-validator.d.ts.map +1 -0
  219. package/dist/validator/structural-validator.js +549 -0
  220. package/dist/validator/structural-validator.js.map +1 -0
  221. package/dist/validator/utils.d.ts +51 -0
  222. package/dist/validator/utils.d.ts.map +1 -0
  223. package/dist/validator/utils.js +132 -0
  224. package/dist/validator/utils.js.map +1 -0
  225. package/package.json +44 -12
  226. package/CLAUDE.md +0 -109
  227. package/api/analyze-feed.js +0 -140
  228. package/api/badge.js +0 -185
  229. package/api/benchmark.js +0 -177
  230. package/api/directory-stats.ts +0 -29
  231. package/api/directory.ts +0 -73
  232. package/api/generate-compliance.js +0 -143
  233. package/api/generate-schema.js +0 -457
  234. package/api/generate.js +0 -132
  235. package/api/security-scan.js +0 -133
  236. package/api/simulate.js +0 -187
  237. package/api/tsconfig.json +0 -10
  238. package/api/validate.js +0 -1351
  239. package/apify-actor/.actor/actor.json +0 -68
  240. package/apify-actor/.actor/input_schema.json +0 -32
  241. package/apify-actor/APIFY-STORE-LISTING.md +0 -412
  242. package/apify-actor/Dockerfile +0 -8
  243. package/apify-actor/README.md +0 -166
  244. package/apify-actor/main.ts +0 -111
  245. package/apify-actor/package.json +0 -17
  246. package/apify-actor/src/main.js +0 -199
  247. package/docs/BRAND-IDENTITY.md +0 -238
  248. package/docs/BRAND-STYLE-GUIDE.md +0 -356
  249. package/drizzle/0000_black_king_cobra.sql +0 -39
  250. package/drizzle/meta/0000_snapshot.json +0 -309
  251. package/drizzle/meta/_journal.json +0 -13
  252. package/drizzle.config.ts +0 -10
  253. package/public/.well-known/ucp +0 -25
  254. package/public/android-chrome-192x192.png +0 -0
  255. package/public/android-chrome-512x512.png +0 -0
  256. package/public/apple-touch-icon.png +0 -0
  257. package/public/brand.css +0 -321
  258. package/public/directory.html +0 -701
  259. package/public/favicon-16x16.png +0 -0
  260. package/public/favicon-32x32.png +0 -0
  261. package/public/favicon.ico +0 -0
  262. package/public/guides/bigcommerce.html +0 -743
  263. package/public/guides/fastucp.html +0 -838
  264. package/public/guides/magento.html +0 -779
  265. package/public/guides/shopify.html +0 -726
  266. package/public/guides/squarespace.html +0 -749
  267. package/public/guides/wix.html +0 -747
  268. package/public/guides/woocommerce.html +0 -733
  269. package/public/index.html +0 -3835
  270. package/public/learn.html +0 -396
  271. package/public/logo.jpeg +0 -0
  272. package/public/og-image-icon.png +0 -0
  273. package/public/og-image.png +0 -0
  274. package/public/robots.txt +0 -6
  275. package/public/site.webmanifest +0 -31
  276. package/public/sitemap.xml +0 -69
  277. package/public/social/linkedin-banner-1128x191.png +0 -0
  278. package/public/social/temp.PNG +0 -0
  279. package/public/social/x-header-1500x500.png +0 -0
  280. package/public/verify.html +0 -410
  281. package/scripts/generate-favicons.js +0 -44
  282. package/scripts/generate-ico.js +0 -23
  283. package/scripts/generate-og-image.js +0 -45
  284. package/scripts/reset-db.ts +0 -77
  285. package/scripts/seed-db.ts +0 -71
  286. package/scripts/setup-benchmark-db.js +0 -70
  287. package/src/api/server.ts +0 -266
  288. package/src/cli/index.ts +0 -302
  289. package/src/compliance/compliance-generator.ts +0 -452
  290. package/src/compliance/index.ts +0 -28
  291. package/src/compliance/types.ts +0 -170
  292. package/src/db/index.ts +0 -28
  293. package/src/db/schema.ts +0 -84
  294. package/src/feed-analyzer/index.ts +0 -34
  295. package/src/feed-analyzer/types.ts +0 -354
  296. package/src/generator/key-generator.ts +0 -124
  297. package/src/generator/profile-builder.ts +0 -402
  298. package/src/index.ts +0 -105
  299. package/src/security/security-scanner.ts +0 -604
  300. package/src/security/types.ts +0 -55
  301. package/src/services/directory.ts +0 -434
  302. package/src/simulator/agent-simulator.ts +0 -941
  303. package/src/types/generator.ts +0 -140
  304. package/src/types/ucp-profile.ts +0 -140
  305. package/src/types/validation.ts +0 -89
  306. package/src/validator/index.ts +0 -194
  307. package/src/validator/network-validator.ts +0 -417
  308. package/src/validator/rules-validator.ts +0 -297
  309. package/src/validator/structural-validator.ts +0 -476
  310. package/tests/fixtures/non-compliant-profile.json +0 -25
  311. package/tests/fixtures/official-sample-profile.json +0 -75
  312. package/tests/integration/benchmark.test.ts +0 -207
  313. package/tests/integration/database.test.ts +0 -163
  314. package/tests/integration/directory-api.test.ts +0 -268
  315. package/tests/integration/simulate-api.test.ts +0 -230
  316. package/tests/integration/validate-api.test.ts +0 -269
  317. package/tests/setup.ts +0 -15
  318. package/tests/unit/agent-simulator.test.ts +0 -575
  319. package/tests/unit/compliance-generator.test.ts +0 -374
  320. package/tests/unit/directory-service.test.ts +0 -272
  321. package/tests/unit/feed-analyzer.test.ts +0 -517
  322. package/tests/unit/lint-suggestions.test.ts +0 -423
  323. package/tests/unit/official-samples.test.ts +0 -211
  324. package/tests/unit/pdf-report.test.ts +0 -390
  325. package/tests/unit/sdk-validator.test.ts +0 -531
  326. package/tests/unit/security-scanner.test.ts +0 -410
  327. package/tests/unit/validation.test.ts +0 -390
  328. package/tsconfig.json +0 -20
  329. package/vercel.json +0 -34
  330. package/vitest.config.ts +0 -22
package/src/db/schema.ts DELETED
@@ -1,84 +0,0 @@
1
- import {
2
- pgTable,
3
- uuid,
4
- varchar,
5
- text,
6
- integer,
7
- timestamp,
8
- boolean,
9
- index,
10
- decimal,
11
- } from 'drizzle-orm/pg-core';
12
-
13
- /**
14
- * Merchants table - stores UCP-enabled merchant directory entries
15
- */
16
- export const merchants = pgTable(
17
- 'merchants',
18
- {
19
- id: uuid('id').primaryKey().defaultRandom(),
20
- // The merchant's primary domain (e.g., "example.com")
21
- domain: varchar('domain', { length: 255 }).notNull().unique(),
22
- // Display name for the merchant
23
- displayName: varchar('display_name', { length: 255 }).notNull(),
24
- // Optional description
25
- description: text('description'),
26
- // Logo URL
27
- logoUrl: varchar('logo_url', { length: 512 }),
28
- // Website URL (full URL including protocol)
29
- websiteUrl: varchar('website_url', { length: 512 }),
30
- // Category (e-commerce, saas, marketplace, etc.)
31
- category: varchar('category', { length: 100 }),
32
- // Country code (ISO 3166-1 alpha-2)
33
- countryCode: varchar('country_code', { length: 2 }),
34
- // UCP readiness score (0-100)
35
- ucpScore: integer('ucp_score'),
36
- // UCP grade (A, B, C, D, F)
37
- ucpGrade: varchar('ucp_grade', { length: 2 }),
38
- // Supported transports (comma-separated: REST, MCP, A2A, Embedded)
39
- transports: varchar('transports', { length: 255 }),
40
- // Whether the merchant has opted into the directory
41
- isPublic: boolean('is_public').default(true).notNull(),
42
- // Whether the merchant has been verified
43
- isVerified: boolean('is_verified').default(false).notNull(),
44
- // Last validation timestamp
45
- lastValidatedAt: timestamp('last_validated_at'),
46
- // Record timestamps
47
- createdAt: timestamp('created_at').defaultNow().notNull(),
48
- updatedAt: timestamp('updated_at').defaultNow().notNull(),
49
- },
50
- (table) => [
51
- index('idx_merchants_domain').on(table.domain),
52
- index('idx_merchants_category').on(table.category),
53
- index('idx_merchants_country').on(table.countryCode),
54
- index('idx_merchants_score').on(table.ucpScore),
55
- index('idx_merchants_public').on(table.isPublic),
56
- ]
57
- );
58
-
59
- /**
60
- * Benchmark stats table - stores aggregate validation statistics
61
- * (migrated from setup script)
62
- */
63
- export const benchmarkStats = pgTable('benchmark_stats', {
64
- id: integer('id').primaryKey().generatedAlwaysAsIdentity(),
65
- scoreBucket: integer('score_bucket').notNull().unique(),
66
- count: integer('count').default(0).notNull(),
67
- });
68
-
69
- /**
70
- * Benchmark summary table - quick aggregate stats
71
- * (migrated from setup script)
72
- */
73
- export const benchmarkSummary = pgTable('benchmark_summary', {
74
- id: integer('id').primaryKey().default(1),
75
- totalValidations: integer('total_validations').default(0).notNull(),
76
- avgScore: decimal('avg_score', { precision: 5, scale: 2 }).default('0'),
77
- updatedAt: timestamp('updated_at').defaultNow().notNull(),
78
- });
79
-
80
- // Type exports for use in application code
81
- export type Merchant = typeof merchants.$inferSelect;
82
- export type NewMerchant = typeof merchants.$inferInsert;
83
- export type BenchmarkStat = typeof benchmarkStats.$inferSelect;
84
- export type BenchmarkSummary = typeof benchmarkSummary.$inferSelect;
@@ -1,34 +0,0 @@
1
- /**
2
- * Product Feed Quality Analyzer Module
3
- * Deep analysis of product data quality for AI agent visibility
4
- */
5
-
6
- export {
7
- analyzeProductFeed,
8
- analyzeProductFeedFromHtml,
9
- analyzeProduct,
10
- extractProductsFromHtml,
11
- validateGtin,
12
- } from './feed-analyzer.js';
13
-
14
- export type {
15
- ProductData,
16
- ProductOffer,
17
- ProductAnalysis,
18
- QualityCheck,
19
- FeedAnalysisResult,
20
- FeedAnalysisInput,
21
- CategoryScores,
22
- Recommendation,
23
- FeedSummary,
24
- GtinValidation,
25
- IssueSeverity,
26
- CheckCategory,
27
- } from './types.js';
28
-
29
- export {
30
- QUALITY_CHECKS,
31
- VALID_AVAILABILITY_VALUES,
32
- CATEGORY_WEIGHTS,
33
- GRADE_THRESHOLDS,
34
- } from './types.js';
@@ -1,354 +0,0 @@
1
- /**
2
- * Product Feed Quality Analyzer Types
3
- * Deep analysis of product data quality for AI agent visibility
4
- */
5
-
6
- /**
7
- * Severity levels for feed issues
8
- */
9
- export type IssueSeverity = 'critical' | 'warning' | 'info';
10
-
11
- /**
12
- * Categories of feed quality checks
13
- */
14
- export type CheckCategory =
15
- | 'completeness'
16
- | 'identifiers'
17
- | 'images'
18
- | 'pricing'
19
- | 'descriptions'
20
- | 'categories'
21
- | 'availability';
22
-
23
- /**
24
- * Individual product data from Schema.org JSON-LD
25
- */
26
- export interface ProductData {
27
- name?: string;
28
- description?: string;
29
- sku?: string;
30
- gtin?: string;
31
- gtin8?: string;
32
- gtin12?: string;
33
- gtin13?: string;
34
- gtin14?: string;
35
- mpn?: string;
36
- brand?: string | { name?: string };
37
- image?: string | string[] | { url?: string }[];
38
- offers?: ProductOffer | ProductOffer[];
39
- category?: string;
40
- color?: string;
41
- size?: string;
42
- material?: string;
43
- weight?: string | { value?: number; unitCode?: string };
44
- aggregateRating?: {
45
- ratingValue?: number;
46
- reviewCount?: number;
47
- ratingCount?: number;
48
- };
49
- review?: unknown[];
50
- url?: string;
51
- '@type'?: string;
52
- }
53
-
54
- /**
55
- * Product offer/pricing data
56
- */
57
- export interface ProductOffer {
58
- '@type'?: string;
59
- price?: number | string;
60
- priceCurrency?: string;
61
- availability?: string;
62
- url?: string;
63
- seller?: { name?: string };
64
- priceValidUntil?: string;
65
- itemCondition?: string;
66
- shippingDetails?: unknown;
67
- }
68
-
69
- /**
70
- * Individual quality check result
71
- */
72
- export interface QualityCheck {
73
- id: string;
74
- name: string;
75
- category: CheckCategory;
76
- passed: boolean;
77
- severity: IssueSeverity;
78
- message: string;
79
- details?: string;
80
- recommendation?: string;
81
- affectedProducts?: string[];
82
- }
83
-
84
- /**
85
- * Product-level analysis result
86
- */
87
- export interface ProductAnalysis {
88
- name: string;
89
- url?: string;
90
- sku?: string;
91
- score: number;
92
- issues: QualityCheck[];
93
- attributes: {
94
- hasName: boolean;
95
- hasDescription: boolean;
96
- hasSku: boolean;
97
- hasGtin: boolean;
98
- hasBrand: boolean;
99
- hasImage: boolean;
100
- hasPrice: boolean;
101
- hasAvailability: boolean;
102
- hasCategory: boolean;
103
- descriptionLength: number;
104
- imageCount: number;
105
- };
106
- }
107
-
108
- /**
109
- * Category scores breakdown
110
- */
111
- export interface CategoryScores {
112
- completeness: number;
113
- identifiers: number;
114
- images: number;
115
- pricing: number;
116
- descriptions: number;
117
- categories: number;
118
- availability: number;
119
- }
120
-
121
- /**
122
- * Overall feed analysis result
123
- */
124
- export interface FeedAnalysisResult {
125
- url: string;
126
- analyzedAt: string;
127
- productsFound: number;
128
- productsAnalyzed: number;
129
- overallScore: number;
130
- agentVisibilityScore: number;
131
- grade: 'A' | 'B' | 'C' | 'D' | 'F';
132
- categoryScores: CategoryScores;
133
- issues: QualityCheck[];
134
- topIssues: QualityCheck[];
135
- products: ProductAnalysis[];
136
- recommendations: Recommendation[];
137
- summary: FeedSummary;
138
- }
139
-
140
- /**
141
- * Recommendation for improving feed quality
142
- */
143
- export interface Recommendation {
144
- priority: 'high' | 'medium' | 'low';
145
- category: CheckCategory;
146
- title: string;
147
- description: string;
148
- impact: string;
149
- affectedCount: number;
150
- }
151
-
152
- /**
153
- * Summary statistics for the feed
154
- */
155
- export interface FeedSummary {
156
- totalProducts: number;
157
- withName: number;
158
- withDescription: number;
159
- withSku: number;
160
- withGtin: number;
161
- withBrand: number;
162
- withImages: number;
163
- withPrice: number;
164
- withAvailability: number;
165
- withCategory: number;
166
- averageDescriptionLength: number;
167
- averageImageCount: number;
168
- }
169
-
170
- /**
171
- * Input options for feed analysis
172
- */
173
- export interface FeedAnalysisInput {
174
- url: string;
175
- maxProducts?: number;
176
- includeProductDetails?: boolean;
177
- }
178
-
179
- /**
180
- * GTIN validation result
181
- */
182
- export interface GtinValidation {
183
- isValid: boolean;
184
- type?: 'GTIN-8' | 'GTIN-12' | 'GTIN-13' | 'GTIN-14' | 'UPC' | 'EAN';
185
- error?: string;
186
- }
187
-
188
- /**
189
- * Quality check definitions
190
- */
191
- export const QUALITY_CHECKS: Record<string, {
192
- name: string;
193
- category: CheckCategory;
194
- severity: IssueSeverity;
195
- description: string;
196
- }> = {
197
- // Completeness checks
198
- 'missing-name': {
199
- name: 'Missing Product Name',
200
- category: 'completeness',
201
- severity: 'critical',
202
- description: 'Product name is required for AI agents to identify products',
203
- },
204
- 'missing-description': {
205
- name: 'Missing Description',
206
- category: 'completeness',
207
- severity: 'warning',
208
- description: 'Product description helps AI agents understand and recommend products',
209
- },
210
- 'short-description': {
211
- name: 'Short Description',
212
- category: 'descriptions',
213
- severity: 'info',
214
- description: 'Longer descriptions provide better context for AI agents',
215
- },
216
- 'missing-brand': {
217
- name: 'Missing Brand',
218
- category: 'completeness',
219
- severity: 'warning',
220
- description: 'Brand information helps with product identification and search',
221
- },
222
-
223
- // Identifier checks
224
- 'missing-sku': {
225
- name: 'Missing SKU',
226
- category: 'identifiers',
227
- severity: 'warning',
228
- description: 'SKU helps uniquely identify products in your catalog',
229
- },
230
- 'missing-gtin': {
231
- name: 'Missing GTIN/UPC/EAN',
232
- category: 'identifiers',
233
- severity: 'warning',
234
- description: 'Global identifiers enable cross-platform product matching',
235
- },
236
- 'invalid-gtin': {
237
- name: 'Invalid GTIN Format',
238
- category: 'identifiers',
239
- severity: 'critical',
240
- description: 'GTIN has invalid format or check digit',
241
- },
242
-
243
- // Image checks
244
- 'missing-image': {
245
- name: 'Missing Product Image',
246
- category: 'images',
247
- severity: 'critical',
248
- description: 'Product images are essential for AI shopping experiences',
249
- },
250
- 'single-image': {
251
- name: 'Single Image Only',
252
- category: 'images',
253
- severity: 'info',
254
- description: 'Multiple images improve product presentation',
255
- },
256
- 'missing-image-alt': {
257
- name: 'Missing Image Alt Text',
258
- category: 'images',
259
- severity: 'info',
260
- description: 'Alt text helps with accessibility and SEO',
261
- },
262
-
263
- // Pricing checks
264
- 'missing-price': {
265
- name: 'Missing Price',
266
- category: 'pricing',
267
- severity: 'critical',
268
- description: 'Price is required for AI agents to complete purchases',
269
- },
270
- 'missing-currency': {
271
- name: 'Missing Currency',
272
- category: 'pricing',
273
- severity: 'warning',
274
- description: 'Currency must be specified for international commerce',
275
- },
276
- 'invalid-price': {
277
- name: 'Invalid Price Format',
278
- category: 'pricing',
279
- severity: 'critical',
280
- description: 'Price must be a valid number',
281
- },
282
-
283
- // Availability checks
284
- 'missing-availability': {
285
- name: 'Missing Availability',
286
- category: 'availability',
287
- severity: 'warning',
288
- description: 'Availability status helps AI agents make purchase decisions',
289
- },
290
- 'invalid-availability': {
291
- name: 'Invalid Availability Value',
292
- category: 'availability',
293
- severity: 'warning',
294
- description: 'Availability should use Schema.org ItemAvailability values',
295
- },
296
-
297
- // Category checks
298
- 'missing-category': {
299
- name: 'Missing Category',
300
- category: 'categories',
301
- severity: 'info',
302
- description: 'Product categorization improves discoverability',
303
- },
304
- };
305
-
306
- /**
307
- * Valid Schema.org availability values
308
- */
309
- export const VALID_AVAILABILITY_VALUES = [
310
- 'https://schema.org/InStock',
311
- 'https://schema.org/OutOfStock',
312
- 'https://schema.org/PreOrder',
313
- 'https://schema.org/PreSale',
314
- 'https://schema.org/SoldOut',
315
- 'https://schema.org/InStoreOnly',
316
- 'https://schema.org/OnlineOnly',
317
- 'https://schema.org/LimitedAvailability',
318
- 'https://schema.org/Discontinued',
319
- 'https://schema.org/BackOrder',
320
- 'InStock',
321
- 'OutOfStock',
322
- 'PreOrder',
323
- 'PreSale',
324
- 'SoldOut',
325
- 'InStoreOnly',
326
- 'OnlineOnly',
327
- 'LimitedAvailability',
328
- 'Discontinued',
329
- 'BackOrder',
330
- ];
331
-
332
- /**
333
- * Scoring weights for different categories
334
- */
335
- export const CATEGORY_WEIGHTS: Record<CheckCategory, number> = {
336
- completeness: 25,
337
- identifiers: 15,
338
- images: 20,
339
- pricing: 20,
340
- descriptions: 10,
341
- categories: 5,
342
- availability: 5,
343
- };
344
-
345
- /**
346
- * Grade thresholds (aligned with all other scoring models)
347
- */
348
- export const GRADE_THRESHOLDS = {
349
- A: 90,
350
- B: 80,
351
- C: 70,
352
- D: 60,
353
- F: 0,
354
- };
@@ -1,124 +0,0 @@
1
- /**
2
- * Signing Key Generator for UCP Webhook Signing
3
- * Generates EC or RSA key pairs in JWK format
4
- */
5
-
6
- import * as jose from 'jose';
7
- import { nanoid } from 'nanoid';
8
- import type { JwkKey } from '../types/ucp-profile.js';
9
-
10
- export type KeyAlgorithm = 'ES256' | 'RS256';
11
-
12
- export interface KeyPairResult {
13
- publicKey: JwkKey;
14
- privateKey: string; // PEM format for merchant storage
15
- }
16
-
17
- /**
18
- * Generate a new signing key pair
19
- */
20
- export async function generateSigningKeyPair(
21
- algorithm: KeyAlgorithm = 'ES256'
22
- ): Promise<KeyPairResult> {
23
- const keyId = `ucp-${nanoid(12)}`;
24
-
25
- if (algorithm === 'ES256') {
26
- return generateECKeyPair(keyId);
27
- } else {
28
- return generateRSAKeyPair(keyId);
29
- }
30
- }
31
-
32
- /**
33
- * Generate EC (P-256) key pair
34
- */
35
- async function generateECKeyPair(keyId: string): Promise<KeyPairResult> {
36
- const { publicKey, privateKey } = await jose.generateKeyPair('ES256', {
37
- extractable: true,
38
- });
39
-
40
- // Export public key as JWK
41
- const publicJwk = await jose.exportJWK(publicKey);
42
-
43
- // Export private key as PEM
44
- const privatePem = await jose.exportPKCS8(privateKey);
45
-
46
- return {
47
- publicKey: {
48
- kty: 'EC',
49
- kid: keyId,
50
- use: 'sig',
51
- alg: 'ES256',
52
- crv: publicJwk.crv as string,
53
- x: publicJwk.x as string,
54
- y: publicJwk.y as string,
55
- },
56
- privateKey: privatePem,
57
- };
58
- }
59
-
60
- /**
61
- * Generate RSA (2048-bit) key pair
62
- */
63
- async function generateRSAKeyPair(keyId: string): Promise<KeyPairResult> {
64
- const { publicKey, privateKey } = await jose.generateKeyPair('RS256', {
65
- extractable: true,
66
- modulusLength: 2048,
67
- });
68
-
69
- // Export public key as JWK
70
- const publicJwk = await jose.exportJWK(publicKey);
71
-
72
- // Export private key as PEM
73
- const privatePem = await jose.exportPKCS8(privateKey);
74
-
75
- return {
76
- publicKey: {
77
- kty: 'RSA',
78
- kid: keyId,
79
- use: 'sig',
80
- alg: 'RS256',
81
- n: publicJwk.n as string,
82
- e: publicJwk.e as string,
83
- },
84
- privateKey: privatePem,
85
- };
86
- }
87
-
88
- /**
89
- * Validate a JWK public key structure
90
- */
91
- export function validatePublicKey(key: JwkKey): string[] {
92
- const errors: string[] = [];
93
-
94
- if (!key.kty) {
95
- errors.push('Missing required field: kty');
96
- }
97
-
98
- if (!key.kid) {
99
- errors.push('Missing required field: kid');
100
- }
101
-
102
- if (key.kty === 'EC') {
103
- if (!key.crv) errors.push('EC key missing curve (crv)');
104
- if (!key.x) errors.push('EC key missing x coordinate');
105
- if (!key.y) errors.push('EC key missing y coordinate');
106
- if (key.crv && !['P-256', 'P-384', 'P-521'].includes(key.crv)) {
107
- errors.push(`Unsupported EC curve: ${key.crv}`);
108
- }
109
- } else if (key.kty === 'RSA') {
110
- if (!key.n) errors.push('RSA key missing modulus (n)');
111
- if (!key.e) errors.push('RSA key missing exponent (e)');
112
- } else if (key.kty) {
113
- errors.push(`Unsupported key type: ${key.kty}`);
114
- }
115
-
116
- return errors;
117
- }
118
-
119
- /**
120
- * Import and validate a public key from JWK
121
- */
122
- export async function importPublicKey(jwk: JwkKey): Promise<jose.KeyLike | Uint8Array> {
123
- return jose.importJWK(jwk as jose.JWK, jwk.alg);
124
- }