@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/api/badge.js DELETED
@@ -1,185 +0,0 @@
1
- /**
2
- * Vercel Serverless Function: Generate AI Commerce Ready Badge
3
- * GET /api/badge?domain=example.com&style=flat
4
- *
5
- * Returns an SVG badge showing the AI readiness grade
6
- */
7
-
8
- const GRADE_COLORS = {
9
- A: { bg: '#16A34A', text: '#DCFCE7' },
10
- B: { bg: '#2563EB', text: '#DBEAFE' },
11
- C: { bg: '#CA8A04', text: '#FEF9C3' },
12
- D: { bg: '#EA580C', text: '#FED7AA' },
13
- F: { bg: '#DC2626', text: '#FEE2E2' },
14
- };
15
-
16
- const READINESS_LABELS = {
17
- A: 'AI Commerce Ready',
18
- B: 'Mostly Ready',
19
- C: 'Partially Ready',
20
- D: 'Limited Readiness',
21
- F: 'Not Ready',
22
- };
23
-
24
- function generateFlatBadge(grade, domain, score) {
25
- const colors = GRADE_COLORS[grade] || GRADE_COLORS.F;
26
- const label = READINESS_LABELS[grade] || 'Not Ready';
27
-
28
- return `<svg xmlns="http://www.w3.org/2000/svg" width="180" height="20" role="img" aria-label="AI Commerce: ${grade}">
29
- <title>AI Commerce: Grade ${grade} - ${label}</title>
30
- <linearGradient id="s" x2="0" y2="100%">
31
- <stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
32
- <stop offset="1" stop-opacity=".1"/>
33
- </linearGradient>
34
- <clipPath id="r">
35
- <rect width="180" height="20" rx="3" fill="#fff"/>
36
- </clipPath>
37
- <g clip-path="url(#r)">
38
- <rect width="95" height="20" fill="#555"/>
39
- <rect x="95" width="85" height="20" fill="${colors.bg}"/>
40
- <rect width="180" height="20" fill="url(#s)"/>
41
- </g>
42
- <g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="11">
43
- <text x="48.5" y="14">AI Commerce</text>
44
- <text x="137.5" y="14" font-weight="bold">${grade} ${score}/100</text>
45
- </g>
46
- </svg>`;
47
- }
48
-
49
- function generateFlatSquareBadge(grade, domain, score) {
50
- const colors = GRADE_COLORS[grade] || GRADE_COLORS.F;
51
- const label = READINESS_LABELS[grade] || 'Not Ready';
52
-
53
- return `<svg xmlns="http://www.w3.org/2000/svg" width="180" height="20" role="img" aria-label="AI Commerce: ${grade}">
54
- <title>AI Commerce: Grade ${grade} - ${label}</title>
55
- <g shape-rendering="crispEdges">
56
- <rect width="95" height="20" fill="#555"/>
57
- <rect x="95" width="85" height="20" fill="${colors.bg}"/>
58
- </g>
59
- <g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="11">
60
- <text x="48.5" y="14">AI Commerce</text>
61
- <text x="137.5" y="14" font-weight="bold">${grade} ${score}/100</text>
62
- </g>
63
- </svg>`;
64
- }
65
-
66
- function generateLargeBadge(grade, domain, score) {
67
- const colors = GRADE_COLORS[grade] || GRADE_COLORS.F;
68
- const label = READINESS_LABELS[grade] || 'Not Ready';
69
-
70
- return `<svg xmlns="http://www.w3.org/2000/svg" width="200" height="80" role="img" aria-label="AI Commerce Ready: ${grade}">
71
- <title>AI Commerce: Grade ${grade} - ${label}</title>
72
- <defs>
73
- <linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%">
74
- <stop offset="0%" style="stop-color:#2E86AB;stop-opacity:1" />
75
- <stop offset="50%" style="stop-color:#36B5A2;stop-opacity:1" />
76
- <stop offset="100%" style="stop-color:#47C97A;stop-opacity:1" />
77
- </linearGradient>
78
- </defs>
79
- <rect width="200" height="80" rx="8" fill="#1A2B3C"/>
80
- <rect x="2" y="2" width="196" height="76" rx="6" fill="none" stroke="url(#grad)" stroke-width="2"/>
81
-
82
- <!-- Grade circle -->
83
- <circle cx="40" cy="40" r="25" fill="${colors.bg}"/>
84
- <text x="40" y="47" text-anchor="middle" font-family="Verdana,Geneva,sans-serif" font-size="24" font-weight="bold" fill="#fff">${grade}</text>
85
-
86
- <!-- Text -->
87
- <text x="75" y="30" font-family="Verdana,Geneva,sans-serif" font-size="11" fill="#94A3B8">AI Commerce</text>
88
- <text x="75" y="48" font-family="Verdana,Geneva,sans-serif" font-size="14" font-weight="bold" fill="#fff">${label}</text>
89
- <text x="75" y="65" font-family="Verdana,Geneva,sans-serif" font-size="10" fill="#94A3B8">Score: ${score}/100 • ucptools.dev</text>
90
- </svg>`;
91
- }
92
-
93
- function generateMiniBadge(grade) {
94
- const colors = GRADE_COLORS[grade] || GRADE_COLORS.F;
95
-
96
- return `<svg xmlns="http://www.w3.org/2000/svg" width="40" height="20" role="img" aria-label="Grade ${grade}">
97
- <title>AI Commerce Grade ${grade}</title>
98
- <rect width="40" height="20" rx="3" fill="${colors.bg}"/>
99
- <text x="20" y="14" text-anchor="middle" font-family="Verdana,Geneva,sans-serif" font-size="11" font-weight="bold" fill="#fff">${grade}</text>
100
- </svg>`;
101
- }
102
-
103
- export default async function handler(req, res) {
104
- // CORS headers
105
- res.setHeader('Access-Control-Allow-Origin', '*');
106
- res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');
107
- res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
108
- res.setHeader('Cache-Control', 'public, max-age=3600'); // Cache for 1 hour
109
-
110
- if (req.method === 'OPTIONS') {
111
- return res.status(200).end();
112
- }
113
-
114
- if (req.method !== 'GET') {
115
- return res.status(405).json({ error: 'Method not allowed' });
116
- }
117
-
118
- const { domain, style = 'flat', grade: staticGrade, score: staticScore } = req.query;
119
-
120
- // If static grade provided (for previews), use that
121
- if (staticGrade) {
122
- const grade = staticGrade.toUpperCase();
123
- const score = parseInt(staticScore) || (grade === 'A' ? 95 : grade === 'B' ? 82 : grade === 'C' ? 71 : grade === 'D' ? 55 : 30);
124
-
125
- res.setHeader('Content-Type', 'image/svg+xml');
126
-
127
- switch (style) {
128
- case 'flat-square':
129
- return res.send(generateFlatSquareBadge(grade, '', score));
130
- case 'large':
131
- return res.send(generateLargeBadge(grade, '', score));
132
- case 'mini':
133
- return res.send(generateMiniBadge(grade));
134
- default:
135
- return res.send(generateFlatBadge(grade, '', score));
136
- }
137
- }
138
-
139
- if (!domain) {
140
- return res.status(400).json({ error: 'Missing required parameter: domain' });
141
- }
142
-
143
- const cleanDomain = domain.replace(/^https?:\/\//, '').replace(/\/$/, '').split('/')[0];
144
-
145
- try {
146
- // Fetch validation data from our own API
147
- const baseUrl = process.env.VERCEL_URL
148
- ? `https://${process.env.VERCEL_URL}`
149
- : 'https://ucptools.dev';
150
-
151
- const validateRes = await fetch(`${baseUrl}/api/validate`, {
152
- method: 'POST',
153
- headers: { 'Content-Type': 'application/json' },
154
- body: JSON.stringify({ domain: cleanDomain }),
155
- });
156
-
157
- if (!validateRes.ok) {
158
- throw new Error('Validation failed');
159
- }
160
-
161
- const data = await validateRes.json();
162
- const grade = data.ai_readiness?.grade || 'F';
163
- const score = data.ai_readiness?.score || 0;
164
-
165
- res.setHeader('Content-Type', 'image/svg+xml');
166
-
167
- switch (style) {
168
- case 'flat-square':
169
- return res.send(generateFlatSquareBadge(grade, cleanDomain, score));
170
- case 'large':
171
- return res.send(generateLargeBadge(grade, cleanDomain, score));
172
- case 'mini':
173
- return res.send(generateMiniBadge(grade));
174
- default:
175
- return res.send(generateFlatBadge(grade, cleanDomain, score));
176
- }
177
- } catch (error) {
178
- // Return a gray "unknown" badge on error
179
- res.setHeader('Content-Type', 'image/svg+xml');
180
- return res.send(`<svg xmlns="http://www.w3.org/2000/svg" width="180" height="20" role="img">
181
- <rect width="180" height="20" rx="3" fill="#9CA3AF"/>
182
- <text x="90" y="14" text-anchor="middle" font-family="Verdana,Geneva,sans-serif" font-size="11" fill="#fff">AI Commerce • Unknown</text>
183
- </svg>`);
184
- }
185
- }
package/api/benchmark.js DELETED
@@ -1,177 +0,0 @@
1
- /**
2
- * Vercel Serverless Function: Benchmark Statistics
3
- *
4
- * POST /api/benchmark - Record a new validation score
5
- * GET /api/benchmark - Get benchmark statistics and percentile
6
- *
7
- * Privacy: Only stores aggregate statistics, not individual domains
8
- */
9
-
10
- import pg from 'pg';
11
-
12
- const { Pool } = pg;
13
-
14
- let pool = null;
15
-
16
- function getPool() {
17
- if (!pool) {
18
- pool = new Pool({
19
- connectionString: process.env.DATABASE_URL,
20
- ssl: { rejectUnauthorized: false },
21
- max: 5,
22
- idleTimeoutMillis: 30000,
23
- });
24
- }
25
- return pool;
26
- }
27
-
28
- /**
29
- * Get the score bucket for a given score (0, 10, 20, ..., 100)
30
- */
31
- function getScoreBucket(score) {
32
- return Math.floor(score / 10) * 10;
33
- }
34
-
35
- /**
36
- * Calculate percentile for a given score based on distribution
37
- */
38
- async function calculatePercentile(pool, score) {
39
- const result = await pool.query(`
40
- SELECT
41
- score_bucket,
42
- count,
43
- SUM(count) OVER (ORDER BY score_bucket) as cumulative
44
- FROM benchmark_stats
45
- ORDER BY score_bucket
46
- `);
47
-
48
- const summary = await pool.query('SELECT total_validations FROM benchmark_summary WHERE id = 1');
49
- const total = summary.rows[0]?.total_validations || 0;
50
-
51
- if (total === 0) {
52
- return 50; // Default to 50th percentile if no data
53
- }
54
-
55
- const scoreBucket = getScoreBucket(score);
56
- let belowCount = 0;
57
-
58
- for (const row of result.rows) {
59
- if (row.score_bucket < scoreBucket) {
60
- belowCount = row.cumulative;
61
- } else if (row.score_bucket === scoreBucket) {
62
- // For the current bucket, count half of it (assume uniform distribution within bucket)
63
- belowCount = (row.cumulative - row.count) + Math.floor(row.count / 2);
64
- break;
65
- }
66
- }
67
-
68
- return Math.round((belowCount / total) * 100);
69
- }
70
-
71
- /**
72
- * Record a new validation score
73
- */
74
- async function recordScore(pool, score) {
75
- const bucket = getScoreBucket(score);
76
-
77
- // Increment the bucket count
78
- await pool.query(`
79
- UPDATE benchmark_stats
80
- SET count = count + 1
81
- WHERE score_bucket = $1
82
- `, [bucket]);
83
-
84
- // Update summary statistics
85
- await pool.query(`
86
- UPDATE benchmark_summary
87
- SET
88
- total_validations = total_validations + 1,
89
- avg_score = (avg_score * total_validations + $1) / (total_validations + 1),
90
- updated_at = NOW()
91
- WHERE id = 1
92
- `, [score]);
93
- }
94
-
95
- /**
96
- * Get benchmark statistics
97
- */
98
- async function getStats(pool) {
99
- const summary = await pool.query('SELECT * FROM benchmark_summary WHERE id = 1');
100
- const distribution = await pool.query('SELECT score_bucket, count FROM benchmark_stats ORDER BY score_bucket');
101
-
102
- const stats = summary.rows[0] || { total_validations: 0, avg_score: 0 };
103
-
104
- return {
105
- total_validations: stats.total_validations,
106
- avg_score: Math.round(stats.avg_score * 10) / 10,
107
- distribution: distribution.rows.reduce((acc, row) => {
108
- acc[row.score_bucket] = row.count;
109
- return acc;
110
- }, {}),
111
- updated_at: stats.updated_at,
112
- };
113
- }
114
-
115
- export default async function handler(req, res) {
116
- // CORS headers
117
- res.setHeader('Access-Control-Allow-Origin', '*');
118
- res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
119
- res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
120
-
121
- if (req.method === 'OPTIONS') {
122
- return res.status(200).end();
123
- }
124
-
125
- if (!process.env.DATABASE_URL) {
126
- return res.status(500).json({ error: 'Database not configured' });
127
- }
128
-
129
- const pool = getPool();
130
-
131
- try {
132
- if (req.method === 'POST') {
133
- // Record a new score
134
- const { score } = req.body;
135
-
136
- if (typeof score !== 'number' || score < 0 || score > 100) {
137
- return res.status(400).json({ error: 'Invalid score. Must be a number between 0 and 100.' });
138
- }
139
-
140
- await recordScore(pool, score);
141
- const percentile = await calculatePercentile(pool, score);
142
- const stats = await getStats(pool);
143
-
144
- return res.status(200).json({
145
- recorded: true,
146
- percentile,
147
- stats: {
148
- total_validations: stats.total_validations,
149
- avg_score: stats.avg_score,
150
- }
151
- });
152
-
153
- } else if (req.method === 'GET') {
154
- // Get benchmark statistics
155
- const score = req.query.score ? parseInt(req.query.score, 10) : null;
156
- const stats = await getStats(pool);
157
-
158
- const response = {
159
- stats,
160
- };
161
-
162
- // If score provided, calculate percentile
163
- if (score !== null && !isNaN(score) && score >= 0 && score <= 100) {
164
- response.percentile = await calculatePercentile(pool, score);
165
- }
166
-
167
- return res.status(200).json(response);
168
-
169
- } else {
170
- return res.status(405).json({ error: 'Method not allowed' });
171
- }
172
-
173
- } catch (error) {
174
- console.error('Benchmark API error:', error);
175
- return res.status(500).json({ error: 'Internal server error' });
176
- }
177
- }
@@ -1,29 +0,0 @@
1
- /**
2
- * Vercel Serverless Function: Directory Statistics
3
- * GET /api/directory-stats
4
- */
5
-
6
- import type { VercelRequest, VercelResponse } from '@vercel/node';
7
- import { getDirectoryStats } from '../src/services/directory.js';
8
-
9
- export default async function handler(req: VercelRequest, res: VercelResponse) {
10
- res.setHeader('Access-Control-Allow-Origin', '*');
11
- res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');
12
- res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
13
-
14
- if (req.method === 'OPTIONS') {
15
- return res.status(200).end();
16
- }
17
-
18
- if (req.method !== 'GET') {
19
- return res.status(405).json({ error: 'Method not allowed' });
20
- }
21
-
22
- try {
23
- const stats = await getDirectoryStats();
24
- return res.status(200).json(stats);
25
- } catch (error: any) {
26
- console.error('Directory stats error:', error);
27
- return res.status(500).json({ error: 'Internal server error' });
28
- }
29
- }
package/api/directory.ts DELETED
@@ -1,73 +0,0 @@
1
- /**
2
- * Vercel Serverless Function: UCP Merchant Directory
3
- *
4
- * GET /api/directory - List merchants with pagination and filters
5
- * POST /api/directory - Submit a new merchant to the directory
6
- */
7
-
8
- import type { VercelRequest, VercelResponse } from '@vercel/node';
9
- import { listMerchants, submitMerchant } from '../src/services/directory.js';
10
-
11
- export default async function handler(req: VercelRequest, res: VercelResponse) {
12
- // CORS handled by vercel.json, but keep for local dev
13
- res.setHeader('Access-Control-Allow-Origin', '*');
14
- res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
15
- res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
16
-
17
- if (req.method === 'OPTIONS') {
18
- return res.status(200).end();
19
- }
20
-
21
- try {
22
- if (req.method === 'GET') {
23
- const result = await listMerchants({
24
- page: parseInt(req.query.page as string) || 1,
25
- limit: parseInt(req.query.limit as string) || 20,
26
- category: req.query.category as string,
27
- country: req.query.country as string,
28
- search: req.query.search as string,
29
- sort: req.query.sort as 'score' | 'domain' | 'displayName' | 'createdAt',
30
- order: req.query.order as 'asc' | 'desc',
31
- });
32
-
33
- return res.status(200).json(result);
34
- }
35
-
36
- if (req.method === 'POST') {
37
- const { domain, displayName, description, logoUrl, websiteUrl, category, countryCode } = req.body;
38
-
39
- if (!domain) {
40
- return res.status(400).json({ error: 'Missing required field: domain' });
41
- }
42
-
43
- const result = await submitMerchant({
44
- domain,
45
- displayName,
46
- description,
47
- logoUrl,
48
- websiteUrl,
49
- category,
50
- countryCode,
51
- });
52
-
53
- if (!result.success) {
54
- return res.status(400).json({
55
- error: result.error,
56
- details: result.details,
57
- });
58
- }
59
-
60
- return res.status(201).json({
61
- success: true,
62
- message: 'Merchant added to directory',
63
- merchant: result.merchant,
64
- directoryUrl: `https://ucptools.dev/directory#${result.merchant?.domain}`,
65
- });
66
- }
67
-
68
- return res.status(405).json({ error: 'Method not allowed' });
69
- } catch (error: any) {
70
- console.error('Directory API error:', error);
71
- return res.status(500).json({ error: 'Internal server error' });
72
- }
73
- }
@@ -1,143 +0,0 @@
1
- /**
2
- * Vercel Serverless Function: GDPR/Privacy Compliance Generator
3
- * POST /api/generate-compliance
4
- *
5
- * Generates privacy policy addendums and consent language for agentic commerce.
6
- *
7
- * Request body:
8
- * {
9
- * "companyName": "Your Company",
10
- * "companyEmail": "privacy@example.com",
11
- * "dpoEmail": "dpo@example.com",
12
- * "regions": ["eu", "uk", "california"],
13
- * "platforms": ["openai", "google"],
14
- * "lawfulBasis": "contract",
15
- * "includeMarketingConsent": true,
16
- * "includeDataRetention": true,
17
- * "retentionPeriodYears": 7
18
- * }
19
- *
20
- * GET /api/generate-compliance
21
- * Returns available options for regions, platforms, and lawful bases.
22
- */
23
-
24
- export default async function handler(req, res) {
25
- // Handle CORS
26
- res.setHeader('Access-Control-Allow-Origin', '*');
27
- res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
28
- res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
29
-
30
- if (req.method === 'OPTIONS') {
31
- return res.status(200).end();
32
- }
33
-
34
- // GET: Return available options
35
- if (req.method === 'GET') {
36
- try {
37
- const {
38
- getAvailableRegions,
39
- getLawfulBasisOptions,
40
- getAiPlatformOptions,
41
- } = await import('../src/compliance/index.js');
42
-
43
- return res.status(200).json({
44
- success: true,
45
- options: {
46
- regions: getAvailableRegions(),
47
- lawfulBases: getLawfulBasisOptions(),
48
- platforms: getAiPlatformOptions(),
49
- },
50
- });
51
- } catch (error) {
52
- console.error('Error getting options:', error);
53
- return res.status(500).json({
54
- error: 'Failed to get options',
55
- message: error.message,
56
- });
57
- }
58
- }
59
-
60
- // POST: Generate compliance documents
61
- if (req.method === 'POST') {
62
- try {
63
- const {
64
- companyName,
65
- companyEmail,
66
- companyAddress,
67
- dpoEmail,
68
- regions,
69
- platforms,
70
- lawfulBasis,
71
- includeMarketingConsent,
72
- includeDataRetention,
73
- retentionPeriodYears,
74
- additionalProcessors,
75
- } = req.body || {};
76
-
77
- // Validate required fields
78
- if (!companyName || companyName.trim() === '') {
79
- return res.status(400).json({
80
- error: 'Missing company name',
81
- message: 'Please provide your company name',
82
- });
83
- }
84
-
85
- if (!regions || regions.length === 0) {
86
- return res.status(400).json({
87
- error: 'Missing regions',
88
- message: 'Please select at least one compliance region',
89
- });
90
- }
91
-
92
- if (!platforms || platforms.length === 0) {
93
- return res.status(400).json({
94
- error: 'Missing platforms',
95
- message: 'Please select at least one AI platform',
96
- });
97
- }
98
-
99
- if (!lawfulBasis) {
100
- return res.status(400).json({
101
- error: 'Missing lawful basis',
102
- message: 'Please select a lawful basis for processing',
103
- });
104
- }
105
-
106
- // Import the generator
107
- const { generateComplianceDocuments } = await import('../src/compliance/index.js');
108
-
109
- // Generate documents
110
- const result = generateComplianceDocuments({
111
- companyName: companyName.trim(),
112
- companyEmail: companyEmail || `privacy@${companyName.toLowerCase().replace(/\s+/g, '')}.com`,
113
- companyAddress,
114
- dpoEmail,
115
- regions,
116
- platforms,
117
- lawfulBasis,
118
- includeMarketingConsent: includeMarketingConsent || false,
119
- includeDataRetention: includeDataRetention || false,
120
- retentionPeriodYears: retentionPeriodYears || 7,
121
- additionalProcessors,
122
- });
123
-
124
- return res.status(200).json({
125
- success: true,
126
- ...result,
127
- });
128
-
129
- } catch (error) {
130
- console.error('Compliance generation error:', error);
131
- return res.status(500).json({
132
- error: 'Generation failed',
133
- message: error.message || 'An unexpected error occurred',
134
- });
135
- }
136
- }
137
-
138
- // Method not allowed
139
- return res.status(405).json({
140
- error: 'Method not allowed',
141
- message: 'Use GET for options or POST to generate documents',
142
- });
143
- }