twzrd-x402-gate 0.8.8 → 0.8.10

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/QUICKSTART.md ADDED
@@ -0,0 +1,61 @@
1
+ # twzrd-x402-gate — Quickstart (15 minutes, 0 USDC)
2
+
3
+ Refuses payment to a wash-flagged merchant **before your wallet signs**. Free intel, no
4
+ API key, no signup, no config — every `TWZRD_*` env var is an optional override. If intel
5
+ is unreachable the gate never *invents* a wash flag (the wash check fails open); a failed
6
+ preflight blocks the payment by default (`TWZRD_FAIL_OPEN=true` to allow).
7
+
8
+ ## 1. Install + gate your client (5 lines)
9
+
10
+ ```bash
11
+ npm install twzrd-x402-gate@0.8.10 @x402/core @x402/fetch @x402/svm
12
+ ```
13
+
14
+ ```typescript
15
+ import { x402Client } from "@x402/core/client";
16
+ import { installTwzrdAutoGate } from "twzrd-x402-gate";
17
+
18
+ const client = new x402Client();
19
+ // refuseWashFlagged defaults true; gateOnCanSpend stays false unless you opt in
20
+ installTwzrdAutoGate(client, { refuseWashFlagged: true });
21
+ // then register schemes + wrapFetchWithPayment as usual
22
+ ```
23
+
24
+ ## 2. Prove it blocked something (spends nothing)
25
+
26
+ ```bash
27
+ npm run autogate-block-proof
28
+ # preflights a live wash_flagged seller; the gate aborts before any signer runs
29
+ # writes block-proof-<run_id>.json — reason: TWZRD_TRUST_GATE_BLOCK: wash_flagged
30
+ ```
31
+
32
+ That JSON is your receipt: a bad merchant intercepted with 0 USDC at risk.
33
+
34
+ ## 3. See your own seat
35
+
36
+ Every preflight is stamped `X-Twzrd-Caller: twzrd-x402-gate/<version>` — your seat
37
+ identity in TWZRD's metrics. To make runs attributable to *you* (recommended):
38
+
39
+ ```typescript
40
+ installTwzrdAutoGate(client, {
41
+ refuseWashFlagged: true,
42
+ attribution: { integration: "<your-host-or-project>", runId: "<uuid-per-run>" },
43
+ });
44
+ ```
45
+
46
+ ## 4. The only three knobs you need
47
+
48
+ | Knob | Effect |
49
+ |------|--------|
50
+ | `TWZRD_AUTO_GATE=0` | Kill switch — gate fully off, payments proceed unguarded |
51
+ | `refuseWashFlagged: false` | Stop refusing wash-flagged merchants (default `true`) |
52
+ | `gateOnCanSpend: true` | Opt-in hard cap: also block when `can_spend=false` (default `false`) |
53
+
54
+ Everything else (thresholds, wash caps, fail posture, settle guard): [README](./README.md).
55
+
56
+ ## What this will NOT do
57
+
58
+ - **No Base/EVM reputation.** Non-Solana networks get an explicit `unknown` (payment
59
+ allowed, observed) unless you set `TWZRD_UNSUPPORTED_NETWORK_MODE=strict`.
60
+ - **No delivery guarantee.** It screens the merchant before you pay, nothing after.
61
+ - **Not a wallet.** It never holds keys or signs — it only decides if your signer runs.
package/README.md CHANGED
@@ -10,7 +10,7 @@ refuse. Protects the **payer** from a risky **merchant** (`payTo`). Chain-neutra
10
10
  ### Default-on AutoGate (5 lines)
11
11
 
12
12
  ```bash
13
- npm install twzrd-x402-gate@0.8.6 @x402/core @x402/fetch @x402/svm
13
+ npm install twzrd-x402-gate@0.8.10 @x402/core @x402/fetch @x402/svm
14
14
  ```
15
15
 
16
16
  ```typescript
@@ -49,7 +49,7 @@ transfer on-chain. Wash/sybil edges are primarily discounted in TWZRD scoring, n
49
49
  revenue refusal.
50
50
 
51
51
  ```bash
52
- npm install twzrd-x402-gate@0.8.6
52
+ npm install twzrd-x402-gate@0.8.10
53
53
  ```
54
54
 
55
55
  ```typescript
@@ -93,7 +93,7 @@ Fixture-backed SVM extract tests live in `test/seller-hook.test.ts` +
93
93
  Install the published gate and run against wash fixtures:
94
94
 
95
95
  ```bash
96
- npm install twzrd-x402-gate@0.8.6
96
+ npm install twzrd-x402-gate@0.8.10
97
97
  # from package root after install, or from a checkout:
98
98
  npm run wash-dogfood
99
99
  ```
@@ -238,10 +238,10 @@ Dogfood (one public live proof path):
238
238
  ## Install
239
239
 
240
240
  ```bash
241
- npm install twzrd-x402-gate@0.8.6
241
+ npm install twzrd-x402-gate@0.8.10
242
242
  ```
243
243
 
244
- Current npm truth: `0.8.5` (buyer gate + optional seller settle guard + payer-extract hardening).
244
+ Current npm truth: `0.8.10` (buyer gate + optional seller settle guard + payer-extract hardening).
245
245
  Check `npm view twzrd-x402-gate version` if in doubt (do not pin stale **0.5.4** / **0.7.1**).
246
246
 
247
247
  Optional settle guard (resource-server **payer** policy): see **Seller settle guard
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Publishable bin for twzrd-gate-doctor.
4
+ * Prefers compiled dist; falls back to tsx source in dev checkouts.
5
+ * Mirrors bin/twzrd-safe-fetch.js so packaging behaves identically.
6
+ */
7
+ import { spawnSync } from "node:child_process";
8
+ import { existsSync } from "node:fs";
9
+ import { dirname, join } from "node:path";
10
+ import { fileURLToPath, pathToFileURL } from "node:url";
11
+
12
+ const __dirname = dirname(fileURLToPath(import.meta.url));
13
+ const root = join(__dirname, "..");
14
+ const dist = join(root, "dist", "doctor.js");
15
+ const src = join(root, "src", "doctor.ts");
16
+
17
+ if (existsSync(dist)) {
18
+ await import(pathToFileURL(dist).href);
19
+ } else if (existsSync(src)) {
20
+ // Do NOT set cwd to the package root here (unlike twzrd-safe-fetch): the
21
+ // doctor inspects process.cwd() to find the OPERATOR's package.json. Running
22
+ // it from the package root made it read our own manifest and report a
23
+ // signing surface for every project, including ones with nothing to gate.
24
+ // tsx resolves `src` by absolute path, so the user's cwd is safe to keep.
25
+ const r = spawnSync("npx", ["--yes", "tsx", src, ...process.argv.slice(2)], {
26
+ stdio: "inherit",
27
+ });
28
+ process.exit(r.status ?? 1);
29
+ } else {
30
+ console.error(
31
+ "twzrd-gate-doctor: missing dist/doctor.js — run npm run build in twzrd-x402-gate",
32
+ );
33
+ process.exit(1);
34
+ }
@@ -16,8 +16,9 @@ import { dirname, join } from "node:path";
16
16
  import { fileURLToPath, pathToFileURL } from "node:url";
17
17
  import { existsSync } from "node:fs";
18
18
 
19
- const TARGET_URL = "https://three.ws/api/x402/model-check";
20
- const EXPECT_PAYTO = "wwwwwDxFWRn7grgr3Esrsg5C6NvDoDHSA4gaCffccrU";
19
+ // Owned TWZRD refuse dogfood (not a third-party brand). Live 402 + force hard-block.
20
+ const TARGET_URL = "https://intel.twzrd.xyz/v1/intel/refuse-fixture";
21
+ const EXPECT_PAYTO = "CnTmHDXVEafkc8sFSzNky9w5zwk63Bk2mHZZodorjhvR";
21
22
  const NETWORK = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp";
22
23
  const USDC = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
23
24
  const INTEL_PREFLIGHT = "https://intel.twzrd.xyz/v1/intel/preflight";
@@ -79,7 +80,7 @@ async function main() {
79
80
  if (!resolveImport(pkg)) {
80
81
  console.error(
81
82
  `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
+ ` npm install twzrd-x402-gate@0.8.10 @x402/core @x402/fetch @x402/svm @solana/kit @scure/base`,
83
84
  );
84
85
  process.exit(2);
85
86
  }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * `npx twzrd-gate-doctor` — one command that turns "should I gate this?" into
3
+ * "here are the exact lines for THIS project, and here is the gate refusing."
4
+ *
5
+ * Why a doctor and not a codemod: patching someone else's source is invasive,
6
+ * hard to review, and the first thing an operator reverts. The adoption blocker
7
+ * is not typing three lines — it is not knowing WHICH three lines apply to the
8
+ * client you already use, and not believing the gate actually refuses anything.
9
+ * So this does exactly two things:
10
+ *
11
+ * 1. DETECT the x402 / agent surface already in package.json and print the
12
+ * snippet for that specific host (not a generic README excerpt).
13
+ * 2. PROVE a refusal, offline, spending nothing: a wash-flagged verdict is fed
14
+ * to the real hook and we assert the signer was never invoked.
15
+ *
16
+ * Exit codes: 0 = a seam was found and the refusal proof passed. 1 = proof
17
+ * failed (a real problem — report it). 2 = no x402 surface detected (nothing to
18
+ * gate here yet, not an error).
19
+ *
20
+ * No network by default: the refusal proof is deterministic and local, so it
21
+ * works in CI and on a plane. Pass --live to additionally preflight a real
22
+ * wash-flagged seller against intel.
23
+ */
24
+ type Host = {
25
+ id: string;
26
+ label: string;
27
+ /** Any of these dependency names present ⇒ this host applies. */
28
+ deps: string[];
29
+ install: string;
30
+ snippet: string;
31
+ note?: string;
32
+ };
33
+ export declare function detectHosts(pkg: Record<string, unknown> | null): Host[];
34
+ /**
35
+ * Deterministic, offline refusal proof.
36
+ *
37
+ * Feeds a wash-flagged card straight to the policy layer and asserts the signer
38
+ * never ran. This is the claim an operator needs to believe before adopting,
39
+ * and it must be checkable without spending or reaching the network.
40
+ */
41
+ export declare function proveRefusal(): Promise<{
42
+ refused: boolean;
43
+ signerInvocations: number;
44
+ reason: string;
45
+ }>;
46
+ export declare function main(argv?: string[]): Promise<number>;
47
+ export {};
48
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAOH,KAAK,IAAI,GAAG;IACV,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AA4EF,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,IAAI,EAAE,CASvE;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC;IAC5C,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC,CAuED;AAMD,wBAAsB,IAAI,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAAC,MAAM,CAAC,CAwDlF"}
package/dist/doctor.js ADDED
@@ -0,0 +1,246 @@
1
+ /**
2
+ * `npx twzrd-gate-doctor` — one command that turns "should I gate this?" into
3
+ * "here are the exact lines for THIS project, and here is the gate refusing."
4
+ *
5
+ * Why a doctor and not a codemod: patching someone else's source is invasive,
6
+ * hard to review, and the first thing an operator reverts. The adoption blocker
7
+ * is not typing three lines — it is not knowing WHICH three lines apply to the
8
+ * client you already use, and not believing the gate actually refuses anything.
9
+ * So this does exactly two things:
10
+ *
11
+ * 1. DETECT the x402 / agent surface already in package.json and print the
12
+ * snippet for that specific host (not a generic README excerpt).
13
+ * 2. PROVE a refusal, offline, spending nothing: a wash-flagged verdict is fed
14
+ * to the real hook and we assert the signer was never invoked.
15
+ *
16
+ * Exit codes: 0 = a seam was found and the refusal proof passed. 1 = proof
17
+ * failed (a real problem — report it). 2 = no x402 surface detected (nothing to
18
+ * gate here yet, not an error).
19
+ *
20
+ * No network by default: the refusal proof is deterministic and local, so it
21
+ * works in CI and on a plane. Pass --live to additionally preflight a real
22
+ * wash-flagged seller against intel.
23
+ */
24
+ import { readFileSync } from "node:fs";
25
+ import { join } from "node:path";
26
+ import { CLIENT_VERSION } from "./version.js";
27
+ /**
28
+ * Ordered most-specific first: a project using solana-agent-kit AND @x402/core
29
+ * should be told about the SAK seat, because that is where its signing happens.
30
+ */
31
+ const HOSTS = [
32
+ {
33
+ id: "solana-agent-kit",
34
+ label: "Solana Agent Kit (SolanaAgentKit)",
35
+ deps: ["solana-agent-kit"],
36
+ install: "npm install twzrd-x402-gate",
37
+ snippet: `import { SolanaAgentKit } from "solana-agent-kit";
38
+ import { twzrdBeforeSign } from "twzrd-x402-gate";
39
+
40
+ // Every plugin that signs goes through this policy, including plugins that
41
+ // call agent.wallet.signAndSendTransaction directly.
42
+ const agent = new SolanaAgentKit(wallet, rpcUrl, {
43
+ beforeSign: twzrdBeforeSign({ refuseWashFlagged: true }),
44
+ });`,
45
+ note: "Requires the optional beforeSign hook on Config (sendaifun/solana-agent-kit#599). " +
46
+ "Until that lands, wrap the wallet yourself with wrapWallet() from that PR.",
47
+ },
48
+ {
49
+ id: "x402-client",
50
+ label: "official x402 client (@x402/core)",
51
+ deps: ["@x402/core", "@x402/fetch", "@x402/svm"],
52
+ install: "npm install twzrd-x402-gate @x402/core @x402/fetch @x402/svm",
53
+ snippet: `import { x402Client } from "@x402/core/client";
54
+ import { installTwzrdAutoGate } from "twzrd-x402-gate";
55
+
56
+ const client = new x402Client();
57
+ // Runs after requirement selection, BEFORE payload creation / signing.
58
+ installTwzrdAutoGate(client, { refuseWashFlagged: true });`,
59
+ },
60
+ {
61
+ id: "elizaos",
62
+ label: "elizaOS agent runtime",
63
+ deps: ["@elizaos/core", "elizaos"],
64
+ install: "npm install twzrd-x402-gate",
65
+ snippet: `import { installTwzrdAutoGate } from "twzrd-x402-gate";
66
+
67
+ // Gate the payment client your plugin hands to the runtime, not the runtime
68
+ // itself — the seam is wherever the signer lives.
69
+ installTwzrdAutoGate(paymentClient, { refuseWashFlagged: true });`,
70
+ },
71
+ {
72
+ id: "goat",
73
+ label: "GOAT SDK",
74
+ deps: ["@goat-sdk/core"],
75
+ install: "npm install twzrd-x402-gate",
76
+ snippet: `import { installTwzrdAutoGate } from "twzrd-x402-gate";
77
+
78
+ installTwzrdAutoGate(walletClient, { refuseWashFlagged: true });`,
79
+ },
80
+ {
81
+ id: "raw-fetch",
82
+ label: "raw fetch + x402 payer",
83
+ deps: ["x402-fetch", "x402"],
84
+ install: "npm install twzrd-x402-gate",
85
+ snippet: `import { installTwzrdAutoGate } from "twzrd-x402-gate";
86
+
87
+ // Wraps fetch: a refused payment never reaches the payer.
88
+ const gatedFetch = installTwzrdAutoGate(payFetch, { refuseWashFlagged: true });`,
89
+ },
90
+ ];
91
+ function readPackageJson(cwd) {
92
+ try {
93
+ return JSON.parse(readFileSync(join(cwd, "package.json"), "utf8"));
94
+ }
95
+ catch {
96
+ return null;
97
+ }
98
+ }
99
+ export function detectHosts(pkg) {
100
+ if (!pkg)
101
+ return [];
102
+ const all = {
103
+ ...(pkg.dependencies ?? {}),
104
+ ...(pkg.devDependencies ?? {}),
105
+ ...(pkg.peerDependencies ?? {}),
106
+ };
107
+ const names = new Set(Object.keys(all));
108
+ return HOSTS.filter((h) => h.deps.some((d) => names.has(d)));
109
+ }
110
+ /**
111
+ * Deterministic, offline refusal proof.
112
+ *
113
+ * Feeds a wash-flagged card straight to the policy layer and asserts the signer
114
+ * never ran. This is the claim an operator needs to believe before adopting,
115
+ * and it must be checkable without spending or reaching the network.
116
+ */
117
+ export async function proveRefusal() {
118
+ const { installTwzrdAutoGate } = await import("./auto-gate.js");
119
+ // Model the official-client seam, which is the path with existing coverage
120
+ // (see test/autogate-intercept.test.ts). A wash-flagged card must come back
121
+ // as abort, and the signer stub must never be reached.
122
+ let signerInvocations = 0;
123
+ let hook;
124
+ const client = {
125
+ onBeforePaymentCreation(h) {
126
+ hook = h;
127
+ return client;
128
+ },
129
+ };
130
+ installTwzrdAutoGate(client, {
131
+ refuseWashFlagged: true,
132
+ gateOnCanSpend: false,
133
+ preflightMinScore: 0,
134
+ failOpen: true,
135
+ // Injected preflight response: wash_flagged ⇒ the policy must refuse. No network.
136
+ fetch: (async () => new Response(JSON.stringify({
137
+ readiness_card: {
138
+ decision: "block",
139
+ trust_score: 30,
140
+ can_spend: false,
141
+ wash_flagged: true,
142
+ wash_label: "ring",
143
+ },
144
+ }), { status: 200, headers: { "content-type": "application/json" } })),
145
+ });
146
+ if (!hook) {
147
+ return {
148
+ refused: false,
149
+ signerInvocations,
150
+ reason: "gate did not install a pre-payment hook",
151
+ };
152
+ }
153
+ let refused = false;
154
+ let reason = "";
155
+ try {
156
+ const out = await hook({
157
+ selectedRequirements: {
158
+ payTo: "34w53UkhfBBmVLBcphD1M4dRhbBTQaLLbnRfyTeXzc5m",
159
+ network: "solana",
160
+ asset: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
161
+ maxAmountRequired: "50000",
162
+ scheme: "exact",
163
+ },
164
+ // If the gate ever approved, a real client would call this next.
165
+ sign: async () => {
166
+ signerInvocations += 1;
167
+ },
168
+ });
169
+ if (out && typeof out === "object" && out.abort) {
170
+ refused = true;
171
+ reason = String(out.reason ?? "abort");
172
+ }
173
+ }
174
+ catch (err) {
175
+ // A throwing refusal is equally acceptable: nothing got signed.
176
+ refused = true;
177
+ reason = String(err?.message ?? err).slice(0, 160);
178
+ }
179
+ return { refused, signerInvocations, reason };
180
+ }
181
+ function line(s = "") {
182
+ process.stdout.write(`${s}\n`);
183
+ }
184
+ export async function main(argv = process.argv.slice(2)) {
185
+ const cwd = process.cwd();
186
+ const pkg = readPackageJson(cwd);
187
+ const detected = detectHosts(pkg);
188
+ line(`twzrd-gate-doctor (twzrd-x402-gate ${CLIENT_VERSION})`);
189
+ line();
190
+ if (!pkg) {
191
+ line("No package.json here. Run this from your project root.");
192
+ return 2;
193
+ }
194
+ if (detected.length === 0) {
195
+ line("No x402 / agent signing surface detected in this project.");
196
+ line("Nothing to gate yet — this is not an error.");
197
+ line();
198
+ line("The gate is useful once something here signs a Solana USDC payment.");
199
+ line("Surfaces it recognises: @x402/core, solana-agent-kit, @elizaos/core,");
200
+ line("@goat-sdk/core, x402-fetch.");
201
+ return 2;
202
+ }
203
+ line(`Detected ${detected.length} signing surface(s):`);
204
+ for (const h of detected)
205
+ line(` • ${h.label}`);
206
+ line();
207
+ for (const h of detected) {
208
+ line(`── ${h.label} ${"─".repeat(Math.max(0, 58 - h.label.length))}`);
209
+ line();
210
+ line(` ${h.install}`);
211
+ line();
212
+ for (const l of h.snippet.split("\n"))
213
+ line(` ${l}`);
214
+ if (h.note) {
215
+ line();
216
+ line(` Note: ${h.note}`);
217
+ }
218
+ line();
219
+ }
220
+ line("── Refusal proof (offline, spends nothing) ──────────────────");
221
+ line();
222
+ const proof = await proveRefusal();
223
+ if (proof.refused && proof.signerInvocations === 0) {
224
+ line(" PASS — wash-flagged seller refused before signing.");
225
+ line(` signer invocations: ${proof.signerInvocations}`);
226
+ line(` reason: ${proof.reason}`);
227
+ line();
228
+ line(" That is the whole product: the payment did not happen, and it cost 0.");
229
+ return 0;
230
+ }
231
+ line(" FAIL — the gate did NOT refuse a wash-flagged seller.");
232
+ line(` refused=${proof.refused} signer_invocations=${proof.signerInvocations}`);
233
+ line(" Please report this with your package versions — it is a real bug.");
234
+ return 1;
235
+ }
236
+ // Only auto-run as a CLI, never on import (keeps it testable). Anchored on a
237
+ // path separator so a file merely ENDING in "doctor.ts" (e.g. probe-doctor.ts)
238
+ // does not trigger the CLI — that bit me while testing this very function.
239
+ if (process.argv[1] &&
240
+ /(^|[\\/])doctor(\.[cm]?[jt]s)?$/.test(process.argv[1])) {
241
+ main().then((code) => process.exit(code), (err) => {
242
+ process.stderr.write(`twzrd-gate-doctor: ${String(err)}\n`);
243
+ process.exit(1);
244
+ });
245
+ }
246
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "twzrd-x402-gate",
3
- "version": "0.8.8",
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 — 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 — 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.",
3
+ "version": "0.8.10",
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",
10
- "twzrd-gate-eval-refuse": "bin/twzrd-gate-eval-refuse.js"
9
+ "twzrd-safe-fetch": "./bin/twzrd-safe-fetch.js",
10
+ "twzrd-gate-eval-refuse": "./bin/twzrd-gate-eval-refuse.js",
11
+ "twzrd-gate-doctor": "./bin/twzrd-gate-doctor.js"
11
12
  },
12
13
  "exports": {
13
14
  ".": {
@@ -23,13 +24,14 @@
23
24
  "files": [
24
25
  "dist",
25
26
  "bin",
26
- "README.md"
27
+ "README.md",
28
+ "QUICKSTART.md"
27
29
  ],
28
30
  "scripts": {
29
31
  "build": "tsc",
30
32
  "prepublishOnly": "tsc",
31
33
  "typecheck": "tsc --noEmit -p tsconfig.check.json",
32
- "test": "tsx test/version-identity.test.ts && tsx test/policy.test.ts && tsx test/wrap-fetch.test.ts && tsx test/mcp-hook.test.ts && tsx test/attribution.test.ts && tsx test/auto-receipt.test.ts && tsx test/quick.test.ts && tsx test/sponsored.test.ts && tsx test/escalation.test.ts && tsx test/wash-refuse.test.ts && tsx test/auto-gate.test.ts && tsx test/autogate-intercept.test.ts && tsx test/network.test.ts && tsx test/safe-fetch.test.ts && tsx test/payto-prefer.test.ts && tsx test/challenge-swap.test.ts && tsx test/x402-client-hook.test.ts && tsx test/hook-single-eval.test.ts && tsx test/run-attribution.test.ts && tsx test/payment-control.test.ts && tsx test/intent-binding.test.ts && tsx test/mpp-hook.test.ts && tsx test/mpp-safety.test.ts && tsx test/payment-control-followup.test.ts && tsx test/payment-control-hardening.test.ts && tsx test/x402-official-compat.test.ts && tsx test/seller-hook.test.ts && tsx test/adoption-proof.test.ts && tsx test/delivery-capture.test.ts",
34
+ "test": "tsx test/version-identity.test.ts && tsx test/policy.test.ts && tsx test/wrap-fetch.test.ts && tsx test/mcp-hook.test.ts && tsx test/attribution.test.ts && tsx test/auto-receipt.test.ts && tsx test/quick.test.ts && tsx test/sponsored.test.ts && tsx test/escalation.test.ts && tsx test/wash-refuse.test.ts && tsx test/auto-gate.test.ts && tsx test/autogate-intercept.test.ts && tsx test/network.test.ts && tsx test/safe-fetch.test.ts && tsx test/payto-prefer.test.ts && tsx test/challenge-swap.test.ts && tsx test/x402-client-hook.test.ts && tsx test/hook-single-eval.test.ts && tsx test/run-attribution.test.ts && tsx test/payment-control.test.ts && tsx test/intent-binding.test.ts && tsx test/mpp-hook.test.ts && tsx test/mpp-safety.test.ts && tsx test/payment-control-followup.test.ts && tsx test/payment-control-hardening.test.ts && tsx test/x402-official-compat.test.ts && tsx test/seller-hook.test.ts && tsx test/adoption-proof.test.ts && tsx test/delivery-capture.test.ts && tsx test/doctor.test.ts",
33
35
  "pack-smoke": "node scripts/pack-smoke.mjs",
34
36
  "safe-fetch": "tsx src/safe-fetch.ts",
35
37
  "guard-demo": "tsx examples/agentic-market-gate.ts",
@@ -41,7 +43,8 @@
41
43
  "adoption-proof": "tsx src/adoption-proof.ts",
42
44
  "demo:buyer-no-spend": "tsx src/adoption-proof.ts -- --integration ops-demo-buyer-no-spend",
43
45
  "live-autogate-matrix": "tsx examples/live-autogate-matrix.ts",
44
- "gate-eval-refuse": "node bin/twzrd-gate-eval-refuse.js"
46
+ "gate-eval-refuse": "node bin/twzrd-gate-eval-refuse.js",
47
+ "gate-doctor": "tsx src/doctor.ts"
45
48
  },
46
49
  "keywords": [
47
50
  "x402",