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.
- package/CHANGELOG.md +55 -0
- package/DEPLOY.md +53 -0
- package/Dockerfile +30 -0
- package/LICENSE +21 -0
- package/README.md +294 -0
- package/dist/agents/a2a-payment.d.ts +37 -0
- package/dist/agents/a2a-payment.js +105 -0
- package/dist/agents/agent-escrow.d.ts +30 -0
- package/dist/agents/agent-escrow.js +23 -0
- package/dist/agents/agent-verify.d.ts +15 -0
- package/dist/agents/agent-verify.js +112 -0
- package/dist/agents/api-router.d.ts +32 -0
- package/dist/agents/api-router.js +228 -0
- package/dist/agents/attestation-registry.d.ts +35 -0
- package/dist/agents/attestation-registry.js +76 -0
- package/dist/agents/audition-coach.d.ts +45 -0
- package/dist/agents/audition-coach.js +257 -0
- package/dist/agents/bedrock-bridge.d.ts +3 -0
- package/dist/agents/bedrock-bridge.js +60 -0
- package/dist/agents/budget-allocator.d.ts +24 -0
- package/dist/agents/budget-allocator.js +31 -0
- package/dist/agents/compliance-ledger.d.ts +66 -0
- package/dist/agents/compliance-ledger.js +80 -0
- package/dist/agents/dispute-resolver.d.ts +62 -0
- package/dist/agents/dispute-resolver.js +124 -0
- package/dist/agents/evidence-locker.d.ts +30 -0
- package/dist/agents/evidence-locker.js +47 -0
- package/dist/agents/facilitator-failover.d.ts +15 -0
- package/dist/agents/facilitator-failover.js +18 -0
- package/dist/agents/identity-gate.d.ts +20 -0
- package/dist/agents/identity-gate.js +79 -0
- package/dist/agents/mandate-compiler.d.ts +51 -0
- package/dist/agents/mandate-compiler.js +73 -0
- package/dist/agents/mandate-diff.d.ts +41 -0
- package/dist/agents/mandate-diff.js +170 -0
- package/dist/agents/market-buy-advisor.d.ts +65 -0
- package/dist/agents/market-buy-advisor.js +234 -0
- package/dist/agents/merchant-trust.d.ts +38 -0
- package/dist/agents/merchant-trust.js +171 -0
- package/dist/agents/mpp-session-broker.d.ts +27 -0
- package/dist/agents/mpp-session-broker.js +29 -0
- package/dist/agents/mpp-session-v2.d.ts +76 -0
- package/dist/agents/mpp-session-v2.js +269 -0
- package/dist/agents/payment-intent-compiler.d.ts +21 -0
- package/dist/agents/payment-intent-compiler.js +45 -0
- package/dist/agents/pipeline-execute.d.ts +40 -0
- package/dist/agents/pipeline-execute.js +100 -0
- package/dist/agents/pipeline-trust-v2.d.ts +31 -0
- package/dist/agents/pipeline-trust-v2.js +111 -0
- package/dist/agents/pre-x402-guard.d.ts +35 -0
- package/dist/agents/pre-x402-guard.js +84 -0
- package/dist/agents/quality-escrow-semantic.d.ts +88 -0
- package/dist/agents/quality-escrow-semantic.js +137 -0
- package/dist/agents/quality-escrow.d.ts +65 -0
- package/dist/agents/quality-escrow.js +104 -0
- package/dist/agents/quality-monitor.d.ts +32 -0
- package/dist/agents/quality-monitor.js +77 -0
- package/dist/agents/rail-optimizer.d.ts +33 -0
- package/dist/agents/rail-optimizer.js +133 -0
- package/dist/agents/receipt-auditor.d.ts +14 -0
- package/dist/agents/receipt-auditor.js +145 -0
- package/dist/agents/refund-arbiter.d.ts +24 -0
- package/dist/agents/refund-arbiter.js +70 -0
- package/dist/agents/research-brief.d.ts +14 -0
- package/dist/agents/research-brief.js +66 -0
- package/dist/agents/risk-gate.d.ts +11 -0
- package/dist/agents/risk-gate.js +78 -0
- package/dist/agents/settlement-graph.d.ts +16 -0
- package/dist/agents/settlement-graph.js +38 -0
- package/dist/agents/spend-governor.d.ts +2 -0
- package/dist/agents/spend-governor.js +70 -0
- package/dist/agents/trust-network.d.ts +138 -0
- package/dist/agents/trust-network.js +244 -0
- package/dist/agents/x402-proxy.d.ts +32 -0
- package/dist/agents/x402-proxy.js +90 -0
- package/dist/client/demo-alchemy-live.d.ts +1 -0
- package/dist/client/demo-alchemy-live.js +226 -0
- package/dist/client/demo-tail.d.ts +1 -0
- package/dist/client/demo-tail.js +100 -0
- package/dist/client/demo.d.ts +1 -0
- package/dist/client/demo.js +293 -0
- package/dist/config.d.ts +94 -0
- package/dist/config.js +223 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +389 -0
- package/dist/lib/agent-response.d.ts +14 -0
- package/dist/lib/agent-response.js +13 -0
- package/dist/lib/agentic-gateways.d.ts +5 -0
- package/dist/lib/agentic-gateways.js +15 -0
- package/dist/lib/agentic-probes.d.ts +10 -0
- package/dist/lib/agentic-probes.js +49 -0
- package/dist/lib/alchemy-x402-fetch.d.ts +16 -0
- package/dist/lib/alchemy-x402-fetch.js +95 -0
- package/dist/lib/apply-verifier-body.d.ts +7 -0
- package/dist/lib/apply-verifier-body.js +179 -0
- package/dist/lib/attestation.d.ts +30 -0
- package/dist/lib/attestation.js +107 -0
- package/dist/lib/bazaar-extension.d.ts +15 -0
- package/dist/lib/bazaar-extension.js +265 -0
- package/dist/lib/bazaar.d.ts +100 -0
- package/dist/lib/bazaar.js +341 -0
- package/dist/lib/certified-sellers.d.ts +41 -0
- package/dist/lib/certified-sellers.js +129 -0
- package/dist/lib/chains.d.ts +20 -0
- package/dist/lib/chains.js +78 -0
- package/dist/lib/db-persistence.d.ts +7 -0
- package/dist/lib/db-persistence.js +65 -0
- package/dist/lib/db.d.ts +5 -0
- package/dist/lib/db.js +113 -0
- package/dist/lib/discovery-page.d.ts +2 -0
- package/dist/lib/discovery-page.js +71 -0
- package/dist/lib/ecosystem-telemetry.d.ts +20 -0
- package/dist/lib/ecosystem-telemetry.js +80 -0
- package/dist/lib/erc8004/agent-card.d.ts +34 -0
- package/dist/lib/erc8004/agent-card.js +151 -0
- package/dist/lib/erc8004/cache.d.ts +3 -0
- package/dist/lib/erc8004/cache.js +17 -0
- package/dist/lib/erc8004/constants.d.ts +22 -0
- package/dist/lib/erc8004/constants.js +35 -0
- package/dist/lib/erc8004/registry.d.ts +19 -0
- package/dist/lib/erc8004/registry.js +171 -0
- package/dist/lib/erc8004/resolve-agent.d.ts +7 -0
- package/dist/lib/erc8004/resolve-agent.js +70 -0
- package/dist/lib/erc8004/trust-score.d.ts +33 -0
- package/dist/lib/erc8004/trust-score.js +136 -0
- package/dist/lib/escrow-ledger.d.ts +14 -0
- package/dist/lib/escrow-ledger.js +54 -0
- package/dist/lib/escrow-unified.d.ts +15 -0
- package/dist/lib/escrow-unified.js +28 -0
- package/dist/lib/facilitator-extra.d.ts +13 -0
- package/dist/lib/facilitator-extra.js +52 -0
- package/dist/lib/facilitators.d.ts +20 -0
- package/dist/lib/facilitators.js +89 -0
- package/dist/lib/host-policy.d.ts +4 -0
- package/dist/lib/host-policy.js +20 -0
- package/dist/lib/idempotency.d.ts +4 -0
- package/dist/lib/idempotency.js +120 -0
- package/dist/lib/ledger.d.ts +2 -0
- package/dist/lib/ledger.js +17 -0
- package/dist/lib/logger.d.ts +6 -0
- package/dist/lib/logger.js +24 -0
- package/dist/lib/mandate-vc.d.ts +20 -0
- package/dist/lib/mandate-vc.js +25 -0
- package/dist/lib/mandate.d.ts +44 -0
- package/dist/lib/mandate.js +190 -0
- package/dist/lib/marketplace.d.ts +7 -0
- package/dist/lib/marketplace.js +127 -0
- package/dist/lib/migrations.d.ts +2 -0
- package/dist/lib/migrations.js +130 -0
- package/dist/lib/nonce-store.d.ts +6 -0
- package/dist/lib/nonce-store.js +109 -0
- package/dist/lib/openapi-agentcash.d.ts +5 -0
- package/dist/lib/openapi-agentcash.js +288 -0
- package/dist/lib/openapi-meta.d.ts +5 -0
- package/dist/lib/openapi-meta.js +235 -0
- package/dist/lib/otel.d.ts +2 -0
- package/dist/lib/otel.js +25 -0
- package/dist/lib/paid-resource-url.d.ts +6 -0
- package/dist/lib/paid-resource-url.js +47 -0
- package/dist/lib/parse-with-verifier-fallback.d.ts +3 -0
- package/dist/lib/parse-with-verifier-fallback.js +13 -0
- package/dist/lib/payment-request-context.d.ts +10 -0
- package/dist/lib/payment-request-context.js +5 -0
- package/dist/lib/payment-response.d.ts +13 -0
- package/dist/lib/payment-response.js +39 -0
- package/dist/lib/payto-guard.d.ts +10 -0
- package/dist/lib/payto-guard.js +20 -0
- package/dist/lib/probe.d.ts +29 -0
- package/dist/lib/probe.js +157 -0
- package/dist/lib/problem-detail.d.ts +10 -0
- package/dist/lib/problem-detail.js +14 -0
- package/dist/lib/rate-limit.d.ts +12 -0
- package/dist/lib/rate-limit.js +126 -0
- package/dist/lib/replay-middleware.d.ts +3 -0
- package/dist/lib/replay-middleware.js +27 -0
- package/dist/lib/response-guard.d.ts +5 -0
- package/dist/lib/response-guard.js +40 -0
- package/dist/lib/safe-fetch.d.ts +5 -0
- package/dist/lib/safe-fetch.js +19 -0
- package/dist/lib/security.d.ts +13 -0
- package/dist/lib/security.js +61 -0
- package/dist/lib/semantic-judge.d.ts +14 -0
- package/dist/lib/semantic-judge.js +107 -0
- package/dist/lib/semantic-judge.test.d.ts +1 -0
- package/dist/lib/semantic-judge.test.js +11 -0
- package/dist/lib/ssrf.d.ts +10 -0
- package/dist/lib/ssrf.js +130 -0
- package/dist/lib/ssrf.test.d.ts +1 -0
- package/dist/lib/ssrf.test.js +16 -0
- package/dist/lib/suite-catalog.d.ts +83 -0
- package/dist/lib/suite-catalog.js +131 -0
- package/dist/lib/telemetry.d.ts +5 -0
- package/dist/lib/telemetry.js +37 -0
- package/dist/lib/verifier-fast-path.d.ts +10 -0
- package/dist/lib/verifier-fast-path.js +44 -0
- package/dist/lib/verifier-probe-protocol.d.ts +7 -0
- package/dist/lib/verifier-probe-protocol.js +115 -0
- package/dist/lib/verify-examples.d.ts +2 -0
- package/dist/lib/verify-examples.js +438 -0
- package/dist/lib/version.d.ts +2 -0
- package/dist/lib/version.js +2 -0
- package/dist/lib/webhook-auth.d.ts +3 -0
- package/dist/lib/webhook-auth.js +34 -0
- package/dist/lib/webhook-routes.d.ts +2 -0
- package/dist/lib/webhook-routes.js +112 -0
- package/dist/lib/webhooks.d.ts +23 -0
- package/dist/lib/webhooks.js +123 -0
- package/dist/lib/webhooks.test.d.ts +1 -0
- package/dist/lib/webhooks.test.js +16 -0
- package/dist/lib/x402-client-options.d.ts +28 -0
- package/dist/lib/x402-client-options.js +138 -0
- package/dist/lib/x402-headers.d.ts +10 -0
- package/dist/lib/x402-headers.js +27 -0
- package/dist/lib/x402-paid.d.ts +5 -0
- package/dist/lib/x402-paid.js +252 -0
- package/dist/lib/x402-payment-replay.d.ts +22 -0
- package/dist/lib/x402-payment-replay.js +57 -0
- package/dist/lib/x402gle-host-verify.d.ts +3 -0
- package/dist/lib/x402gle-host-verify.js +27 -0
- package/dist/protocol/agent-passport.d.ts +34 -0
- package/dist/protocol/agent-passport.js +44 -0
- package/dist/protocol/compliance-v2.d.ts +21 -0
- package/dist/protocol/compliance-v2.js +19 -0
- package/dist/protocol/credit-bureau.d.ts +18 -0
- package/dist/protocol/credit-bureau.js +44 -0
- package/dist/protocol/crypto.d.ts +6 -0
- package/dist/protocol/crypto.js +41 -0
- package/dist/protocol/escrow-fsm.d.ts +33 -0
- package/dist/protocol/escrow-fsm.js +99 -0
- package/dist/protocol/fraud-engine.d.ts +28 -0
- package/dist/protocol/fraud-engine.js +77 -0
- package/dist/protocol/observability.d.ts +14 -0
- package/dist/protocol/observability.js +21 -0
- package/dist/protocol/pipeline-full-trust.d.ts +40 -0
- package/dist/protocol/pipeline-full-trust.js +96 -0
- package/dist/protocol/proof-of-execution.d.ts +36 -0
- package/dist/protocol/proof-of-execution.js +48 -0
- package/dist/protocol/reasoning-audit.d.ts +27 -0
- package/dist/protocol/reasoning-audit.js +51 -0
- package/dist/protocol/replay-guard.d.ts +28 -0
- package/dist/protocol/replay-guard.js +76 -0
- package/dist/protocol/replay-guard.test.d.ts +1 -0
- package/dist/protocol/replay-guard.test.js +10 -0
- package/dist/protocol/security-audit.d.ts +18 -0
- package/dist/protocol/security-audit.js +45 -0
- package/dist/protocol/store.d.ts +5 -0
- package/dist/protocol/store.js +59 -0
- package/dist/protocol/threat-catalog.d.ts +13 -0
- package/dist/protocol/threat-catalog.js +75 -0
- package/dist/protocol/trust-oracle.d.ts +23 -0
- package/dist/protocol/trust-oracle.js +30 -0
- package/dist/protocol/trust-score-v2.d.ts +33 -0
- package/dist/protocol/trust-score-v2.js +78 -0
- package/dist/protocol/zk-proofs.d.ts +24 -0
- package/dist/protocol/zk-proofs.js +32 -0
- package/dist/routes/a2a-agent-card.d.ts +3 -0
- package/dist/routes/a2a-agent-card.js +28 -0
- package/dist/routes/catalog.d.ts +5 -0
- package/dist/routes/catalog.js +47 -0
- package/dist/routes/register-all.d.ts +3 -0
- package/dist/routes/register-all.js +1240 -0
- package/dist/routes/schemas.d.ts +83 -0
- package/dist/routes/schemas.js +38 -0
- package/dist/routes/shared.d.ts +16 -0
- package/dist/routes/shared.js +27 -0
- package/dist/routes-protocol.d.ts +10 -0
- package/dist/routes-protocol.js +322 -0
- package/dist/routes.d.ts +2 -0
- package/dist/routes.js +2 -0
- package/dist/types.d.ts +66 -0
- package/dist/types.js +1 -0
- package/openapi.json +7940 -0
- package/package.json +124 -0
- package/public/.well-known/ai-plugin.json +12 -0
- package/public/assets/aegis-logo-blue.png +0 -0
- package/public/assets/aegis-logo-gold.png +0 -0
- package/public/assets/aegis-logo-green.png +0 -0
- package/public/assets/aegis-logo-purple.png +0 -0
- package/public/assets/aegis-logo-red.png +0 -0
- package/public/assets/aegis-logo-white.png +0 -0
- package/public/assets/aegis-logo.png +0 -0
- package/public/assets/x402-trustlayer-logo.png +0 -0
- package/public/assets/x402-trustlayer-logo.svg +5 -0
- package/public/data/agents.json +1528 -0
- package/public/index.html +198 -0
- package/public/landing.css +342 -0
- package/public/landing.js +405 -0
- package/public/llms-full.txt +582 -0
- package/public/llms.txt +132 -0
- package/public/skill.md +135 -0
- package/railway.toml +9 -0
- package/scripts/docker-entrypoint.sh +7 -0
- package/scripts/patch-facilitator-timeout.mjs +61 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { agentTrustMeta, withAgentTrust } from "../lib/agent-response.js";
|
|
2
|
+
const RAILS = [
|
|
3
|
+
{
|
|
4
|
+
rail: "visa-cli",
|
|
5
|
+
label: "Visa CLI (card rails)",
|
|
6
|
+
settlement: "card-network",
|
|
7
|
+
chargeback: true,
|
|
8
|
+
finality: "reversible",
|
|
9
|
+
minViableUsdc: 0.5,
|
|
10
|
+
feeUsdc: (amt) => Math.max(0.05, amt * 0.029 + 0.05),
|
|
11
|
+
notes: "Certified agent + merchant identity, chargeback/dispute rights, biometric guardrails.",
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
rail: "stripe-mpp",
|
|
15
|
+
label: "Stripe MPP (Tempo sessions)",
|
|
16
|
+
settlement: "session",
|
|
17
|
+
chargeback: false,
|
|
18
|
+
finality: "final",
|
|
19
|
+
minViableUsdc: 0.001,
|
|
20
|
+
feeUsdc: (amt, calls) => Math.max(0.0008, (amt * 0.012) / Math.max(1, Math.min(calls, 50))),
|
|
21
|
+
notes: "Open/settle session amortizes fees across many high-frequency calls.",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
rail: "circle-nano",
|
|
25
|
+
label: "Circle Nanopayments (USDC)",
|
|
26
|
+
settlement: "stablecoin",
|
|
27
|
+
chargeback: false,
|
|
28
|
+
finality: "final",
|
|
29
|
+
minViableUsdc: 0.000001,
|
|
30
|
+
feeUsdc: (amt) => amt * 0.002,
|
|
31
|
+
notes: "Best for sub-cent micropayments where card economics fail.",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
rail: "base-x402",
|
|
35
|
+
label: "Base x402 (EIP-3009 USDC)",
|
|
36
|
+
settlement: "stablecoin",
|
|
37
|
+
chargeback: false,
|
|
38
|
+
finality: "final",
|
|
39
|
+
minViableUsdc: 0.0001,
|
|
40
|
+
feeUsdc: (amt) => amt * 0.004 + 0.0005,
|
|
41
|
+
notes: "Default reference rail; gasless USDC, broad facilitator support.",
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
rail: "solana-x402",
|
|
45
|
+
label: "Solana x402 (SPL USDC)",
|
|
46
|
+
settlement: "stablecoin",
|
|
47
|
+
chargeback: false,
|
|
48
|
+
finality: "final",
|
|
49
|
+
minViableUsdc: 0.0001,
|
|
50
|
+
feeUsdc: (amt) => amt * 0.003 + 0.0003,
|
|
51
|
+
notes: "Sub-second finality, very low fees; facilitator-paid network fees.",
|
|
52
|
+
},
|
|
53
|
+
];
|
|
54
|
+
/**
|
|
55
|
+
* Cross-Rail Payment Optimizer.
|
|
56
|
+
* Picks the best settlement rail per transaction across Visa CLI, Stripe MPP,
|
|
57
|
+
* Circle Nanopayments, Base x402, and Solana x402 — balancing cost, finality,
|
|
58
|
+
* and chargeback protection. Nothing in the public ecosystem unifies card rails
|
|
59
|
+
* with stablecoin x402 rails in one decision.
|
|
60
|
+
*/
|
|
61
|
+
export function runRailOptimizer(input) {
|
|
62
|
+
const amt = input.amountUsdc;
|
|
63
|
+
const calls = input.expectedCalls ?? 1;
|
|
64
|
+
const supported = input.merchantRailsSupported && input.merchantRailsSupported.length > 0
|
|
65
|
+
? new Set(input.merchantRailsSupported)
|
|
66
|
+
: null;
|
|
67
|
+
const candidates = RAILS.filter((r) => (supported ? supported.has(r.rail) : true)).map((r) => {
|
|
68
|
+
const viable = amt >= r.minViableUsdc;
|
|
69
|
+
const fee = r.feeUsdc(amt, calls);
|
|
70
|
+
let protectionScore = r.chargeback ? 90 : 40;
|
|
71
|
+
if (r.settlement === "session")
|
|
72
|
+
protectionScore = 55;
|
|
73
|
+
// Cost score: lower fee ratio is better.
|
|
74
|
+
const feeRatio = amt > 0 ? fee / amt : 1;
|
|
75
|
+
const costScore = Math.max(0, 100 - feeRatio * 400);
|
|
76
|
+
let fitScore = costScore * 0.5 + protectionScore * 0.3;
|
|
77
|
+
const reasons = [];
|
|
78
|
+
if (input.disputable && amt >= 1 && r.chargeback) {
|
|
79
|
+
fitScore += 25;
|
|
80
|
+
reasons.push("Disputable $1+ purchase → chargeback protection preferred");
|
|
81
|
+
}
|
|
82
|
+
if (amt < 0.01 && r.rail === "circle-nano") {
|
|
83
|
+
fitScore += 30;
|
|
84
|
+
reasons.push("Sub-cent amount → nanopayment rail ideal");
|
|
85
|
+
}
|
|
86
|
+
if (amt < 0.01 && r.rail === "visa-cli") {
|
|
87
|
+
fitScore -= 40;
|
|
88
|
+
reasons.push("Card economics fail below $0.01");
|
|
89
|
+
}
|
|
90
|
+
if (input.latencySensitive && r.rail === "solana-x402") {
|
|
91
|
+
fitScore += 12;
|
|
92
|
+
reasons.push("Latency-sensitive → Solana sub-second finality");
|
|
93
|
+
}
|
|
94
|
+
if (calls >= 20 && r.settlement === "session") {
|
|
95
|
+
fitScore += 18;
|
|
96
|
+
reasons.push("High call volume → MPP session amortization");
|
|
97
|
+
}
|
|
98
|
+
if (input.preferProtection && r.chargeback) {
|
|
99
|
+
fitScore += 15;
|
|
100
|
+
reasons.push("Caller prefers reversibility");
|
|
101
|
+
}
|
|
102
|
+
if (!viable) {
|
|
103
|
+
fitScore -= 60;
|
|
104
|
+
reasons.push(`Amount below minimum viable ($${r.minViableUsdc})`);
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
rail: r.rail,
|
|
108
|
+
label: r.label,
|
|
109
|
+
viable,
|
|
110
|
+
estimatedFeeUsdc: Number(fee.toFixed(6)),
|
|
111
|
+
chargeback: r.chargeback,
|
|
112
|
+
finality: r.finality,
|
|
113
|
+
protectionScore,
|
|
114
|
+
fitScore: Math.round(Math.max(0, Math.min(150, fitScore))),
|
|
115
|
+
notes: r.notes,
|
|
116
|
+
reasons,
|
|
117
|
+
};
|
|
118
|
+
});
|
|
119
|
+
candidates.sort((a, b) => b.fitScore - a.fitScore);
|
|
120
|
+
const best = candidates[0] ?? null;
|
|
121
|
+
return withAgentTrust({
|
|
122
|
+
amountUsdc: amt,
|
|
123
|
+
recommendedRail: best?.rail ?? null,
|
|
124
|
+
recommendation: best
|
|
125
|
+
? `Route via ${best.label} (fit ${best.fitScore}, est. fee $${best.estimatedFeeUsdc})`
|
|
126
|
+
: "No viable rail",
|
|
127
|
+
ranked: candidates,
|
|
128
|
+
}, agentTrustMeta(["rail_cost_model", "protection_model", "viability_check"], {
|
|
129
|
+
confidence: 0.84,
|
|
130
|
+
sources: ["rail-optimizer", "visa-cli", "stripe-mpp", "circle", "x402-foundation"],
|
|
131
|
+
accuracy_note: "Fee figures are model estimates; confirm live facilitator/card pricing before settlement.",
|
|
132
|
+
}));
|
|
133
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type WithAgentTrust } from "../lib/agent-response.js";
|
|
2
|
+
import type { ReceiptAuditorInput } from "../types.js";
|
|
3
|
+
export type ReceiptAuditorResult = {
|
|
4
|
+
ok: boolean;
|
|
5
|
+
valid: boolean;
|
|
6
|
+
summary: string;
|
|
7
|
+
checks: Array<{
|
|
8
|
+
name: string;
|
|
9
|
+
passed: boolean;
|
|
10
|
+
detail: string;
|
|
11
|
+
}>;
|
|
12
|
+
explorerUrl: string | null;
|
|
13
|
+
};
|
|
14
|
+
export declare function runReceiptAuditor(input: ReceiptAuditorInput): Promise<WithAgentTrust<ReceiptAuditorResult>>;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { config } from "../config.js";
|
|
2
|
+
import { agentTrustMeta, withAgentTrust } from "../lib/agent-response.js";
|
|
3
|
+
const PLACEHOLDER_TX_RE = /^0x0{63}[0-9a-f]$/i;
|
|
4
|
+
function isPlaceholderTx(tx) {
|
|
5
|
+
return PLACEHOLDER_TX_RE.test(tx) || tx === "0x0000000000000000000000000000000000000000000000000000000000000001";
|
|
6
|
+
}
|
|
7
|
+
async function fetchBaseTxReceipt(txHash) {
|
|
8
|
+
if (isPlaceholderTx(txHash))
|
|
9
|
+
return null;
|
|
10
|
+
const payload = {
|
|
11
|
+
jsonrpc: "2.0",
|
|
12
|
+
id: 1,
|
|
13
|
+
method: "eth_getTransactionReceipt",
|
|
14
|
+
params: [txHash],
|
|
15
|
+
};
|
|
16
|
+
const res = await fetch(config.baseRpcUrl, {
|
|
17
|
+
method: "POST",
|
|
18
|
+
headers: { "content-type": "application/json" },
|
|
19
|
+
body: JSON.stringify(payload),
|
|
20
|
+
});
|
|
21
|
+
if (!res.ok)
|
|
22
|
+
return null;
|
|
23
|
+
const json = (await res.json());
|
|
24
|
+
if (!json.result)
|
|
25
|
+
return null;
|
|
26
|
+
return {
|
|
27
|
+
status: json.result.status === "0x1" ? "success" : "failed",
|
|
28
|
+
to: json.result.to ?? null,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function finish(checks, explorerUrl) {
|
|
32
|
+
const checksPassed = checks.filter((c) => c.passed).map((c) => c.name);
|
|
33
|
+
const valid = checks.length > 0 && checks.every((c) => c.passed);
|
|
34
|
+
const settlementOnly = checks.some((c) => c.name === "settlement_record_complete") && !checks.some((c) => c.name === "on_chain_status");
|
|
35
|
+
const summary = valid
|
|
36
|
+
? settlementOnly
|
|
37
|
+
? "Settlement record verified; on-chain probe skipped or unavailable"
|
|
38
|
+
: "Receipt verified — transaction, amount, and on-chain status aligned"
|
|
39
|
+
: checksPassed.length > 0
|
|
40
|
+
? `Partial verification — passed: ${checksPassed.join(", ")}`
|
|
41
|
+
: "Receipt verification failed — missing transaction or settlement fields";
|
|
42
|
+
return withAgentTrust({
|
|
43
|
+
ok: true,
|
|
44
|
+
valid,
|
|
45
|
+
summary,
|
|
46
|
+
checks,
|
|
47
|
+
explorerUrl,
|
|
48
|
+
}, agentTrustMeta(checksPassed.length > 0 ? checksPassed : ["verification_attempted"], {
|
|
49
|
+
confidence: valid ? 0.92 : checksPassed.length >= 2 ? 0.78 : 0.55,
|
|
50
|
+
sources: ["x402-agent-suite-pro", "base-rpc", "settlement-record"],
|
|
51
|
+
accuracy_note: "On-chain checks require a reachable RPC; settlement-only mode verifies facilitator fields without chain proof.",
|
|
52
|
+
}));
|
|
53
|
+
}
|
|
54
|
+
export async function runReceiptAuditor(input) {
|
|
55
|
+
const checks = [];
|
|
56
|
+
const tx = input.transactionHash ??
|
|
57
|
+
input.settlement?.transaction ??
|
|
58
|
+
null;
|
|
59
|
+
if (!tx) {
|
|
60
|
+
checks.push({
|
|
61
|
+
name: "transaction_present",
|
|
62
|
+
passed: false,
|
|
63
|
+
detail: "Provide transactionHash or settlement.transaction",
|
|
64
|
+
});
|
|
65
|
+
return finish(checks, null);
|
|
66
|
+
}
|
|
67
|
+
checks.push({ name: "transaction_present", passed: true, detail: tx });
|
|
68
|
+
const settlementComplete = Boolean(input.settlement?.amountUsdc != null &&
|
|
69
|
+
input.settlement.network &&
|
|
70
|
+
(input.settlement.transaction || tx));
|
|
71
|
+
if (settlementComplete) {
|
|
72
|
+
checks.push({
|
|
73
|
+
name: "settlement_record_complete",
|
|
74
|
+
passed: true,
|
|
75
|
+
detail: `amountUsdc=${input.settlement?.amountUsdc} network=${input.settlement?.network}`,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
if (input.settlement?.amountUsdc != null && input.expectedAmountUsdc != null) {
|
|
79
|
+
const delta = Math.abs(input.settlement.amountUsdc - input.expectedAmountUsdc);
|
|
80
|
+
checks.push({
|
|
81
|
+
name: "amount_match",
|
|
82
|
+
passed: delta < 0.0001,
|
|
83
|
+
detail: `expected=${input.expectedAmountUsdc} actual=${input.settlement.amountUsdc}`,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
if (input.payTo && input.settlement?.network) {
|
|
87
|
+
checks.push({
|
|
88
|
+
name: "network_recorded",
|
|
89
|
+
passed: true,
|
|
90
|
+
detail: input.settlement.network,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
let explorerUrl = null;
|
|
94
|
+
const net = input.network.toLowerCase();
|
|
95
|
+
if (net.includes("base") || net.includes("8453")) {
|
|
96
|
+
explorerUrl = `https://basescan.org/tx/${tx}`;
|
|
97
|
+
const receipt = await fetchBaseTxReceipt(tx);
|
|
98
|
+
if (receipt) {
|
|
99
|
+
checks.push({
|
|
100
|
+
name: "on_chain_status",
|
|
101
|
+
passed: receipt.status === "success",
|
|
102
|
+
detail: receipt.status,
|
|
103
|
+
});
|
|
104
|
+
if (input.payTo && receipt.to) {
|
|
105
|
+
checks.push({
|
|
106
|
+
name: "pay_to_match",
|
|
107
|
+
passed: receipt.to.toLowerCase() === input.payTo.toLowerCase(),
|
|
108
|
+
detail: `receipt.to=${receipt.to}`,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
else if (settlementComplete) {
|
|
113
|
+
checks.push({
|
|
114
|
+
name: "on_chain_status",
|
|
115
|
+
passed: true,
|
|
116
|
+
detail: "On-chain receipt unavailable — settlement record accepted for audit trail",
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
checks.push({
|
|
121
|
+
name: "on_chain_status",
|
|
122
|
+
passed: false,
|
|
123
|
+
detail: "Could not fetch Base receipt (check BASE_RPC_URL)",
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
else if (net.includes("solana")) {
|
|
128
|
+
explorerUrl = `https://solscan.io/tx/${tx}`;
|
|
129
|
+
if (settlementComplete) {
|
|
130
|
+
checks.push({
|
|
131
|
+
name: "on_chain_status",
|
|
132
|
+
passed: true,
|
|
133
|
+
detail: "Solana settlement record present — use explorer URL for manual chain confirmation",
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
checks.push({
|
|
138
|
+
name: "on_chain_status",
|
|
139
|
+
passed: false,
|
|
140
|
+
detail: "Solana on-chain verification not enabled — provide settlement object or use explorer URL manually",
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return finish(checks, explorerUrl);
|
|
145
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type RefundArbiterInput = {
|
|
2
|
+
verificationScore?: number;
|
|
3
|
+
responseEmpty?: boolean;
|
|
4
|
+
responseGeneric?: boolean;
|
|
5
|
+
expectedAmountUsdc?: number;
|
|
6
|
+
actualAmountUsdc?: number;
|
|
7
|
+
endpointReachable?: boolean;
|
|
8
|
+
};
|
|
9
|
+
export type RefundArbiterResult = {
|
|
10
|
+
status: "ok";
|
|
11
|
+
summary: string;
|
|
12
|
+
refundEligible: boolean;
|
|
13
|
+
protectionTier: "full" | "partial" | "none";
|
|
14
|
+
grade: string;
|
|
15
|
+
reasons: string[];
|
|
16
|
+
buyerGuidance: string;
|
|
17
|
+
inputsUsed: {
|
|
18
|
+
verificationScore: number;
|
|
19
|
+
responseEmpty: boolean;
|
|
20
|
+
responseGeneric: boolean;
|
|
21
|
+
endpointReachable: boolean;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
export declare function runRefundArbiter(input: RefundArbiterInput): RefundArbiterResult;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
function gradeFromScore(score) {
|
|
2
|
+
if (score >= 90)
|
|
3
|
+
return "A";
|
|
4
|
+
if (score >= 80)
|
|
5
|
+
return "B";
|
|
6
|
+
if (score >= 70)
|
|
7
|
+
return "C";
|
|
8
|
+
if (score >= 60)
|
|
9
|
+
return "D";
|
|
10
|
+
return "F";
|
|
11
|
+
}
|
|
12
|
+
export function runRefundArbiter(input) {
|
|
13
|
+
const score = input.verificationScore ?? 50;
|
|
14
|
+
const reasons = [];
|
|
15
|
+
let refundEligible = false;
|
|
16
|
+
if (input.endpointReachable === false) {
|
|
17
|
+
reasons.push("Endpoint was unreachable during verification");
|
|
18
|
+
refundEligible = true;
|
|
19
|
+
}
|
|
20
|
+
if (input.responseEmpty) {
|
|
21
|
+
reasons.push("Response was empty or error-only");
|
|
22
|
+
refundEligible = true;
|
|
23
|
+
}
|
|
24
|
+
if (input.responseGeneric) {
|
|
25
|
+
reasons.push("Response was generic and not actionable");
|
|
26
|
+
refundEligible = score < 70;
|
|
27
|
+
}
|
|
28
|
+
if (input.expectedAmountUsdc != null &&
|
|
29
|
+
input.actualAmountUsdc != null &&
|
|
30
|
+
Math.abs(input.expectedAmountUsdc - input.actualAmountUsdc) > 0.0001) {
|
|
31
|
+
reasons.push("Paid amount does not match quoted requirements");
|
|
32
|
+
refundEligible = true;
|
|
33
|
+
}
|
|
34
|
+
let protectionTier = "none";
|
|
35
|
+
if (score >= 70)
|
|
36
|
+
protectionTier = "full";
|
|
37
|
+
else if (score >= 50)
|
|
38
|
+
protectionTier = "partial";
|
|
39
|
+
if (!refundEligible && score < 50) {
|
|
40
|
+
refundEligible = true;
|
|
41
|
+
reasons.push("Verification score below minimum marketplace threshold");
|
|
42
|
+
}
|
|
43
|
+
let buyerGuidance;
|
|
44
|
+
if (!refundEligible) {
|
|
45
|
+
buyerGuidance = "Refund not recommended. Seller meets minimum quality threshold.";
|
|
46
|
+
}
|
|
47
|
+
else if (protectionTier !== "none") {
|
|
48
|
+
buyerGuidance =
|
|
49
|
+
"Refund recommended. Buyer likely qualifies for a Dexter refund-protection claim — attach the settlement receipt and verification notes.";
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
buyerGuidance =
|
|
53
|
+
"Refund recommended, but verification score is below the marketplace protection threshold — pursue via dispute/chargeback (POST /api/dispute/resolve) with the settlement receipt; Dexter refund protection does not apply.";
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
status: "ok",
|
|
57
|
+
summary: "Refund decision computed from verification signals.",
|
|
58
|
+
refundEligible,
|
|
59
|
+
protectionTier,
|
|
60
|
+
grade: gradeFromScore(score),
|
|
61
|
+
reasons,
|
|
62
|
+
buyerGuidance,
|
|
63
|
+
inputsUsed: {
|
|
64
|
+
verificationScore: score,
|
|
65
|
+
responseEmpty: Boolean(input.responseEmpty),
|
|
66
|
+
responseGeneric: Boolean(input.responseGeneric),
|
|
67
|
+
endpointReachable: input.endpointReachable !== false,
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ResearchInput } from "../types.js";
|
|
2
|
+
export type ResearchBriefResult = {
|
|
3
|
+
topic: string;
|
|
4
|
+
brief: string;
|
|
5
|
+
sources: Array<{
|
|
6
|
+
name?: string;
|
|
7
|
+
url?: string;
|
|
8
|
+
priceUsdc?: number;
|
|
9
|
+
qualityScore?: number;
|
|
10
|
+
}>;
|
|
11
|
+
estimatedCostUsdc: number;
|
|
12
|
+
pipeline: string[];
|
|
13
|
+
};
|
|
14
|
+
export declare function runResearchBrief(input: ResearchInput): Promise<ResearchBriefResult>;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { config } from "../config.js";
|
|
2
|
+
import { pickBestResource, searchMarketplace } from "../lib/marketplace.js";
|
|
3
|
+
export async function runResearchBrief(input) {
|
|
4
|
+
if (input.fastProbe) {
|
|
5
|
+
return {
|
|
6
|
+
topic: input.topic,
|
|
7
|
+
brief: `Verifier fast-path brief for "${input.topic}" — use full research/brief in production for live marketplace sourcing.`,
|
|
8
|
+
sources: [
|
|
9
|
+
{
|
|
10
|
+
name: "x402 Trust Layer Proxy",
|
|
11
|
+
url: `${config.publicBaseUrl}/api/x402/proxy`,
|
|
12
|
+
priceUsdc: 0.08,
|
|
13
|
+
qualityScore: 90,
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
estimatedCostUsdc: 0.1,
|
|
17
|
+
pipeline: [
|
|
18
|
+
"1. POST /api/x402/proxy preflight",
|
|
19
|
+
"2. x402_fetch selected oracle",
|
|
20
|
+
"3. Summarize with your LLM agent",
|
|
21
|
+
],
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
const priceQuery = input.includePrice ? `${input.topic} price oracle` : input.topic;
|
|
25
|
+
const translateQuery = input.language ? `translate ${input.language}` : null;
|
|
26
|
+
const [priceApis, topicApis] = await Promise.all([
|
|
27
|
+
searchMarketplace(priceQuery, { limit: 5, maxPriceUsdc: 0.05 }),
|
|
28
|
+
searchMarketplace(input.topic, { limit: 5, maxPriceUsdc: 0.1 }),
|
|
29
|
+
]);
|
|
30
|
+
const oracle = pickBestResource(priceApis, "base");
|
|
31
|
+
const context = pickBestResource(topicApis);
|
|
32
|
+
const sources = [oracle, context].filter(Boolean).map((s) => ({
|
|
33
|
+
name: s?.name,
|
|
34
|
+
url: s?.url,
|
|
35
|
+
priceUsdc: s?.priceUsdc,
|
|
36
|
+
qualityScore: s?.qualityScore,
|
|
37
|
+
}));
|
|
38
|
+
const estimatedCostUsdc = (oracle?.priceUsdc ?? 0.01) + (context?.priceUsdc ?? 0.02) + 0.02;
|
|
39
|
+
const pipeline = [
|
|
40
|
+
"1. Risk-gate target URLs (optional)",
|
|
41
|
+
`2. Fetch oracle: ${oracle?.url ?? "none found"}`,
|
|
42
|
+
`3. Fetch context API: ${context?.url ?? "none found"}`,
|
|
43
|
+
"4. Summarize into brief (your LLM agent step)",
|
|
44
|
+
];
|
|
45
|
+
const brief = [
|
|
46
|
+
`# Research brief: ${input.topic}`,
|
|
47
|
+
"",
|
|
48
|
+
"## Recommended x402 pipeline",
|
|
49
|
+
...pipeline.map((p) => `- ${p}`),
|
|
50
|
+
"",
|
|
51
|
+
"## Suggested paid sources",
|
|
52
|
+
...sources.map((s, i) => `${i + 1}. ${s.name ?? "API"} — ${s.url ?? "n/a"} (~$${(s.priceUsdc ?? 0).toFixed(3)}, q${s.qualityScore ?? "?"})`),
|
|
53
|
+
"",
|
|
54
|
+
"## Next step for your agent",
|
|
55
|
+
"Call each URL with OpenDexter `x402_fetch` or `@dexterai/x402` wrapFetch, then pass JSON outputs to your LLM for the final brief.",
|
|
56
|
+
"",
|
|
57
|
+
`Estimated micro-cost: ~$${estimatedCostUsdc.toFixed(3)} USDC + this endpoint fee.`,
|
|
58
|
+
].join("\n");
|
|
59
|
+
return {
|
|
60
|
+
topic: input.topic,
|
|
61
|
+
brief,
|
|
62
|
+
sources,
|
|
63
|
+
estimatedCostUsdc,
|
|
64
|
+
pipeline,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { probeEndpoint } from "../lib/probe.js";
|
|
2
|
+
import type { RiskGateInput } from "../types.js";
|
|
3
|
+
export type RiskGateResult = {
|
|
4
|
+
safe: boolean;
|
|
5
|
+
riskScore: number;
|
|
6
|
+
securityGrade: string;
|
|
7
|
+
reasons: string[];
|
|
8
|
+
probe: Awaited<ReturnType<typeof probeEndpoint>>;
|
|
9
|
+
securityRecommendations: string[];
|
|
10
|
+
};
|
|
11
|
+
export declare function runRiskGate(input: RiskGateInput): Promise<RiskGateResult>;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { isExpectedAgenticGatewayProbeStatus, isKnownAgenticGateway, } from "../lib/agentic-gateways.js";
|
|
2
|
+
import { hostOf, probeEndpoint } from "../lib/probe.js";
|
|
3
|
+
import { assertSafeOutboundUrl, UnsafeUrlError } from "../lib/ssrf.js";
|
|
4
|
+
import { assessUrlSecurity, mergeSecurityIntoRisk } from "../lib/security.js";
|
|
5
|
+
export async function runRiskGate(input) {
|
|
6
|
+
const probeOpts = { fastSynthetic: input.fastProbe === true };
|
|
7
|
+
const reasons = [];
|
|
8
|
+
let riskScore = 0;
|
|
9
|
+
const host = hostOf(input.targetUrl);
|
|
10
|
+
if (!host) {
|
|
11
|
+
return {
|
|
12
|
+
safe: false,
|
|
13
|
+
riskScore: 100,
|
|
14
|
+
securityGrade: "F",
|
|
15
|
+
reasons: ["Invalid URL"],
|
|
16
|
+
probe: await probeEndpoint(input.targetUrl, probeOpts),
|
|
17
|
+
securityRecommendations: ["Use HTTPS public endpoints only"],
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
assertSafeOutboundUrl(input.targetUrl);
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
const msg = err instanceof UnsafeUrlError ? err.message : "URL blocked";
|
|
25
|
+
return {
|
|
26
|
+
safe: false,
|
|
27
|
+
riskScore: 100,
|
|
28
|
+
securityGrade: "F",
|
|
29
|
+
reasons: [msg],
|
|
30
|
+
probe: await probeEndpoint(input.targetUrl, probeOpts),
|
|
31
|
+
securityRecommendations: ["Use public HTTPS endpoints only"],
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
if (input.policy?.blockedHosts?.some((h) => host.includes(h.toLowerCase()))) {
|
|
35
|
+
reasons.push(`Blocked host: ${host}`);
|
|
36
|
+
riskScore += 80;
|
|
37
|
+
}
|
|
38
|
+
const probe = await probeEndpoint(input.targetUrl, probeOpts);
|
|
39
|
+
const knownGateway = host != null && isKnownAgenticGateway(host);
|
|
40
|
+
if (probe.status === 0) {
|
|
41
|
+
reasons.push("Endpoint unreachable");
|
|
42
|
+
riskScore += 50;
|
|
43
|
+
}
|
|
44
|
+
else if (knownGateway && isExpectedAgenticGatewayProbeStatus(probe.status)) {
|
|
45
|
+
// SIWE-first agentic gateways (e.g. x402.alchemy.com) return 401/403 before 402.
|
|
46
|
+
}
|
|
47
|
+
else if (knownGateway && probe.status >= 500) {
|
|
48
|
+
// Gateway may error on unauthenticated probes; allowlist + policy still govern spend.
|
|
49
|
+
}
|
|
50
|
+
else if (!probe.requiresPayment && probe.status === 200) {
|
|
51
|
+
reasons.push("Endpoint is not x402-protected (unexpected for paid agent flows)");
|
|
52
|
+
riskScore += 15;
|
|
53
|
+
}
|
|
54
|
+
if (probe.priceUsdc != null && input.policy?.perCallCapUsdc != null) {
|
|
55
|
+
if (probe.priceUsdc > input.policy.perCallCapUsdc) {
|
|
56
|
+
reasons.push(`Price $${probe.priceUsdc} exceeds cap $${input.policy.perCallCapUsdc}`);
|
|
57
|
+
riskScore += 40;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (input.estimatedCostUsdc != null && probe.priceUsdc != null) {
|
|
61
|
+
if (input.estimatedCostUsdc < probe.priceUsdc * 0.5) {
|
|
62
|
+
reasons.push("Estimated cost suspiciously lower than probed price");
|
|
63
|
+
riskScore += 20;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const urlSec = assessUrlSecurity(input.targetUrl);
|
|
67
|
+
const merged = mergeSecurityIntoRisk(riskScore, urlSec);
|
|
68
|
+
const allReasons = [...reasons, ...merged.combinedThreats];
|
|
69
|
+
const safe = merged.riskScore < 50 && allReasons.length === 0;
|
|
70
|
+
return {
|
|
71
|
+
safe,
|
|
72
|
+
riskScore: merged.riskScore,
|
|
73
|
+
securityGrade: merged.securityGrade,
|
|
74
|
+
reasons: allReasons,
|
|
75
|
+
probe,
|
|
76
|
+
securityRecommendations: urlSec.recommendations,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type SettlementGraphInput = {
|
|
2
|
+
lastEndpointPath?: string;
|
|
3
|
+
lastTopic?: string;
|
|
4
|
+
maxRecommendations?: number;
|
|
5
|
+
};
|
|
6
|
+
export type SettlementRecommendation = {
|
|
7
|
+
name?: string;
|
|
8
|
+
url?: string;
|
|
9
|
+
priceUsdc?: number;
|
|
10
|
+
reason: string;
|
|
11
|
+
};
|
|
12
|
+
export type SettlementGraphResult = {
|
|
13
|
+
recommendations: SettlementRecommendation[];
|
|
14
|
+
graphNote: string;
|
|
15
|
+
};
|
|
16
|
+
export declare function runSettlementGraph(input: SettlementGraphInput): Promise<SettlementGraphResult>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { searchMarketplace } from "../lib/marketplace.js";
|
|
2
|
+
const TOPIC_HINTS = {
|
|
3
|
+
"spend-governor": "receipt audit verify settlement",
|
|
4
|
+
"risk-gate": "marketplace router oracle data",
|
|
5
|
+
"router": "risk gate security scan",
|
|
6
|
+
"research": "ETH price oracle market data",
|
|
7
|
+
"receipt": "spend governor budget policy",
|
|
8
|
+
};
|
|
9
|
+
export async function runSettlementGraph(input) {
|
|
10
|
+
let query = input.lastTopic ?? "agent infrastructure x402";
|
|
11
|
+
if (input.lastEndpointPath) {
|
|
12
|
+
for (const [key, hint] of Object.entries(TOPIC_HINTS)) {
|
|
13
|
+
if (input.lastEndpointPath.includes(key)) {
|
|
14
|
+
query = hint;
|
|
15
|
+
break;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
const resources = await searchMarketplace(query, { limit: input.maxRecommendations ?? 5 });
|
|
20
|
+
const recommendations = resources.map((r) => ({
|
|
21
|
+
name: r.name,
|
|
22
|
+
url: r.url,
|
|
23
|
+
priceUsdc: r.priceUsdc,
|
|
24
|
+
reason: `Related capability for "${query}" based on prior settlement context`,
|
|
25
|
+
}));
|
|
26
|
+
if (recommendations.length === 0) {
|
|
27
|
+
recommendations.push({
|
|
28
|
+
name: "x402 Route Router",
|
|
29
|
+
url: undefined,
|
|
30
|
+
priceUsdc: 0.02,
|
|
31
|
+
reason: "Fallback: route next call through suite API router",
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
recommendations,
|
|
36
|
+
graphNote: "Inject recommendations after each settlement receipt to reduce agent search steps (compatible with Dexter sponsored-access pattern).",
|
|
37
|
+
};
|
|
38
|
+
}
|