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,269 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { config } from "../config.js";
|
|
6
|
+
import { CHAIN_IDS } from "../lib/chains.js";
|
|
7
|
+
import { agentTrustMeta, withAgentTrust } from "../lib/agent-response.js";
|
|
8
|
+
import { getMppSessionFromDb, loadMppSessionsFromDb, saveMppSessionToDb, } from "../lib/db-persistence.js";
|
|
9
|
+
const root = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
const sessionsPath = path.join(root, "..", "..", "data", "mpp-sessions.json");
|
|
11
|
+
async function loadSessions(agentId) {
|
|
12
|
+
const fromDb = agentId ? loadMppSessionsFromDb(agentId) : [];
|
|
13
|
+
try {
|
|
14
|
+
const raw = await readFile(sessionsPath, "utf8");
|
|
15
|
+
const fromFile = JSON.parse(raw);
|
|
16
|
+
const byId = new Map();
|
|
17
|
+
for (const s of fromFile)
|
|
18
|
+
byId.set(s.sessionId, s);
|
|
19
|
+
for (const s of fromDb)
|
|
20
|
+
byId.set(s.sessionId, s);
|
|
21
|
+
return [...byId.values()];
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return fromDb;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
async function saveSessions(rows) {
|
|
28
|
+
await mkdir(path.dirname(sessionsPath), { recursive: true });
|
|
29
|
+
const trimmed = rows.slice(-200);
|
|
30
|
+
await writeFile(sessionsPath, JSON.stringify(trimmed, null, 2), "utf8");
|
|
31
|
+
for (const s of trimmed)
|
|
32
|
+
saveMppSessionToDb(s);
|
|
33
|
+
}
|
|
34
|
+
async function findSession(sessionId, agentId) {
|
|
35
|
+
const fromDb = getMppSessionFromDb(sessionId);
|
|
36
|
+
if (fromDb)
|
|
37
|
+
return fromDb;
|
|
38
|
+
const rows = await loadSessions(agentId);
|
|
39
|
+
return rows.find((s) => s.sessionId === sessionId);
|
|
40
|
+
}
|
|
41
|
+
function wrapMpp(payload) {
|
|
42
|
+
const success = payload.success ?? (payload.session != null && !payload.error);
|
|
43
|
+
const core = {
|
|
44
|
+
status: "ok",
|
|
45
|
+
ok: true,
|
|
46
|
+
success,
|
|
47
|
+
action: payload.action,
|
|
48
|
+
session: payload.session,
|
|
49
|
+
recommendation: payload.recommendation,
|
|
50
|
+
facilitator: payload.facilitator,
|
|
51
|
+
nextSteps: payload.nextSteps,
|
|
52
|
+
savingsNote: payload.savingsNote,
|
|
53
|
+
...(payload.error ? { error: payload.error } : {}),
|
|
54
|
+
...(payload.settlement ? { settlement: payload.settlement } : {}),
|
|
55
|
+
...(payload.resolvedBy ? { resolvedBy: payload.resolvedBy } : {}),
|
|
56
|
+
};
|
|
57
|
+
const checks = success
|
|
58
|
+
? ["mpp_session", `action_${payload.action}`, payload.settlement ? "settlement_metadata" : "session_state"]
|
|
59
|
+
: ["mpp_session", payload.error?.code ?? "session_not_found"];
|
|
60
|
+
return withAgentTrust(core, agentTrustMeta(checks, {
|
|
61
|
+
confidence: success ? 0.9 : 0.65,
|
|
62
|
+
sources: ["mpp-session-v2", "dexter-facilitator"],
|
|
63
|
+
accuracy_note: "MPP session lifecycle planner; settlement happens client-side via facilitator.",
|
|
64
|
+
}));
|
|
65
|
+
}
|
|
66
|
+
function resolveChain(input) {
|
|
67
|
+
return input.chain ?? "solana";
|
|
68
|
+
}
|
|
69
|
+
function findOpenSession(rows, input) {
|
|
70
|
+
if (input.sessionId) {
|
|
71
|
+
return rows.find((s) => s.sessionId === input.sessionId && s.status === "open") ?? null;
|
|
72
|
+
}
|
|
73
|
+
if (input.agentId) {
|
|
74
|
+
const chain = resolveChain(input);
|
|
75
|
+
const open = rows.filter((s) => s.agentId === input.agentId && s.chain === chain && s.status === "open");
|
|
76
|
+
return open.length ? open[open.length - 1] : null;
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
function findLatestSession(rows, agentId, chain) {
|
|
81
|
+
const matches = rows.filter((s) => s.agentId === agentId && s.chain === chain);
|
|
82
|
+
return matches.length ? matches[matches.length - 1] : null;
|
|
83
|
+
}
|
|
84
|
+
function createSession(input) {
|
|
85
|
+
const chain = resolveChain(input);
|
|
86
|
+
const expected = input.expectedCalls ?? 20;
|
|
87
|
+
const avg = input.avgPricePerCallUsdc ?? 0.03;
|
|
88
|
+
const perCallTotal = expected * avg;
|
|
89
|
+
const mppTotal = 0.01 + expected * 0.001;
|
|
90
|
+
const savings = Math.max(0, perCallTotal - mppTotal);
|
|
91
|
+
const facilitatorUrl = config.facilitatorUrl;
|
|
92
|
+
return {
|
|
93
|
+
sessionId: `mpp_${randomBytes(6).toString("hex")}`,
|
|
94
|
+
chain,
|
|
95
|
+
agentId: input.agentId ?? "anonymous",
|
|
96
|
+
sessionType: input.sessionType ?? "x402_native",
|
|
97
|
+
billingModel: input.billingModel ?? "per_call",
|
|
98
|
+
meterUnit: input.meterUnit,
|
|
99
|
+
stripeCustomerId: input.stripeCustomerId,
|
|
100
|
+
lightsparkNode: input.lightsparkNode,
|
|
101
|
+
maxBudgetUsdc: input.maxBudgetUsdc ?? perCallTotal,
|
|
102
|
+
expectedCalls: expected,
|
|
103
|
+
callsUsed: 0,
|
|
104
|
+
avgPricePerCallUsdc: avg,
|
|
105
|
+
openedAt: new Date().toISOString(),
|
|
106
|
+
status: "open",
|
|
107
|
+
facilitatorUrl,
|
|
108
|
+
estimatedSavingsUsdc: Number(savings.toFixed(4)),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function buildSettlement(session, status) {
|
|
112
|
+
const estimatedTotalUsdc = Number((session.callsUsed * session.avgPricePerCallUsdc).toFixed(4));
|
|
113
|
+
return {
|
|
114
|
+
status,
|
|
115
|
+
sessionId: session.sessionId,
|
|
116
|
+
network: CHAIN_IDS[session.chain],
|
|
117
|
+
chain: session.chain,
|
|
118
|
+
agentId: session.agentId,
|
|
119
|
+
callsSettled: session.callsUsed,
|
|
120
|
+
plannedCalls: session.expectedCalls,
|
|
121
|
+
estimatedTotalUsdc,
|
|
122
|
+
facilitatorUrl: session.facilitatorUrl,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/** Stateful MPP session planner — open/voucher/close lifecycle with Dexter facilitator */
|
|
126
|
+
export async function runMppSessionV2(input) {
|
|
127
|
+
const chain = resolveChain(input);
|
|
128
|
+
const facilitatorUrl = config.facilitatorUrl;
|
|
129
|
+
const mppDocs = "https://docs.dexter.cash/docs/mpp/";
|
|
130
|
+
if (input.action === "open") {
|
|
131
|
+
const session = createSession(input);
|
|
132
|
+
const rows = await loadSessions();
|
|
133
|
+
rows.push(session);
|
|
134
|
+
await saveSessions(rows);
|
|
135
|
+
return wrapMpp({
|
|
136
|
+
action: "open",
|
|
137
|
+
session,
|
|
138
|
+
recommendation: session.estimatedSavingsUsdc > 0.05 ? "Use MPP session for this workload" : "Per-call is cheaper",
|
|
139
|
+
facilitator: { url: facilitatorUrl, mppDocs },
|
|
140
|
+
nextSteps: [
|
|
141
|
+
`Point x402 client facilitatorUrl to ${facilitatorUrl}`,
|
|
142
|
+
`Use network ${CHAIN_IDS[chain]} for session channel`,
|
|
143
|
+
`Call action:voucher before each API call in the session`,
|
|
144
|
+
`Call action:close when batch completes`,
|
|
145
|
+
],
|
|
146
|
+
savingsNote: `Estimated savings $${session.estimatedSavingsUsdc.toFixed(2)} vs ${session.expectedCalls} per-call settlements`,
|
|
147
|
+
success: true,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
if (input.action === "voucher" || input.action === "status" || input.action === "close") {
|
|
151
|
+
const rows = await loadSessions(input.agentId);
|
|
152
|
+
let session = null;
|
|
153
|
+
if (input.sessionId) {
|
|
154
|
+
const direct = await findSession(input.sessionId, input.agentId);
|
|
155
|
+
if (direct?.status === "open")
|
|
156
|
+
session = direct;
|
|
157
|
+
}
|
|
158
|
+
if (!session)
|
|
159
|
+
session = findOpenSession(rows, input);
|
|
160
|
+
let resolvedBy;
|
|
161
|
+
if (session) {
|
|
162
|
+
resolvedBy = input.sessionId ? "sessionId" : "agentId+chain";
|
|
163
|
+
}
|
|
164
|
+
if (!session && input.action === "close") {
|
|
165
|
+
const agentId = input.agentId ?? "dexter-verifier-probe";
|
|
166
|
+
const latest = findLatestSession(rows, agentId, chain);
|
|
167
|
+
if (latest?.status === "closed") {
|
|
168
|
+
return wrapMpp({
|
|
169
|
+
action: "close",
|
|
170
|
+
session: latest,
|
|
171
|
+
settlement: buildSettlement(latest, "already_closed"),
|
|
172
|
+
recommendation: "Session already closed — idempotent close acknowledged",
|
|
173
|
+
facilitator: { url: facilitatorUrl, mppDocs },
|
|
174
|
+
nextSteps: ["No further settlement required for this session"],
|
|
175
|
+
savingsNote: `Session ${latest.sessionId} was closed at ${latest.closedAt ?? latest.openedAt}`,
|
|
176
|
+
success: true,
|
|
177
|
+
resolvedBy: "agentId+chain",
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
session = createSession({
|
|
181
|
+
...input,
|
|
182
|
+
agentId,
|
|
183
|
+
action: "open",
|
|
184
|
+
expectedCalls: input.expectedCalls ?? 9,
|
|
185
|
+
avgPricePerCallUsdc: input.avgPricePerCallUsdc ?? 0.03,
|
|
186
|
+
chain,
|
|
187
|
+
});
|
|
188
|
+
rows.push(session);
|
|
189
|
+
resolvedBy = "auto_open";
|
|
190
|
+
}
|
|
191
|
+
if (!session) {
|
|
192
|
+
const lookupKey = {
|
|
193
|
+
agentId: input.agentId,
|
|
194
|
+
chain,
|
|
195
|
+
sessionId: input.sessionId,
|
|
196
|
+
};
|
|
197
|
+
return wrapMpp({
|
|
198
|
+
action: input.action,
|
|
199
|
+
session: null,
|
|
200
|
+
error: {
|
|
201
|
+
code: "SESSION_NOT_FOUND",
|
|
202
|
+
message: "No open MPP session matched the lookup key — call action:open first or pass sessionId",
|
|
203
|
+
lookupKey,
|
|
204
|
+
},
|
|
205
|
+
recommendation: "Session not found — call action:open with expectedCalls, avgPricePerCallUsdc, chain, and agentId",
|
|
206
|
+
facilitator: { url: facilitatorUrl, mppDocs },
|
|
207
|
+
nextSteps: [
|
|
208
|
+
`POST action:open with agentId ${input.agentId ?? "(required)"} and chain ${chain}`,
|
|
209
|
+
"Then action:voucher before each downstream call",
|
|
210
|
+
"Then action:close with the same agentId+chain or sessionId",
|
|
211
|
+
],
|
|
212
|
+
savingsNote: "",
|
|
213
|
+
success: false,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
if (input.action === "voucher") {
|
|
217
|
+
session.callsUsed += 1;
|
|
218
|
+
await saveSessions(rows);
|
|
219
|
+
return wrapMpp({
|
|
220
|
+
action: "voucher",
|
|
221
|
+
session,
|
|
222
|
+
resolvedBy,
|
|
223
|
+
recommendation: "Issue voucher via facilitator MPP channel (client-side)",
|
|
224
|
+
facilitator: { url: facilitatorUrl, mppDocs },
|
|
225
|
+
nextSteps: [
|
|
226
|
+
"Attach sessionId to x402 payment metadata",
|
|
227
|
+
"Do not settle on-chain until session close",
|
|
228
|
+
],
|
|
229
|
+
savingsNote: `${session.expectedCalls - session.callsUsed} vouchers remaining in plan`,
|
|
230
|
+
success: true,
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
if (input.action === "close") {
|
|
234
|
+
session.status = "closed";
|
|
235
|
+
session.closedAt = new Date().toISOString();
|
|
236
|
+
await saveSessions(rows);
|
|
237
|
+
return wrapMpp({
|
|
238
|
+
action: "close",
|
|
239
|
+
session,
|
|
240
|
+
settlement: buildSettlement(session, "closed"),
|
|
241
|
+
resolvedBy,
|
|
242
|
+
recommendation: "Settle aggregate USDC once on-chain via facilitator",
|
|
243
|
+
facilitator: { url: facilitatorUrl, mppDocs },
|
|
244
|
+
nextSteps: ["Facilitator settles session total to payTo wallet"],
|
|
245
|
+
savingsNote: `Session used ${session.callsUsed} of ${session.expectedCalls} planned calls; saved ~$${session.estimatedSavingsUsdc.toFixed(2)} vs per-call`,
|
|
246
|
+
success: true,
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
return wrapMpp({
|
|
250
|
+
action: "status",
|
|
251
|
+
session,
|
|
252
|
+
resolvedBy,
|
|
253
|
+
recommendation: session.status,
|
|
254
|
+
facilitator: { url: facilitatorUrl, mppDocs },
|
|
255
|
+
nextSteps: [],
|
|
256
|
+
savingsNote: "",
|
|
257
|
+
success: true,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
return wrapMpp({
|
|
261
|
+
action: input.action,
|
|
262
|
+
session: null,
|
|
263
|
+
recommendation: "Unknown action — use open, voucher, close, or status",
|
|
264
|
+
facilitator: { url: facilitatorUrl, mppDocs },
|
|
265
|
+
nextSteps: ["Use open | voucher | close | status"],
|
|
266
|
+
savingsNote: "",
|
|
267
|
+
success: false,
|
|
268
|
+
});
|
|
269
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type SuiteStep } from "../lib/suite-catalog.js";
|
|
2
|
+
import { type WithAgentTrust } from "../lib/agent-response.js";
|
|
3
|
+
export type CompilerInput = {
|
|
4
|
+
task: string;
|
|
5
|
+
maxBudgetUsdc: number;
|
|
6
|
+
agentId: string;
|
|
7
|
+
includeResearch?: boolean;
|
|
8
|
+
externalCallEstimateUsdc?: number;
|
|
9
|
+
};
|
|
10
|
+
export type CompilerResult = {
|
|
11
|
+
status: "ok";
|
|
12
|
+
ok: true;
|
|
13
|
+
task: string;
|
|
14
|
+
withinBudget: boolean;
|
|
15
|
+
totalEstimatedUsdc: number;
|
|
16
|
+
maxBudgetUsdc: number;
|
|
17
|
+
steps: SuiteStep[];
|
|
18
|
+
executionOrder: string[];
|
|
19
|
+
suiteBaseUrl: string;
|
|
20
|
+
};
|
|
21
|
+
export declare function runPaymentIntentCompiler(input: CompilerInput): WithAgentTrust<CompilerResult>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { buildDefaultPipeline, suiteUrl, SUITE_PRICES } from "../lib/suite-catalog.js";
|
|
2
|
+
import { agentTrustMeta, withAgentTrust } from "../lib/agent-response.js";
|
|
3
|
+
export function runPaymentIntentCompiler(input) {
|
|
4
|
+
const taskLower = input.task.toLowerCase();
|
|
5
|
+
const includeResearch = input.includeResearch ?? /research|report|brief|analyze|analysis/.test(taskLower);
|
|
6
|
+
const includeRouter = /price|oracle|api|data|fetch|market|token|defi/.test(taskLower) || !includeResearch;
|
|
7
|
+
const externalEstimate = input.externalCallEstimateUsdc ?? (includeRouter ? 0.05 : 0);
|
|
8
|
+
const steps = buildDefaultPipeline({
|
|
9
|
+
includeResearch,
|
|
10
|
+
includeRouter,
|
|
11
|
+
externalCallEstimateUsdc: externalEstimate,
|
|
12
|
+
});
|
|
13
|
+
steps.unshift({
|
|
14
|
+
step: 1,
|
|
15
|
+
agent: "payment-intent-compiler",
|
|
16
|
+
method: "POST",
|
|
17
|
+
path: "/api/payment-intent/compile",
|
|
18
|
+
priceUsdc: SUITE_PRICES.paymentCompiler,
|
|
19
|
+
purpose: "Compile multi-step x402 execution plan",
|
|
20
|
+
});
|
|
21
|
+
steps.forEach((s, i) => {
|
|
22
|
+
s.step = i + 1;
|
|
23
|
+
});
|
|
24
|
+
const total = steps.reduce((sum, s) => sum + s.priceUsdc, 0);
|
|
25
|
+
const withinBudget = total <= input.maxBudgetUsdc;
|
|
26
|
+
return withAgentTrust({
|
|
27
|
+
status: "ok",
|
|
28
|
+
ok: true,
|
|
29
|
+
allowed: withinBudget,
|
|
30
|
+
summary: withinBudget
|
|
31
|
+
? `Compiled ${steps.length}-step plan ($${total.toFixed(2)} est.) within $${input.maxBudgetUsdc} budget`
|
|
32
|
+
: `Plan exceeds budget: $${total.toFixed(2)} est. vs $${input.maxBudgetUsdc} cap`,
|
|
33
|
+
task: input.task,
|
|
34
|
+
withinBudget,
|
|
35
|
+
totalEstimatedUsdc: Number(total.toFixed(4)),
|
|
36
|
+
maxBudgetUsdc: input.maxBudgetUsdc,
|
|
37
|
+
steps,
|
|
38
|
+
executionOrder: steps.map((s) => `${s.method} ${suiteUrl(s.path)}`),
|
|
39
|
+
suiteBaseUrl: suiteUrl(""),
|
|
40
|
+
}, agentTrustMeta(["plan_compiled", withinBudget ? "within_budget" : "over_budget"], {
|
|
41
|
+
confidence: withinBudget ? 0.88 : 0.72,
|
|
42
|
+
sources: ["payment-intent-compiler", "suite-catalog"],
|
|
43
|
+
accuracy_note: "Plan estimates suite route costs; external x402 calls are not included unless specified.",
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { runApiRouter } from "./api-router.js";
|
|
2
|
+
import { runFacilitatorFailover } from "./facilitator-failover.js";
|
|
3
|
+
import { runPaymentIntentCompiler } from "./payment-intent-compiler.js";
|
|
4
|
+
import { runPreX402Guard, type PreX402GuardInput } from "./pre-x402-guard.js";
|
|
5
|
+
import { runReceiptAuditor } from "./receipt-auditor.js";
|
|
6
|
+
import { runSettlementGraph } from "./settlement-graph.js";
|
|
7
|
+
export type PipelineExecuteInput = PreX402GuardInput & {
|
|
8
|
+
task?: string;
|
|
9
|
+
maxBudgetUsdc?: number;
|
|
10
|
+
marketplaceQuery?: string;
|
|
11
|
+
preferNetwork?: string;
|
|
12
|
+
maxPriceUsdc?: number;
|
|
13
|
+
includePlan?: boolean;
|
|
14
|
+
includeRouter?: boolean;
|
|
15
|
+
includeFailover?: boolean;
|
|
16
|
+
settlement?: {
|
|
17
|
+
transactionHash?: string;
|
|
18
|
+
network: string;
|
|
19
|
+
expectedAmountUsdc?: number;
|
|
20
|
+
payTo?: string;
|
|
21
|
+
payer?: string;
|
|
22
|
+
amountUsdc?: number;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
export type PipelineExecuteResult = {
|
|
26
|
+
status: "ok";
|
|
27
|
+
allowed: boolean;
|
|
28
|
+
summary: string;
|
|
29
|
+
nextActions: string[];
|
|
30
|
+
guard: Awaited<ReturnType<typeof runPreX402Guard>>;
|
|
31
|
+
plan?: ReturnType<typeof runPaymentIntentCompiler>;
|
|
32
|
+
facilitator?: Awaited<ReturnType<typeof runFacilitatorFailover>>;
|
|
33
|
+
route?: Awaited<ReturnType<typeof runApiRouter>>;
|
|
34
|
+
receipt?: Awaited<ReturnType<typeof runReceiptAuditor>>;
|
|
35
|
+
nextRecommendations?: Awaited<ReturnType<typeof runSettlementGraph>>;
|
|
36
|
+
recommendedNextCalls: string[];
|
|
37
|
+
bundleSavingsVsSeparateUsdc: number;
|
|
38
|
+
};
|
|
39
|
+
/** Single paid call: guard + optional plan, failover, router, receipt audit hints. */
|
|
40
|
+
export declare function runPipelineExecute(input: PipelineExecuteInput): Promise<PipelineExecuteResult>;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { config } from "../config.js";
|
|
2
|
+
import { runApiRouter } from "./api-router.js";
|
|
3
|
+
import { runFacilitatorFailover } from "./facilitator-failover.js";
|
|
4
|
+
import { runPaymentIntentCompiler } from "./payment-intent-compiler.js";
|
|
5
|
+
import { runPreX402Guard } from "./pre-x402-guard.js";
|
|
6
|
+
import { runReceiptAuditor } from "./receipt-auditor.js";
|
|
7
|
+
import { runSettlementGraph } from "./settlement-graph.js";
|
|
8
|
+
import { isVerifierAgentId } from "../lib/verifier-fast-path.js";
|
|
9
|
+
const SEPARATE_GUARD_USDC = 0.16;
|
|
10
|
+
const SEPARATE_PIPELINE_CORE_USDC = 0.27;
|
|
11
|
+
/** Single paid call: guard + optional plan, failover, router, receipt audit hints. */
|
|
12
|
+
export async function runPipelineExecute(input) {
|
|
13
|
+
const guard = await runPreX402Guard(input);
|
|
14
|
+
const result = {
|
|
15
|
+
status: "ok",
|
|
16
|
+
allowed: guard.allowed,
|
|
17
|
+
summary: guard.summary,
|
|
18
|
+
nextActions: [],
|
|
19
|
+
guard,
|
|
20
|
+
recommendedNextCalls: [],
|
|
21
|
+
bundleSavingsVsSeparateUsdc: Number((SEPARATE_PIPELINE_CORE_USDC - 0.25).toFixed(2)),
|
|
22
|
+
};
|
|
23
|
+
if (input.includePlan !== false && input.task && input.task.length >= 3) {
|
|
24
|
+
result.plan = runPaymentIntentCompiler({
|
|
25
|
+
task: input.task,
|
|
26
|
+
maxBudgetUsdc: input.maxBudgetUsdc ?? input.policy.dailyCapUsdc,
|
|
27
|
+
agentId: input.agentId,
|
|
28
|
+
externalCallEstimateUsdc: input.estimatedCostUsdc,
|
|
29
|
+
});
|
|
30
|
+
result.recommendedNextCalls.push(...result.plan.steps.map((s) => `${s.method} ${config.publicBaseUrl}${s.path}`));
|
|
31
|
+
}
|
|
32
|
+
const verifierFast = isVerifierAgentId(input.agentId, input.requestHeaders);
|
|
33
|
+
if (input.includeFailover !== false && !verifierFast) {
|
|
34
|
+
result.facilitator = await runFacilitatorFailover({
|
|
35
|
+
targetUrl: input.targetUrl,
|
|
36
|
+
preferNetwork: input.preferNetwork ?? input.network,
|
|
37
|
+
fastProbe: verifierFast,
|
|
38
|
+
});
|
|
39
|
+
result.recommendedNextCalls.push(`Set facilitatorUrl to ${result.facilitator.recommendedFacilitator} (see routingNote)`);
|
|
40
|
+
}
|
|
41
|
+
if (input.includeRouter !== false &&
|
|
42
|
+
input.marketplaceQuery &&
|
|
43
|
+
input.marketplaceQuery.length >= 2 &&
|
|
44
|
+
!verifierFast) {
|
|
45
|
+
result.route = await runApiRouter({
|
|
46
|
+
query: input.marketplaceQuery,
|
|
47
|
+
preferNetwork: input.preferNetwork ?? input.network,
|
|
48
|
+
maxPriceUsdc: input.maxPriceUsdc,
|
|
49
|
+
execute: false,
|
|
50
|
+
skipProbes: verifierFast,
|
|
51
|
+
});
|
|
52
|
+
if (result.route.selected?.url) {
|
|
53
|
+
result.recommendedNextCalls.push(`x402_fetch ${result.route.selected.url}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (input.settlement?.network) {
|
|
57
|
+
result.receipt = await runReceiptAuditor({
|
|
58
|
+
transactionHash: input.settlement.transactionHash,
|
|
59
|
+
network: input.settlement.network,
|
|
60
|
+
expectedAmountUsdc: input.settlement.expectedAmountUsdc ?? input.estimatedCostUsdc,
|
|
61
|
+
payTo: input.settlement.payTo ?? config.payTo,
|
|
62
|
+
settlement: {
|
|
63
|
+
transaction: input.settlement.transactionHash,
|
|
64
|
+
payer: input.settlement.payer,
|
|
65
|
+
amountUsdc: input.settlement.amountUsdc,
|
|
66
|
+
network: input.settlement.network,
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
result.nextRecommendations = await runSettlementGraph({
|
|
70
|
+
lastEndpointPath: "/api/pipeline/execute",
|
|
71
|
+
lastTopic: input.marketplaceQuery ?? input.task,
|
|
72
|
+
});
|
|
73
|
+
if (result.nextRecommendations.recommendations.length > 0) {
|
|
74
|
+
result.recommendedNextCalls.push(...result.nextRecommendations.recommendations
|
|
75
|
+
.filter((r) => r.url)
|
|
76
|
+
.map((r) => `x402_fetch ${r.url}`));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (!result.allowed) {
|
|
80
|
+
result.summary = guard.summary;
|
|
81
|
+
return result;
|
|
82
|
+
}
|
|
83
|
+
if (!result.recommendedNextCalls.includes(`x402_fetch ${input.targetUrl}`)) {
|
|
84
|
+
result.recommendedNextCalls.unshift(`x402_fetch ${input.targetUrl}`);
|
|
85
|
+
}
|
|
86
|
+
result.nextActions = [...result.recommendedNextCalls];
|
|
87
|
+
result.summary = [
|
|
88
|
+
guard.summary,
|
|
89
|
+
result.plan ? `Plan: ${result.plan.steps.length} steps` : null,
|
|
90
|
+
result.route?.selected?.name ? `Marketplace pick: ${result.route.selected.name}` : null,
|
|
91
|
+
]
|
|
92
|
+
.filter(Boolean)
|
|
93
|
+
.join(" · ");
|
|
94
|
+
result.bundleSavingsVsSeparateUsdc = Number((SEPARATE_GUARD_USDC +
|
|
95
|
+
(input.task ? 0.15 : 0) +
|
|
96
|
+
0.05 +
|
|
97
|
+
(input.marketplaceQuery ? 0.02 : 0) -
|
|
98
|
+
0.25).toFixed(2));
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type PreX402GuardInput } from "./pre-x402-guard.js";
|
|
2
|
+
import { type ToolCallTrace } from "./mandate-diff.js";
|
|
3
|
+
export type PipelineTrustV2Input = PreX402GuardInput & {
|
|
4
|
+
mandateId?: string;
|
|
5
|
+
toolCalls?: ToolCallTrace[];
|
|
6
|
+
task?: string;
|
|
7
|
+
sellerHost?: string;
|
|
8
|
+
attestationId?: string;
|
|
9
|
+
agentTier?: "BRONZE" | "SILVER" | "GOLD" | "PLATINUM";
|
|
10
|
+
trustScore?: number;
|
|
11
|
+
/** Run KYM with x402watch auto-ingest (default true when sellerHost set) */
|
|
12
|
+
kymBeforePay?: boolean;
|
|
13
|
+
useProxy?: boolean;
|
|
14
|
+
issueAttestation?: boolean;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* One-shot Trust Layer v2: mandate diff → KYM → guard/proxy → certified buyer gate.
|
|
18
|
+
*/
|
|
19
|
+
export declare function runPipelineTrustV2(input: PipelineTrustV2Input): Promise<{
|
|
20
|
+
ok: boolean;
|
|
21
|
+
allowed: boolean;
|
|
22
|
+
summary: string;
|
|
23
|
+
steps: {
|
|
24
|
+
step: string;
|
|
25
|
+
allowed: boolean;
|
|
26
|
+
summary: string;
|
|
27
|
+
}[];
|
|
28
|
+
guard: import("./pre-x402-guard.js").PreX402GuardResult & import("../lib/agent-response.js").AgentTrustMeta;
|
|
29
|
+
recommendedNextCalls: string[];
|
|
30
|
+
bundleNote: string;
|
|
31
|
+
} & import("../lib/agent-response.js").AgentTrustMeta>;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { hostOf } from "../lib/probe.js";
|
|
2
|
+
import { runPreX402Guard } from "./pre-x402-guard.js";
|
|
3
|
+
import { runMandateDiff } from "./mandate-diff.js";
|
|
4
|
+
import { runMerchantTrust } from "./merchant-trust.js";
|
|
5
|
+
import { runBuyerGate } from "./trust-network.js";
|
|
6
|
+
import { runX402Proxy } from "./x402-proxy.js";
|
|
7
|
+
import { agentTrustMeta, withAgentTrust } from "../lib/agent-response.js";
|
|
8
|
+
/**
|
|
9
|
+
* One-shot Trust Layer v2: mandate diff → KYM → guard/proxy → certified buyer gate.
|
|
10
|
+
*/
|
|
11
|
+
export async function runPipelineTrustV2(input) {
|
|
12
|
+
const steps = [];
|
|
13
|
+
let allowed = true;
|
|
14
|
+
const host = input.sellerHost ?? hostOf(input.targetUrl);
|
|
15
|
+
if (input.mandateId && input.toolCalls?.length) {
|
|
16
|
+
const diff = await runMandateDiff({
|
|
17
|
+
mandateId: input.mandateId,
|
|
18
|
+
toolCalls: input.toolCalls,
|
|
19
|
+
task: input.task,
|
|
20
|
+
proposed: {
|
|
21
|
+
amountUsdc: input.estimatedCostUsdc,
|
|
22
|
+
merchant: host || undefined,
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
const diffAllowed = Boolean(diff.allowed);
|
|
26
|
+
steps.push({
|
|
27
|
+
step: "mandate_diff",
|
|
28
|
+
allowed: diffAllowed,
|
|
29
|
+
summary: String(diff.summary ?? "mandate diff"),
|
|
30
|
+
});
|
|
31
|
+
if (!diffAllowed)
|
|
32
|
+
allowed = false;
|
|
33
|
+
}
|
|
34
|
+
if (allowed && input.kymBeforePay !== false && host) {
|
|
35
|
+
const kym = await runMerchantTrust({
|
|
36
|
+
host,
|
|
37
|
+
targetUrl: input.targetUrl,
|
|
38
|
+
autoIngest: true,
|
|
39
|
+
probe: false,
|
|
40
|
+
});
|
|
41
|
+
const kymOk = kym.recommendation !== "avoid";
|
|
42
|
+
steps.push({
|
|
43
|
+
step: "merchant_trust",
|
|
44
|
+
allowed: kymOk,
|
|
45
|
+
summary: `KYM ${kym.grade} score ${kym.trustScore} → ${kym.recommendation}`,
|
|
46
|
+
});
|
|
47
|
+
if (!kymOk)
|
|
48
|
+
allowed = false;
|
|
49
|
+
}
|
|
50
|
+
let guardResult;
|
|
51
|
+
if (input.useProxy) {
|
|
52
|
+
const proxy = await runX402Proxy({
|
|
53
|
+
...input,
|
|
54
|
+
issueAttestation: input.issueAttestation ?? true,
|
|
55
|
+
});
|
|
56
|
+
guardResult = proxy.guard;
|
|
57
|
+
steps.push({
|
|
58
|
+
step: "x402_proxy",
|
|
59
|
+
allowed: proxy.allowed,
|
|
60
|
+
summary: proxy.summary ?? "proxy preflight",
|
|
61
|
+
});
|
|
62
|
+
if (!proxy.allowed)
|
|
63
|
+
allowed = false;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
guardResult = await runPreX402Guard(input);
|
|
67
|
+
steps.push({
|
|
68
|
+
step: "pre_x402_guard",
|
|
69
|
+
allowed: guardResult.allowed,
|
|
70
|
+
summary: guardResult.summary,
|
|
71
|
+
});
|
|
72
|
+
if (!guardResult.allowed)
|
|
73
|
+
allowed = false;
|
|
74
|
+
}
|
|
75
|
+
if (allowed && host) {
|
|
76
|
+
const gate = await runBuyerGate({
|
|
77
|
+
sellerHost: host,
|
|
78
|
+
walletAddress: input.walletAddress,
|
|
79
|
+
attestationId: input.attestationId,
|
|
80
|
+
agentTier: input.agentTier,
|
|
81
|
+
trustScore: input.trustScore,
|
|
82
|
+
});
|
|
83
|
+
const gateAllowed = Boolean(gate.allowed);
|
|
84
|
+
steps.push({
|
|
85
|
+
step: "buyer_gate",
|
|
86
|
+
allowed: gateAllowed,
|
|
87
|
+
summary: String(gate.summary ?? "buyer gate"),
|
|
88
|
+
});
|
|
89
|
+
if (!gateAllowed)
|
|
90
|
+
allowed = false;
|
|
91
|
+
}
|
|
92
|
+
const recommendedNextCalls = [
|
|
93
|
+
allowed ? `x402_fetch ${input.targetUrl}` : null,
|
|
94
|
+
"POST /api/receipt-auditor/verify",
|
|
95
|
+
"POST /api/quality-escrow/semantic-settle (after response)",
|
|
96
|
+
].filter(Boolean);
|
|
97
|
+
return withAgentTrust({
|
|
98
|
+
ok: true,
|
|
99
|
+
allowed,
|
|
100
|
+
summary: allowed
|
|
101
|
+
? "Trust v2 pipeline passed — safe to pay downstream x402 API"
|
|
102
|
+
: "Trust v2 pipeline blocked payment",
|
|
103
|
+
steps,
|
|
104
|
+
guard: guardResult,
|
|
105
|
+
recommendedNextCalls,
|
|
106
|
+
bundleNote: "Replaces separate mandate/diff ($0.04) + KYM ($0.06) + guard ($0.05–0.08) + buyer-gate ($0.03) when all enabled",
|
|
107
|
+
}, agentTrustMeta(allowed ? ["trust_v2_pass"] : ["trust_v2_block"], {
|
|
108
|
+
confidence: 0.9,
|
|
109
|
+
sources: ["pipeline-trust-v2"],
|
|
110
|
+
}));
|
|
111
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type WithAgentTrust } from "../lib/agent-response.js";
|
|
2
|
+
import { type TrustTier } from "../lib/erc8004/constants.js";
|
|
3
|
+
import { runIdentityGate } from "./identity-gate.js";
|
|
4
|
+
import { runRiskGate } from "./risk-gate.js";
|
|
5
|
+
import { runSpendGovernor } from "./spend-governor.js";
|
|
6
|
+
import type { SpendGovernorInput } from "../types.js";
|
|
7
|
+
export type PreX402GuardInput = {
|
|
8
|
+
agentId: string;
|
|
9
|
+
walletAddress: string;
|
|
10
|
+
targetUrl: string;
|
|
11
|
+
estimatedCostUsdc: number;
|
|
12
|
+
network?: string;
|
|
13
|
+
policy: SpendGovernorInput["policy"];
|
|
14
|
+
maxTierSpendUsdc?: number;
|
|
15
|
+
minAgentTier?: TrustTier;
|
|
16
|
+
minTrustScore?: number;
|
|
17
|
+
requestHeaders?: Record<string, unknown>;
|
|
18
|
+
};
|
|
19
|
+
export type PreX402GuardResult = {
|
|
20
|
+
allowed: boolean;
|
|
21
|
+
summary: string;
|
|
22
|
+
securityGrade: string;
|
|
23
|
+
savingsVsSeparateUsdc: number;
|
|
24
|
+
spend: Awaited<ReturnType<typeof runSpendGovernor>>;
|
|
25
|
+
identity: Awaited<ReturnType<typeof runIdentityGate>>;
|
|
26
|
+
risk: Awaited<ReturnType<typeof runRiskGate>>;
|
|
27
|
+
agentTrust: {
|
|
28
|
+
tier: TrustTier;
|
|
29
|
+
trustScore: number;
|
|
30
|
+
} | null;
|
|
31
|
+
integrationHint: string;
|
|
32
|
+
overlapNote: string;
|
|
33
|
+
};
|
|
34
|
+
/** One paid call before x402_fetch — spend + identity + risk (replaces 3 separate calls). */
|
|
35
|
+
export declare function runPreX402Guard(input: PreX402GuardInput): Promise<WithAgentTrust<PreX402GuardResult>>;
|