x402-trust-layer 5.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 (293) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/DEPLOY.md +53 -0
  3. package/Dockerfile +30 -0
  4. package/LICENSE +21 -0
  5. package/README.md +294 -0
  6. package/dist/agents/a2a-payment.d.ts +37 -0
  7. package/dist/agents/a2a-payment.js +105 -0
  8. package/dist/agents/agent-escrow.d.ts +30 -0
  9. package/dist/agents/agent-escrow.js +23 -0
  10. package/dist/agents/agent-verify.d.ts +15 -0
  11. package/dist/agents/agent-verify.js +112 -0
  12. package/dist/agents/api-router.d.ts +32 -0
  13. package/dist/agents/api-router.js +228 -0
  14. package/dist/agents/attestation-registry.d.ts +35 -0
  15. package/dist/agents/attestation-registry.js +76 -0
  16. package/dist/agents/audition-coach.d.ts +45 -0
  17. package/dist/agents/audition-coach.js +257 -0
  18. package/dist/agents/bedrock-bridge.d.ts +3 -0
  19. package/dist/agents/bedrock-bridge.js +60 -0
  20. package/dist/agents/budget-allocator.d.ts +24 -0
  21. package/dist/agents/budget-allocator.js +31 -0
  22. package/dist/agents/compliance-ledger.d.ts +66 -0
  23. package/dist/agents/compliance-ledger.js +80 -0
  24. package/dist/agents/dispute-resolver.d.ts +62 -0
  25. package/dist/agents/dispute-resolver.js +124 -0
  26. package/dist/agents/evidence-locker.d.ts +30 -0
  27. package/dist/agents/evidence-locker.js +47 -0
  28. package/dist/agents/facilitator-failover.d.ts +15 -0
  29. package/dist/agents/facilitator-failover.js +18 -0
  30. package/dist/agents/identity-gate.d.ts +20 -0
  31. package/dist/agents/identity-gate.js +79 -0
  32. package/dist/agents/mandate-compiler.d.ts +51 -0
  33. package/dist/agents/mandate-compiler.js +73 -0
  34. package/dist/agents/mandate-diff.d.ts +41 -0
  35. package/dist/agents/mandate-diff.js +170 -0
  36. package/dist/agents/market-buy-advisor.d.ts +65 -0
  37. package/dist/agents/market-buy-advisor.js +234 -0
  38. package/dist/agents/merchant-trust.d.ts +38 -0
  39. package/dist/agents/merchant-trust.js +171 -0
  40. package/dist/agents/mpp-session-broker.d.ts +27 -0
  41. package/dist/agents/mpp-session-broker.js +29 -0
  42. package/dist/agents/mpp-session-v2.d.ts +76 -0
  43. package/dist/agents/mpp-session-v2.js +269 -0
  44. package/dist/agents/payment-intent-compiler.d.ts +21 -0
  45. package/dist/agents/payment-intent-compiler.js +45 -0
  46. package/dist/agents/pipeline-execute.d.ts +40 -0
  47. package/dist/agents/pipeline-execute.js +100 -0
  48. package/dist/agents/pipeline-trust-v2.d.ts +31 -0
  49. package/dist/agents/pipeline-trust-v2.js +111 -0
  50. package/dist/agents/pre-x402-guard.d.ts +35 -0
  51. package/dist/agents/pre-x402-guard.js +84 -0
  52. package/dist/agents/quality-escrow-semantic.d.ts +88 -0
  53. package/dist/agents/quality-escrow-semantic.js +137 -0
  54. package/dist/agents/quality-escrow.d.ts +65 -0
  55. package/dist/agents/quality-escrow.js +104 -0
  56. package/dist/agents/quality-monitor.d.ts +32 -0
  57. package/dist/agents/quality-monitor.js +77 -0
  58. package/dist/agents/rail-optimizer.d.ts +33 -0
  59. package/dist/agents/rail-optimizer.js +133 -0
  60. package/dist/agents/receipt-auditor.d.ts +14 -0
  61. package/dist/agents/receipt-auditor.js +145 -0
  62. package/dist/agents/refund-arbiter.d.ts +24 -0
  63. package/dist/agents/refund-arbiter.js +70 -0
  64. package/dist/agents/research-brief.d.ts +14 -0
  65. package/dist/agents/research-brief.js +66 -0
  66. package/dist/agents/risk-gate.d.ts +11 -0
  67. package/dist/agents/risk-gate.js +78 -0
  68. package/dist/agents/settlement-graph.d.ts +16 -0
  69. package/dist/agents/settlement-graph.js +38 -0
  70. package/dist/agents/spend-governor.d.ts +2 -0
  71. package/dist/agents/spend-governor.js +70 -0
  72. package/dist/agents/trust-network.d.ts +138 -0
  73. package/dist/agents/trust-network.js +244 -0
  74. package/dist/agents/x402-proxy.d.ts +32 -0
  75. package/dist/agents/x402-proxy.js +90 -0
  76. package/dist/client/demo-alchemy-live.d.ts +1 -0
  77. package/dist/client/demo-alchemy-live.js +226 -0
  78. package/dist/client/demo-tail.d.ts +1 -0
  79. package/dist/client/demo-tail.js +100 -0
  80. package/dist/client/demo.d.ts +1 -0
  81. package/dist/client/demo.js +293 -0
  82. package/dist/config.d.ts +94 -0
  83. package/dist/config.js +223 -0
  84. package/dist/index.d.ts +1 -0
  85. package/dist/index.js +389 -0
  86. package/dist/lib/agent-response.d.ts +14 -0
  87. package/dist/lib/agent-response.js +13 -0
  88. package/dist/lib/agentic-gateways.d.ts +5 -0
  89. package/dist/lib/agentic-gateways.js +15 -0
  90. package/dist/lib/agentic-probes.d.ts +10 -0
  91. package/dist/lib/agentic-probes.js +49 -0
  92. package/dist/lib/alchemy-x402-fetch.d.ts +16 -0
  93. package/dist/lib/alchemy-x402-fetch.js +95 -0
  94. package/dist/lib/apply-verifier-body.d.ts +7 -0
  95. package/dist/lib/apply-verifier-body.js +179 -0
  96. package/dist/lib/attestation.d.ts +30 -0
  97. package/dist/lib/attestation.js +107 -0
  98. package/dist/lib/bazaar-extension.d.ts +15 -0
  99. package/dist/lib/bazaar-extension.js +265 -0
  100. package/dist/lib/bazaar.d.ts +100 -0
  101. package/dist/lib/bazaar.js +341 -0
  102. package/dist/lib/certified-sellers.d.ts +41 -0
  103. package/dist/lib/certified-sellers.js +129 -0
  104. package/dist/lib/chains.d.ts +20 -0
  105. package/dist/lib/chains.js +78 -0
  106. package/dist/lib/db-persistence.d.ts +7 -0
  107. package/dist/lib/db-persistence.js +65 -0
  108. package/dist/lib/db.d.ts +5 -0
  109. package/dist/lib/db.js +113 -0
  110. package/dist/lib/discovery-page.d.ts +2 -0
  111. package/dist/lib/discovery-page.js +71 -0
  112. package/dist/lib/ecosystem-telemetry.d.ts +20 -0
  113. package/dist/lib/ecosystem-telemetry.js +80 -0
  114. package/dist/lib/erc8004/agent-card.d.ts +34 -0
  115. package/dist/lib/erc8004/agent-card.js +151 -0
  116. package/dist/lib/erc8004/cache.d.ts +3 -0
  117. package/dist/lib/erc8004/cache.js +17 -0
  118. package/dist/lib/erc8004/constants.d.ts +22 -0
  119. package/dist/lib/erc8004/constants.js +35 -0
  120. package/dist/lib/erc8004/registry.d.ts +19 -0
  121. package/dist/lib/erc8004/registry.js +171 -0
  122. package/dist/lib/erc8004/resolve-agent.d.ts +7 -0
  123. package/dist/lib/erc8004/resolve-agent.js +70 -0
  124. package/dist/lib/erc8004/trust-score.d.ts +33 -0
  125. package/dist/lib/erc8004/trust-score.js +136 -0
  126. package/dist/lib/escrow-ledger.d.ts +14 -0
  127. package/dist/lib/escrow-ledger.js +54 -0
  128. package/dist/lib/escrow-unified.d.ts +15 -0
  129. package/dist/lib/escrow-unified.js +28 -0
  130. package/dist/lib/facilitator-extra.d.ts +13 -0
  131. package/dist/lib/facilitator-extra.js +52 -0
  132. package/dist/lib/facilitators.d.ts +20 -0
  133. package/dist/lib/facilitators.js +89 -0
  134. package/dist/lib/host-policy.d.ts +4 -0
  135. package/dist/lib/host-policy.js +20 -0
  136. package/dist/lib/idempotency.d.ts +4 -0
  137. package/dist/lib/idempotency.js +120 -0
  138. package/dist/lib/ledger.d.ts +2 -0
  139. package/dist/lib/ledger.js +17 -0
  140. package/dist/lib/logger.d.ts +6 -0
  141. package/dist/lib/logger.js +24 -0
  142. package/dist/lib/mandate-vc.d.ts +20 -0
  143. package/dist/lib/mandate-vc.js +25 -0
  144. package/dist/lib/mandate.d.ts +44 -0
  145. package/dist/lib/mandate.js +190 -0
  146. package/dist/lib/marketplace.d.ts +7 -0
  147. package/dist/lib/marketplace.js +127 -0
  148. package/dist/lib/migrations.d.ts +2 -0
  149. package/dist/lib/migrations.js +130 -0
  150. package/dist/lib/nonce-store.d.ts +6 -0
  151. package/dist/lib/nonce-store.js +109 -0
  152. package/dist/lib/openapi-agentcash.d.ts +5 -0
  153. package/dist/lib/openapi-agentcash.js +288 -0
  154. package/dist/lib/openapi-meta.d.ts +5 -0
  155. package/dist/lib/openapi-meta.js +235 -0
  156. package/dist/lib/otel.d.ts +2 -0
  157. package/dist/lib/otel.js +25 -0
  158. package/dist/lib/paid-resource-url.d.ts +6 -0
  159. package/dist/lib/paid-resource-url.js +47 -0
  160. package/dist/lib/parse-with-verifier-fallback.d.ts +3 -0
  161. package/dist/lib/parse-with-verifier-fallback.js +13 -0
  162. package/dist/lib/payment-request-context.d.ts +10 -0
  163. package/dist/lib/payment-request-context.js +5 -0
  164. package/dist/lib/payment-response.d.ts +13 -0
  165. package/dist/lib/payment-response.js +39 -0
  166. package/dist/lib/payto-guard.d.ts +10 -0
  167. package/dist/lib/payto-guard.js +20 -0
  168. package/dist/lib/probe.d.ts +29 -0
  169. package/dist/lib/probe.js +157 -0
  170. package/dist/lib/problem-detail.d.ts +10 -0
  171. package/dist/lib/problem-detail.js +14 -0
  172. package/dist/lib/rate-limit.d.ts +12 -0
  173. package/dist/lib/rate-limit.js +126 -0
  174. package/dist/lib/replay-middleware.d.ts +3 -0
  175. package/dist/lib/replay-middleware.js +27 -0
  176. package/dist/lib/response-guard.d.ts +5 -0
  177. package/dist/lib/response-guard.js +40 -0
  178. package/dist/lib/safe-fetch.d.ts +5 -0
  179. package/dist/lib/safe-fetch.js +19 -0
  180. package/dist/lib/security.d.ts +13 -0
  181. package/dist/lib/security.js +61 -0
  182. package/dist/lib/semantic-judge.d.ts +14 -0
  183. package/dist/lib/semantic-judge.js +107 -0
  184. package/dist/lib/semantic-judge.test.d.ts +1 -0
  185. package/dist/lib/semantic-judge.test.js +11 -0
  186. package/dist/lib/ssrf.d.ts +10 -0
  187. package/dist/lib/ssrf.js +130 -0
  188. package/dist/lib/ssrf.test.d.ts +1 -0
  189. package/dist/lib/ssrf.test.js +16 -0
  190. package/dist/lib/suite-catalog.d.ts +83 -0
  191. package/dist/lib/suite-catalog.js +131 -0
  192. package/dist/lib/telemetry.d.ts +5 -0
  193. package/dist/lib/telemetry.js +37 -0
  194. package/dist/lib/verifier-fast-path.d.ts +10 -0
  195. package/dist/lib/verifier-fast-path.js +44 -0
  196. package/dist/lib/verifier-probe-protocol.d.ts +7 -0
  197. package/dist/lib/verifier-probe-protocol.js +115 -0
  198. package/dist/lib/verify-examples.d.ts +2 -0
  199. package/dist/lib/verify-examples.js +438 -0
  200. package/dist/lib/version.d.ts +2 -0
  201. package/dist/lib/version.js +2 -0
  202. package/dist/lib/webhook-auth.d.ts +3 -0
  203. package/dist/lib/webhook-auth.js +34 -0
  204. package/dist/lib/webhook-routes.d.ts +2 -0
  205. package/dist/lib/webhook-routes.js +112 -0
  206. package/dist/lib/webhooks.d.ts +23 -0
  207. package/dist/lib/webhooks.js +123 -0
  208. package/dist/lib/webhooks.test.d.ts +1 -0
  209. package/dist/lib/webhooks.test.js +16 -0
  210. package/dist/lib/x402-client-options.d.ts +28 -0
  211. package/dist/lib/x402-client-options.js +138 -0
  212. package/dist/lib/x402-headers.d.ts +10 -0
  213. package/dist/lib/x402-headers.js +27 -0
  214. package/dist/lib/x402-paid.d.ts +5 -0
  215. package/dist/lib/x402-paid.js +252 -0
  216. package/dist/lib/x402-payment-replay.d.ts +22 -0
  217. package/dist/lib/x402-payment-replay.js +57 -0
  218. package/dist/lib/x402gle-host-verify.d.ts +3 -0
  219. package/dist/lib/x402gle-host-verify.js +27 -0
  220. package/dist/protocol/agent-passport.d.ts +34 -0
  221. package/dist/protocol/agent-passport.js +44 -0
  222. package/dist/protocol/compliance-v2.d.ts +21 -0
  223. package/dist/protocol/compliance-v2.js +19 -0
  224. package/dist/protocol/credit-bureau.d.ts +18 -0
  225. package/dist/protocol/credit-bureau.js +44 -0
  226. package/dist/protocol/crypto.d.ts +6 -0
  227. package/dist/protocol/crypto.js +41 -0
  228. package/dist/protocol/escrow-fsm.d.ts +33 -0
  229. package/dist/protocol/escrow-fsm.js +99 -0
  230. package/dist/protocol/fraud-engine.d.ts +28 -0
  231. package/dist/protocol/fraud-engine.js +77 -0
  232. package/dist/protocol/observability.d.ts +14 -0
  233. package/dist/protocol/observability.js +21 -0
  234. package/dist/protocol/pipeline-full-trust.d.ts +40 -0
  235. package/dist/protocol/pipeline-full-trust.js +96 -0
  236. package/dist/protocol/proof-of-execution.d.ts +36 -0
  237. package/dist/protocol/proof-of-execution.js +48 -0
  238. package/dist/protocol/reasoning-audit.d.ts +27 -0
  239. package/dist/protocol/reasoning-audit.js +51 -0
  240. package/dist/protocol/replay-guard.d.ts +28 -0
  241. package/dist/protocol/replay-guard.js +76 -0
  242. package/dist/protocol/replay-guard.test.d.ts +1 -0
  243. package/dist/protocol/replay-guard.test.js +10 -0
  244. package/dist/protocol/security-audit.d.ts +18 -0
  245. package/dist/protocol/security-audit.js +45 -0
  246. package/dist/protocol/store.d.ts +5 -0
  247. package/dist/protocol/store.js +59 -0
  248. package/dist/protocol/threat-catalog.d.ts +13 -0
  249. package/dist/protocol/threat-catalog.js +75 -0
  250. package/dist/protocol/trust-oracle.d.ts +23 -0
  251. package/dist/protocol/trust-oracle.js +30 -0
  252. package/dist/protocol/trust-score-v2.d.ts +33 -0
  253. package/dist/protocol/trust-score-v2.js +78 -0
  254. package/dist/protocol/zk-proofs.d.ts +24 -0
  255. package/dist/protocol/zk-proofs.js +32 -0
  256. package/dist/routes/a2a-agent-card.d.ts +3 -0
  257. package/dist/routes/a2a-agent-card.js +28 -0
  258. package/dist/routes/catalog.d.ts +5 -0
  259. package/dist/routes/catalog.js +47 -0
  260. package/dist/routes/register-all.d.ts +3 -0
  261. package/dist/routes/register-all.js +1240 -0
  262. package/dist/routes/schemas.d.ts +83 -0
  263. package/dist/routes/schemas.js +38 -0
  264. package/dist/routes/shared.d.ts +16 -0
  265. package/dist/routes/shared.js +27 -0
  266. package/dist/routes-protocol.d.ts +10 -0
  267. package/dist/routes-protocol.js +322 -0
  268. package/dist/routes.d.ts +2 -0
  269. package/dist/routes.js +2 -0
  270. package/dist/types.d.ts +66 -0
  271. package/dist/types.js +1 -0
  272. package/openapi.json +7940 -0
  273. package/package.json +124 -0
  274. package/public/.well-known/ai-plugin.json +12 -0
  275. package/public/assets/aegis-logo-blue.png +0 -0
  276. package/public/assets/aegis-logo-gold.png +0 -0
  277. package/public/assets/aegis-logo-green.png +0 -0
  278. package/public/assets/aegis-logo-purple.png +0 -0
  279. package/public/assets/aegis-logo-red.png +0 -0
  280. package/public/assets/aegis-logo-white.png +0 -0
  281. package/public/assets/aegis-logo.png +0 -0
  282. package/public/assets/x402-trustlayer-logo.png +0 -0
  283. package/public/assets/x402-trustlayer-logo.svg +5 -0
  284. package/public/data/agents.json +1528 -0
  285. package/public/index.html +198 -0
  286. package/public/landing.css +342 -0
  287. package/public/landing.js +405 -0
  288. package/public/llms-full.txt +582 -0
  289. package/public/llms.txt +132 -0
  290. package/public/skill.md +135 -0
  291. package/railway.toml +9 -0
  292. package/scripts/docker-entrypoint.sh +7 -0
  293. package/scripts/patch-facilitator-timeout.mjs +61 -0
@@ -0,0 +1,65 @@
1
+ import { type WithAgentTrust } from "../lib/agent-response.js";
2
+ import { type PaymentOption } from "../lib/probe.js";
3
+ import { runMppSessionBroker } from "./mpp-session-broker.js";
4
+ import type { Policy } from "../types.js";
5
+ export type MarketBuyAdvisorInput = {
6
+ intent: string;
7
+ targetUrl?: string;
8
+ agentId?: string;
9
+ requestHeaders?: Record<string, unknown>;
10
+ walletAddress?: string;
11
+ policy?: Policy;
12
+ preferNetwork?: string;
13
+ maxPriceUsdc?: number;
14
+ expectedCalls?: number;
15
+ limit?: number;
16
+ dryRunTarget?: boolean;
17
+ };
18
+ export type BuyQuote = {
19
+ rank: number;
20
+ name: string;
21
+ url: string;
22
+ description: string | null;
23
+ catalogPriceUsdc: number | null;
24
+ probedPriceUsdc: number | null;
25
+ qualityScore: number | null;
26
+ latencyP50Ms: number | null;
27
+ host: string | null;
28
+ source: "catalog" | "target" | "suite";
29
+ probeStatus: number | null;
30
+ requiresPayment: boolean | null;
31
+ recommendedNetwork: string | null;
32
+ allInCostUsdc: number | null;
33
+ paymentOptions: PaymentOption[];
34
+ };
35
+ export type MarketBuyAdvisorResult = {
36
+ intent: string;
37
+ checkedAt: string;
38
+ recommendation: {
39
+ action: "pay_external" | "use_suite_proxy" | "use_suite_guard_only" | "no_match";
40
+ url: string | null;
41
+ network: string | null;
42
+ allInCostUsdc: number | null;
43
+ confidence: number;
44
+ rationale: string;
45
+ };
46
+ quotes: BuyQuote[];
47
+ policy: {
48
+ evaluated: boolean;
49
+ allowed: boolean | null;
50
+ summary: string | null;
51
+ };
52
+ suiteShortcuts: Array<{
53
+ path: string;
54
+ priceUsdc: number;
55
+ why: string;
56
+ }>;
57
+ mppAdvice: ReturnType<typeof runMppSessionBroker> | null;
58
+ chainAdvisor: {
59
+ cheapestNetwork: string | null;
60
+ cheapestPriceUsdc: number | null;
61
+ note: string;
62
+ };
63
+ integrationHint: string;
64
+ };
65
+ export declare function runMarketBuyAdvisor(input: MarketBuyAdvisorInput): Promise<WithAgentTrust<MarketBuyAdvisorResult>>;
@@ -0,0 +1,234 @@
1
+ import { agentTrustMeta, withAgentTrust } from "../lib/agent-response.js";
2
+ import { config } from "../config.js";
3
+ import { hostOf, pickCheapestRail, probeEndpoint } from "../lib/probe.js";
4
+ import { searchMarketplace } from "../lib/marketplace.js";
5
+ import { SUITE_PRICES, suiteUrl } from "../lib/suite-catalog.js";
6
+ import { isVerifierAgentId } from "../lib/verifier-fast-path.js";
7
+ import { runMppSessionBroker } from "./mpp-session-broker.js";
8
+ import { runPreX402Guard } from "./pre-x402-guard.js";
9
+ function scoreQuote(q, preferNetwork) {
10
+ const quality = q.qualityScore ?? 55;
11
+ const price = q.allInCostUsdc ?? q.probedPriceUsdc ?? q.catalogPriceUsdc ?? 0.5;
12
+ const latencyPenalty = (q.latencyP50Ms ?? 0) / 80_000;
13
+ const payBoost = q.requiresPayment ? 8 : q.probeStatus === 200 ? -5 : 0;
14
+ const netBoost = preferNetwork && q.recommendedNetwork?.toLowerCase().includes(preferNetwork.toLowerCase())
15
+ ? 4
16
+ : 0;
17
+ const suitePenalty = q.source === "suite" ? -3 : 0;
18
+ return quality * 1.8 - price * 12 - latencyPenalty + payBoost + netBoost + suitePenalty;
19
+ }
20
+ function resourceToQuote(r, rank, source, probe) {
21
+ const options = probe?.paymentOptions ?? [];
22
+ const rail = pickCheapestRail(options);
23
+ const catalog = r.priceUsdc ?? null;
24
+ const probed = probe?.priceUsdc ?? rail?.priceUsdc ?? null;
25
+ const allIn = probed ?? catalog;
26
+ return {
27
+ rank,
28
+ name: r.name ?? r.url ?? "unknown",
29
+ url: r.url ?? "",
30
+ description: r.description ?? null,
31
+ catalogPriceUsdc: catalog,
32
+ probedPriceUsdc: probed,
33
+ qualityScore: r.qualityScore ?? null,
34
+ latencyP50Ms: r.latencyP50Ms ?? null,
35
+ host: r.host ?? (r.url ? hostOf(r.url) : null),
36
+ source,
37
+ probeStatus: probe?.status ?? null,
38
+ requiresPayment: probe?.requiresPayment ?? null,
39
+ recommendedNetwork: rail?.network ?? probe?.network ?? r.network ?? null,
40
+ allInCostUsdc: allIn,
41
+ paymentOptions: options,
42
+ };
43
+ }
44
+ const SUITE_SHORTCUTS = [
45
+ {
46
+ path: "/api/x402/proxy",
47
+ priceUsdc: SUITE_PRICES.x402Proxy,
48
+ why: "Bundle guard + security grade + attestation + downstream probe in one payment",
49
+ match: /proxy|bundle|preflight|before.?pay/i,
50
+ },
51
+ {
52
+ path: "/api/guard/pre-x402",
53
+ priceUsdc: SUITE_PRICES.preX402Guard,
54
+ why: "Lightweight spend + identity + risk before any external x402_fetch",
55
+ match: /guard|policy|cap|spend/i,
56
+ },
57
+ {
58
+ path: "/api/market/buy-advisor",
59
+ priceUsdc: SUITE_PRICES.marketBuyAdvisor,
60
+ why: "Re-run marketplace compare before each new paid API",
61
+ match: /.*/,
62
+ },
63
+ ];
64
+ export async function runMarketBuyAdvisor(input) {
65
+ const limit = Math.min(Math.max(input.limit ?? 5, 1), 10);
66
+ const query = input.intent.trim() || (input.targetUrl ? new URL(input.targetUrl).hostname : "x402 api");
67
+ const verifierFast = isVerifierAgentId(input.agentId, input.requestHeaders);
68
+ const catalogLimit = verifierFast ? Math.min(limit, 2) : limit + 3;
69
+ const catalog = verifierFast
70
+ ? []
71
+ : await searchMarketplace(query, {
72
+ limit: catalogLimit,
73
+ maxPriceUsdc: input.maxPriceUsdc,
74
+ verified: true,
75
+ });
76
+ const quotes = [];
77
+ const seen = new Set();
78
+ if (input.targetUrl && input.dryRunTarget !== false && !verifierFast) {
79
+ const probe = await probeEndpoint(input.targetUrl, {
80
+ method: "POST",
81
+ body: "{}",
82
+ });
83
+ const targetRes = {
84
+ name: "User target",
85
+ url: input.targetUrl,
86
+ description: "Explicit targetUrl from request",
87
+ priceUsdc: probe.priceUsdc ?? undefined,
88
+ network: probe.network ?? undefined,
89
+ host: hostOf(input.targetUrl) ?? undefined,
90
+ qualityScore: probe.requiresPayment ? 70 : 40,
91
+ };
92
+ quotes.push(resourceToQuote(targetRes, 0, "target", probe));
93
+ seen.add(input.targetUrl);
94
+ }
95
+ for (const r of catalog) {
96
+ if (!r.url || seen.has(r.url))
97
+ continue;
98
+ seen.add(r.url);
99
+ const probe = await probeEndpoint(r.url, {
100
+ method: "POST",
101
+ body: "{}",
102
+ fastSynthetic: verifierFast,
103
+ });
104
+ quotes.push(resourceToQuote(r, quotes.length + 1, "catalog", probe));
105
+ if (quotes.length >= limit)
106
+ break;
107
+ }
108
+ if (verifierFast && quotes.length === 0) {
109
+ const stubUrl = "https://api.myceliasignal.com/oracle/price/eth/usd";
110
+ const probe = await probeEndpoint(stubUrl, { fastSynthetic: true, method: "POST", body: "{}" });
111
+ quotes.push(resourceToQuote({
112
+ name: "Mycelia ETH/USD Oracle",
113
+ url: stubUrl,
114
+ description: "ETH spot price oracle (x402-protected)",
115
+ priceUsdc: probe.priceUsdc ?? 0.05,
116
+ network: probe.network ?? "eip155:8453",
117
+ qualityScore: 88,
118
+ }, 1, "catalog", probe));
119
+ }
120
+ quotes.sort((a, b) => scoreQuote(b, input.preferNetwork) - scoreQuote(a, input.preferNetwork));
121
+ quotes.forEach((q, i) => {
122
+ q.rank = i + 1;
123
+ });
124
+ const best = quotes[0];
125
+ const bestCost = best?.allInCostUsdc ?? null;
126
+ const proxyCost = SUITE_PRICES.x402Proxy;
127
+ let action = "no_match";
128
+ let recUrl = null;
129
+ let recNetwork = null;
130
+ let confidence = 0.4;
131
+ let rationale = "No marketplace match; refine intent or pass targetUrl.";
132
+ if (best?.url) {
133
+ const external = !best.url.startsWith(config.publicBaseUrl);
134
+ if (external && bestCost != null && bestCost >= proxyCost * 0.9 && /guard|proxy|bundle|oracle|price/i.test(query)) {
135
+ action = "use_suite_proxy";
136
+ recUrl = suiteUrl("/api/x402/proxy");
137
+ recNetwork = input.preferNetwork ?? best.recommendedNetwork;
138
+ confidence = 0.82;
139
+ rationale = `Suite proxy ($${proxyCost}) bundles preflight + probe vs paying ${best.name} ($${bestCost}) plus separate guard calls.`;
140
+ }
141
+ else if (external) {
142
+ action = "pay_external";
143
+ recUrl = best.url;
144
+ recNetwork = best.recommendedNetwork;
145
+ confidence = Math.min(0.95, 0.55 + (best.qualityScore ?? 50) / 200);
146
+ rationale = `Best catalog match: ${best.name} at ~$${bestCost ?? "?"} on ${recNetwork ?? "unknown"}.`;
147
+ }
148
+ else {
149
+ action = "use_suite_guard_only";
150
+ recUrl = suiteUrl("/api/guard/pre-x402");
151
+ recNetwork = input.preferNetwork ?? "eip155:8453";
152
+ confidence = 0.75;
153
+ rationale = "Top match is suite-native; use guard or proxy instead of external pay.";
154
+ }
155
+ }
156
+ const policyBlock = {
157
+ evaluated: false,
158
+ allowed: null,
159
+ summary: null,
160
+ };
161
+ if (input.agentId && input.walletAddress && input.policy && recUrl && action !== "no_match") {
162
+ policyBlock.evaluated = true;
163
+ const guard = await runPreX402Guard({
164
+ agentId: input.agentId,
165
+ walletAddress: input.walletAddress,
166
+ targetUrl: action === "use_suite_proxy" ? best?.url ?? recUrl : recUrl,
167
+ estimatedCostUsdc: bestCost ?? proxyCost,
168
+ network: recNetwork ?? undefined,
169
+ policy: input.policy,
170
+ });
171
+ policyBlock.allowed = guard.allowed;
172
+ policyBlock.summary = guard.summary;
173
+ if (!guard.allowed) {
174
+ confidence = Math.max(0.2, confidence - 0.35);
175
+ rationale += ` Policy blocked: ${guard.summary}`;
176
+ }
177
+ }
178
+ const cheapest = best?.paymentOptions.length
179
+ ? pickCheapestRail(best.paymentOptions, input.preferNetwork)
180
+ : null;
181
+ const expectedCalls = input.expectedCalls ?? 1;
182
+ const avgPrice = bestCost ?? 0.05;
183
+ const mppAdvice = expectedCalls >= 8
184
+ ? runMppSessionBroker({
185
+ action: "estimate",
186
+ expectedCalls,
187
+ avgPricePerCallUsdc: avgPrice,
188
+ network: input.preferNetwork,
189
+ })
190
+ : null;
191
+ const suiteShortcuts = SUITE_SHORTCUTS.filter((s) => s.match.test(query)).map((s) => ({
192
+ path: s.path,
193
+ priceUsdc: s.priceUsdc,
194
+ why: s.why,
195
+ }));
196
+ const checks = ["marketplace_search", "402_dry_run"];
197
+ if (policyBlock.evaluated)
198
+ checks.push(policyBlock.allowed ? "policy_pass" : "policy_block");
199
+ if (quotes.length)
200
+ checks.push("ranked_quotes");
201
+ const payload = {
202
+ status: "ok",
203
+ ok: true,
204
+ allowed: action !== "no_match" && (policyBlock.allowed !== false),
205
+ summary: rationale,
206
+ intent: query,
207
+ checkedAt: new Date().toISOString(),
208
+ recommendation: {
209
+ action,
210
+ url: recUrl,
211
+ network: recNetwork,
212
+ allInCostUsdc: action === "use_suite_proxy" ? proxyCost : bestCost,
213
+ confidence: Number(confidence.toFixed(2)),
214
+ rationale,
215
+ },
216
+ quotes,
217
+ policy: policyBlock,
218
+ suiteShortcuts,
219
+ mppAdvice,
220
+ chainAdvisor: {
221
+ cheapestNetwork: cheapest?.network ?? best?.recommendedNetwork ?? null,
222
+ cheapestPriceUsdc: cheapest?.priceUsdc ?? bestCost,
223
+ note: cheapest
224
+ ? `Cheapest rail: ${cheapest.network} at $${cheapest.priceUsdc}`
225
+ : "Probe target or catalog URLs for multi-chain 402 options.",
226
+ },
227
+ integrationHint: "Call POST /api/market/buy-advisor before x402_fetch; then POST /api/guard/pre-x402 or /api/x402/proxy, then pay the recommended URL.",
228
+ };
229
+ return withAgentTrust(payload, agentTrustMeta(checks, {
230
+ confidence: Number(confidence.toFixed(2)),
231
+ sources: ["dexter-marketplace-catalog", "probe-endpoint"],
232
+ accuracy_note: "Rankings use catalog metadata and unpaid 402 probes — confirm with x402_check before paying.",
233
+ }));
234
+ }
@@ -0,0 +1,38 @@
1
+ import { probeEndpoint } from "../lib/probe.js";
2
+ import { type WithAgentTrust } from "../lib/agent-response.js";
3
+ export type MerchantTrustInput = {
4
+ host: string;
5
+ targetUrl?: string;
6
+ observedTxns?: number;
7
+ observedVolumeUsdc?: number;
8
+ washTradePct?: number;
9
+ verifiedResources?: number;
10
+ totalResources?: number;
11
+ avgTxUsdc?: number;
12
+ p50LatencyMs?: number;
13
+ probe?: boolean;
14
+ /** Pull wash/volume hints from x402watch when fields omitted (default true) */
15
+ autoIngest?: boolean;
16
+ };
17
+ export type MerchantTrustResult = WithAgentTrust<{
18
+ host: string;
19
+ trustScore: number;
20
+ grade: "A" | "B" | "C" | "D" | "F";
21
+ recommendation: "pay" | "caution" | "avoid";
22
+ washTradeRisk: "low" | "medium" | "high";
23
+ verifiedRatio: number | null;
24
+ signals: string[];
25
+ penalties: {
26
+ reason: string;
27
+ points: number;
28
+ }[];
29
+ liveProbe: Awaited<ReturnType<typeof probeEndpoint>> | null;
30
+ }>;
31
+ /**
32
+ * Know-Your-Merchant (KYM) pre-payment trust oracle.
33
+ * Scores an x402 merchant host from authenticity signals before an agent pays:
34
+ * wash-trading rate, verification ratio, volume realism, latency, and an
35
+ * optional live x402 probe. No equivalent exists across the public ecosystem
36
+ * (x402gle surfaces raw wash %, but does not synthesize a pay/avoid decision).
37
+ */
38
+ export declare function runMerchantTrust(input: MerchantTrustInput): Promise<MerchantTrustResult>;
@@ -0,0 +1,171 @@
1
+ import { hostOf, probeEndpoint } from "../lib/probe.js";
2
+ import { assessUrlSecurity } from "../lib/security.js";
3
+ import { agentTrustMeta, withAgentTrust } from "../lib/agent-response.js";
4
+ import { fetchHostTelemetry } from "../lib/ecosystem-telemetry.js";
5
+ function gradeFor(score) {
6
+ if (score >= 85)
7
+ return "A";
8
+ if (score >= 70)
9
+ return "B";
10
+ if (score >= 55)
11
+ return "C";
12
+ if (score >= 40)
13
+ return "D";
14
+ return "F";
15
+ }
16
+ /**
17
+ * Know-Your-Merchant (KYM) pre-payment trust oracle.
18
+ * Scores an x402 merchant host from authenticity signals before an agent pays:
19
+ * wash-trading rate, verification ratio, volume realism, latency, and an
20
+ * optional live x402 probe. No equivalent exists across the public ecosystem
21
+ * (x402gle surfaces raw wash %, but does not synthesize a pay/avoid decision).
22
+ */
23
+ export async function runMerchantTrust(input) {
24
+ let enriched = { ...input };
25
+ const hostPre = (input.host || hostOf(input.targetUrl ?? "") || "").toLowerCase();
26
+ if (input.autoIngest !== false && hostPre) {
27
+ const telemetry = await fetchHostTelemetry(hostPre, input.targetUrl);
28
+ if (telemetry?.washTradePct != null || telemetry?.observedTxns != null) {
29
+ enriched = {
30
+ ...enriched,
31
+ washTradePct: enriched.washTradePct ?? telemetry.washTradePct,
32
+ observedTxns: enriched.observedTxns ?? telemetry.observedTxns,
33
+ observedVolumeUsdc: enriched.observedVolumeUsdc ?? telemetry.observedVolumeUsdc,
34
+ verifiedResources: enriched.verifiedResources ?? telemetry.verifiedResources,
35
+ totalResources: enriched.totalResources ?? telemetry.totalResources,
36
+ };
37
+ }
38
+ }
39
+ const host = (enriched.host || hostOf(enriched.targetUrl ?? "") || "").toLowerCase();
40
+ const signals = [];
41
+ const penalties = [];
42
+ let score = 80;
43
+ if (!host) {
44
+ return withAgentTrust({
45
+ host: "",
46
+ trustScore: 0,
47
+ grade: "F",
48
+ recommendation: "avoid",
49
+ washTradeRisk: "high",
50
+ verifiedRatio: null,
51
+ signals: ["No host or targetUrl supplied"],
52
+ penalties: [{ reason: "missing_host", points: 80 }],
53
+ liveProbe: null,
54
+ }, agentTrustMeta(["input_validation"], { confidence: 0.4, sources: ["merchant-trust-oracle"] }));
55
+ }
56
+ // Wash-trading penalty (x402gle reports ~17% baseline; treat >25% as serious).
57
+ const wash = typeof enriched.washTradePct === "number" ? enriched.washTradePct : null;
58
+ let washTradeRisk = "low";
59
+ if (wash != null) {
60
+ if (wash >= 40) {
61
+ penalties.push({ reason: `Wash-trade rate ${wash}% is high`, points: 35 });
62
+ score -= 35;
63
+ washTradeRisk = "high";
64
+ }
65
+ else if (wash >= 20) {
66
+ penalties.push({ reason: `Wash-trade rate ${wash}% above ecosystem norm`, points: 15 });
67
+ score -= 15;
68
+ washTradeRisk = "medium";
69
+ }
70
+ else {
71
+ signals.push(`Wash-trade rate ${wash}% within healthy band`);
72
+ }
73
+ }
74
+ else {
75
+ signals.push("No wash-trade telemetry supplied — using neutral prior");
76
+ }
77
+ // Verification ratio (verified resources / total resources).
78
+ let verifiedRatio = null;
79
+ if (typeof enriched.verifiedResources === "number" &&
80
+ typeof enriched.totalResources === "number" &&
81
+ enriched.totalResources > 0) {
82
+ verifiedRatio = enriched.verifiedResources / enriched.totalResources;
83
+ if (verifiedRatio >= 0.5) {
84
+ score += 8;
85
+ signals.push(`${Math.round(verifiedRatio * 100)}% of resources verified`);
86
+ }
87
+ else if (verifiedRatio < 0.05) {
88
+ penalties.push({ reason: `Only ${Math.round(verifiedRatio * 100)}% resources verified`, points: 18 });
89
+ score -= 18;
90
+ }
91
+ else {
92
+ penalties.push({ reason: `Low verification ratio ${Math.round(verifiedRatio * 100)}%`, points: 8 });
93
+ score -= 8;
94
+ }
95
+ }
96
+ // Volume realism: extremely high txns with near-zero volume signals spam/wash.
97
+ if (typeof enriched.observedTxns === "number" && typeof enriched.observedVolumeUsdc === "number") {
98
+ const perTx = enriched.observedTxns > 0 ? enriched.observedVolumeUsdc / enriched.observedTxns : 0;
99
+ if (enriched.observedTxns > 50_000 && perTx < 0.011) {
100
+ penalties.push({ reason: "Very high txn count with sub-cent average — spam/wash pattern", points: 20 });
101
+ score -= 20;
102
+ if (washTradeRisk === "low")
103
+ washTradeRisk = "medium";
104
+ }
105
+ else if (perTx > 0) {
106
+ signals.push(`Average settlement ~$${perTx.toFixed(4)} per txn`);
107
+ }
108
+ }
109
+ // Latency band (p50).
110
+ if (typeof enriched.p50LatencyMs === "number") {
111
+ if (enriched.p50LatencyMs > 4000) {
112
+ penalties.push({ reason: `Slow p50 latency ${enriched.p50LatencyMs}ms`, points: 10 });
113
+ score -= 10;
114
+ }
115
+ else if (enriched.p50LatencyMs <= 1500) {
116
+ score += 4;
117
+ signals.push(`Fast p50 latency ${enriched.p50LatencyMs}ms`);
118
+ }
119
+ }
120
+ // Optional live probe.
121
+ let liveProbe = null;
122
+ if (enriched.probe && enriched.targetUrl) {
123
+ try {
124
+ liveProbe = await probeEndpoint(enriched.targetUrl);
125
+ if (liveProbe.status === 0) {
126
+ penalties.push({ reason: "Live endpoint unreachable", points: 25 });
127
+ score -= 25;
128
+ }
129
+ else if (liveProbe.requiresPayment) {
130
+ signals.push("Live endpoint returns a valid 402 payment challenge");
131
+ score += 5;
132
+ }
133
+ else if (liveProbe.status === 200) {
134
+ penalties.push({ reason: "Endpoint is open (not x402-protected) — unexpected for paid host", points: 6 });
135
+ score -= 6;
136
+ }
137
+ const sec = assessUrlSecurity(enriched.targetUrl);
138
+ if (sec.grade === "F") {
139
+ penalties.push({ reason: "URL security grade F", points: 20 });
140
+ score -= 20;
141
+ }
142
+ }
143
+ catch (err) {
144
+ signals.push(`Live probe skipped: ${err instanceof Error ? err.message : String(err)}`);
145
+ }
146
+ }
147
+ score = Math.max(0, Math.min(100, Math.round(score)));
148
+ const grade = gradeFor(score);
149
+ const recommendation = score >= 70 ? "pay" : score >= 45 ? "caution" : "avoid";
150
+ return withAgentTrust({
151
+ host,
152
+ trustScore: score,
153
+ grade,
154
+ recommendation,
155
+ washTradeRisk,
156
+ verifiedRatio,
157
+ signals,
158
+ penalties,
159
+ liveProbe,
160
+ }, agentTrustMeta([
161
+ "wash_trade_check",
162
+ "verification_ratio",
163
+ "volume_realism",
164
+ enriched.probe ? "live_probe" : "telemetry_only",
165
+ input.autoIngest !== false ? "x402watch_ingest" : "manual_telemetry",
166
+ ], {
167
+ confidence: enriched.probe ? 0.85 : 0.7,
168
+ sources: ["merchant-trust-oracle", "x402gle-signals"],
169
+ accuracy_note: "KYM trust is a pre-payment heuristic from supplied telemetry and optional live probe; not a guarantee of settlement quality.",
170
+ }));
171
+ }
@@ -0,0 +1,27 @@
1
+ export type MppBrokerInput = {
2
+ action?: "estimate" | "plan";
3
+ expectedCalls?: number;
4
+ avgPricePerCallUsdc?: number;
5
+ network?: string;
6
+ objective?: string;
7
+ topic?: string;
8
+ sessionContext?: string;
9
+ teamName?: string;
10
+ durationMinutes?: number;
11
+ constraints?: string[];
12
+ deliverables?: string[];
13
+ };
14
+ export type MppBrokerResult = {
15
+ status: "ok";
16
+ action: string;
17
+ summary: string;
18
+ expectedCalls: number;
19
+ avgPricePerCallUsdc: number;
20
+ estimatedSessionCostUSDC: number;
21
+ estimatedPerCallCostUSDC: number;
22
+ estimatedSavingsUSDC: number;
23
+ breakEvenCallCount: number;
24
+ recommendation: "mpp" | "per_call";
25
+ assumptions: string[];
26
+ };
27
+ export declare function runMppSessionBroker(input: MppBrokerInput): MppBrokerResult;
@@ -0,0 +1,29 @@
1
+ export function runMppSessionBroker(input) {
2
+ const expectedCalls = input.expectedCalls ?? 25;
3
+ const avgPricePerCallUsdc = input.avgPricePerCallUsdc ?? 0.03;
4
+ const action = input.action ?? "estimate";
5
+ const perCallTotal = expectedCalls * avgPricePerCallUsdc;
6
+ const sessionOverhead = 0.01;
7
+ const mppTotal = sessionOverhead + expectedCalls * 0.001;
8
+ const savings = Math.max(0, perCallTotal - mppTotal);
9
+ const breakEvenCallCount = Math.ceil(sessionOverhead / Math.max(avgPricePerCallUsdc - 0.001, 0.0001));
10
+ const useMpp = expectedCalls >= 10 && savings > 0.05;
11
+ return {
12
+ status: "ok",
13
+ action,
14
+ summary: "Estimated MPP session cost versus per-call settlement cost.",
15
+ expectedCalls,
16
+ avgPricePerCallUsdc: Number(avgPricePerCallUsdc.toFixed(4)),
17
+ estimatedSessionCostUSDC: Number(mppTotal.toFixed(4)),
18
+ estimatedPerCallCostUSDC: Number(perCallTotal.toFixed(4)),
19
+ estimatedSavingsUSDC: Number(savings.toFixed(4)),
20
+ breakEvenCallCount,
21
+ recommendation: useMpp ? "mpp" : "per_call",
22
+ assumptions: [
23
+ "MPP session overhead is fixed at 0.01 USDC",
24
+ "Per-call MPP marginal cost is 0.001 USDC",
25
+ "Per-call settlement uses provided avgPricePerCallUsdc",
26
+ `Action mode: ${action}`,
27
+ ],
28
+ };
29
+ }
@@ -0,0 +1,76 @@
1
+ import { type ChainKey } from "../lib/chains.js";
2
+ import { type WithAgentTrust } from "../lib/agent-response.js";
3
+ export type MppSessionType = "stripe_mpp" | "dexter_mpp" | "visa_cli" | "x402_native";
4
+ export type MppBillingModel = "per_call" | "per_token" | "per_second" | "flat_rate";
5
+ export type MppV2Input = {
6
+ action: "open" | "voucher" | "close" | "status";
7
+ sessionId?: string;
8
+ sessionType?: MppSessionType;
9
+ stripeCustomerId?: string;
10
+ lightsparkNode?: string;
11
+ billingModel?: MppBillingModel;
12
+ meterUnit?: string;
13
+ expectedCalls?: number;
14
+ avgPricePerCallUsdc?: number;
15
+ chain?: ChainKey;
16
+ maxBudgetUsdc?: number;
17
+ agentId?: string;
18
+ };
19
+ export type MppSession = {
20
+ sessionId: string;
21
+ chain: ChainKey;
22
+ agentId: string;
23
+ sessionType: MppSessionType;
24
+ billingModel: MppBillingModel;
25
+ meterUnit?: string;
26
+ stripeCustomerId?: string;
27
+ lightsparkNode?: string;
28
+ maxBudgetUsdc: number;
29
+ expectedCalls: number;
30
+ callsUsed: number;
31
+ avgPricePerCallUsdc: number;
32
+ openedAt: string;
33
+ closedAt?: string;
34
+ status: "open" | "closed";
35
+ facilitatorUrl: string;
36
+ estimatedSavingsUsdc: number;
37
+ };
38
+ export type MppSessionError = {
39
+ code: "SESSION_NOT_FOUND" | "SESSION_ALREADY_CLOSED";
40
+ message: string;
41
+ lookupKey: {
42
+ agentId?: string;
43
+ chain?: ChainKey;
44
+ sessionId?: string;
45
+ };
46
+ };
47
+ export type MppSettlement = {
48
+ status: "closed" | "already_closed";
49
+ sessionId: string;
50
+ network: string;
51
+ chain: ChainKey;
52
+ agentId: string;
53
+ callsSettled: number;
54
+ plannedCalls: number;
55
+ estimatedTotalUsdc: number;
56
+ facilitatorUrl: string;
57
+ };
58
+ export type MppV2Result = {
59
+ status: "ok";
60
+ ok: true;
61
+ success: boolean;
62
+ action: string;
63
+ session: MppSession | null;
64
+ recommendation: string;
65
+ facilitator: {
66
+ url: string;
67
+ mppDocs: string;
68
+ };
69
+ nextSteps: string[];
70
+ savingsNote: string;
71
+ error?: MppSessionError;
72
+ settlement?: MppSettlement;
73
+ resolvedBy?: "sessionId" | "agentId+chain" | "auto_open";
74
+ };
75
+ /** Stateful MPP session planner — open/voucher/close lifecycle with Dexter facilitator */
76
+ export declare function runMppSessionV2(input: MppV2Input): Promise<WithAgentTrust<MppV2Result>>;