twzrd-x402-gate 0.8.6 → 0.8.7
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/bin/twzrd-gate-eval-refuse.js +193 -0
- package/package.json +6 -3
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Buyer protection loop — refuse transcript (no USDC when block fires).
|
|
4
|
+
*
|
|
5
|
+
* Success (north-star fields):
|
|
6
|
+
* target_url, pay_to, twzrd_decision, twzrd_reason,
|
|
7
|
+
* signer_invocation_count (=0), payment_retry_count (=0)
|
|
8
|
+
*
|
|
9
|
+
* Does NOT increment intel day0.gate_evals (that counter is Path B settle-gate).
|
|
10
|
+
*
|
|
11
|
+
* Usage (after npm install of this package + @x402/* peers):
|
|
12
|
+
* node node_modules/twzrd-x402-gate/bin/twzrd-gate-eval-refuse.js
|
|
13
|
+
*/
|
|
14
|
+
import { createRequire } from "node:module";
|
|
15
|
+
import { dirname, join } from "node:path";
|
|
16
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
17
|
+
import { existsSync } from "node:fs";
|
|
18
|
+
|
|
19
|
+
const TARGET_URL = "https://three.ws/api/x402/model-check";
|
|
20
|
+
const EXPECT_PAYTO = "wwwwwDxFWRn7grgr3Esrsg5C6NvDoDHSA4gaCffccrU";
|
|
21
|
+
const NETWORK = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp";
|
|
22
|
+
const USDC = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
|
|
23
|
+
const INTEL_PREFLIGHT = "https://intel.twzrd.xyz/v1/intel/preflight";
|
|
24
|
+
const SIGNER_SPY_STOP = "TWZRD_SIGNER_SPY_STOP_BEFORE_SIGNATURE";
|
|
25
|
+
|
|
26
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
27
|
+
const pkgRoot = join(__dirname, "..");
|
|
28
|
+
const require = createRequire(import.meta.url);
|
|
29
|
+
|
|
30
|
+
function resolveImport(spec) {
|
|
31
|
+
try {
|
|
32
|
+
return require.resolve(spec);
|
|
33
|
+
} catch {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function loadHook() {
|
|
39
|
+
const dist = join(pkgRoot, "dist", "x402-client-hook.js");
|
|
40
|
+
const src = join(pkgRoot, "src", "x402-client-hook.ts");
|
|
41
|
+
if (existsSync(dist)) {
|
|
42
|
+
return import(pathToFileURL(dist).href);
|
|
43
|
+
}
|
|
44
|
+
if (existsSync(src)) {
|
|
45
|
+
// Dev checkout: prefer compiled; otherwise dynamic tsx is out of scope for bin.
|
|
46
|
+
console.error(
|
|
47
|
+
"twzrd-gate-eval-refuse: run `npm run build` in twzrd-x402-gate or install the published package",
|
|
48
|
+
);
|
|
49
|
+
process.exit(2);
|
|
50
|
+
}
|
|
51
|
+
console.error("twzrd-gate-eval-refuse: package dist missing");
|
|
52
|
+
process.exit(2);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function immediatePreflight() {
|
|
56
|
+
const res = await fetch(INTEL_PREFLIGHT, {
|
|
57
|
+
method: "POST",
|
|
58
|
+
headers: { "content-type": "application/json" },
|
|
59
|
+
body: JSON.stringify({
|
|
60
|
+
seller_wallet: EXPECT_PAYTO,
|
|
61
|
+
price_usdc: 0.001,
|
|
62
|
+
}),
|
|
63
|
+
});
|
|
64
|
+
if (!res.ok) {
|
|
65
|
+
throw new Error(`preflight HTTP ${res.status}`);
|
|
66
|
+
}
|
|
67
|
+
const body = await res.json();
|
|
68
|
+
const card = body.readiness_card ?? body;
|
|
69
|
+
if (card.decision !== "block" || card.can_spend !== false) {
|
|
70
|
+
throw new Error(
|
|
71
|
+
`refuse fixture drifted: expected block/can_spend=false, got ${card.decision}/${card.can_spend}`,
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
return card;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async function main() {
|
|
78
|
+
for (const pkg of ["@x402/core", "@x402/fetch", "@x402/svm", "@solana/kit"]) {
|
|
79
|
+
if (!resolveImport(pkg)) {
|
|
80
|
+
console.error(
|
|
81
|
+
`twzrd-gate-eval-refuse: missing peer ${pkg}. Run:\n` +
|
|
82
|
+
` npm install twzrd-x402-gate@0.8.6 @x402/core @x402/fetch @x402/svm @solana/kit @scure/base`,
|
|
83
|
+
);
|
|
84
|
+
process.exit(2);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const preflight = await immediatePreflight();
|
|
89
|
+
|
|
90
|
+
const { generateKeyPairSigner } = await import("@solana/kit");
|
|
91
|
+
const { x402Client } = await import("@x402/core/client");
|
|
92
|
+
const { wrapFetchWithPayment } = await import("@x402/fetch");
|
|
93
|
+
const { ExactSvmScheme } = await import("@x402/svm/exact/client");
|
|
94
|
+
const { installTwzrdX402ClientHook } = await loadHook();
|
|
95
|
+
|
|
96
|
+
const ephemeral = await generateKeyPairSigner();
|
|
97
|
+
let signerInvocationCount = 0;
|
|
98
|
+
let paymentRetryCount = 0;
|
|
99
|
+
let gateDecision = null;
|
|
100
|
+
|
|
101
|
+
const signerSpy = {
|
|
102
|
+
address: ephemeral.address,
|
|
103
|
+
async signTransactions() {
|
|
104
|
+
signerInvocationCount += 1;
|
|
105
|
+
throw new Error(SIGNER_SPY_STOP);
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const observedFetch = async (input, init) => {
|
|
110
|
+
const headers = new Headers(init?.headers);
|
|
111
|
+
if (
|
|
112
|
+
headers.has("payment-signature") ||
|
|
113
|
+
headers.has("x-payment") ||
|
|
114
|
+
headers.has("payment")
|
|
115
|
+
) {
|
|
116
|
+
paymentRetryCount += 1;
|
|
117
|
+
}
|
|
118
|
+
return fetch(input, init);
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const client = new x402Client();
|
|
122
|
+
client.register(NETWORK, new ExactSvmScheme(signerSpy));
|
|
123
|
+
|
|
124
|
+
client.onBeforePaymentCreation(async ({ selectedRequirements: selected }) => {
|
|
125
|
+
const mismatch =
|
|
126
|
+
selected.payTo !== EXPECT_PAYTO ||
|
|
127
|
+
selected.asset !== USDC ||
|
|
128
|
+
selected.network !== NETWORK;
|
|
129
|
+
if (mismatch) {
|
|
130
|
+
return { abort: true, reason: "fixture mismatch" };
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
installTwzrdX402ClientHook(client, {
|
|
135
|
+
failOpen: false,
|
|
136
|
+
gateOnCanSpend: true,
|
|
137
|
+
refuseWashFlagged: true,
|
|
138
|
+
preflightMinScore: 40,
|
|
139
|
+
onDecision(detail) {
|
|
140
|
+
gateDecision = { ...detail };
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
const payingFetch = wrapFetchWithPayment(observedFetch, client);
|
|
145
|
+
let observedError = null;
|
|
146
|
+
try {
|
|
147
|
+
await payingFetch(TARGET_URL, { method: "GET" });
|
|
148
|
+
} catch (e) {
|
|
149
|
+
observedError = e instanceof Error ? e.message : String(e);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const approved = gateDecision?.approved === true;
|
|
153
|
+
const blocked =
|
|
154
|
+
approved === false &&
|
|
155
|
+
signerInvocationCount === 0 &&
|
|
156
|
+
Boolean(observedError?.match(/twzrd|abort|can_spend|wash|block/i));
|
|
157
|
+
|
|
158
|
+
const report = {
|
|
159
|
+
schema: "twzrd.gate_eval_refuse.v1",
|
|
160
|
+
lineage: "self_serve_handoff_command",
|
|
161
|
+
closes_external_adoption_metric: false,
|
|
162
|
+
note: "Buyer refuse transcript. day0.gate_evals is settle-gate only — not this path.",
|
|
163
|
+
target_url: TARGET_URL,
|
|
164
|
+
pay_to: EXPECT_PAYTO,
|
|
165
|
+
twzrd_decision: gateDecision?.verdict ?? null,
|
|
166
|
+
twzrd_reason: gateDecision?.reason ?? null,
|
|
167
|
+
signer_invocation_count: signerInvocationCount,
|
|
168
|
+
payment_retry_count: paymentRetryCount,
|
|
169
|
+
usdc_spent: 0,
|
|
170
|
+
preflight_immediately_before_run: {
|
|
171
|
+
decision: preflight.decision,
|
|
172
|
+
can_spend: preflight.can_spend,
|
|
173
|
+
},
|
|
174
|
+
observed_error: observedError,
|
|
175
|
+
verified: blocked,
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
console.log("=== FINAL REPORT ===");
|
|
179
|
+
console.log(JSON.stringify(report, null, 2));
|
|
180
|
+
|
|
181
|
+
if (!report.verified) {
|
|
182
|
+
console.error("FAIL: expected hard block with signer_invocation_count=0");
|
|
183
|
+
process.exit(1);
|
|
184
|
+
}
|
|
185
|
+
console.error(
|
|
186
|
+
"OK: refuse transcript green (internal self-serve command — not external partner proof)",
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
main().catch((e) => {
|
|
191
|
+
console.error("twzrd-gate-eval-refuse FAILED", e);
|
|
192
|
+
process.exit(1);
|
|
193
|
+
});
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "twzrd-x402-gate",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.7",
|
|
4
4
|
"description": "Core: buyer-side x402 trust gate. Free TWZRD preflight (ReadinessCard) before signing USDC to any merchant, with optional $0.001 paid trust escalate on warn \u2014 blocking spend on bad intel, no human in the loop. Optional: createTwzrdSettleGuard for resource servers to apply merchant policy on the payer before settle+serve. installTwzrdAutoGate is the canonical default-on entry across fetch payWrap, x402 client (onBeforePaymentCreation), and MPP onChallenge. Fail-closed by default \u2014 set TWZRD_FAIL_OPEN=true for outage allow; kill switch TWZRD_GATE_ENABLED=false or TWZRD_AUTO_GATE=0. Always stamps X-Twzrd-Caller for seat metrics.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
8
8
|
"bin": {
|
|
9
|
-
"twzrd-safe-fetch": "./bin/twzrd-safe-fetch.js"
|
|
9
|
+
"twzrd-safe-fetch": "./bin/twzrd-safe-fetch.js",
|
|
10
|
+
"twzrd-gate-eval-refuse": "./bin/twzrd-gate-eval-refuse.js"
|
|
10
11
|
},
|
|
11
12
|
"exports": {
|
|
12
13
|
".": {
|
|
@@ -38,7 +39,9 @@
|
|
|
38
39
|
"autogate-block-proof": "tsx examples/autogate-block-proof.ts",
|
|
39
40
|
"official-dogfood": "tsx examples/official-x402-dogfood.ts",
|
|
40
41
|
"adoption-proof": "tsx src/adoption-proof.ts",
|
|
41
|
-
"demo:buyer-no-spend": "tsx src/adoption-proof.ts -- --integration ops-demo-buyer-no-spend"
|
|
42
|
+
"demo:buyer-no-spend": "tsx src/adoption-proof.ts -- --integration ops-demo-buyer-no-spend",
|
|
43
|
+
"live-autogate-matrix": "tsx examples/live-autogate-matrix.ts",
|
|
44
|
+
"gate-eval-refuse": "node bin/twzrd-gate-eval-refuse.js"
|
|
42
45
|
},
|
|
43
46
|
"keywords": [
|
|
44
47
|
"x402",
|