twzrd-x402-gate 0.7.0 → 0.8.1
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/README.md +36 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/seller-hook.d.ts +160 -0
- package/dist/seller-hook.d.ts.map +1 -0
- package/dist/seller-hook.js +299 -0
- package/dist/seller-hook.js.map +1 -0
- package/dist/types.d.ts +2 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -6,6 +6,39 @@ Agent-side firewall: after the client selects the exact payment requirement and
|
|
|
6
6
|
payment payload creation / wallet signing — free preflight + merchant_card wash refuse.
|
|
7
7
|
Chain-neutral envelope; **Solana-deep** reputation only (Base/EVM = explicit `unknown`).
|
|
8
8
|
|
|
9
|
+
|
|
10
|
+
## Demonstrable refuse mechanism (free, fail-open, reproducible)
|
|
11
|
+
|
|
12
|
+
**Status (2026-07-16):** mechanism proof — not adoption or demand.
|
|
13
|
+
|
|
14
|
+
Install the published gate and run against wash fixtures:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install twzrd-x402-gate@0.7.1
|
|
18
|
+
# from package root after install, or from a checkout:
|
|
19
|
+
npm run wash-dogfood
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Verified live (2026-07-16):**
|
|
23
|
+
|
|
24
|
+
| Fixture | preflight_id | decision | note |
|
|
25
|
+
|---------|--------------|----------|------|
|
|
26
|
+
| `7G73PL…` wash dogfood | 378468 | **block** | wash_flagged=true |
|
|
27
|
+
| `HuSiSpc…` | 378469 | **block** | wash_flagged=true, fleet≈98% |
|
|
28
|
+
| `BJGds…` alt wash | 378470 | warn | wash_flagged=true (nuance — not all wash is hard-block) |
|
|
29
|
+
| `4LkEF…` clean control | 378471 | warn | not wash |
|
|
30
|
+
|
|
31
|
+
Gate dogfood: `approved=false` `reason=twzrd_decision_block`, **USDC spent = 0**, **tx broadcast = none**, ALL PASS.
|
|
32
|
+
|
|
33
|
+
**Public transcript:** https://gist.github.com/twzrd-sol/2882bddee912f89e99061f3bc1da8227
|
|
34
|
+
|
|
35
|
+
**Accurate paste line:**
|
|
36
|
+
|
|
37
|
+
> 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.7.1 && npm run wash-dogfood` or gist above.
|
|
38
|
+
|
|
39
|
+
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.
|
|
40
|
+
|
|
41
|
+
|
|
9
42
|
## Canonical integration (official x402 client)
|
|
10
43
|
|
|
11
44
|
```typescript
|
|
@@ -90,9 +123,11 @@ Dogfood:
|
|
|
90
123
|
## Install
|
|
91
124
|
|
|
92
125
|
```bash
|
|
93
|
-
npm install twzrd-x402-gate
|
|
126
|
+
npm install twzrd-x402-gate@0.7.1
|
|
94
127
|
```
|
|
95
128
|
|
|
129
|
+
Current npm truth: check `npm view twzrd-x402-gate version` (do not pin stale **0.5.4**).
|
|
130
|
+
|
|
96
131
|
## TWZRD Payment Control (protocol-neutral authorization core)
|
|
97
132
|
|
|
98
133
|
The gate now ships a protocol-neutral policy runtime underneath the x402 surface.
|
package/dist/index.d.ts
CHANGED
|
@@ -21,4 +21,5 @@ export { createMemorySpendLedger, evaluateIntent, POLICY_VERSION, type Counterpa
|
|
|
21
21
|
export { ap2CheckoutToIntent, x402RequirementsToIntent, type Ap2Cart, type Ap2UserMandate, type X402IntentContext, } from "./intent-adapters.js";
|
|
22
22
|
export { createTwzrdMppOnChallenge, mppChallengeToIntent, mppChallengeDigest, NATIVE_SOL_CURRENCY, TwzrdMppBlockError, type MppChallenge, type MppIntentContext, type MppOnChallengeHelpers, type MppOnChallengeOptions, type MppSolanaChargeRequest, } from "./mpp-hook.js";
|
|
23
23
|
export { approvalToIntelligence, counterpartyKnownFromApproval, createTwzrdIntelligenceProvider, intentAmountToPriceUsd, type TwzrdIntelligenceOptions, } from "./intelligence.js";
|
|
24
|
+
export { createTwzrdSettleGuard, defaultExtractPayer, extractSvmPayerFromTransaction, twzrdPayerScreen, toPayaiVerifyResult, type SettleGuardContext, type SettleGuardAbort, type SettleGuardResult, type PayerScreen, type ScreenFn, type GetPayerFn, type SettleGuardOptions, } from "./seller-hook.js";
|
|
24
25
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -24,4 +24,7 @@ export { createMemorySpendLedger, evaluateIntent, POLICY_VERSION, } from "./poli
|
|
|
24
24
|
export { ap2CheckoutToIntent, x402RequirementsToIntent, } from "./intent-adapters.js";
|
|
25
25
|
export { createTwzrdMppOnChallenge, mppChallengeToIntent, mppChallengeDigest, NATIVE_SOL_CURRENCY, TwzrdMppBlockError, } from "./mpp-hook.js";
|
|
26
26
|
export { approvalToIntelligence, counterpartyKnownFromApproval, createTwzrdIntelligenceProvider, intentAmountToPriceUsd, } from "./intelligence.js";
|
|
27
|
+
// Seller-side (resource server) pre-settlement payer screening — the mirror of
|
|
28
|
+
// the buyer gate. Attaches to x402ResourceServer.onBeforeSettle; advisory + fail-open.
|
|
29
|
+
export { createTwzrdSettleGuard, defaultExtractPayer, extractSvmPayerFromTransaction, twzrdPayerScreen, toPayaiVerifyResult, } from "./seller-hook.js";
|
|
27
30
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,qFAAqF;AACrF,uFAAuF;AACvF,qFAAqF;AACrF,OAAO,EAAE,eAAe,EAAE,WAAW,EAAkB,MAAM,WAAW,CAAC;AACzE,OAAO,EAAE,aAAa,EAAgC,MAAM,aAAa,CAAC;AAC1E,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,mBAAmB,GAEpB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC/F,OAAO,EACL,eAAe,EACf,wBAAwB,EACxB,YAAY,GAKb,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,iBAAiB,EACjB,sBAAsB,GAIvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EACL,sBAAsB,GAGvB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,cAAc,EAA0B,MAAM,iBAAiB,CAAC;AACzE,OAAO,EACL,oBAAoB,GAGrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,SAAS,EACT,iBAAiB,EACjB,IAAI,IAAI,aAAa,GAGtB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,0BAA0B,EAC1B,0BAA0B,GAO3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,UAAU,EACV,gBAAgB,GAIjB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,wBAAwB,GAGzB,MAAM,gBAAgB,CAAC;AAexB,uEAAuE;AACvE,OAAO,EACL,aAAa,EACb,UAAU,EACV,UAAU,EACV,kBAAkB,GAGnB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,yBAAyB,EACzB,0BAA0B,EAC1B,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,uBAAuB,EACvB,uBAAuB,GAQxB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,uBAAuB,EACvB,cAAc,EACd,cAAc,GAOf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,mBAAmB,EACnB,wBAAwB,GAIzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,yBAAyB,EACzB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,GAMnB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,sBAAsB,EACtB,6BAA6B,EAC7B,+BAA+B,EAC/B,sBAAsB,GAEvB,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,qFAAqF;AACrF,uFAAuF;AACvF,qFAAqF;AACrF,OAAO,EAAE,eAAe,EAAE,WAAW,EAAkB,MAAM,WAAW,CAAC;AACzE,OAAO,EAAE,aAAa,EAAgC,MAAM,aAAa,CAAC;AAC1E,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,mBAAmB,GAEpB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC/F,OAAO,EACL,eAAe,EACf,wBAAwB,EACxB,YAAY,GAKb,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,iBAAiB,EACjB,sBAAsB,GAIvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EACL,sBAAsB,GAGvB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,cAAc,EAA0B,MAAM,iBAAiB,CAAC;AACzE,OAAO,EACL,oBAAoB,GAGrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,SAAS,EACT,iBAAiB,EACjB,IAAI,IAAI,aAAa,GAGtB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,0BAA0B,EAC1B,0BAA0B,GAO3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,UAAU,EACV,gBAAgB,GAIjB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,wBAAwB,GAGzB,MAAM,gBAAgB,CAAC;AAexB,uEAAuE;AACvE,OAAO,EACL,aAAa,EACb,UAAU,EACV,UAAU,EACV,kBAAkB,GAGnB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,yBAAyB,EACzB,0BAA0B,EAC1B,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,uBAAuB,EACvB,uBAAuB,GAQxB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,uBAAuB,EACvB,cAAc,EACd,cAAc,GAOf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,mBAAmB,EACnB,wBAAwB,GAIzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,yBAAyB,EACzB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,GAMnB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,sBAAsB,EACtB,6BAA6B,EAC7B,+BAA+B,EAC/B,sBAAsB,GAEvB,MAAM,mBAAmB,CAAC;AAC3B,+EAA+E;AAC/E,uFAAuF;AACvF,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EACnB,8BAA8B,EAC9B,gBAAgB,EAChB,mBAAmB,GAQpB,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seller-side x402 pre-settlement guard — the MIRROR of the buyer gate.
|
|
3
|
+
*
|
|
4
|
+
* The rest of this package gates a PAYER's outgoing spend (buyer screens the
|
|
5
|
+
* seller before paying). This module is the other direction: a resource server
|
|
6
|
+
* (SELLER), before it settles an incoming x402 payment, screens the PAYER
|
|
7
|
+
* against TWZRD's payer-graph reputation and can veto settlement of
|
|
8
|
+
* wash / sybil / abusive payers — keeping the seller's own demand-quality
|
|
9
|
+
* reputation clean (captive/wash inbound is exactly what TWZRD flags).
|
|
10
|
+
*
|
|
11
|
+
* Attaches to the official, unit-tested `x402ResourceServer.onBeforeSettle`
|
|
12
|
+
* hook (inherited by @x402/express|hono|next|fastify and python x402), whose
|
|
13
|
+
* contract is:
|
|
14
|
+
* BeforeSettleHook = (ctx) => Promise<void | { abort: true; reason; message? }>
|
|
15
|
+
* TWZRD is NEVER in the settlement path: the guard is ADVISORY and FAIL-OPEN —
|
|
16
|
+
* any error, timeout, unresolved payer, or unavailable signal returns "continue"
|
|
17
|
+
* (void), never blocking legitimate revenue on infra failure (unless
|
|
18
|
+
* `failOpen: false` is set intentionally).
|
|
19
|
+
*
|
|
20
|
+
* Vendor-neutral: the context view and payer extractor are structural, so the
|
|
21
|
+
* same guard fits PayAI agentic-payments `onPaymentVerified` (returns
|
|
22
|
+
* `{ reject: true }` — see toPayaiVerifyResult) and any hook that exposes the
|
|
23
|
+
* payer. Zero hard runtime deps; `screen` is injected for testability.
|
|
24
|
+
* Optional peer `@x402/svm` is used only to recover the token payer from an
|
|
25
|
+
* exact-SVM base64 transaction payload.
|
|
26
|
+
*/
|
|
27
|
+
import type { TwzrdDecision } from "./types.js";
|
|
28
|
+
/**
|
|
29
|
+
* Minimal structural view of an x402 `BeforeSettleHook`/`BeforeVerifyHook`
|
|
30
|
+
* context. Mirrors @x402/core (paymentPayload + requirements) WITHOUT importing
|
|
31
|
+
* the SDK, so this stays zero-dep and runtime-agnostic. x402 `PaymentPayload`
|
|
32
|
+
* carries the scheme-specific `payload: Record<string, unknown>` where the payer
|
|
33
|
+
* lives (its exact key varies by scheme: exact-svm vs exact-evm).
|
|
34
|
+
*/
|
|
35
|
+
export type SettleGuardContext = {
|
|
36
|
+
paymentPayload?: {
|
|
37
|
+
payload?: Record<string, unknown> | null;
|
|
38
|
+
payer?: unknown;
|
|
39
|
+
[k: string]: unknown;
|
|
40
|
+
} | null;
|
|
41
|
+
requirements?: unknown;
|
|
42
|
+
[k: string]: unknown;
|
|
43
|
+
};
|
|
44
|
+
/** The abort object the x402 onBeforeSettle/onBeforeVerify hook understands. */
|
|
45
|
+
export type SettleGuardAbort = {
|
|
46
|
+
abort: true;
|
|
47
|
+
reason: string;
|
|
48
|
+
message?: string;
|
|
49
|
+
};
|
|
50
|
+
/** void = continue settlement; SettleGuardAbort = veto before money moves. */
|
|
51
|
+
export type SettleGuardResult = void | SettleGuardAbort;
|
|
52
|
+
/**
|
|
53
|
+
* Result of screening a payer wallet against TWZRD. All fields optional so an
|
|
54
|
+
* unavailable signal fails open (undefined/null -> no abort) when failOpen.
|
|
55
|
+
*/
|
|
56
|
+
export type PayerScreen = {
|
|
57
|
+
decision?: TwzrdDecision;
|
|
58
|
+
/** true = wash/sybil payer; false = clean; null/undefined = signal unavailable. */
|
|
59
|
+
washFlagged?: boolean | null;
|
|
60
|
+
tier?: string | null;
|
|
61
|
+
inCorpus?: boolean;
|
|
62
|
+
score?: number | null;
|
|
63
|
+
reason?: string;
|
|
64
|
+
};
|
|
65
|
+
export type ScreenFn = (payer: string, ctx: SettleGuardContext) => Promise<PayerScreen | null> | PayerScreen | null;
|
|
66
|
+
export type GetPayerFn = (ctx: SettleGuardContext) => string | null | undefined | Promise<string | null | undefined>;
|
|
67
|
+
export type SettleGuardOptions = {
|
|
68
|
+
/**
|
|
69
|
+
* How to score the incoming payer. Injected for testability + vendor
|
|
70
|
+
* neutrality. Use `twzrdPayerScreen()` for the default free merchant_card
|
|
71
|
+
* screen, or supply your own (e.g. a paid /v1/intel/trust call, or a cache).
|
|
72
|
+
*/
|
|
73
|
+
screen: ScreenFn;
|
|
74
|
+
/** Extract the payer wallet from the hook context. Default: defaultExtractPayer. */
|
|
75
|
+
getPayer?: GetPayerFn;
|
|
76
|
+
/**
|
|
77
|
+
* Which screen outcomes abort settlement. Default: block + wash-flagged abort;
|
|
78
|
+
* warn is allowed (matches the buyer gate's "gate only on block/wash" default).
|
|
79
|
+
*/
|
|
80
|
+
abortOn?: {
|
|
81
|
+
block?: boolean;
|
|
82
|
+
warn?: boolean;
|
|
83
|
+
washFlagged?: boolean;
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* On screen error/timeout/unresolved-payer/null-screen, continue (never block
|
|
87
|
+
* real revenue on infra failure). Default: true. Set false only if you would
|
|
88
|
+
* rather refuse a payment than settle one you could not screen.
|
|
89
|
+
*/
|
|
90
|
+
failOpen?: boolean;
|
|
91
|
+
/**
|
|
92
|
+
* Max ms to wait for `screen` (and async payer extraction). Default 3000.
|
|
93
|
+
* On timeout: fail-open continues, fail-closed aborts with
|
|
94
|
+
* `twzrd_screen_timeout`. Set 0 to disable.
|
|
95
|
+
*/
|
|
96
|
+
timeoutMs?: number;
|
|
97
|
+
/** Optional per-call observability. Never throws into the payment path. */
|
|
98
|
+
onDecision?: (info: {
|
|
99
|
+
payer: string | null;
|
|
100
|
+
screen: PayerScreen | null;
|
|
101
|
+
aborted: boolean;
|
|
102
|
+
reason: string;
|
|
103
|
+
}) => void;
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Recover the token payer (owner of the source ATA) from an exact-SVM base64
|
|
107
|
+
* transaction via optional peer `@x402/svm`. Returns null when the peer is
|
|
108
|
+
* missing or the payload cannot be decoded.
|
|
109
|
+
*/
|
|
110
|
+
export declare function extractSvmPayerFromTransaction(transaction: string): Promise<string | null>;
|
|
111
|
+
/**
|
|
112
|
+
* Authoritative payer extraction across x402 schemes (svm/evm) and PayAI-flat
|
|
113
|
+
* shapes.
|
|
114
|
+
*
|
|
115
|
+
* Priority (signed/encoded first — never let a client-supplied alias outrank
|
|
116
|
+
* them):
|
|
117
|
+
* 1. exact-EVM EIP-3009 `payload.authorization.from`
|
|
118
|
+
* 2. exact-EVM Permit2 `payload.permit2Authorization.from`
|
|
119
|
+
* 3. exact-SVM `payload.transaction` → decode via optional `@x402/svm`
|
|
120
|
+
* 4. Loose aliases (`payload.payer|from|account|sender`, top-level
|
|
121
|
+
* `paymentPayload.payer`, flat `ctx.payer`) ONLY when no authoritative
|
|
122
|
+
* scheme shape is present — otherwise a spoofed `payer: "clean"` next to
|
|
123
|
+
* a signed wash authorization would bypass screening.
|
|
124
|
+
*
|
|
125
|
+
* Async because SVM recovery may dynamic-import the optional peer.
|
|
126
|
+
* Returns null when unresolved (-> fail-open / fail-closed per options).
|
|
127
|
+
*/
|
|
128
|
+
export declare function defaultExtractPayer(ctx: SettleGuardContext): Promise<string | null>;
|
|
129
|
+
/**
|
|
130
|
+
* Create an x402 `onBeforeSettle(hook)` that screens the incoming PAYER against
|
|
131
|
+
* TWZRD and vetoes wash/blocked payers before settlement. Advisory + fail-open
|
|
132
|
+
* by default (with a hard timeout around screening).
|
|
133
|
+
*
|
|
134
|
+
* const server = new x402ResourceServer(facilitator);
|
|
135
|
+
* server.onBeforeSettle(createTwzrdSettleGuard({ screen: twzrdPayerScreen() }));
|
|
136
|
+
*/
|
|
137
|
+
export declare function createTwzrdSettleGuard(opts: SettleGuardOptions): (ctx: SettleGuardContext) => Promise<SettleGuardResult>;
|
|
138
|
+
/**
|
|
139
|
+
* Reference payer screen: free `GET /v1/intel/merchant_card/{payer}`. Returns
|
|
140
|
+
* the wash signal for the payer wallet (fail-open null on outage/absent). The
|
|
141
|
+
* free merchant_card is keyed by any wallet that appears in the corpus as a
|
|
142
|
+
* counterparty, so it resolves payer wallets too. For richer screening
|
|
143
|
+
* (decision/score) inject a `screen` that calls the paid `/v1/intel/trust`
|
|
144
|
+
* endpoint instead — kept out of the default to avoid a per-payment cost on the
|
|
145
|
+
* hot path.
|
|
146
|
+
*/
|
|
147
|
+
export declare function twzrdPayerScreen(opts?: {
|
|
148
|
+
intelBase?: string;
|
|
149
|
+
fetch?: typeof fetch;
|
|
150
|
+
}): ScreenFn;
|
|
151
|
+
/**
|
|
152
|
+
* Adapt a SettleGuardResult to the PayAI agentic-payments `onPaymentVerified`
|
|
153
|
+
* return shape (`{ reject: true, reason }`). PayAI swallows thrown hook errors,
|
|
154
|
+
* so a guard must RETURN the reject object, not throw — this helper does that.
|
|
155
|
+
*/
|
|
156
|
+
export declare function toPayaiVerifyResult(result: SettleGuardResult): {
|
|
157
|
+
reject: true;
|
|
158
|
+
reason: string;
|
|
159
|
+
} | undefined;
|
|
160
|
+
//# sourceMappingURL=seller-hook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seller-hook.d.ts","sourceRoot":"","sources":["../src/seller-hook.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seller-side x402 pre-settlement guard — the MIRROR of the buyer gate.
|
|
3
|
+
*
|
|
4
|
+
* The rest of this package gates a PAYER's outgoing spend (buyer screens the
|
|
5
|
+
* seller before paying). This module is the other direction: a resource server
|
|
6
|
+
* (SELLER), before it settles an incoming x402 payment, screens the PAYER
|
|
7
|
+
* against TWZRD's payer-graph reputation and can veto settlement of
|
|
8
|
+
* wash / sybil / abusive payers — keeping the seller's own demand-quality
|
|
9
|
+
* reputation clean (captive/wash inbound is exactly what TWZRD flags).
|
|
10
|
+
*
|
|
11
|
+
* Attaches to the official, unit-tested `x402ResourceServer.onBeforeSettle`
|
|
12
|
+
* hook (inherited by @x402/express|hono|next|fastify and python x402), whose
|
|
13
|
+
* contract is:
|
|
14
|
+
* BeforeSettleHook = (ctx) => Promise<void | { abort: true; reason; message? }>
|
|
15
|
+
* TWZRD is NEVER in the settlement path: the guard is ADVISORY and FAIL-OPEN —
|
|
16
|
+
* any error, timeout, unresolved payer, or unavailable signal returns "continue"
|
|
17
|
+
* (void), never blocking legitimate revenue on infra failure (unless
|
|
18
|
+
* `failOpen: false` is set intentionally).
|
|
19
|
+
*
|
|
20
|
+
* Vendor-neutral: the context view and payer extractor are structural, so the
|
|
21
|
+
* same guard fits PayAI agentic-payments `onPaymentVerified` (returns
|
|
22
|
+
* `{ reject: true }` — see toPayaiVerifyResult) and any hook that exposes the
|
|
23
|
+
* payer. Zero hard runtime deps; `screen` is injected for testability.
|
|
24
|
+
* Optional peer `@x402/svm` is used only to recover the token payer from an
|
|
25
|
+
* exact-SVM base64 transaction payload.
|
|
26
|
+
*/
|
|
27
|
+
import { fetchMerchantCard } from "./merchant-card.js";
|
|
28
|
+
const DEFAULT_ABORT_ON = { block: true, warn: false, washFlagged: true };
|
|
29
|
+
/** Default screen budget — short so settlement is not held open. */
|
|
30
|
+
const DEFAULT_TIMEOUT_MS = 3000;
|
|
31
|
+
function asNonEmptyString(v) {
|
|
32
|
+
if (typeof v === "string" && v.trim())
|
|
33
|
+
return v.trim();
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
function recordOf(v) {
|
|
37
|
+
return v && typeof v === "object" ? v : null;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* True when the payload has an authoritative scheme shape whose payer must come
|
|
41
|
+
* from signed/encoded fields — not from client-supplied aliases like `payer`.
|
|
42
|
+
*/
|
|
43
|
+
function hasAuthoritativeSchemeShape(pl) {
|
|
44
|
+
if (!pl)
|
|
45
|
+
return false;
|
|
46
|
+
if (recordOf(pl.authorization))
|
|
47
|
+
return true;
|
|
48
|
+
if (recordOf(pl.permit2Authorization))
|
|
49
|
+
return true;
|
|
50
|
+
if (typeof pl.transaction === "string" && pl.transaction.trim())
|
|
51
|
+
return true;
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Recover the token payer (owner of the source ATA) from an exact-SVM base64
|
|
56
|
+
* transaction via optional peer `@x402/svm`. Returns null when the peer is
|
|
57
|
+
* missing or the payload cannot be decoded.
|
|
58
|
+
*/
|
|
59
|
+
export async function extractSvmPayerFromTransaction(transaction) {
|
|
60
|
+
const tx = transaction.trim();
|
|
61
|
+
// Cheap reject before dynamic import / upstream console.error on garbage.
|
|
62
|
+
if (!tx || tx.length < 32 || !/^[A-Za-z0-9+/]+=*$/.test(tx))
|
|
63
|
+
return null;
|
|
64
|
+
try {
|
|
65
|
+
const svm = await import("@x402/svm");
|
|
66
|
+
const decoded = svm.decodeTransactionFromPayload({ transaction: tx });
|
|
67
|
+
const payer = svm.getTokenPayerFromTransaction(decoded);
|
|
68
|
+
return asNonEmptyString(payer);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async function withTimeout(work, timeoutMs, label) {
|
|
75
|
+
if (!timeoutMs || timeoutMs <= 0)
|
|
76
|
+
return work;
|
|
77
|
+
let timer;
|
|
78
|
+
try {
|
|
79
|
+
return await Promise.race([
|
|
80
|
+
work,
|
|
81
|
+
new Promise((_, reject) => {
|
|
82
|
+
timer = setTimeout(() => reject(new Error(label)), timeoutMs);
|
|
83
|
+
}),
|
|
84
|
+
]);
|
|
85
|
+
}
|
|
86
|
+
finally {
|
|
87
|
+
if (timer)
|
|
88
|
+
clearTimeout(timer);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Authoritative payer extraction across x402 schemes (svm/evm) and PayAI-flat
|
|
93
|
+
* shapes.
|
|
94
|
+
*
|
|
95
|
+
* Priority (signed/encoded first — never let a client-supplied alias outrank
|
|
96
|
+
* them):
|
|
97
|
+
* 1. exact-EVM EIP-3009 `payload.authorization.from`
|
|
98
|
+
* 2. exact-EVM Permit2 `payload.permit2Authorization.from`
|
|
99
|
+
* 3. exact-SVM `payload.transaction` → decode via optional `@x402/svm`
|
|
100
|
+
* 4. Loose aliases (`payload.payer|from|account|sender`, top-level
|
|
101
|
+
* `paymentPayload.payer`, flat `ctx.payer`) ONLY when no authoritative
|
|
102
|
+
* scheme shape is present — otherwise a spoofed `payer: "clean"` next to
|
|
103
|
+
* a signed wash authorization would bypass screening.
|
|
104
|
+
*
|
|
105
|
+
* Async because SVM recovery may dynamic-import the optional peer.
|
|
106
|
+
* Returns null when unresolved (-> fail-open / fail-closed per options).
|
|
107
|
+
*/
|
|
108
|
+
export async function defaultExtractPayer(ctx) {
|
|
109
|
+
const pp = ctx?.paymentPayload ?? null;
|
|
110
|
+
const pl = pp && typeof pp === "object"
|
|
111
|
+
? (pp.payload ?? null)
|
|
112
|
+
: null;
|
|
113
|
+
// 1) EIP-3009 exact-EVM
|
|
114
|
+
const auth = recordOf(pl?.authorization);
|
|
115
|
+
const eipFrom = asNonEmptyString(auth?.from) ?? asNonEmptyString(auth?.payer);
|
|
116
|
+
if (eipFrom)
|
|
117
|
+
return eipFrom;
|
|
118
|
+
// 2) Permit2 exact-EVM
|
|
119
|
+
const permit2 = recordOf(pl?.permit2Authorization);
|
|
120
|
+
const permitFrom = asNonEmptyString(permit2?.from);
|
|
121
|
+
if (permitFrom)
|
|
122
|
+
return permitFrom;
|
|
123
|
+
// 3) exact-SVM base64 transaction (optional peer)
|
|
124
|
+
if (typeof pl?.transaction === "string" && pl.transaction.trim()) {
|
|
125
|
+
const svmPayer = await extractSvmPayerFromTransaction(pl.transaction);
|
|
126
|
+
if (svmPayer)
|
|
127
|
+
return svmPayer;
|
|
128
|
+
// Authoritative shape present but unrecoverable — do NOT fall through to
|
|
129
|
+
// spoofable aliases.
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
// 4) Loose / PayAI shapes only when no signed scheme body is present.
|
|
133
|
+
if (hasAuthoritativeSchemeShape(pl)) {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
const loose = [
|
|
137
|
+
pl?.payer,
|
|
138
|
+
pl?.from,
|
|
139
|
+
pl?.account,
|
|
140
|
+
pl?.sender,
|
|
141
|
+
pp && typeof pp === "object" ? pp.payer : null,
|
|
142
|
+
ctx?.payer,
|
|
143
|
+
];
|
|
144
|
+
for (const c of loose) {
|
|
145
|
+
const s = asNonEmptyString(c);
|
|
146
|
+
if (s)
|
|
147
|
+
return s;
|
|
148
|
+
}
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
function decideAbort(screen, abortOn) {
|
|
152
|
+
if (abortOn.washFlagged && screen.washFlagged === true) {
|
|
153
|
+
return {
|
|
154
|
+
abort: true,
|
|
155
|
+
reason: "twzrd_payer_wash_flagged",
|
|
156
|
+
message: "payer flagged as wash/sybil by TWZRD",
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
if (abortOn.block && screen.decision === "block") {
|
|
160
|
+
return {
|
|
161
|
+
abort: true,
|
|
162
|
+
reason: "twzrd_payer_block",
|
|
163
|
+
message: "payer scored block by TWZRD",
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
if (abortOn.warn && screen.decision === "warn") {
|
|
167
|
+
return {
|
|
168
|
+
abort: true,
|
|
169
|
+
reason: "twzrd_payer_warn",
|
|
170
|
+
message: "payer scored warn by TWZRD",
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Create an x402 `onBeforeSettle(hook)` that screens the incoming PAYER against
|
|
177
|
+
* TWZRD and vetoes wash/blocked payers before settlement. Advisory + fail-open
|
|
178
|
+
* by default (with a hard timeout around screening).
|
|
179
|
+
*
|
|
180
|
+
* const server = new x402ResourceServer(facilitator);
|
|
181
|
+
* server.onBeforeSettle(createTwzrdSettleGuard({ screen: twzrdPayerScreen() }));
|
|
182
|
+
*/
|
|
183
|
+
export function createTwzrdSettleGuard(opts) {
|
|
184
|
+
const abortOn = { ...DEFAULT_ABORT_ON, ...(opts.abortOn ?? {}) };
|
|
185
|
+
const failOpen = opts.failOpen !== false;
|
|
186
|
+
const getPayer = opts.getPayer ?? defaultExtractPayer;
|
|
187
|
+
const timeoutMs = typeof opts.timeoutMs === "number" ? opts.timeoutMs : DEFAULT_TIMEOUT_MS;
|
|
188
|
+
return async function twzrdSettleGuard(ctx) {
|
|
189
|
+
let payer = null;
|
|
190
|
+
const emit = (screen, aborted, reason) => {
|
|
191
|
+
try {
|
|
192
|
+
opts.onDecision?.({ payer, screen, aborted, reason });
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
/* observability must never break the payment path */
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
const run = async () => {
|
|
199
|
+
payer = (await getPayer(ctx)) ?? null;
|
|
200
|
+
if (!payer) {
|
|
201
|
+
if (!failOpen) {
|
|
202
|
+
emit(null, true, "twzrd_payer_unresolved_failclosed");
|
|
203
|
+
return {
|
|
204
|
+
abort: true,
|
|
205
|
+
reason: "twzrd_payer_unresolved",
|
|
206
|
+
message: "could not resolve payer wallet for screening",
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
emit(null, false, "twzrd_payer_unresolved");
|
|
210
|
+
return; // fail-open: cannot screen an unknown payer
|
|
211
|
+
}
|
|
212
|
+
const screen = await opts.screen(payer, ctx);
|
|
213
|
+
if (!screen) {
|
|
214
|
+
if (!failOpen) {
|
|
215
|
+
emit(null, true, "twzrd_screen_unavailable_failclosed");
|
|
216
|
+
return {
|
|
217
|
+
abort: true,
|
|
218
|
+
reason: "twzrd_screen_unavailable",
|
|
219
|
+
message: "payer screen returned no signal",
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
emit(null, false, "twzrd_screen_unavailable");
|
|
223
|
+
return; // fail-open: no signal, do not invent risk
|
|
224
|
+
}
|
|
225
|
+
const abort = decideAbort(screen, abortOn);
|
|
226
|
+
if (abort) {
|
|
227
|
+
emit(screen, true, abort.reason);
|
|
228
|
+
return abort;
|
|
229
|
+
}
|
|
230
|
+
emit(screen, false, screen.reason ?? "twzrd_payer_ok");
|
|
231
|
+
return;
|
|
232
|
+
};
|
|
233
|
+
try {
|
|
234
|
+
// Single end-to-end budget for extract + screen (documented timeout).
|
|
235
|
+
return await withTimeout(run(), timeoutMs, "twzrd_screen_timeout");
|
|
236
|
+
}
|
|
237
|
+
catch (err) {
|
|
238
|
+
const msg = String(err?.message ?? err);
|
|
239
|
+
const isTimeout = msg === "twzrd_screen_timeout" || /timeout/i.test(msg);
|
|
240
|
+
if (failOpen) {
|
|
241
|
+
emit(null, false, isTimeout ? "twzrd_screen_timeout_failopen" : "twzrd_screen_error_failopen");
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
emit(null, true, isTimeout ? "twzrd_screen_timeout_failclosed" : "twzrd_screen_error_failclosed");
|
|
245
|
+
return {
|
|
246
|
+
abort: true,
|
|
247
|
+
reason: isTimeout ? "twzrd_screen_timeout" : "twzrd_screen_error",
|
|
248
|
+
message: msg,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Reference payer screen: free `GET /v1/intel/merchant_card/{payer}`. Returns
|
|
255
|
+
* the wash signal for the payer wallet (fail-open null on outage/absent). The
|
|
256
|
+
* free merchant_card is keyed by any wallet that appears in the corpus as a
|
|
257
|
+
* counterparty, so it resolves payer wallets too. For richer screening
|
|
258
|
+
* (decision/score) inject a `screen` that calls the paid `/v1/intel/trust`
|
|
259
|
+
* endpoint instead — kept out of the default to avoid a per-payment cost on the
|
|
260
|
+
* hot path.
|
|
261
|
+
*/
|
|
262
|
+
export function twzrdPayerScreen(opts) {
|
|
263
|
+
const intelBase = (opts?.intelBase ??
|
|
264
|
+
process.env.TWZRD_INTEL_BASE ??
|
|
265
|
+
"https://intel.twzrd.xyz").replace(/\/+$/, "");
|
|
266
|
+
const fetchImpl = opts?.fetch ?? globalThis.fetch;
|
|
267
|
+
return async function screen(payer) {
|
|
268
|
+
const card = await fetchMerchantCard(payer, {
|
|
269
|
+
intelBase,
|
|
270
|
+
fetch: fetchImpl,
|
|
271
|
+
});
|
|
272
|
+
if (!card)
|
|
273
|
+
return null; // fail-open
|
|
274
|
+
const washFlagged = typeof card.wash_flagged === "boolean" ? card.wash_flagged : null;
|
|
275
|
+
const tier = typeof card.provider_reputation_tier === "string"
|
|
276
|
+
? card.provider_reputation_tier
|
|
277
|
+
: null;
|
|
278
|
+
return {
|
|
279
|
+
washFlagged,
|
|
280
|
+
tier,
|
|
281
|
+
inCorpus: card.in_corpus === true,
|
|
282
|
+
reason: washFlagged === true
|
|
283
|
+
? "twzrd_payer_wash_flagged"
|
|
284
|
+
: "twzrd_payer_merchant_card",
|
|
285
|
+
};
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Adapt a SettleGuardResult to the PayAI agentic-payments `onPaymentVerified`
|
|
290
|
+
* return shape (`{ reject: true, reason }`). PayAI swallows thrown hook errors,
|
|
291
|
+
* so a guard must RETURN the reject object, not throw — this helper does that.
|
|
292
|
+
*/
|
|
293
|
+
export function toPayaiVerifyResult(result) {
|
|
294
|
+
if (result && result.abort === true) {
|
|
295
|
+
return { reject: true, reason: result.reason };
|
|
296
|
+
}
|
|
297
|
+
return undefined;
|
|
298
|
+
}
|
|
299
|
+
//# sourceMappingURL=seller-hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seller-hook.js","sourceRoot":"","sources":["../src/seller-hook.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -41,10 +41,10 @@ export type TwzrdGateConfig = {
|
|
|
41
41
|
preflightMinScore?: number;
|
|
42
42
|
/** decision values that deny payment. Default: ["block"] */
|
|
43
43
|
blockDecisions?: Iterable<string>;
|
|
44
|
-
/** On preflight HTTP/network failure, approve payment. Default: true */
|
|
44
|
+
/** On preflight HTTP/network failure, approve payment (fail-open). Default: false (fail-closed); opt in with TWZRD_FAIL_OPEN=true. */
|
|
45
45
|
failOpen?: boolean;
|
|
46
46
|
/**
|
|
47
|
-
* Deny when the card reports can_spend=false. Default: true.
|
|
47
|
+
* Deny when the card reports can_spend=false. Default: false (decision-only; opt in with TWZRD_GATE_ON_CAN_SPEND=true).
|
|
48
48
|
* Free-tier preflight returns can_spend=false for most sellers (including
|
|
49
49
|
* well-known ones), so set false to follow the "gate only on decision=block"
|
|
50
50
|
* policy documented for ClawRouter/BlockRun in the twzrd-clawrouter skill.
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;AAEvD;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,aAAa,GAAG,SAAS,CAAC;AAE1D,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6EAA6E;IAC7E,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,qFAAqF;IACrF,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oGAAoG;IACpG,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,4FAA4F;IAC5F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wDAAwD;IACxD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,4DAA4D;IAC5D,cAAc,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAClC,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "twzrd-x402-gate",
|
|
3
|
-
"version": "0.
|
|
4
|
-
|
|
3
|
+
"version": "0.8.1",
|
|
4
|
+
"description": "Buyer-side x402 trust gate. Run a free TWZRD preflight (ReadinessCard) before signing USDC to any x402 merchant, and autonomously escalate a `warn` to a $0.001 paid trust check that re-decides — blocking the spend on bad paid intel, no human in the loop. Seller-side: screen payers before settling with createTwzrdSettleGuard (one-line x402ResourceServer.onBeforeSettle). Default refuse when free merchant_card.wash_flagged (opt out TWZRD_REFUSE_WASH_FLAGGED=0). A 402 with no extractable payTo fails closed (twzrd_unidentifiable_payment_recipient) instead of falling through to the generic unknown-seller warn. Wraps fetch (HTTP 402) and the @x402/mcp onPaymentRequested hook — fixed in 0.5.2 to read the real @x402/mcp v2 nested `paymentRequired.accepts` shape (verified against @x402/mcp@2.17.0; previously only the flat legacy shape was read, causing a silent 100%-false-block once wired into a real runtime). installTwzrdAutoGate(payWrap) is the default-on one-liner: guards the raw fetch, then hands it to your x402 client, so the correct guard-before-pay composition can't be built backwards. BREAKING(0.2.0): fail-closed by default — set TWZRD_FAIL_OPEN=true to restore legacy allow-on-outage behavior.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"build": "tsc",
|
|
28
28
|
"prepublishOnly": "tsc",
|
|
29
29
|
"typecheck": "tsc --noEmit -p tsconfig.check.json",
|
|
30
|
-
"test": "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/network.test.ts && tsx test/safe-fetch.test.ts && tsx test/challenge-swap.test.ts && tsx test/x402-client-hook.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",
|
|
30
|
+
"test": "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/network.test.ts && tsx test/safe-fetch.test.ts && tsx test/challenge-swap.test.ts && tsx test/x402-client-hook.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",
|
|
31
31
|
"safe-fetch": "tsx src/safe-fetch.ts",
|
|
32
32
|
"guard-demo": "tsx examples/agentic-market-gate.ts",
|
|
33
33
|
"autoreceipt-demo": "tsx examples/auto-receipt.ts --dry-run",
|