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,96 @@
|
|
|
1
|
+
import { config } from "../config.js";
|
|
2
|
+
import { runPreX402Guard } from "../agents/pre-x402-guard.js";
|
|
3
|
+
import { issueAgentPassport } from "./agent-passport.js";
|
|
4
|
+
import { computeTrustScoreV2 } from "./trust-score-v2.js";
|
|
5
|
+
import { runFraudScan } from "./fraud-engine.js";
|
|
6
|
+
import { runTrustOracleConsensus } from "./trust-oracle.js";
|
|
7
|
+
import { createReplayBinding } from "./replay-guard.js";
|
|
8
|
+
import { computeAgentCreditScore } from "./credit-bureau.js";
|
|
9
|
+
import { assessCompliance } from "./compliance-v2.js";
|
|
10
|
+
import { recordProtocolMetric } from "./observability.js";
|
|
11
|
+
export async function runFullTrustPipeline(input) {
|
|
12
|
+
await recordProtocolMetric("pipeline.full_trust.start", { agentId: input.agentId });
|
|
13
|
+
const passport = await issueAgentPassport({
|
|
14
|
+
agentId: input.agentId,
|
|
15
|
+
walletAddress: input.walletAddress,
|
|
16
|
+
});
|
|
17
|
+
const trustV2 = await computeTrustScoreV2({
|
|
18
|
+
agentId: input.agentId,
|
|
19
|
+
walletAddress: input.walletAddress,
|
|
20
|
+
});
|
|
21
|
+
const fraud = await runFraudScan({
|
|
22
|
+
agentId: input.agentId,
|
|
23
|
+
walletAddress: input.walletAddress,
|
|
24
|
+
merchantHost: new URL(input.targetUrl).hostname,
|
|
25
|
+
amountUsdc: input.estimatedCostUsdc,
|
|
26
|
+
});
|
|
27
|
+
const oracle = await runTrustOracleConsensus({
|
|
28
|
+
subjectType: "agent",
|
|
29
|
+
subjectId: input.agentId,
|
|
30
|
+
claims: { trustScore: trustV2.trustScore, fraudScore: fraud.fraudScore },
|
|
31
|
+
});
|
|
32
|
+
const credit = await computeAgentCreditScore({
|
|
33
|
+
agentId: input.agentId,
|
|
34
|
+
walletAddress: input.walletAddress,
|
|
35
|
+
});
|
|
36
|
+
const compliance = assessCompliance({
|
|
37
|
+
organizationId: input.organizationId ?? "default-org",
|
|
38
|
+
agentId: input.agentId,
|
|
39
|
+
monthlyVolumeUsdc: input.estimatedCostUsdc * 30,
|
|
40
|
+
});
|
|
41
|
+
const replayBinding = await createReplayBinding({
|
|
42
|
+
agentId: input.agentId,
|
|
43
|
+
resourceUrl: input.targetUrl,
|
|
44
|
+
requestBody: { estimatedCostUsdc: input.estimatedCostUsdc },
|
|
45
|
+
});
|
|
46
|
+
const guard = await runPreX402Guard({
|
|
47
|
+
agentId: input.agentId,
|
|
48
|
+
walletAddress: input.walletAddress,
|
|
49
|
+
targetUrl: input.targetUrl,
|
|
50
|
+
estimatedCostUsdc: input.estimatedCostUsdc,
|
|
51
|
+
policy: input.policy,
|
|
52
|
+
minTrustScore: 50,
|
|
53
|
+
});
|
|
54
|
+
const allowed = guard.allowed &&
|
|
55
|
+
fraud.fraudScore < 60 &&
|
|
56
|
+
oracle.consensus &&
|
|
57
|
+
compliance.allowed &&
|
|
58
|
+
credit.creditScore >= 500;
|
|
59
|
+
await recordProtocolMetric("pipeline.full_trust.complete", {
|
|
60
|
+
agentId: input.agentId,
|
|
61
|
+
allowed: String(allowed),
|
|
62
|
+
});
|
|
63
|
+
return {
|
|
64
|
+
status: "ok",
|
|
65
|
+
allowed,
|
|
66
|
+
summary: allowed
|
|
67
|
+
? "Full trust pipeline passed — safe to proceed with x402 payment"
|
|
68
|
+
: "Full trust pipeline blocked — review fraud, oracle, compliance, or guard",
|
|
69
|
+
passport: { did: passport.did, riskTier: passport.riskTier },
|
|
70
|
+
trustV2,
|
|
71
|
+
fraud,
|
|
72
|
+
oracle,
|
|
73
|
+
credit,
|
|
74
|
+
compliance,
|
|
75
|
+
replayBinding: {
|
|
76
|
+
bindingId: replayBinding.bindingId,
|
|
77
|
+
header: "X-Trust-Replay-Binding",
|
|
78
|
+
nonce: replayBinding.nonce,
|
|
79
|
+
expiresAt: replayBinding.expiresAt,
|
|
80
|
+
},
|
|
81
|
+
guard: {
|
|
82
|
+
allowed: guard.allowed,
|
|
83
|
+
securityGrade: guard.securityGrade,
|
|
84
|
+
summary: guard.summary,
|
|
85
|
+
},
|
|
86
|
+
nextSteps: allowed
|
|
87
|
+
? [
|
|
88
|
+
`Attach header X-Trust-Replay-Binding: ${replayBinding.bindingId}`,
|
|
89
|
+
"Pay target with x402_fetch / OpenDexter",
|
|
90
|
+
"POST /api/protocol/execution/issue with tool trace + settlement",
|
|
91
|
+
]
|
|
92
|
+
: ["Review blockers", "POST /api/protocol/fraud/scan for detail"],
|
|
93
|
+
protocolVersion: "4.0.0",
|
|
94
|
+
docs: `${config.publicBaseUrl}/api/protocol/architecture`,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export type ExecutionReceiptInput = {
|
|
2
|
+
agentId: string;
|
|
3
|
+
taskId?: string;
|
|
4
|
+
targetUrl?: string;
|
|
5
|
+
toolTrace?: Array<{
|
|
6
|
+
name: string;
|
|
7
|
+
url?: string;
|
|
8
|
+
amountUsdc?: number;
|
|
9
|
+
}>;
|
|
10
|
+
decisionTrace?: string[];
|
|
11
|
+
settlement?: {
|
|
12
|
+
transactionHash?: string;
|
|
13
|
+
network?: string;
|
|
14
|
+
amountUsdc?: number;
|
|
15
|
+
};
|
|
16
|
+
responseSummary?: string;
|
|
17
|
+
};
|
|
18
|
+
export type ExecutionReceipt = {
|
|
19
|
+
receiptId: string;
|
|
20
|
+
taskId: string;
|
|
21
|
+
executionHash: string;
|
|
22
|
+
toolTraceHash: string;
|
|
23
|
+
decisionTraceHash: string;
|
|
24
|
+
verificationProof: string;
|
|
25
|
+
settlementProof: string | null;
|
|
26
|
+
issuedAt: string;
|
|
27
|
+
thirdPartyVerifyUrl: string;
|
|
28
|
+
};
|
|
29
|
+
export declare function issueExecutionReceipt(input: ExecutionReceiptInput, publicBaseUrl: string): Promise<ExecutionReceipt & {
|
|
30
|
+
signature: string;
|
|
31
|
+
}>;
|
|
32
|
+
export declare function verifyExecutionReceipt(receiptId: string): Promise<{
|
|
33
|
+
valid: boolean;
|
|
34
|
+
receipt: ExecutionReceipt | null;
|
|
35
|
+
reason?: string;
|
|
36
|
+
}>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { hmacSign, sha256Hex } from "./crypto.js";
|
|
2
|
+
import { readProtocolStore, writeProtocolStore } from "./store.js";
|
|
3
|
+
export async function issueExecutionReceipt(input, publicBaseUrl) {
|
|
4
|
+
const store = await readProtocolStore("execution-receipts", {});
|
|
5
|
+
const taskId = input.taskId ?? `task_${Date.now().toString(36)}`;
|
|
6
|
+
const toolTraceJson = JSON.stringify(input.toolTrace ?? []);
|
|
7
|
+
const decisionJson = JSON.stringify(input.decisionTrace ?? []);
|
|
8
|
+
const executionHash = sha256Hex(`${input.agentId}:${taskId}:${input.targetUrl ?? ""}:${input.responseSummary ?? ""}`);
|
|
9
|
+
const toolTraceHash = sha256Hex(toolTraceJson);
|
|
10
|
+
const decisionTraceHash = sha256Hex(decisionJson);
|
|
11
|
+
const settlementProof = input.settlement?.transactionHash
|
|
12
|
+
? sha256Hex(JSON.stringify(input.settlement))
|
|
13
|
+
: null;
|
|
14
|
+
const receiptId = `poe_${sha256Hex(executionHash).slice(0, 16)}`;
|
|
15
|
+
const verificationProof = hmacSign(`${receiptId}:${executionHash}:${toolTraceHash}:${decisionTraceHash}`);
|
|
16
|
+
const receipt = {
|
|
17
|
+
receiptId,
|
|
18
|
+
taskId,
|
|
19
|
+
executionHash,
|
|
20
|
+
toolTraceHash,
|
|
21
|
+
decisionTraceHash,
|
|
22
|
+
verificationProof,
|
|
23
|
+
settlementProof,
|
|
24
|
+
issuedAt: new Date().toISOString(),
|
|
25
|
+
thirdPartyVerifyUrl: `${publicBaseUrl}/api/protocol/execution/verify`,
|
|
26
|
+
};
|
|
27
|
+
const payload = JSON.stringify(receipt);
|
|
28
|
+
const signature = hmacSign(payload);
|
|
29
|
+
store[receiptId] = { ...receipt, signature, payload };
|
|
30
|
+
await writeProtocolStore("execution-receipts", store);
|
|
31
|
+
return { ...receipt, signature };
|
|
32
|
+
}
|
|
33
|
+
export async function verifyExecutionReceipt(receiptId) {
|
|
34
|
+
const store = await readProtocolStore("execution-receipts", {});
|
|
35
|
+
const row = store[receiptId];
|
|
36
|
+
if (!row)
|
|
37
|
+
return { valid: false, receipt: null, reason: "Receipt not found" };
|
|
38
|
+
const { signature, payload, ...receipt } = row;
|
|
39
|
+
const expected = hmacSign(payload);
|
|
40
|
+
if (expected !== signature) {
|
|
41
|
+
return { valid: false, receipt, reason: "Receipt signature invalid" };
|
|
42
|
+
}
|
|
43
|
+
const recomputed = hmacSign(`${receipt.receiptId}:${receipt.executionHash}:${receipt.toolTraceHash}:${receipt.decisionTraceHash}`);
|
|
44
|
+
if (recomputed !== receipt.verificationProof) {
|
|
45
|
+
return { valid: false, receipt, reason: "Verification proof mismatch" };
|
|
46
|
+
}
|
|
47
|
+
return { valid: true, receipt };
|
|
48
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type ReasoningCommitInput = {
|
|
2
|
+
agentId: string;
|
|
3
|
+
sessionId?: string;
|
|
4
|
+
toolCalls: Array<{
|
|
5
|
+
name: string;
|
|
6
|
+
argsHash?: string;
|
|
7
|
+
}>;
|
|
8
|
+
policyChecks: string[];
|
|
9
|
+
promptHashes: string[];
|
|
10
|
+
riskAnalysis?: string;
|
|
11
|
+
decisionGraph?: Record<string, unknown>;
|
|
12
|
+
};
|
|
13
|
+
export type ReasoningCommitResult = {
|
|
14
|
+
auditId: string;
|
|
15
|
+
merkleRoot: string;
|
|
16
|
+
leafCount: number;
|
|
17
|
+
committedAt: string;
|
|
18
|
+
zkReady: boolean;
|
|
19
|
+
disclosureHint: string;
|
|
20
|
+
};
|
|
21
|
+
export declare function commitReasoningAudit(input: ReasoningCommitInput): Promise<ReasoningCommitResult>;
|
|
22
|
+
export declare function selectiveDisclose(auditId: string, leafIndices: number[]): Promise<{
|
|
23
|
+
ok: boolean;
|
|
24
|
+
disclosed: string[];
|
|
25
|
+
merkleProof: string[];
|
|
26
|
+
reason?: string;
|
|
27
|
+
}>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { merkleRoot, sha256Hex, hmacSign } from "./crypto.js";
|
|
2
|
+
import { readProtocolStore, writeProtocolStore } from "./store.js";
|
|
3
|
+
export async function commitReasoningAudit(input) {
|
|
4
|
+
const leaves = [];
|
|
5
|
+
for (const t of input.toolCalls) {
|
|
6
|
+
leaves.push(sha256Hex(`tool:${t.name}:${t.argsHash ?? ""}`));
|
|
7
|
+
}
|
|
8
|
+
for (const p of input.promptHashes) {
|
|
9
|
+
leaves.push(sha256Hex(`prompt:${p}`));
|
|
10
|
+
}
|
|
11
|
+
for (const c of input.policyChecks) {
|
|
12
|
+
leaves.push(sha256Hex(`policy:${c}`));
|
|
13
|
+
}
|
|
14
|
+
if (input.riskAnalysis)
|
|
15
|
+
leaves.push(sha256Hex(`risk:${input.riskAnalysis}`));
|
|
16
|
+
if (input.decisionGraph)
|
|
17
|
+
leaves.push(sha256Hex(`graph:${JSON.stringify(input.decisionGraph)}`));
|
|
18
|
+
const root = merkleRoot(leaves);
|
|
19
|
+
const auditId = `aud_${sha256Hex(root).slice(0, 16)}`;
|
|
20
|
+
const store = await readProtocolStore("reasoning-audits", {});
|
|
21
|
+
store[auditId] = {
|
|
22
|
+
merkleRoot: root,
|
|
23
|
+
leaves,
|
|
24
|
+
agentId: input.agentId,
|
|
25
|
+
committedAt: new Date().toISOString(),
|
|
26
|
+
signature: hmacSign(`${auditId}:${root}`),
|
|
27
|
+
};
|
|
28
|
+
await writeProtocolStore("reasoning-audits", store);
|
|
29
|
+
return {
|
|
30
|
+
auditId,
|
|
31
|
+
merkleRoot: root,
|
|
32
|
+
leafCount: leaves.length,
|
|
33
|
+
committedAt: store[auditId].committedAt,
|
|
34
|
+
zkReady: true,
|
|
35
|
+
disclosureHint: "Use POST /api/protocol/reasoning/disclose with leaf indices for selective reveal",
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export async function selectiveDisclose(auditId, leafIndices) {
|
|
39
|
+
const store = await readProtocolStore("reasoning-audits", {});
|
|
40
|
+
const row = store[auditId];
|
|
41
|
+
if (!row)
|
|
42
|
+
return { ok: false, disclosed: [], merkleProof: [], reason: "Audit not found" };
|
|
43
|
+
const disclosed = leafIndices
|
|
44
|
+
.filter((i) => i >= 0 && i < row.leaves.length)
|
|
45
|
+
.map((i) => row.leaves[i]);
|
|
46
|
+
return {
|
|
47
|
+
ok: true,
|
|
48
|
+
disclosed,
|
|
49
|
+
merkleProof: [row.merkleRoot, ...disclosed],
|
|
50
|
+
};
|
|
51
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type ReplayBindingInput = {
|
|
2
|
+
agentId: string;
|
|
3
|
+
sessionId?: string;
|
|
4
|
+
resourceUrl: string;
|
|
5
|
+
method?: string;
|
|
6
|
+
requestBody?: unknown;
|
|
7
|
+
ttlSeconds?: number;
|
|
8
|
+
};
|
|
9
|
+
export type ReplayBinding = {
|
|
10
|
+
bindingId: string;
|
|
11
|
+
nonce: string;
|
|
12
|
+
resourceHash: string;
|
|
13
|
+
requestHash: string;
|
|
14
|
+
agentId: string;
|
|
15
|
+
sessionId: string;
|
|
16
|
+
expiresAt: string;
|
|
17
|
+
signature: string;
|
|
18
|
+
};
|
|
19
|
+
export declare function createReplayBinding(input: ReplayBindingInput): Promise<ReplayBinding>;
|
|
20
|
+
export declare function verifyReplayBinding(bindingId: string, headers: {
|
|
21
|
+
nonce?: string;
|
|
22
|
+
resourceUrl?: string;
|
|
23
|
+
requestBody?: unknown;
|
|
24
|
+
agentId?: string;
|
|
25
|
+
}): Promise<{
|
|
26
|
+
valid: boolean;
|
|
27
|
+
reason?: string;
|
|
28
|
+
}>;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { sha256Hex, hmacSign, verifyHmac } from "./crypto.js";
|
|
2
|
+
import { claimNonceKey, isNonceKeyUsed } from "../lib/nonce-store.js";
|
|
3
|
+
import { readProtocolStore, writeProtocolStore } from "./store.js";
|
|
4
|
+
async function claimNonceOnce(nonce) {
|
|
5
|
+
const safe = nonce.replace(/[^a-f0-9]/gi, "").slice(0, 64);
|
|
6
|
+
if (!safe)
|
|
7
|
+
return false;
|
|
8
|
+
const key = `proto:${safe}`;
|
|
9
|
+
if (isNonceKeyUsed(key))
|
|
10
|
+
return false;
|
|
11
|
+
return claimNonceKey(key, "protocol-replay");
|
|
12
|
+
}
|
|
13
|
+
export async function createReplayBinding(input) {
|
|
14
|
+
const nonce = sha256Hex(`${Date.now()}:${input.agentId}`).slice(0, 32);
|
|
15
|
+
const resourceHash = sha256Hex(`${input.method ?? "POST"}:${input.resourceUrl}`);
|
|
16
|
+
const requestHash = sha256Hex(JSON.stringify(input.requestBody ?? {}));
|
|
17
|
+
const sessionId = input.sessionId ?? `sess_${input.agentId}`;
|
|
18
|
+
const ttl = input.ttlSeconds ?? 300;
|
|
19
|
+
const expiresAt = new Date(Date.now() + ttl * 1000).toISOString();
|
|
20
|
+
const bindingId = `rb_${nonce.slice(0, 16)}`;
|
|
21
|
+
const payload = {
|
|
22
|
+
bindingId,
|
|
23
|
+
nonce,
|
|
24
|
+
resourceHash,
|
|
25
|
+
requestHash,
|
|
26
|
+
agentId: input.agentId,
|
|
27
|
+
sessionId,
|
|
28
|
+
expiresAt,
|
|
29
|
+
};
|
|
30
|
+
const signature = hmacSign(JSON.stringify(payload));
|
|
31
|
+
const binding = { ...payload, signature };
|
|
32
|
+
const store = await readProtocolStore("replay-bindings", {});
|
|
33
|
+
store[bindingId] = binding;
|
|
34
|
+
await writeProtocolStore("replay-bindings", store);
|
|
35
|
+
return binding;
|
|
36
|
+
}
|
|
37
|
+
export async function verifyReplayBinding(bindingId, headers) {
|
|
38
|
+
const store = await readProtocolStore("replay-bindings", {});
|
|
39
|
+
const binding = store[bindingId];
|
|
40
|
+
if (!binding)
|
|
41
|
+
return { valid: false, reason: "Binding not found" };
|
|
42
|
+
const payload = JSON.stringify({
|
|
43
|
+
bindingId: binding.bindingId,
|
|
44
|
+
nonce: binding.nonce,
|
|
45
|
+
resourceHash: binding.resourceHash,
|
|
46
|
+
requestHash: binding.requestHash,
|
|
47
|
+
agentId: binding.agentId,
|
|
48
|
+
sessionId: binding.sessionId,
|
|
49
|
+
expiresAt: binding.expiresAt,
|
|
50
|
+
});
|
|
51
|
+
if (!verifyHmac(payload, binding.signature)) {
|
|
52
|
+
return { valid: false, reason: "Binding signature invalid" };
|
|
53
|
+
}
|
|
54
|
+
if (new Date(binding.expiresAt).getTime() < Date.now()) {
|
|
55
|
+
return { valid: false, reason: "Binding expired" };
|
|
56
|
+
}
|
|
57
|
+
if (headers.nonce && headers.nonce !== binding.nonce) {
|
|
58
|
+
return { valid: false, reason: "Nonce mismatch" };
|
|
59
|
+
}
|
|
60
|
+
if (headers.resourceUrl) {
|
|
61
|
+
const rh = sha256Hex(`POST:${headers.resourceUrl}`);
|
|
62
|
+
if (rh !== binding.resourceHash) {
|
|
63
|
+
return { valid: false, reason: "Resource substitution detected" };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (headers.requestBody !== undefined) {
|
|
67
|
+
const rq = sha256Hex(JSON.stringify(headers.requestBody));
|
|
68
|
+
if (rq !== binding.requestHash) {
|
|
69
|
+
return { valid: false, reason: "Request body hash mismatch" };
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const claimed = await claimNonceOnce(binding.nonce);
|
|
73
|
+
if (!claimed)
|
|
74
|
+
return { valid: false, reason: "Nonce already consumed (replay)" };
|
|
75
|
+
return { valid: true };
|
|
76
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { hmacSign, verifyHmac } from "./crypto.js";
|
|
3
|
+
describe("replay binding signature", () => {
|
|
4
|
+
it("verifyHmac is timing-safe compatible", () => {
|
|
5
|
+
const payload = JSON.stringify({ bindingId: "rb_abc", nonce: "n1" });
|
|
6
|
+
const sig = hmacSign(payload);
|
|
7
|
+
expect(verifyHmac(payload, sig)).toBe(true);
|
|
8
|
+
expect(verifyHmac(payload, sig + "0")).toBe(false);
|
|
9
|
+
});
|
|
10
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { getThreatModel } from "./threat-catalog.js";
|
|
2
|
+
export declare function generateSecurityAuditReport(): {
|
|
3
|
+
auditId: string;
|
|
4
|
+
suiteVersion: string;
|
|
5
|
+
auditedAt: string;
|
|
6
|
+
summary: string;
|
|
7
|
+
phases: Array<{
|
|
8
|
+
phase: number;
|
|
9
|
+
name: string;
|
|
10
|
+
status: "implemented" | "partial" | "planned";
|
|
11
|
+
}>;
|
|
12
|
+
findings: Array<{
|
|
13
|
+
severity: string;
|
|
14
|
+
area: string;
|
|
15
|
+
note: string;
|
|
16
|
+
}>;
|
|
17
|
+
threatModel: ReturnType<typeof getThreatModel>;
|
|
18
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { SUITE_VERSION } from "../lib/version.js";
|
|
2
|
+
import { getThreatModel } from "./threat-catalog.js";
|
|
3
|
+
export function generateSecurityAuditReport() {
|
|
4
|
+
return {
|
|
5
|
+
auditId: `audit_${Date.now().toString(36)}`,
|
|
6
|
+
suiteVersion: SUITE_VERSION,
|
|
7
|
+
auditedAt: new Date().toISOString(),
|
|
8
|
+
summary: "Protocol v4 modules deployed: identity passport, trust v2, fraud graph, oracle quorum, PoE receipts, reasoning Merkle, escrow FSM, replay bindings, zk stubs, credit bureau.",
|
|
9
|
+
phases: [
|
|
10
|
+
{ phase: 1, name: "Security audit catalog", status: "implemented" },
|
|
11
|
+
{ phase: 2, name: "Agent identity (DID passport)", status: "implemented" },
|
|
12
|
+
{ phase: 3, name: "TrustScore v2", status: "implemented" },
|
|
13
|
+
{ phase: 4, name: "Fraud detection graph", status: "implemented" },
|
|
14
|
+
{ phase: 5, name: "Trust oracle network", status: "partial" },
|
|
15
|
+
{ phase: 6, name: "Proof of execution", status: "implemented" },
|
|
16
|
+
{ phase: 7, name: "Reasoning audit + Merkle", status: "implemented" },
|
|
17
|
+
{ phase: 8, name: "Escrow FSM", status: "implemented" },
|
|
18
|
+
{ phase: 9, name: "Replay protection", status: "implemented" },
|
|
19
|
+
{ phase: 10, name: "ZK layer", status: "partial" },
|
|
20
|
+
{ phase: 11, name: "Compliance engine", status: "partial" },
|
|
21
|
+
{ phase: 12, name: "Agent credit bureau", status: "implemented" },
|
|
22
|
+
{ phase: 13, name: "Enterprise RBAC/OPA", status: "planned" },
|
|
23
|
+
{ phase: 14, name: "OpenTelemetry", status: "partial" },
|
|
24
|
+
{ phase: 15, name: "K8s / contracts production", status: "planned" },
|
|
25
|
+
],
|
|
26
|
+
findings: [
|
|
27
|
+
{
|
|
28
|
+
severity: "info",
|
|
29
|
+
area: "ZK",
|
|
30
|
+
note: "ZK proofs are simulated; wire Groth16 verifier before enterprise claims",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
severity: "medium",
|
|
34
|
+
area: "Oracle",
|
|
35
|
+
note: "Oracle quorum is simulated; deploy validator set on-chain for BFT",
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
severity: "low",
|
|
39
|
+
area: "Storage",
|
|
40
|
+
note: "Protocol state is JSON files; migrate to Postgres for multi-tenant scale",
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
threatModel: getThreatModel(),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function readProtocolStore<T>(name: string, fallback: T): Promise<T>;
|
|
2
|
+
export declare function writeProtocolStore<T>(name: string, data: T): Promise<void>;
|
|
3
|
+
/** Per-agent keyed store (e.g. credit-bureau history by agentId). */
|
|
4
|
+
export declare function readProtocolStoreKey<T>(store: string, key: string, fallback: T): Promise<T>;
|
|
5
|
+
export declare function writeProtocolStoreKey<T>(store: string, key: string, data: T): Promise<void>;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { db } from "../lib/db.js";
|
|
4
|
+
const ROOT_KEY = "__root__";
|
|
5
|
+
const SAFE_STORE_NAME = /^[a-z0-9_-]{1,64}$/;
|
|
6
|
+
const LEGACY_DIR = path.join(process.cwd(), "data", "protocol");
|
|
7
|
+
function assertSafeStoreName(name) {
|
|
8
|
+
if (!SAFE_STORE_NAME.test(name)) {
|
|
9
|
+
throw new Error(`Invalid protocol store name: ${name}`);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function readKv(store, key) {
|
|
13
|
+
const row = db
|
|
14
|
+
.prepare("SELECT value FROM protocol_kv WHERE store = ? AND key = ?")
|
|
15
|
+
.get(store, key);
|
|
16
|
+
if (!row)
|
|
17
|
+
return null;
|
|
18
|
+
return JSON.parse(row.value);
|
|
19
|
+
}
|
|
20
|
+
function writeKv(store, key, data) {
|
|
21
|
+
db.prepare("INSERT OR REPLACE INTO protocol_kv (store, key, value, updated_at) VALUES (?, ?, ?, unixepoch())").run(store, key, JSON.stringify(data));
|
|
22
|
+
}
|
|
23
|
+
async function migrateLegacyFile(name) {
|
|
24
|
+
const file = path.join(LEGACY_DIR, `${name}.json`);
|
|
25
|
+
try {
|
|
26
|
+
return JSON.parse(await readFile(file, "utf8"));
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export async function readProtocolStore(name, fallback) {
|
|
33
|
+
assertSafeStoreName(name);
|
|
34
|
+
const hit = readKv(name, ROOT_KEY);
|
|
35
|
+
if (hit != null)
|
|
36
|
+
return hit;
|
|
37
|
+
const legacy = await migrateLegacyFile(name);
|
|
38
|
+
if (legacy != null) {
|
|
39
|
+
writeKv(name, ROOT_KEY, legacy);
|
|
40
|
+
return legacy;
|
|
41
|
+
}
|
|
42
|
+
return fallback;
|
|
43
|
+
}
|
|
44
|
+
export async function writeProtocolStore(name, data) {
|
|
45
|
+
assertSafeStoreName(name);
|
|
46
|
+
writeKv(name, ROOT_KEY, data);
|
|
47
|
+
}
|
|
48
|
+
/** Per-agent keyed store (e.g. credit-bureau history by agentId). */
|
|
49
|
+
export async function readProtocolStoreKey(store, key, fallback) {
|
|
50
|
+
assertSafeStoreName(store);
|
|
51
|
+
const hit = readKv(store, key);
|
|
52
|
+
if (hit != null)
|
|
53
|
+
return hit;
|
|
54
|
+
return fallback;
|
|
55
|
+
}
|
|
56
|
+
export async function writeProtocolStoreKey(store, key, data) {
|
|
57
|
+
assertSafeStoreName(store);
|
|
58
|
+
writeKv(store, key, data);
|
|
59
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type ThreatSurface = {
|
|
2
|
+
id: string;
|
|
3
|
+
layer: string;
|
|
4
|
+
threat: string;
|
|
5
|
+
mitigations: string[];
|
|
6
|
+
residualRisk: "low" | "medium" | "high";
|
|
7
|
+
};
|
|
8
|
+
export declare const THREAT_CATALOG: ThreatSurface[];
|
|
9
|
+
export declare function getThreatModel(): {
|
|
10
|
+
version: string;
|
|
11
|
+
surfaces: ThreatSurface[];
|
|
12
|
+
attackCategories: string[];
|
|
13
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
export const THREAT_CATALOG = [
|
|
2
|
+
{
|
|
3
|
+
id: "T-REPLAY-01",
|
|
4
|
+
layer: "Settlement",
|
|
5
|
+
threat: "Payment signature replay on different resource URL",
|
|
6
|
+
mitigations: ["replay-bindings", "resourceHash", "nonce consumption", "idempotency-key"],
|
|
7
|
+
residualRisk: "low",
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
id: "T-SYBIL-01",
|
|
11
|
+
layer: "Identity",
|
|
12
|
+
threat: "Wallet farming / reputation farming",
|
|
13
|
+
mitigations: ["erc8004-registration", "trustscore-v2-history", "fraud-graph-clusters"],
|
|
14
|
+
residualRisk: "medium",
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
id: "T-WASH-01",
|
|
18
|
+
layer: "Fraud",
|
|
19
|
+
threat: "Wash trading volume inflation",
|
|
20
|
+
mitigations: ["merchant-trust-score", "fraud-scan", "bond-slash"],
|
|
21
|
+
residualRisk: "medium",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: "T-MCP-01",
|
|
25
|
+
layer: "Agent",
|
|
26
|
+
threat: "Tool poisoning / prompt injection via MCP",
|
|
27
|
+
mitigations: ["mandate-diff", "reasoning-audit-merkle", "guard-allowedHosts"],
|
|
28
|
+
residualRisk: "medium",
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
id: "T-ESCROW-01",
|
|
32
|
+
layer: "Escrow",
|
|
33
|
+
threat: "Escrow bypass / race on state transition",
|
|
34
|
+
mitigations: ["escrow-fsm-valid-transitions", "stateProof-hmac", "semantic-settle"],
|
|
35
|
+
residualRisk: "low",
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
id: "T-ORACLE-01",
|
|
39
|
+
layer: "Trust",
|
|
40
|
+
threat: "Centralized trust manipulation",
|
|
41
|
+
mitigations: ["trust-oracle-quorum", "multi-oracle-consensus", "slashing-note"],
|
|
42
|
+
residualRisk: "medium",
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
id: "T-PII-01",
|
|
46
|
+
layer: "Compliance",
|
|
47
|
+
threat: "PII leakage in audit logs",
|
|
48
|
+
mitigations: ["prompt-hashes-only", "zk-selective-disclosure", "evidence-locker-org-scope"],
|
|
49
|
+
residualRisk: "low",
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: "T-DOS-01",
|
|
53
|
+
layer: "API",
|
|
54
|
+
threat: "Rate limit exhaustion / unpaid probe abuse",
|
|
55
|
+
mitigations: ["rate-limit-unpaid", "rate-limit-per-min", "402-on-paid-routes"],
|
|
56
|
+
residualRisk: "low",
|
|
57
|
+
},
|
|
58
|
+
];
|
|
59
|
+
export function getThreatModel() {
|
|
60
|
+
return {
|
|
61
|
+
version: "4.0.0",
|
|
62
|
+
surfaces: THREAT_CATALOG,
|
|
63
|
+
attackCategories: [
|
|
64
|
+
"replay",
|
|
65
|
+
"sybil",
|
|
66
|
+
"wash_trading",
|
|
67
|
+
"prompt_injection",
|
|
68
|
+
"tool_poisoning",
|
|
69
|
+
"escrow_bypass",
|
|
70
|
+
"oracle_manipulation",
|
|
71
|
+
"settlement_exploit",
|
|
72
|
+
"pii_exposure",
|
|
73
|
+
],
|
|
74
|
+
};
|
|
75
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type OracleVerifyInput = {
|
|
2
|
+
subjectType: "agent" | "merchant" | "receipt";
|
|
3
|
+
subjectId: string;
|
|
4
|
+
claims: Record<string, unknown>;
|
|
5
|
+
minQuorum?: number;
|
|
6
|
+
};
|
|
7
|
+
export type OracleConsensusResult = {
|
|
8
|
+
consensus: boolean;
|
|
9
|
+
quorum: number;
|
|
10
|
+
votes: Array<{
|
|
11
|
+
oracleId: string;
|
|
12
|
+
approve: boolean;
|
|
13
|
+
stake: number;
|
|
14
|
+
reason: string;
|
|
15
|
+
}>;
|
|
16
|
+
byzantineFaultTolerance: string;
|
|
17
|
+
slashingNote: string;
|
|
18
|
+
proof: {
|
|
19
|
+
digest: string;
|
|
20
|
+
signature: string;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
export declare function runTrustOracleConsensus(input: OracleVerifyInput): Promise<OracleConsensusResult>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { hmacSign, sha256Hex } from "./crypto.js";
|
|
2
|
+
const ORACLES = ["oracle-a", "oracle-b", "oracle-c", "oracle-d"];
|
|
3
|
+
function oracleVote(oracleId, claims) {
|
|
4
|
+
const blob = JSON.stringify({ oracleId, claims });
|
|
5
|
+
const hash = sha256Hex(blob);
|
|
6
|
+
const n = parseInt(hash.slice(0, 8), 16);
|
|
7
|
+
const trustClaim = Number(claims.trustScore ?? claims.score ?? 50);
|
|
8
|
+
const approve = trustClaim >= 40 && n % 7 !== 0;
|
|
9
|
+
return {
|
|
10
|
+
oracleId,
|
|
11
|
+
approve,
|
|
12
|
+
stake: 100 + (n % 50),
|
|
13
|
+
reason: approve ? "claims within policy" : "claims failed quorum policy",
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export async function runTrustOracleConsensus(input) {
|
|
17
|
+
const quorum = input.minQuorum ?? 3;
|
|
18
|
+
const votes = ORACLES.map((id) => oracleVote(id, input.claims));
|
|
19
|
+
const approvals = votes.filter((v) => v.approve).length;
|
|
20
|
+
const consensus = approvals >= quorum;
|
|
21
|
+
const digest = sha256Hex(JSON.stringify({ subjectId: input.subjectId, approvals, votes: votes.map((v) => v.oracleId) }));
|
|
22
|
+
return {
|
|
23
|
+
consensus,
|
|
24
|
+
quorum,
|
|
25
|
+
votes,
|
|
26
|
+
byzantineFaultTolerance: "tolerates f=1 faulty oracle of 4 (simulated BFT quorum)",
|
|
27
|
+
slashingNote: "Production: misbehaving oracles lose stake on divergence from on-chain anchor receipts",
|
|
28
|
+
proof: { digest, signature: hmacSign(digest) },
|
|
29
|
+
};
|
|
30
|
+
}
|