twzrd-x402-gate 0.9.3 → 0.9.4
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 +52 -8
- package/README.md +288 -59
- package/dist/auto-gate.d.ts +5 -2
- package/dist/auto-gate.d.ts.map +1 -1
- package/dist/auto-gate.js +12 -3
- package/dist/auto-gate.js.map +1 -1
- package/dist/cloudflare-base.d.ts +49 -0
- package/dist/cloudflare-base.d.ts.map +1 -0
- package/dist/cloudflare-base.js +113 -0
- package/dist/cloudflare-base.js.map +1 -0
- package/dist/cloudflare-x402.d.ts +29 -0
- package/dist/cloudflare-x402.d.ts.map +1 -0
- package/dist/cloudflare-x402.js +31 -0
- package/dist/cloudflare-x402.js.map +1 -0
- package/dist/config.js +2 -2
- package/dist/config.js.map +1 -1
- package/dist/decision-token.d.ts.map +1 -1
- package/dist/decision-token.js.map +1 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +24 -2
- package/dist/doctor.js.map +1 -1
- package/dist/evidence-verify.d.ts +145 -0
- package/dist/evidence-verify.d.ts.map +1 -0
- package/dist/evidence-verify.js +784 -0
- package/dist/evidence-verify.js.map +1 -0
- package/dist/foreign-key.d.ts +19 -0
- package/dist/foreign-key.d.ts.map +1 -0
- package/dist/foreign-key.js +61 -0
- package/dist/foreign-key.js.map +1 -0
- package/dist/gate.d.ts +0 -13
- package/dist/gate.d.ts.map +1 -1
- package/dist/gate.js +0 -22
- package/dist/gate.js.map +1 -1
- package/dist/index.d.ts +13 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -6
- package/dist/index.js.map +1 -1
- package/dist/merchant-card.d.ts +57 -18
- package/dist/merchant-card.d.ts.map +1 -1
- package/dist/merchant-card.js +108 -23
- package/dist/merchant-card.js.map +1 -1
- package/dist/mpp-hook.d.ts +39 -12
- package/dist/mpp-hook.d.ts.map +1 -1
- package/dist/mpp-hook.js +76 -13
- package/dist/mpp-hook.js.map +1 -1
- package/dist/paying-fetch.d.ts +15 -0
- package/dist/paying-fetch.d.ts.map +1 -0
- package/dist/paying-fetch.js +67 -0
- package/dist/paying-fetch.js.map +1 -0
- package/dist/policy-fetch.d.ts +18 -0
- package/dist/policy-fetch.d.ts.map +1 -0
- package/dist/policy-fetch.js +77 -0
- package/dist/policy-fetch.js.map +1 -0
- package/dist/policy-runtime.d.ts +15 -2
- package/dist/policy-runtime.d.ts.map +1 -1
- package/dist/policy-runtime.js +52 -16
- package/dist/policy-runtime.js.map +1 -1
- package/dist/policy.d.ts +1 -3
- package/dist/policy.d.ts.map +1 -1
- package/dist/policy.js +79 -47
- package/dist/policy.js.map +1 -1
- package/dist/record-leash-settle.d.ts +20 -0
- package/dist/record-leash-settle.d.ts.map +1 -0
- package/dist/record-leash-settle.js +25 -0
- package/dist/record-leash-settle.js.map +1 -0
- package/dist/resource-bind.d.ts.map +1 -1
- package/dist/resource-bind.js +1 -0
- package/dist/resource-bind.js.map +1 -1
- package/dist/spend-control.d.ts +2 -9
- package/dist/spend-control.d.ts.map +1 -1
- package/dist/spend-control.js +120 -64
- package/dist/spend-control.js.map +1 -1
- package/dist/types.d.ts +3 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/wash-default.d.ts +112 -0
- package/dist/wash-default.d.ts.map +1 -0
- package/dist/wash-default.js +229 -0
- package/dist/wash-default.js.map +1 -0
- package/dist/x402-client-hook.d.ts +83 -11
- package/dist/x402-client-hook.d.ts.map +1 -1
- package/dist/x402-client-hook.js +168 -13
- package/dist/x402-client-hook.js.map +1 -1
- package/package.json +20 -10
- package/dist/decision-ledger-file.d.ts +0 -49
- package/dist/decision-ledger-file.d.ts.map +0 -1
- package/dist/decision-ledger-file.js +0 -95
- package/dist/decision-ledger-file.js.map +0 -1
package/QUICKSTART.md
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
# twzrd-x402-gate — Quickstart (15 minutes, 0 USDC)
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
preflight blocks the payment by default (`TWZRD_FAIL_OPEN=true` to allow).
|
|
3
|
+
**Product:** replace naked `createX402Client({ wallet })` with a client that
|
|
4
|
+
**refuses wash before sign**. Free `merchant_card`, no API key. Intel down →
|
|
5
|
+
**fail-open** (never invents wash). No Path A in the default path.
|
|
7
6
|
|
|
8
|
-
**Pin:** `twzrd-x402-gate@0.9.3` +
|
|
9
|
-
`beforePayment` seat). `@x402/core` Path E remains supported; refuse script is fallback.
|
|
7
|
+
**Pin:** `twzrd-x402-gate@0.9.3` + `x402-solana@3.0.0`.
|
|
10
8
|
|
|
11
9
|
## 1. Stock PayAI client (default seat — copy-paste)
|
|
12
10
|
|
|
@@ -19,6 +17,16 @@ npm install twzrd-x402-gate@0.9.3 x402-solana@3.0.0
|
|
|
19
17
|
> fails with `ERR_PACKAGE_PATH_NOT_EXPORTED`. Set `"type": "module"` in your
|
|
20
18
|
> package.json, use `.mjs`, or bundle ESM.
|
|
21
19
|
|
|
20
|
+
```typescript
|
|
21
|
+
import { createX402Client } from "x402-solana";
|
|
22
|
+
import { createTwzrdPayingClient } from "twzrd-x402-gate";
|
|
23
|
+
|
|
24
|
+
// was: createX402Client({ wallet })
|
|
25
|
+
const client = createX402Client(createTwzrdPayingClient({ wallet }));
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Or hook-only:
|
|
29
|
+
|
|
22
30
|
```typescript
|
|
23
31
|
import { createX402Client } from "x402-solana";
|
|
24
32
|
import { createTwzrdBeforePaymentHook } from "twzrd-x402-gate";
|
|
@@ -26,11 +34,12 @@ import { createTwzrdBeforePaymentHook } from "twzrd-x402-gate";
|
|
|
26
34
|
const client = createX402Client({
|
|
27
35
|
wallet,
|
|
28
36
|
network: "solana",
|
|
29
|
-
beforePayment: createTwzrdBeforePaymentHook(
|
|
37
|
+
beforePayment: createTwzrdBeforePaymentHook(),
|
|
30
38
|
});
|
|
31
39
|
```
|
|
32
40
|
|
|
33
|
-
|
|
41
|
+
Default engine = wash only. Full 0.8 preflight/Path A: `{ engine: "full" }`.
|
|
42
|
+
|
|
34
43
|
Then: `await client.fetch("https://merchant.example/paid");`
|
|
35
44
|
|
|
36
45
|
## 1b. Official `@x402/core` client (Path E)
|
|
@@ -124,3 +133,38 @@ Everything else (thresholds, wash caps, fail posture, settle guard): [README](./
|
|
|
124
133
|
allowed, observed) unless you set `TWZRD_UNSUPPORTED_NETWORK_MODE=strict`.
|
|
125
134
|
- **No delivery guarantee.** It screens the merchant before you pay, nothing after.
|
|
126
135
|
- **Not a wallet.** It never holds keys or signs — it only decides if your signer runs.
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
## Pay Kit before-payment hook (upstream PR pending)
|
|
139
|
+
|
|
140
|
+
`solana-foundation/pay-kit#303` is open as of 2026-09-07. This adapter targets
|
|
141
|
+
that PR's `onBeforeX402PaymentCreation` option; a released Pay Kit client must
|
|
142
|
+
expose that option before this integration can enforce policy.
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
import { createPayKitClient } from "@solana/pay-kit";
|
|
146
|
+
import { installTwzrdAutoGate } from "twzrd-x402-gate";
|
|
147
|
+
|
|
148
|
+
const client = await createPayKitClient({
|
|
149
|
+
accept: ["x402"],
|
|
150
|
+
rpcUrl,
|
|
151
|
+
signer,
|
|
152
|
+
onBeforeX402PaymentCreation: installTwzrdAutoGate("pay-kit", {
|
|
153
|
+
refuseWashFlagged: true,
|
|
154
|
+
}),
|
|
155
|
+
});
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
The adapter returns the official x402 context hook and reuses the shared
|
|
159
|
+
before-payment evaluator. It adds no Pay Kit dependency. Supply it at client
|
|
160
|
+
construction; passing the constructed Pay Kit client to AutoGate is unsupported.
|
|
161
|
+
This hook covers x402 payment creation, not Pay Kit's MPP path.
|
|
162
|
+
|
|
163
|
+
`createTwzrdPayKitBeforePaymentHook(options)` exposes the same evaluator directly.
|
|
164
|
+
The AutoGate form reads environment kill switches on every call; the direct
|
|
165
|
+
factory does not. Calling AutoGate installs protection by default, whereas
|
|
166
|
+
ClawRouter's integration loads AutoGate only after explicit opt-in.
|
|
167
|
+
|
|
168
|
+
Source-checkout verification: `npx tsx test/pay-kit-before-payment.test.ts`.
|
|
169
|
+
The test covers a fake Pay Kit host and the real x402 client with a fake scheme;
|
|
170
|
+
it does not establish released Pay Kit compatibility or external use.
|
package/README.md
CHANGED
|
@@ -1,40 +1,72 @@
|
|
|
1
1
|
# twzrd-x402-gate
|
|
2
2
|
|
|
3
|
-
**
|
|
4
|
-
`onBeforePaymentCreation` policy engine for official x402 clients.
|
|
3
|
+
**Product: the paying client that already has the brake.**
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
Agents pay other machines unsupervised. Most 402s are junk or wash. Something has
|
|
6
|
+
to say **no** before the signature. TWZRD is that no — inside `beforePayment` /
|
|
7
|
+
fetch+sign, not inside PayAI’s SDK defaults, not as a shop at intel.twzrd.xyz.
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
The other reason the no must live at the signature: **attaching a funded wallet
|
|
10
|
+
to an agent that reads untrusted web content is a drain vector** — indirect
|
|
11
|
+
prompt injection can spend anything the agent can sign. The gate closes it by
|
|
12
|
+
attaching the wallet to a policy runtime the injected content cannot
|
|
13
|
+
renegotiate: per-request cap, rolling daily ceiling, wash brake, endpoint
|
|
14
|
+
mandates, and a tamper-evident spend ledger that survives restarts. A fully
|
|
15
|
+
compromised agent spends at most what policy allows, to whom it allows, with
|
|
16
|
+
every decision signed.
|
|
10
17
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
18
|
+
### Replace naked `createX402Client({ wallet })` (5 lines)
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install twzrd-x402-gate@0.9.3 x402-solana@3.0.0
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { createX402Client } from "x402-solana";
|
|
26
|
+
import { createTwzrdPayingClient } from "twzrd-x402-gate";
|
|
27
|
+
|
|
28
|
+
// was: createX402Client({ wallet })
|
|
29
|
+
const client = createX402Client(createTwzrdPayingClient({ wallet }));
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Equivalent one-hook form:
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import { createX402Client } from "x402-solana";
|
|
36
|
+
import { createTwzrdBeforePaymentHook } from "twzrd-x402-gate";
|
|
37
|
+
|
|
38
|
+
const client = createX402Client({
|
|
39
|
+
wallet,
|
|
40
|
+
network: "solana",
|
|
41
|
+
beforePayment: createTwzrdBeforePaymentHook(), // wash default
|
|
15
42
|
});
|
|
16
|
-
// result.verdict: "allow" | "warn" | "block" — blocks have signerInvocations === 0
|
|
17
|
-
// result.receipt: { strength: "hard"|"soft"|"refuse", leaf_hash, fact_type: "resource_bound" }
|
|
18
43
|
```
|
|
19
44
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
validated `transactionBase64`. This SDK never holds keys.
|
|
45
|
+
**Default path (engine `"wash"`):**
|
|
46
|
+
`GET /v1/intel/merchant_card/{payTo}` → abort **iff** `wash_flagged === true` →
|
|
47
|
+
**fail-open** on timeout / non-2xx / throw (never invent wash).
|
|
48
|
+
No Path A, no requireReceipt, no second 402, no payment-control tokens.
|
|
25
49
|
|
|
26
|
-
Full
|
|
27
|
-
|
|
50
|
+
**Full 0.8.x engine (named opt-in):** preflight + optional Path A / escalate /
|
|
51
|
+
paymentControl:
|
|
28
52
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
53
|
+
```typescript
|
|
54
|
+
createTwzrdBeforePaymentHook({ engine: "full", /* … */ })
|
|
55
|
+
// or createTwzrdFullBeforePaymentHook({ … })
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Customer = whoever ships `createX402Client({ wallet })` with no hook (Eliza, MCP
|
|
59
|
+
hosts, agent wallets). Crawlers will never `npm install`.
|
|
33
60
|
|
|
34
|
-
|
|
61
|
+
> **ESM-only:** CommonJS `require()` fails with `ERR_PACKAGE_PATH_NOT_EXPORTED`
|
|
62
|
+
> — set `"type": "module"` (or use `.mjs` / an ESM bundler).
|
|
63
|
+
|
|
64
|
+
### Default-on AutoGate (alternate seats)
|
|
35
65
|
|
|
36
66
|
```bash
|
|
37
|
-
npm install twzrd-x402-gate
|
|
67
|
+
npm install twzrd-x402-gate@0.9.3 x402-solana@3.0.0
|
|
68
|
+
# official @x402/* path (alternate seat):
|
|
69
|
+
# npm install twzrd-x402-gate@0.9.3 @x402/core @x402/fetch @x402/svm
|
|
38
70
|
```
|
|
39
71
|
|
|
40
72
|
```typescript
|
|
@@ -42,26 +74,28 @@ import { x402Client } from "@x402/core/client";
|
|
|
42
74
|
import { installTwzrdAutoGate } from "twzrd-x402-gate";
|
|
43
75
|
|
|
44
76
|
const client = new x402Client();
|
|
45
|
-
//
|
|
77
|
+
// stock solana seat still defaults to wash via createTwzrdBeforePaymentHook()
|
|
46
78
|
installTwzrdAutoGate(client, { refuseWashFlagged: true });
|
|
47
79
|
// then register schemes + wrapFetchWithPayment as usual
|
|
48
80
|
```
|
|
49
81
|
|
|
50
|
-
**Intercept proof (0 USDC,
|
|
82
|
+
**Intercept proof (0 USDC, bad seller never reaches signer):**
|
|
51
83
|
|
|
52
84
|
```bash
|
|
53
85
|
cd packages/twzrd-x402-gate && npm run autogate-block-proof
|
|
54
86
|
# writes block-proof-<run_id>.json (schema twzrd.autogate_block_proof.v1)
|
|
55
|
-
# public reason: TWZRD_TRUST_GATE_BLOCK: wash_flagged
|
|
87
|
+
# public reason: "TWZRD_TRUST_GATE_BLOCK: wash_flagged" (wash basis)
|
|
88
|
+
# or "TWZRD_TRUST_GATE_BLOCK: decision_block" (readiness block basis)
|
|
89
|
+
# fixture resolves live: wash_flagged seller if available, else decision=block
|
|
56
90
|
```
|
|
57
91
|
|
|
58
|
-
`gateOnCanSpend` remains **opt-in** (`false` by default; set `true` or `TWZRD_GATE_ON_CAN_SPEND=1` only when you want hard cap enforcement).
|
|
92
|
+
`gateOnCanSpend` remains **opt-in** (`false` by default; set `true` or `TWZRD_GATE_ON_CAN_SPEND=1` only when you want hard cap enforcement). Full-engine preflight outage default stays fail-closed unless `failOpen: true` / `TWZRD_FAIL_OPEN=1`. The **product wash path always fail-opens** on intel outage.
|
|
59
93
|
|
|
60
|
-
**Optional
|
|
94
|
+
**Optional:** a resource-server settle hook so merchants can apply **customer policy**
|
|
61
95
|
before they settle and serve (abuse, sanctions, bots, “don’t serve this payer”). Not an equal
|
|
62
96
|
mirror of the buyer problem — settled USDC is final; wash resistance is mainly TWZRD scoring.
|
|
63
97
|
|
|
64
|
-
## Seller settle guard (`onBeforeSettle`) — optional
|
|
98
|
+
## Seller settle guard (`onBeforeSettle`) — optional
|
|
65
99
|
|
|
66
100
|
Resource servers can screen the **payer** before *they* settle an inbound payment and serve
|
|
67
101
|
the resource. Use for merchant policy (abuse / sanctions / bots / customer selection). TWZRD is
|
|
@@ -105,7 +139,23 @@ Offline demo: `npx tsx examples/seller-settle-guard.ts`
|
|
|
105
139
|
Fixture-backed SVM extract tests live in `test/seller-hook.test.ts` +
|
|
106
140
|
`test/fixtures/exact-svm-transfer-checked.ts`.
|
|
107
141
|
|
|
108
|
-
**PayAI
|
|
142
|
+
**PayAI x402-solana@2.1.0+** (stock client - primary Solana seat via `beforePayment`).
|
|
143
|
+
Both 2.1.0 and 3.0.0 are supported and produce an identical refuse transcript; 3.0.0
|
|
144
|
+
is the current release and what the install lines pin. The hook absorbs the one
|
|
145
|
+
breaking change between them (`declaredResource` is a string on 2.1.0, `{ url }` on
|
|
146
|
+
3.0.0) - see `src/x402-client-hook.ts` and `test/x402-solana-before-payment.test.ts`.
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
import { createX402Client } from "x402-solana";
|
|
150
|
+
import { createTwzrdPayingClient } from "twzrd-x402-gate";
|
|
151
|
+
|
|
152
|
+
const client = createX402Client(createTwzrdPayingClient({ wallet }));
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Also: `installTwzrdAutoGate("x402-solana", opts)` returns the same wash-default hook.
|
|
156
|
+
Prove refuse-before-sign: `npm run x402-solana-before-payment-proof`.
|
|
157
|
+
|
|
158
|
+
**PayAI agentic-payments** (alternate PayAI surface; prefer x402-solana@3.0.0 when available):
|
|
109
159
|
`npx tsx examples/payai-agentic-onPaymentVerified.ts` — wire `onPaymentVerified`
|
|
110
160
|
→ `toPayaiVerifyResult` to screen payers before serving. Fail-open by default.
|
|
111
161
|
|
|
@@ -137,7 +187,7 @@ Gate dogfood: `approved=false` `reason=twzrd_decision_block`, **USDC spent = 0**
|
|
|
137
187
|
|
|
138
188
|
**Accurate paste line:**
|
|
139
189
|
|
|
140
|
-
> Preflight returned decision=block on wash seller 7G73PL… / HuSiSpc… (preflight_id 378468 / 378469, wash_flagged=true). Gate approved=false reason=twzrd_decision_block. No USDC spent. No tx broadcast. Repro: `npm i twzrd-x402-gate@0.
|
|
190
|
+
> Preflight returned decision=block on wash seller 7G73PL… / HuSiSpc… (preflight_id 378468 / 378469, wash_flagged=true). Gate approved=false reason=twzrd_decision_block. No USDC spent. No tx broadcast. Repro: `npm i twzrd-x402-gate@0.9.1 && npm run wash-dogfood` or gist above.
|
|
141
191
|
|
|
142
192
|
This is a **reproducible demonstration** that the free gate blocks known wash sellers with stamped `preflight_id`s and zero spend. It is **not** proof that external agents already default to this path at scale.
|
|
143
193
|
|
|
@@ -215,11 +265,61 @@ No AgentCash. No marketplace. No second probe. No TWZRD custody.
|
|
|
215
265
|
Wire `twzrdOnPaymentRequested` / prefer `onPaymentRequired` + `onBeforePayment` per
|
|
216
266
|
[lifecycle hooks](https://docs.x402.org/advanced-concepts/lifecycle-hooks). Same policy core.
|
|
217
267
|
|
|
268
|
+
### Cloudflare Agents x402 (Base)
|
|
269
|
+
|
|
270
|
+
Cloudflare's `withX402Client` takes an `onPaymentRequired` callback before its
|
|
271
|
+
automatic payment retry. Use the adapter below at that boundary:
|
|
272
|
+
|
|
273
|
+
```ts
|
|
274
|
+
import { createTwzrdCloudflareX402Approval } from "twzrd-x402-gate";
|
|
275
|
+
|
|
276
|
+
const approvePayment = createTwzrdCloudflareX402Approval({
|
|
277
|
+
// Base/EVM has no TWZRD behavioral reputation yet. Refuse it rather than
|
|
278
|
+
// presenting a policy allow as a trust verdict.
|
|
279
|
+
unsupportedNetworkMode: "strict",
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
await this.x402Client.callTool(approvePayment, {
|
|
283
|
+
name: "paid_tool",
|
|
284
|
+
arguments: {},
|
|
285
|
+
});
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
`observe` is available for an agent that intentionally permits unscored Base
|
|
289
|
+
payments, but it returns policy allow with `decision=unknown`; it is never a
|
|
290
|
+
TWZRD reputation approval. This adapter protects the Cloudflare x402 path only.
|
|
291
|
+
MPP is a separate protocol and belongs on its own `onChallenge` /
|
|
292
|
+
`onPaymentRequired` control path.
|
|
293
|
+
|
|
294
|
+
### Cloudflare Worker / Base x402 (edge-safe preflight)
|
|
295
|
+
|
|
296
|
+
For a Worker, import the dedicated subpath rather than the package root. It has
|
|
297
|
+
no Node-native imports and sends the exact Base `payTo` plus `chain_id: 8453` to
|
|
298
|
+
`/v1/intel/preflight` before a Viem account signs:
|
|
299
|
+
|
|
300
|
+
```ts
|
|
301
|
+
import { withTwzrdBasePreflight } from "twzrd-x402-gate/cloudflare-base";
|
|
302
|
+
|
|
303
|
+
const signature = await withTwzrdBasePreflight(
|
|
304
|
+
paymentRequirements, // accepts: [{ network: "eip155:8453", payTo: "0x..." }]
|
|
305
|
+
{ intelBase: "https://intel.twzrd.xyz" },
|
|
306
|
+
() => account.signTypedData(eip3009Authorization),
|
|
307
|
+
);
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
`block` throws `TwzrdBasePaymentBlockedError` and never invokes the signing
|
|
311
|
+
callback. `allow` and `warn` both proceed; enforce any additional amount or
|
|
312
|
+
mandate policy in the caller. Base is not presented as reputation-scored.
|
|
313
|
+
Checksummed and lowercase EVM addresses are accepted unchanged. The fixture in
|
|
314
|
+
[`test/cloudflare-base-edge.test.ts`](./test/cloudflare-base-edge.test.ts) proves
|
|
315
|
+
`block → zero signTypedData calls` and the compiled subpath is checked for Node
|
|
316
|
+
runtime leaks.
|
|
317
|
+
|
|
218
318
|
### Raw-fetch composition (injectible pay client only)
|
|
219
319
|
|
|
220
320
|
```typescript
|
|
221
321
|
import { installTwzrdAutoGate } from "twzrd-x402-gate";
|
|
222
|
-
import { wrapFetchWithPayment } from "@x402/fetch";
|
|
322
|
+
import { wrapFetchWithPayment } from "@x402/fetch"; // or @x402/svm helper
|
|
223
323
|
|
|
224
324
|
// Guard RAW fetch, then hand to a client that still surfaces 402 to the guard layer
|
|
225
325
|
// — OR installTwzrdAutoGate(x402Client) (canonical) / installTwzrdX402ClientHook alias.
|
|
@@ -241,15 +341,16 @@ Canonical path for every agent that spends USDC on Solana x402:
|
|
|
241
341
|
|
|
242
342
|
**Fail-open (no invent):**
|
|
243
343
|
- Preflight HTTP/network error → default fail-closed in gate 0.2+ (`TWZRD_FAIL_OPEN=true` restores legacy allow-on-outage).
|
|
244
|
-
- Merchant card unreachable / non-2xx /
|
|
245
|
-
-
|
|
344
|
+
- Merchant card unreachable / non-2xx / timeout → fail-open (do not invent wash).
|
|
345
|
+
- A *returned* card with `wash_flagged: null`, missing coverage, `wash_confidence` other than `full`, `ring_evaluated: false`, or `wash_stale: true` is **unknown ≠ clean**: refuse (or configured cap). Reason `twzrd_wash_unknown` / `twzrd_wash_unknown_capped_*` — never `twzrd_wash_ok`.
|
|
246
346
|
|
|
247
347
|
**Wash policy (exact):**
|
|
248
348
|
- Prior preflight deny → unchanged (wash never loosens a block).
|
|
249
|
-
- `refuseWashFlagged=false`
|
|
349
|
+
- `refuseWashFlagged=false` → keep prior approval (opt out).
|
|
250
350
|
- `wash_flagged=true` + no cap → `approved=false`, `reason=twzrd_wash_flagged`, `verdict=block`.
|
|
251
351
|
- `wash_flagged=true` + `washMaxUsdc` set + `priceUsdc <= cap` → allow, `washCapped=true`, reason `twzrd_wash_capped_{price}_le_{cap}`.
|
|
252
352
|
- `wash_flagged=true` + price above cap (or price unknown) → refuse with `twzrd_wash_flagged_above_cap_*`.
|
|
353
|
+
- Adequately measured no-signal (`wash_flagged=false` and `wash_confidence=full`, with no stale or unevaluated-ring flag) → keep prior allow (`twzrd_wash_ok` on the default hook).
|
|
253
354
|
|
|
254
355
|
**Order note:** `onWarnUpsell` (points at paid `/trust`) fires on preflight `warn` **before** the merchant_card wash check. A wash-flagged seller that preflighted as `warn` may still get the upsell hook, then be refused on step 2.
|
|
255
356
|
|
|
@@ -262,11 +363,13 @@ Dogfood (one public live proof path):
|
|
|
262
363
|
## Install
|
|
263
364
|
|
|
264
365
|
```bash
|
|
265
|
-
npm install twzrd-x402-gate@0.9.3
|
|
366
|
+
npm install twzrd-x402-gate@0.9.3 x402-solana@3.0.0
|
|
266
367
|
```
|
|
267
368
|
|
|
268
|
-
|
|
269
|
-
|
|
369
|
+
Install pin is the published version (`GATE_PACKAGE_PIN` in
|
|
370
|
+
`packages/twzrd-agent-intel/src/twzrd_agent_intel/pins.py`). Repo `package.json`
|
|
371
|
+
may be one patch ahead until that release is on npm. Confirm with
|
|
372
|
+
`npm view twzrd-x402-gate version`.
|
|
270
373
|
|
|
271
374
|
Optional settle guard (resource-server **payer** policy): see **Seller settle guard
|
|
272
375
|
(`onBeforeSettle`) — optional 0.8.1** above. Do not confuse with facilitator
|
|
@@ -360,15 +463,16 @@ installTwzrdX402ClientHook(client, {
|
|
|
360
463
|
- Hook binding test:
|
|
361
464
|
[`test/intent-binding.test.ts`](./test/intent-binding.test.ts).
|
|
362
465
|
|
|
363
|
-
### On MPP (Machine Payments Protocol) — Solana charge
|
|
466
|
+
### On MPP (Machine Payments Protocol) — Solana and narrow Base EVM charge
|
|
364
467
|
|
|
365
|
-
`createTwzrdMppOnChallenge` guards `Mppx.create({ onChallenge })`.
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
**`createCredential()` never runs and
|
|
370
|
-
creates the credential for the exact
|
|
371
|
-
|
|
468
|
+
`createTwzrdMppOnChallenge` guards `Mppx.create({ onChallenge })`. It supports
|
|
469
|
+
`solana/charge` and the published native MPP `evm/charge` shape only for
|
|
470
|
+
Base-mainnet native USDC (EIP-3009 authorization). `onChallenge` is the last
|
|
471
|
+
deterministic checkpoint before `createCredential()` makes the credential, so a
|
|
472
|
+
TWZRD block is an exception that means **`createCredential()` never runs and
|
|
473
|
+
nothing signs**. On allow, the guard creates the credential for the exact
|
|
474
|
+
challenge it evaluated; other methods/intents fail closed
|
|
475
|
+
(`allowUnevaluated: true` is an explicit ungated opt-out).
|
|
372
476
|
|
|
373
477
|
```typescript
|
|
374
478
|
import { Mppx } from "mppx/client";
|
|
@@ -384,6 +488,30 @@ const mppx = Mppx.create({
|
|
|
384
488
|
});
|
|
385
489
|
```
|
|
386
490
|
|
|
491
|
+
For Base, use mppx's EVM client with explicit local spend policy:
|
|
492
|
+
|
|
493
|
+
```typescript
|
|
494
|
+
import { Mppx } from "mppx/client";
|
|
495
|
+
import { evm } from "mppx/evm/client";
|
|
496
|
+
import { createTwzrdMppOnChallenge, createLocalDecisionSigner } from "twzrd-x402-gate";
|
|
497
|
+
|
|
498
|
+
const mppx = Mppx.create({
|
|
499
|
+
methods: [evm({ account: wallet })],
|
|
500
|
+
onChallenge: createTwzrdMppOnChallenge({
|
|
501
|
+
signer: createLocalDecisionSigner(),
|
|
502
|
+
policy: {
|
|
503
|
+
allowedNetworks: ["eip155:8453"],
|
|
504
|
+
allowedAssets: ["0x833589fCD6EDb6E08f4c7C32D4f71b54bdA02913"],
|
|
505
|
+
maxAmountUsd: "1.00",
|
|
506
|
+
},
|
|
507
|
+
}),
|
|
508
|
+
});
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
Base is **not reputation-scored**. The EVM path provides an actual pre-credential
|
|
512
|
+
local control point for Base USDC; it does not call a Solana-derived score or
|
|
513
|
+
present a local policy allow as a TWZRD trust verdict.
|
|
514
|
+
|
|
387
515
|
**Scope limit (honest):** the guard is authoritative only when no
|
|
388
516
|
`onChallengeReceived` event handler supplies a credential. mppx resolves
|
|
389
517
|
`eventCredential ?? onChallenge(...)`, so an event handler returning a credential
|
|
@@ -399,6 +527,8 @@ fails closed rather than approve a payment it cannot bind:
|
|
|
399
527
|
| Non-USD-pegged asset | `UNPRICED_ASSET` | Policy ceilings are USD; the wire amount is base-unit tokens. Pricing SOL would store `asset: solana:native` beside a **dollar** `amount` and lose the token quantity actually transferred. (A 1.5 SOL charge of `1500000000` at 9 decimals would otherwise evaluate as "$1.50" and sail under a $5 ceiling while moving ~$270.) USDC/USDT only until an intent version carries token amount + quote. |
|
|
400
528
|
| Unknown cluster | `UNKNOWN_CLUSTER` | mppx-solana's `resolveEndpoint` returns an unrecognized `cluster` **verbatim as the RPC endpoint URL**, and a network string containing "solana" is otherwise scored as mainnet - so `solana:https://seller-rpc.example` would inherit mainnet reputation for a chain never observed. Known cluster names only. |
|
|
401
529
|
| Misdeclared decimals | `MALFORMED_CHALLENGE` | A known stablecoin declaring the wrong decimals is a discount attempt, not a rounding error. |
|
|
530
|
+
| Non-Base EVM chain | `UNSUPPORTED_EVM_NETWORK` | EVM MPP is narrow: Base mainnet only. A testnet or another EVM network cannot inherit a Base USDC valuation. |
|
|
531
|
+
| EVM split recipients | `MULTI_LEG_CHARGE` | mppx EVM permits `splits`; each is an additional recipient. PaymentIntent v1 binds one amount to one payTo, so the guard refuses rather than approve transfers it cannot represent. |
|
|
402
532
|
|
|
403
533
|
The intent binds a **digest of the entire normalized challenge**, not just
|
|
404
534
|
`realm:id` - swapping `recipient` or `amount` under the same challenge id changes
|
|
@@ -451,8 +581,10 @@ Canonical entry point (design: `docs/strategy/install-autogate-design.md`). One
|
|
|
451
581
|
| Call | Adapter |
|
|
452
582
|
|------|---------|
|
|
453
583
|
| `installTwzrdAutoGate(payWrap, opts?)` | Fetch: guard raw fetch → pay client |
|
|
454
|
-
| `installTwzrdAutoGate(x402Client, opts?)` | Official x402 `onBeforePaymentCreation` |
|
|
584
|
+
| `installTwzrdAutoGate(x402Client, opts?)` | Official `@x402/core` `onBeforePaymentCreation` |
|
|
585
|
+
| `installTwzrdAutoGate("x402-solana", opts?)` | PayAI stock client `beforePayment` (2.1.0+) |
|
|
455
586
|
| `installTwzrdAutoGate("mpp", opts)` | MPP `onChallenge` (returns handler) |
|
|
587
|
+
| `createTwzrdBeforePaymentHook(opts?)` | Same as `"x402-solana"` — pass to `createX402Client` |
|
|
456
588
|
|
|
457
589
|
Aliases: `installTwzrdX402ClientHook`, `createTwzrdMppOnChallenge` remain; docs prefer AutoGate.
|
|
458
590
|
Kill switch: `TWZRD_GATE_ENABLED=false` or `TWZRD_AUTO_GATE=0`. Uninstall x402 installs with `uninstallTwzrdAutoGate(client)`.
|
|
@@ -465,7 +597,7 @@ ever gets a chance to sign.
|
|
|
465
597
|
|
|
466
598
|
```typescript
|
|
467
599
|
import { installTwzrdAutoGate } from "twzrd-x402-gate";
|
|
468
|
-
import { wrapFetchWithPayment } from "@x402/
|
|
600
|
+
import { wrapFetchWithPayment } from "@x402/svm";
|
|
469
601
|
|
|
470
602
|
const payingFetch = installTwzrdAutoGate((guarded) => wrapFetchWithPayment(guarded, buyerWallet));
|
|
471
603
|
|
|
@@ -516,7 +648,7 @@ manage the raw/paying composition yourself:
|
|
|
516
648
|
|
|
517
649
|
```typescript
|
|
518
650
|
import { withTwzrdGuard } from "twzrd-x402-gate";
|
|
519
|
-
import { wrapFetchWithPayment } from "@x402/
|
|
651
|
+
import { wrapFetchWithPayment } from "@x402/svm";
|
|
520
652
|
|
|
521
653
|
const raw = globalThis.fetch; // MUST still surface HTTP 402
|
|
522
654
|
const guarded = withTwzrdGuard(raw); // guard sits upstream
|
|
@@ -551,15 +683,49 @@ const safeFetch = withTwzrdGuard(x402Fetch, {
|
|
|
551
683
|
});
|
|
552
684
|
```
|
|
553
685
|
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
686
|
+
### Path A — default on the buyer seat when a paying fetch is wired
|
|
687
|
+
|
|
688
|
+
Free preflight still decides `allow|warn|block`. **Facilitator `onBeforeSettle`
|
|
689
|
+
stays free** (abort on `block` only — we do not tax their rail).
|
|
690
|
+
|
|
691
|
+
On the **buyer** install, if you pass `x402Fetch` (or use
|
|
692
|
+
`installTwzrdAutoGate(payWrap)`, which auto-wires `payWrap(raw)`), Path A
|
|
693
|
+
defaults on:
|
|
694
|
+
|
|
695
|
+
| Free decision | Resource price | What fires |
|
|
696
|
+
|---------------|----------------|------------|
|
|
697
|
+
| `block` | any | free refuse |
|
|
698
|
+
| `warn` | ≥ $2.50 | $0.05 V6 (`requireReceipt`) |
|
|
699
|
+
| `warn` | < $2.50 | $0.001 quick re-decide (`escalateOnWarn`) |
|
|
700
|
+
| `allow` | > $2.50 | $0.05 V6 |
|
|
701
|
+
| `allow` | ≤ $2.50 | free proceed |
|
|
702
|
+
|
|
703
|
+
```typescript
|
|
704
|
+
import { wrapFetchWithPayment } from "@x402/svm";
|
|
705
|
+
import { createTwzrdBeforePaymentHook } from "twzrd-x402-gate";
|
|
706
|
+
|
|
707
|
+
const x402Fetch = wrapFetchWithPayment(fetch, buyerWallet);
|
|
708
|
+
const client = createX402Client({
|
|
709
|
+
wallet: buyerWallet,
|
|
710
|
+
network: "solana",
|
|
711
|
+
beforePayment: createTwzrdBeforePaymentHook({
|
|
712
|
+
refuseWashFlagged: true,
|
|
713
|
+
x402Fetch, // turns Path A defaults on
|
|
714
|
+
}),
|
|
715
|
+
});
|
|
716
|
+
```
|
|
717
|
+
|
|
718
|
+
Opt out: `requireReceipt: false` and/or `escalateOnWarn: false`.
|
|
719
|
+
Refuse-only seats (no `x402Fetch`) stay free.
|
|
720
|
+
|
|
721
|
+
`evaluate_x402_resource` itself stays opt-in. `autoReceipt: true` still buys
|
|
722
|
+
$0.05 on every non-block (broader than the default ladder).
|
|
557
723
|
|
|
558
724
|
**`x402Fetch` is yours to supply** (this package is dependency-free). Wire the proven
|
|
559
725
|
`@x402/svm` sponsored-feePayer client — the same one `twzrd-mcp-server` uses:
|
|
560
726
|
|
|
561
727
|
```typescript
|
|
562
|
-
import { wrapFetchWithPayment } from "@x402/
|
|
728
|
+
import { wrapFetchWithPayment } from "@x402/svm";
|
|
563
729
|
const x402Fetch = wrapFetchWithPayment(fetch, buyerWallet); // settles 402 challenges
|
|
564
730
|
```
|
|
565
731
|
|
|
@@ -751,17 +917,32 @@ const gatedFetch = wrapFetchWithTwzrdGate(fetch, resolveConfig());
|
|
|
751
917
|
|
|
752
918
|
A payment is **blocked** when:
|
|
753
919
|
1. `decision ∈ blockDecisions` (default: `["block"]`)
|
|
754
|
-
2. `trust_score < preflightMinScore` (default: `40`)
|
|
920
|
+
2. `trust_score < preflightMinScore` (default: `40`) — note a card with **no**
|
|
921
|
+
`trust_score` is scored `0` (`policy.ts`: `card.trust_score ?? 0`), so a
|
|
922
|
+
missing score blocks under the default floor
|
|
755
923
|
3. `can_spend === false` — **only** when `gateOnCanSpend: true` (default `false`, opt-in)
|
|
924
|
+
4. `merchant_card.wash_flagged === true` — **on by default**
|
|
925
|
+
(`refuseWashFlagged`, `TWZRD_REFUSE_WASH_FLAGGED`); forces `verdict: "block"`
|
|
926
|
+
with `reason: twzrd_wash_flagged`. A *returned* card with `wash_flagged: null`,
|
|
927
|
+
missing/`base_2cycle` coverage, or `ring_evaluated: false` is unknown ≠ clean
|
|
928
|
+
(`twzrd_wash_unknown`). Unreachable card still fail-opens (no invent).
|
|
929
|
+
Soft-cap instead of hard refuse with `washMaxUsdc` / `TWZRD_WASH_MAX_USDC`.
|
|
756
930
|
|
|
757
931
|
`warn` is allowed unless overridden. Preflight network failure **fails closed** by default (a preflight outage blocks the payment, so an intel hiccup never silently approves a spend); set `failOpen: true` / `TWZRD_FAIL_OPEN=true` to opt into legacy allow-on-outage.
|
|
758
932
|
|
|
759
933
|
A 402 whose payment requirements yield **no identifiable seller wallet** (missing/empty `payTo`, or an unparseable `accepts[]`) is a different case from "unknown seller" — it always **blocks** with `reason: twzrd_unidentifiable_payment_recipient`, without ever calling the preflight network. This is unconditional (not affected by `failOpen`): `failOpen` governs what happens when the TWZRD *service* is unreachable, not what happens when the caller can't say who they're paying.
|
|
760
934
|
|
|
761
935
|
> **`can_spend` note:** the free preflight returns `can_spend=false` for most sellers
|
|
762
|
-
> not yet in the TWZRD corpus, including legitimate ones.
|
|
763
|
-
>
|
|
764
|
-
>
|
|
936
|
+
> not yet in the TWZRD corpus, including legitimate ones. That **`can_spend` leg
|
|
937
|
+
> alone** is opt-in — it is ignored unless you set `gateOnCanSpend: true` — so an
|
|
938
|
+
> unknown seller on a platform like Agentic.Market is not blocked *on that basis*.
|
|
939
|
+
>
|
|
940
|
+
> This is **not** a blanket "unknown sellers are allowed by default". Conditions 1,
|
|
941
|
+
> 2 and 4 above are all active by default, and condition 2 is the one that catches
|
|
942
|
+
> unknown sellers: a card carrying no `trust_score` evaluates as `0` and blocks
|
|
943
|
+
> under the default `preflightMinScore: 40` with `twzrd_score_0_below_40`. To
|
|
944
|
+
> actually let unscored sellers through, lower or disable `preflightMinScore` —
|
|
945
|
+
> setting `gateOnCanSpend` does not govern it.
|
|
765
946
|
|
|
766
947
|
## Config
|
|
767
948
|
|
|
@@ -772,11 +953,24 @@ A 402 whose payment requirements yield **no identifiable seller wallet** (missin
|
|
|
772
953
|
| `blockDecisions` | `TWZRD_BLOCK_DECISIONS` | `block` | Decisions that throw |
|
|
773
954
|
| `failOpen` | `TWZRD_FAIL_OPEN` | `false` | `true` opts into legacy allow-on-outage; default blocks (fail-closed) |
|
|
774
955
|
| `gateOnCanSpend` | `TWZRD_GATE_ON_CAN_SPEND` | `false` | Also block when `can_spend=false` |
|
|
956
|
+
| `refuseWashFlagged` | `TWZRD_REFUSE_WASH_FLAGGED` | **`true`** | Refuse when `merchant_card.wash_flagged === true` (Policy 4). Set `false` / `0` to opt out |
|
|
957
|
+
| `washMaxUsdc` | `TWZRD_WASH_MAX_USDC` | — | Soft cap instead of hard refuse on wash: allow up to this USDC amount |
|
|
958
|
+
| `unsupportedNetworkMode` | `TWZRD_UNSUPPORTED_NETWORK_MODE` | `observe` | Behavior on a non-Solana / unrecognized network |
|
|
959
|
+
| `fetch` | — | global `fetch` | Injected fetch used for preflight + merchant card (testing / custom agents) |
|
|
960
|
+
| `onWarnUpsell` | — | — | Callback fired on a `warn` verdict (Path A upsell hook) |
|
|
961
|
+
| `attribution` | `TWZRD_ATTRIBUTION_INTEGRATION` + `TWZRD_ATTRIBUTION_RUN_ID` | — | Opt-in run attribution (see below) |
|
|
962
|
+
|
|
963
|
+
The four options below are **not** `TwzrdGateConfig` fields — they belong to
|
|
964
|
+
`TwzrdGuardOptions` / `InstallAutoGateOptions` (`withTwzrdGuard` /
|
|
965
|
+
`installTwzrdAutoGate`). Passing them to `createTwzrdGate({...})` is a type error
|
|
966
|
+
and is silently dropped at runtime:
|
|
967
|
+
|
|
968
|
+
| Option | Env | Default | Description |
|
|
969
|
+
|---|---|---|---|
|
|
775
970
|
| `autoReceipt` | — | `false` | Auto-buy $0.05 TWZRD receipt on warn/allow |
|
|
776
971
|
| `x402Fetch` | — | — | x402-capable fetch for `autoReceipt` |
|
|
777
972
|
| `onReceipt` | — | — | Callback after receipt is captured |
|
|
778
973
|
| `disabled` (`installTwzrdAutoGate` only) | `TWZRD_AUTO_GATE=0`/`false` | `false` | Bypass the guard entirely — `payWrap` gets the raw, unguarded fetch |
|
|
779
|
-
| `attribution` | `TWZRD_ATTRIBUTION_INTEGRATION` + `TWZRD_ATTRIBUTION_RUN_ID` | — | Opt-in run attribution (see below) |
|
|
780
974
|
|
|
781
975
|
## Gate adoption proof (no-spend harness)
|
|
782
976
|
|
|
@@ -836,3 +1030,38 @@ whether to proceed before any USDC leaves your wallet.
|
|
|
836
1030
|
## License
|
|
837
1031
|
|
|
838
1032
|
MIT
|
|
1033
|
+
|
|
1034
|
+
|
|
1035
|
+
## Pay Kit before-payment hook (upstream PR pending)
|
|
1036
|
+
|
|
1037
|
+
`solana-foundation/pay-kit#303` is open as of 2026-09-07. This adapter targets
|
|
1038
|
+
that PR's `onBeforeX402PaymentCreation` option; a released Pay Kit client must
|
|
1039
|
+
expose that option before this integration can enforce policy.
|
|
1040
|
+
|
|
1041
|
+
```ts
|
|
1042
|
+
import { createPayKitClient } from "@solana/pay-kit";
|
|
1043
|
+
import { installTwzrdAutoGate } from "twzrd-x402-gate";
|
|
1044
|
+
|
|
1045
|
+
const client = await createPayKitClient({
|
|
1046
|
+
accept: ["x402"],
|
|
1047
|
+
rpcUrl,
|
|
1048
|
+
signer,
|
|
1049
|
+
onBeforeX402PaymentCreation: installTwzrdAutoGate("pay-kit", {
|
|
1050
|
+
refuseWashFlagged: true,
|
|
1051
|
+
}),
|
|
1052
|
+
});
|
|
1053
|
+
```
|
|
1054
|
+
|
|
1055
|
+
The adapter returns the official x402 context hook and reuses the shared
|
|
1056
|
+
before-payment evaluator. It adds no Pay Kit dependency. Supply it at client
|
|
1057
|
+
construction; passing the constructed Pay Kit client to AutoGate is unsupported.
|
|
1058
|
+
This hook covers x402 payment creation, not Pay Kit's MPP path.
|
|
1059
|
+
|
|
1060
|
+
`createTwzrdPayKitBeforePaymentHook(options)` exposes the same evaluator directly.
|
|
1061
|
+
The AutoGate form reads environment kill switches on every call; the direct
|
|
1062
|
+
factory does not. Calling AutoGate installs protection by default, whereas
|
|
1063
|
+
ClawRouter's integration loads AutoGate only after explicit opt-in.
|
|
1064
|
+
|
|
1065
|
+
Source-checkout verification: `npx tsx test/pay-kit-before-payment.test.ts`.
|
|
1066
|
+
The test covers a fake Pay Kit host and the real x402 client with a fake scheme;
|
|
1067
|
+
it does not establish released Pay Kit compatibility or external use.
|
package/dist/auto-gate.d.ts
CHANGED
|
@@ -3,11 +3,12 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Design: docs/strategy/install-autogate-design.md (#1586).
|
|
5
5
|
*
|
|
6
|
-
* One name across
|
|
6
|
+
* One name across five adapters:
|
|
7
7
|
* 1. Fetch / payWrap — guard raw fetch, then hand to x402 payer
|
|
8
8
|
* 2. x402 client — onBeforePaymentCreation (@x402/core Path E)
|
|
9
9
|
* 3. x402-solana seat — beforePayment on createX402Client (PayAI 2.1.0+)
|
|
10
10
|
* 4. MPP — onChallenge via createTwzrdMppOnChallenge
|
|
11
|
+
* 5. PayKit — onBeforeX402PaymentCreation (upstream PR #303)
|
|
11
12
|
*
|
|
12
13
|
* Default ON. Kill switch (any):
|
|
13
14
|
* TWZRD_AUTO_GATE=0|false
|
|
@@ -15,7 +16,7 @@
|
|
|
15
16
|
* options.disabled: true
|
|
16
17
|
*/
|
|
17
18
|
import { type TwzrdGuardOptions } from "./with-guard.js";
|
|
18
|
-
import { type BeforePaymentCreationResult, type InstallX402ClientHookOptions, type X402ClientLike, type X402SelectedRequirements, type X402SolanaBeforePaymentContext } from "./x402-client-hook.js";
|
|
19
|
+
import { type BeforePaymentCreationContext, type BeforePaymentCreationResult, type InstallX402ClientHookOptions, type X402ClientLike, type X402SelectedRequirements, type X402SolanaBeforePaymentContext } from "./x402-client-hook.js";
|
|
19
20
|
import { type MppOnChallengeHelpers, type MppOnChallengeOptions, type MppChallenge } from "./mpp-hook.js";
|
|
20
21
|
/**
|
|
21
22
|
* Takes a guarded (pre-pay-checked) fetch and returns the fetch your agent actually
|
|
@@ -78,6 +79,8 @@ export declare function installTwzrdAutoGate(adapter: "mpp", options: InstallAut
|
|
|
78
79
|
* });
|
|
79
80
|
*/
|
|
80
81
|
export declare function installTwzrdAutoGate(adapter: "x402-solana", options?: InstallAutoGateX402Options): (requirements: X402SelectedRequirements & Record<string, unknown>, context?: X402SolanaBeforePaymentContext) => Promise<BeforePaymentCreationResult>;
|
|
82
|
+
/** PayKit PR #303 construction-time hook; env kill switches are read per call. */
|
|
83
|
+
export declare function installTwzrdAutoGate(adapter: "pay-kit", options?: InstallAutoGateX402Options): (context: BeforePaymentCreationContext) => Promise<BeforePaymentCreationResult>;
|
|
81
84
|
/**
|
|
82
85
|
* Disable a prior installTwzrdAutoGate on an x402 client (soft uninstall).
|
|
83
86
|
* Fetch compositions cannot be uninstalled — rebuild with disabled:true instead.
|
package/dist/auto-gate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auto-gate.d.ts","sourceRoot":"","sources":["../src/auto-gate.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"auto-gate.d.ts","sourceRoot":"","sources":["../src/auto-gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAkB,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzE,OAAO,EAGL,KAAK,4BAA4B,EAEjC,KAAK,2BAA2B,EAChC,KAAK,4BAA4B,EACjC,KAAK,cAAc,EACnB,KAAK,wBAAwB,EAC7B,KAAK,8BAA8B,EACpC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAEL,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,YAAY,EAClB,MAAM,eAAe,CAAC;AAEvB;;;GAGG;AACH,MAAM,MAAM,OAAO,GAAG,CAAC,YAAY,EAAE,OAAO,KAAK,KAAK,OAAO,KAAK,CAAC;AAEnE,MAAM,MAAM,0BAA0B,GAAG;IACvC;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG,iBAAiB,GACzD,0BAA0B,GAAG;IAC3B;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,KAAK,CAAC;CACzB,CAAC;AAEJ,kFAAkF;AAClF,MAAM,MAAM,sBAAsB,GAAG,2BAA2B,CAAC;AAEjE,MAAM,MAAM,0BAA0B,GAAG,4BAA4B,GACnE,0BAA0B,CAAC;AAE7B,MAAM,MAAM,yBAAyB,GAAG,qBAAqB,GAC3D,0BAA0B,CAAC;AAM7B,8DAA8D;AAC9D,wBAAgB,uBAAuB,CAAC,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAOjF;AAcD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,2BAA2B,GACpC,OAAO,KAAK,CAAC;AAEhB;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,cAAc,EACtB,OAAO,CAAC,EAAE,0BAA0B,GACnC,cAAc,CAAC;AAElB;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,KAAK,EACd,OAAO,EAAE,yBAAyB,GACjC,CAAC,SAAS,EAAE,YAAY,EAAE,OAAO,EAAE,qBAAqB,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;AAE5F;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,aAAa,EACtB,OAAO,CAAC,EAAE,0BAA0B,GACnC,CACD,YAAY,EAAE,wBAAwB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChE,OAAO,CAAC,EAAE,8BAA8B,KACrC,OAAO,CAAC,2BAA2B,CAAC,CAAC;AAE1C,kFAAkF;AAClF,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,SAAS,EAClB,OAAO,CAAC,EAAE,0BAA0B,GACnC,CAAC,OAAO,EAAE,4BAA4B,KAAK,OAAO,CAAC,2BAA2B,CAAC,CAAC;AA4FnF;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CASnE"}
|