twzrd-x402-gate 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -178,6 +178,59 @@ installTwzrdX402ClientHook(client, {
178
178
  - Hook binding test:
179
179
  [`test/intent-binding.test.ts`](./test/intent-binding.test.ts).
180
180
 
181
+ ### On MPP (Machine Payments Protocol) — Solana charge only
182
+
183
+ `createTwzrdMppOnChallenge` guards `Mppx.create({ onChallenge })`. The mppx
184
+ Solana method signs AND broadcasts the transaction inside `createCredential()`,
185
+ so `onChallenge` is the last deterministic checkpoint before money moves - and
186
+ mppx re-throws `onChallenge` errors, so a TWZRD block is an exception that means
187
+ **`createCredential()` never runs and nothing signs**. On allow, the guard
188
+ creates the credential for the exact challenge it evaluated; non-`solana/charge`
189
+ challenges fail closed (`allowUnevaluated: true` to opt out).
190
+
191
+ ```typescript
192
+ import { Mppx } from "mppx/client";
193
+ import { client as solanaClient } from "mppx-solana";
194
+ import { createTwzrdMppOnChallenge, createLocalDecisionSigner } from "twzrd-x402-gate";
195
+
196
+ const mppx = Mppx.create({
197
+ methods: [solanaClient({ signer: wallet })],
198
+ onChallenge: createTwzrdMppOnChallenge({
199
+ signer: createLocalDecisionSigner(),
200
+ policy: { maxAmountUsd: "1.00" },
201
+ }),
202
+ });
203
+ ```
204
+
205
+ **Scope limit (honest):** the guard is authoritative only when no
206
+ `onChallengeReceived` event handler supplies a credential. mppx resolves
207
+ `eventCredential ?? onChallenge(...)`, so an event handler returning a credential
208
+ short-circuits the guard and pays ungated. Do not register both on one client.
209
+
210
+ **What it refuses, and why.** Each of these is a case where the transaction mppx
211
+ would actually sign is *not* the transaction the decision covers - so the guard
212
+ fails closed rather than approve a payment it cannot bind:
213
+
214
+ | Case | Code | Reason |
215
+ |---|---|---|
216
+ | Sponsored charge | `SPONSORED_CHARGE` | `sponsored` / `sponsorPath` / `feeTokenAmount` make mppx-solana build a **second transfer** to the sponsor on top of the advertised amount. PaymentIntent v1 binds one amount to one payTo, so approving it would authorize strictly more value than the decision covers. |
217
+ | 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. |
218
+ | 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. |
219
+ | Misdeclared decimals | `MALFORMED_CHALLENGE` | A known stablecoin declaring the wrong decimals is a discount attempt, not a rounding error. |
220
+
221
+ The intent binds a **digest of the entire normalized challenge**, not just
222
+ `realm:id` - swapping `recipient` or `amount` under the same challenge id changes
223
+ the intent hash, so the decision no longer matches.
224
+
225
+ **Verdicts:** `block` throws. `warn` **proceeds to pay** by default - set
226
+ `treatWarnAsBlock: true` to refuse on warn too.
227
+
228
+ - `mppChallengeToIntent` binds the challenge id + realm into the intent
229
+ (`resource.operation`), so the signed decision covers this exact challenge.
230
+ - Cluster names stay honest: `solana:devnet` classifies recognized-but-unscored.
231
+ - Proof: [`test/mpp-hook.test.ts`](./test/mpp-hook.test.ts) - block means
232
+ credential count 0 and signer count 0.
233
+
181
234
  ### Experimental CLI: `twzrd-safe-fetch` (AgentCash advisory pre-check)
182
235
 
183
236
  > **Not a challenge-bound firewall.** Classification: `advisory_precheck`.
File without changes
@@ -49,6 +49,24 @@ export declare function createLocalDecisionSigner(options?: {
49
49
  }): DecisionSigner & {
50
50
  publicKeyPem: string;
51
51
  };
52
+ /**
53
+ * Deterministic Ed25519 signer derived from high-entropy key material
54
+ * (issuer==verifier semantics with real signatures). The same secret always
55
+ * yields the same keypair, so an issuer can re-derive its signer across
56
+ * restarts without a keystore.
57
+ *
58
+ * The secret MUST be 32+ bytes of random material, hex or base64 encoded:
59
+ *
60
+ * openssl rand -hex 32
61
+ *
62
+ * Verifiers receive `publicKeyPem` — never the secret. Anyone holding the
63
+ * secret can mint ALLOW decisions, so it is signing key material, not a
64
+ * shared password. Prefer createLocalDecisionSigner with a managed key for
65
+ * anything beyond single-operator deployments.
66
+ */
67
+ export declare function createSeededDecisionSigner(secret: string, keyId?: string): DecisionSigner & {
68
+ publicKeyPem: string;
69
+ };
52
70
  export declare function signDecision(unsigned: Omit<PaymentDecision, "signature" | "keyId">, signer: DecisionSigner): Promise<PaymentDecision>;
53
71
  export declare function verifyDecisionSignature(token: PaymentDecision, publicKeyPem: string): boolean;
54
72
  export type BindingErrorCode = "INTENT_HASH_MISMATCH" | "DECISION_EXPIRED" | "DECISION_NOT_ALLOW" | "DECISION_REPLAYED" | "BAD_SIGNATURE";
@@ -1 +1 @@
1
- {"version":3,"file":"decision-token.d.ts","sourceRoot":"","sources":["../src/decision-token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAYH,OAAO,EAA6B,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAI5E,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;AAEhE,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,sBAAsB,CAAC;IACjC,WAAW,EAAE,MAAM,EAAE,CAAC;IAEtB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,SAAS,EAAE,MAAM,CAAC;IAElB,WAAW,CAAC,EAAE,mBAAmB,CAAC;IAElC,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAC;IACd,4EAA4E;IAC5E,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,QAAQ,EAAE,UAAU,GAAG,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC7D,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,gEAAgE;AAChE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC,eAAe,EAAE,WAAW,CAAC,GAAG,MAAM,CAKlF;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,CAAC,EAAE;IAClD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,cAAc,GAAG;IAAE,YAAY,EAAE,MAAM,CAAA;CAAE,CAe5C;AAED,wBAAsB,YAAY,CAChC,QAAQ,EAAE,IAAI,CAAC,eAAe,EAAE,WAAW,GAAG,OAAO,CAAC,EACtD,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,eAAe,CAAC,CAM1B;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,eAAe,EACtB,YAAY,EAAE,MAAM,GACnB,OAAO,CAYT;AAMD,MAAM,MAAM,gBAAgB,GACxB,sBAAsB,GACtB,kBAAkB,GAClB,oBAAoB,GACpB,mBAAmB,GACnB,eAAe,CAAC;AAEpB,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;gBAChB,IAAI,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAMvE;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,+DAA+D;IAC/D,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;CACtC,CAAC;AAEF,sEAAsE;AACtE,wBAAgB,sBAAsB,IAAI,gBAAgB,CASzD;AAED,MAAM,MAAM,2BAA2B,GAAG;IACxC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gFAAgF;IAChF,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,eAAe,EACtB,OAAO,CAAC,EAAE,2BAA2B,GACpC,IAAI,CA2CN;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC"}
1
+ {"version":3,"file":"decision-token.d.ts","sourceRoot":"","sources":["../src/decision-token.ts"],"names":[],"mappings":"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"}
@@ -10,7 +10,7 @@
10
10
  * plus expiry, decision === allow, signature, and consume-once. Any mismatch
11
11
  * means refuse — the signer is never invoked.
12
12
  */
13
- import { createPrivateKey, createPublicKey, generateKeyPairSync, randomUUID, sign as edSign, verify as edVerify, } from "node:crypto";
13
+ import { createPrivateKey, createPublicKey, generateKeyPairSync, hkdfSync, randomUUID, sign as edSign, verify as edVerify, } from "node:crypto";
14
14
  import { canonicalJson, intentHash } from "./intent.js";
15
15
  const DECISION_DOMAIN = "twzrd-decision-v1\n";
16
16
  /** Everything signed — the token minus the signature itself. */
@@ -41,6 +41,104 @@ export function createLocalDecisionSigner(options) {
41
41
  sign: (preimage) => edSign(null, Buffer.from(preimage), privateKey),
42
42
  };
43
43
  }
44
+ /** HKDF domain separation for the seeded signer (never reuse this IKM elsewhere). */
45
+ const SEED_SALT = "twzrd-payment-control/decision-signer";
46
+ const SEED_INFO = "ed25519-seed/v1";
47
+ /** Ed25519 seeds are 32 bytes; we demand at least that much real key material. */
48
+ const MIN_SECRET_BYTES = 32;
49
+ /**
50
+ * Decode supplied key material. We accept ONLY encoded random bytes (hex or
51
+ * base64/base64url) — never an arbitrary passphrase.
52
+ *
53
+ * The decision public key is published to verifiers, so a passphrase-derived
54
+ * key is guessable offline: an attacker enumerates candidate passphrases,
55
+ * derives each candidate's public key, and compares. Whoever wins that race
56
+ * can forge ALLOW decisions. Requiring 32 bytes of real entropy makes the
57
+ * search space infeasible rather than merely inconvenient.
58
+ */
59
+ function decodeKeyMaterial(secret) {
60
+ if (/^[0-9a-fA-F]+$/.test(secret) && secret.length % 2 === 0) {
61
+ return Buffer.from(secret, "hex");
62
+ }
63
+ if (/^[A-Za-z0-9+/_-]+={0,2}$/.test(secret)) {
64
+ const buf = Buffer.from(secret, "base64");
65
+ if (buf.length < MIN_SECRET_BYTES)
66
+ return Buffer.alloc(0);
67
+ // Round-trip guard: a genuine base64 encoding re-encodes to itself, but a
68
+ // memorable passphrase that merely happens to use the base64 alphabet
69
+ // (e.g. "MySuperSecretSigningKey2026Production") does NOT — it round-trips
70
+ // to different bytes. Without this check the length + byte-entropy floors
71
+ // both pass for such a passphrase (ASCII text looks high-entropy per byte),
72
+ // and a guessable secret is exactly the offline-forgery target we reject.
73
+ const normalize = (s) => s.replace(/-/g, "+").replace(/_/g, "/").replace(/=+$/, "");
74
+ if (buf.toString("base64").replace(/=+$/, "") !== normalize(secret)) {
75
+ return Buffer.alloc(0);
76
+ }
77
+ return buf;
78
+ }
79
+ return Buffer.alloc(0);
80
+ }
81
+ /** Shannon entropy per byte. Real random material sits near 8; "aaaa…" sits at 0. */
82
+ function entropyBitsPerByte(buf) {
83
+ if (buf.length === 0)
84
+ return 0;
85
+ const counts = new Map();
86
+ for (const b of buf)
87
+ counts.set(b, (counts.get(b) ?? 0) + 1);
88
+ let h = 0;
89
+ for (const n of counts.values()) {
90
+ const p = n / buf.length;
91
+ h -= p * Math.log2(p);
92
+ }
93
+ return h;
94
+ }
95
+ /**
96
+ * Deterministic Ed25519 signer derived from high-entropy key material
97
+ * (issuer==verifier semantics with real signatures). The same secret always
98
+ * yields the same keypair, so an issuer can re-derive its signer across
99
+ * restarts without a keystore.
100
+ *
101
+ * The secret MUST be 32+ bytes of random material, hex or base64 encoded:
102
+ *
103
+ * openssl rand -hex 32
104
+ *
105
+ * Verifiers receive `publicKeyPem` — never the secret. Anyone holding the
106
+ * secret can mint ALLOW decisions, so it is signing key material, not a
107
+ * shared password. Prefer createLocalDecisionSigner with a managed key for
108
+ * anything beyond single-operator deployments.
109
+ */
110
+ export function createSeededDecisionSigner(secret, keyId) {
111
+ if (!secret)
112
+ throw new Error("[twzrd] decision secret must be non-empty");
113
+ const ikm = decodeKeyMaterial(secret);
114
+ if (ikm.length < MIN_SECRET_BYTES) {
115
+ throw new Error(`[twzrd] decision secret must carry >=${MIN_SECRET_BYTES} bytes of high-entropy key material, ` +
116
+ "hex or base64 encoded (generate with: openssl rand -hex 32). " +
117
+ "Passphrases are rejected: the decision public key is published, so a guessable " +
118
+ "secret lets an attacker brute-force the signing key offline and forge ALLOW decisions.");
119
+ }
120
+ if (entropyBitsPerByte(ikm) < 3) {
121
+ throw new Error("[twzrd] decision secret decodes to low-entropy material (repeated/patterned bytes). " +
122
+ "Generate real key material: openssl rand -hex 32");
123
+ }
124
+ // Domain-separated derivation: this IKM cannot collide with any other TWZRD
125
+ // key derived from the same secret.
126
+ const seed = Buffer.from(hkdfSync("sha256", ikm, Buffer.from(SEED_SALT), Buffer.from(SEED_INFO), 32));
127
+ // PKCS#8 DER envelope for a raw Ed25519 seed (RFC 8410).
128
+ const pkcs8 = Buffer.concat([
129
+ Buffer.from("302e020100300506032b657004220420", "hex"),
130
+ seed,
131
+ ]);
132
+ const privateKey = createPrivateKey({ key: pkcs8, format: "der", type: "pkcs8" });
133
+ const publicKeyPem = createPublicKey(privateKey)
134
+ .export({ type: "spki", format: "pem" })
135
+ .toString();
136
+ return {
137
+ keyId: keyId ?? "seeded-ed25519",
138
+ publicKeyPem,
139
+ sign: (preimage) => edSign(null, Buffer.from(preimage), privateKey),
140
+ };
141
+ }
44
142
  export async function signDecision(unsigned, signer) {
45
143
  const payload = { ...unsigned, keyId: signer.keyId };
46
144
  const signature = Buffer.from(await signer.sign(decisionPreimage(payload))).toString("base64");
@@ -1 +1 @@
1
- {"version":3,"file":"decision-token.js","sourceRoot":"","sources":["../src/decision-token.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"decision-token.js","sourceRoot":"","sources":["../src/decision-token.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -16,7 +16,9 @@ export { quickCheck, QUICK_PRICE_USDC, type QuickCheckResult, type QuickCheckOpt
16
16
  export { createSponsoredX402Fetch, type SponsorSettle, type SponsoredX402Options, } from "./sponsored.js";
17
17
  export type { TwzrdDecision, TwzrdReadinessCard, TwzrdPreflightInput, TwzrdGateConfig, TwzrdApproveContext, TwzrdApprovalResult, TwzrdUpsellContext, X402PaymentRequirements, X402PaymentRequiredBody, X402McpPaymentRequest, X402McpPaymentRequestedContext, } from "./types.js";
18
18
  export { canonicalJson, intentHash, toMicroUsd, INTENT_HASH_PREFIX, type PaymentIntent, type PaymentProtocol, } from "./intent.js";
19
- export { assertIntentApproved, createDecisionRegistry, createLocalDecisionSigner, decisionPreimage, newDecisionId, signDecision, verifyDecisionSignature, TwzrdIntentBindingError, type AssertIntentApprovedOptions, type BindingErrorCode, type DecisionConstraints, type DecisionRegistry, type DecisionSigner, type PaymentDecision, type PaymentDecisionVerdict, } from "./decision-token.js";
19
+ export { assertIntentApproved, createDecisionRegistry, createLocalDecisionSigner, createSeededDecisionSigner, decisionPreimage, newDecisionId, signDecision, verifyDecisionSignature, TwzrdIntentBindingError, type AssertIntentApprovedOptions, type BindingErrorCode, type DecisionConstraints, type DecisionRegistry, type DecisionSigner, type PaymentDecision, type PaymentDecisionVerdict, } from "./decision-token.js";
20
20
  export { createMemorySpendLedger, evaluateIntent, POLICY_VERSION, type CounterpartyIntelligence, type EvaluateIntentOptions, type IntelligenceProvider, type Mandate, type SpendLedger, type SpendPolicy, } from "./policy-runtime.js";
21
21
  export { ap2CheckoutToIntent, x402RequirementsToIntent, type Ap2Cart, type Ap2UserMandate, type X402IntentContext, } from "./intent-adapters.js";
22
+ export { createTwzrdMppOnChallenge, mppChallengeToIntent, mppChallengeDigest, NATIVE_SOL_CURRENCY, TwzrdMppBlockError, type MppChallenge, type MppIntentContext, type MppOnChallengeHelpers, type MppOnChallengeOptions, type MppSolanaChargeRequest, } from "./mpp-hook.js";
23
+ export { approvalToIntelligence, counterpartyKnownFromApproval, createTwzrdIntelligenceProvider, intentAmountToPriceUsd, type TwzrdIntelligenceOptions, } from "./intelligence.js";
22
24
  //# sourceMappingURL=index.d.ts.map
@@ -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
@@ -19,7 +19,9 @@ export { quickCheck, QUICK_PRICE_USDC, } from "./quick.js";
19
19
  export { createSponsoredX402Fetch, } from "./sponsored.js";
20
20
  /* ── TWZRD Payment Control (protocol-neutral authorization core) ── */
21
21
  export { canonicalJson, intentHash, toMicroUsd, INTENT_HASH_PREFIX, } from "./intent.js";
22
- export { assertIntentApproved, createDecisionRegistry, createLocalDecisionSigner, decisionPreimage, newDecisionId, signDecision, verifyDecisionSignature, TwzrdIntentBindingError, } from "./decision-token.js";
22
+ export { assertIntentApproved, createDecisionRegistry, createLocalDecisionSigner, createSeededDecisionSigner, decisionPreimage, newDecisionId, signDecision, verifyDecisionSignature, TwzrdIntentBindingError, } from "./decision-token.js";
23
23
  export { createMemorySpendLedger, evaluateIntent, POLICY_VERSION, } from "./policy-runtime.js";
24
24
  export { ap2CheckoutToIntent, x402RequirementsToIntent, } from "./intent-adapters.js";
25
+ export { createTwzrdMppOnChallenge, mppChallengeToIntent, mppChallengeDigest, NATIVE_SOL_CURRENCY, TwzrdMppBlockError, } from "./mpp-hook.js";
26
+ export { approvalToIntelligence, counterpartyKnownFromApproval, createTwzrdIntelligenceProvider, intentAmountToPriceUsd, } from "./intelligence.js";
25
27
  //# 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,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"}
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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * TWZRD Payment Control — the live TWZRD preflight as an IntelligenceProvider.
3
+ *
4
+ * The x402 client hook feeds its own preflight into evaluateIntent inline;
5
+ * this module gives every OTHER core consumer (AP2/UCP adapters, direct
6
+ * evaluateIntent callers, future protocol surfaces) the same live pipeline
7
+ * (network classify -> free preflight -> readiness policy -> merchant_card
8
+ * wash refuse) as an injectable intelligence provider, without duplicating
9
+ * its behavior.
10
+ */
11
+ import type { PaymentIntent } from "./intent.js";
12
+ import type { CounterpartyIntelligence, IntelligenceProvider } from "./policy-runtime.js";
13
+ import type { TwzrdApprovalResult, TwzrdGateConfig } from "./types.js";
14
+ /**
15
+ * Is this counterparty KNOWN to us — did the score rest on observed evidence
16
+ * about this specific wallet?
17
+ *
18
+ * Deliberately NOT `reputationScored`. That flag only says TWZRD ran Solana
19
+ * behavioral scoring on the payment path; it is true even for a wallet we have
20
+ * never seen — precisely the case a caller most needs flagged. Reading it as
21
+ * "known" marks every scored Solana recipient known:true and silently disables
22
+ * the unknownCounterparty policy, which fires only on `known === false`.
23
+ *
24
+ * Ground truth is `trust_score_basis`, published in `card.caveats[]`:
25
+ * corpus_teaser_v1:provider_reputation_v1 -> evidence -> true
26
+ * corpus_teaser_v1:insufficient_free_evidence -> none -> false
27
+ * absent / unrecognized -> ambiguous -> undefined
28
+ *
29
+ * `undefined` ("we cannot say") must never collapse into `false` ("we looked,
30
+ * and there is nothing"). Only `false` may drive a policy.
31
+ */
32
+ export declare function counterpartyKnownFromApproval(approval: TwzrdApprovalResult): boolean | undefined;
33
+ /**
34
+ * Intent amounts are canonical decimal strings, and the deterministic money
35
+ * policy already runs on bigint micro-units. This Number() conversion exists
36
+ * only to price the preflight call — so guard the boundary rather than letting
37
+ * NaN or Infinity reach the network.
38
+ */
39
+ export declare function intentAmountToPriceUsd(amount: string): number;
40
+ /** Map a gate approval onto the core intelligence shape. Pure. */
41
+ export declare function approvalToIntelligence(approval: TwzrdApprovalResult): CounterpartyIntelligence;
42
+ export type TwzrdIntelligenceOptions = TwzrdGateConfig & {
43
+ /** Observe the full approval (telemetry / audit). Never throws into evaluation. */
44
+ onApproval?: (approval: TwzrdApprovalResult, intent: PaymentIntent) => void;
45
+ };
46
+ /**
47
+ * Wrap the existing preflight path as an IntelligenceProvider for
48
+ * `evaluateIntent`. `intent.amount` is the canonical decimal asset string.
49
+ */
50
+ export declare function createTwzrdIntelligenceProvider(options?: TwzrdIntelligenceOptions): IntelligenceProvider;
51
+ //# sourceMappingURL=intelligence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intelligence.d.ts","sourceRoot":"","sources":["../src/intelligence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EACV,wBAAwB,EACxB,oBAAoB,EACrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAcvE;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,mBAAmB,GAC5B,OAAO,GAAG,SAAS,CAiBrB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAe7D;AAED,kEAAkE;AAClE,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,mBAAmB,GAC5B,wBAAwB,CAgB1B;AAED,MAAM,MAAM,wBAAwB,GAAG,eAAe,GAAG;IACvD,mFAAmF;IACnF,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,mBAAmB,EAAE,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;CAC7E,CAAC;AAEF;;;GAGG;AACH,wBAAgB,+BAA+B,CAC7C,OAAO,CAAC,EAAE,wBAAwB,GACjC,oBAAoB,CAoBtB"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * TWZRD Payment Control — the live TWZRD preflight as an IntelligenceProvider.
3
+ *
4
+ * The x402 client hook feeds its own preflight into evaluateIntent inline;
5
+ * this module gives every OTHER core consumer (AP2/UCP adapters, direct
6
+ * evaluateIntent callers, future protocol surfaces) the same live pipeline
7
+ * (network classify -> free preflight -> readiness policy -> merchant_card
8
+ * wash refuse) as an injectable intelligence provider, without duplicating
9
+ * its behavior.
10
+ */
11
+ import { resolveConfig } from "./config.js";
12
+ import { twzrdApprovePayment } from "./policy.js";
13
+ /** Prefix of the readiness-card caveat that carries the scoring basis. */
14
+ const BASIS_PREFIX = "trust_score_basis:";
15
+ /**
16
+ * Basis markers meaning "we hold no real evidence on this wallet". The server
17
+ * states this explicitly rather than leaving it to be inferred from a low score.
18
+ */
19
+ const NO_EVIDENCE = ["insufficient_free_evidence", "default_no_data"];
20
+ /** Basis markers meaning "this verdict rests on observed behavior". */
21
+ const HAS_EVIDENCE = ["provider_reputation"];
22
+ /**
23
+ * Is this counterparty KNOWN to us — did the score rest on observed evidence
24
+ * about this specific wallet?
25
+ *
26
+ * Deliberately NOT `reputationScored`. That flag only says TWZRD ran Solana
27
+ * behavioral scoring on the payment path; it is true even for a wallet we have
28
+ * never seen — precisely the case a caller most needs flagged. Reading it as
29
+ * "known" marks every scored Solana recipient known:true and silently disables
30
+ * the unknownCounterparty policy, which fires only on `known === false`.
31
+ *
32
+ * Ground truth is `trust_score_basis`, published in `card.caveats[]`:
33
+ * corpus_teaser_v1:provider_reputation_v1 -> evidence -> true
34
+ * corpus_teaser_v1:insufficient_free_evidence -> none -> false
35
+ * absent / unrecognized -> ambiguous -> undefined
36
+ *
37
+ * `undefined` ("we cannot say") must never collapse into `false` ("we looked,
38
+ * and there is nothing"). Only `false` may drive a policy.
39
+ */
40
+ export function counterpartyKnownFromApproval(approval) {
41
+ // Unscored network (Base/EVM, Stripe deposit addresses): no reputation ran at
42
+ // all, so we know nothing about the recipient. Never imply otherwise.
43
+ if (approval.reputationScored !== true)
44
+ return undefined;
45
+ const caveats = approval.card?.caveats;
46
+ if (!Array.isArray(caveats))
47
+ return undefined;
48
+ const basis = caveats
49
+ .filter((c) => typeof c === "string")
50
+ .find((c) => c.trim().toLowerCase().startsWith(BASIS_PREFIX));
51
+ if (!basis)
52
+ return undefined;
53
+ const b = basis.toLowerCase();
54
+ if (NO_EVIDENCE.some((m) => b.includes(m)))
55
+ return false;
56
+ if (HAS_EVIDENCE.some((m) => b.includes(m)))
57
+ return true;
58
+ return undefined; // an unrecognized basis is ambiguous, not evidence
59
+ }
60
+ /**
61
+ * Intent amounts are canonical decimal strings, and the deterministic money
62
+ * policy already runs on bigint micro-units. This Number() conversion exists
63
+ * only to price the preflight call — so guard the boundary rather than letting
64
+ * NaN or Infinity reach the network.
65
+ */
66
+ export function intentAmountToPriceUsd(amount) {
67
+ // Number("") and Number(" ") are 0, not NaN — an empty amount would price
68
+ // the call as free instead of being rejected. Reject before coercing.
69
+ if (typeof amount !== "string" || amount.trim() === "") {
70
+ throw new Error(`[twzrd] intent.amount is not a finite, non-negative decimal: ${JSON.stringify(amount)}`);
71
+ }
72
+ const price = Number(amount);
73
+ if (!Number.isFinite(price) || price < 0) {
74
+ throw new Error(`[twzrd] intent.amount is not a finite, non-negative decimal: ${JSON.stringify(amount)}`);
75
+ }
76
+ return price;
77
+ }
78
+ /** Map a gate approval onto the core intelligence shape. Pure. */
79
+ export function approvalToIntelligence(approval) {
80
+ return {
81
+ known: counterpartyKnownFromApproval(approval),
82
+ washFlagged: approval.washFlagged ?? undefined,
83
+ // Any gate DENIAL is a block for the runtime, even when the card verdict
84
+ // was "warn" (can_spend gate, score floor, wash refuse). The verdict only
85
+ // grades approved outcomes.
86
+ decision: !approval.approved
87
+ ? "block"
88
+ : approval.verdict === "warn"
89
+ ? "warn"
90
+ : approval.verdict === "allow"
91
+ ? "allow"
92
+ : undefined,
93
+ trustScore: approval.score ?? undefined,
94
+ };
95
+ }
96
+ /**
97
+ * Wrap the existing preflight path as an IntelligenceProvider for
98
+ * `evaluateIntent`. `intent.amount` is the canonical decimal asset string.
99
+ */
100
+ export function createTwzrdIntelligenceProvider(options) {
101
+ const cfg = resolveConfig(options);
102
+ return async (intent) => {
103
+ const approval = await twzrdApprovePayment({
104
+ resourceUrl: intent.resource?.url,
105
+ payTo: intent.payTo,
106
+ priceUsdc: intentAmountToPriceUsd(intent.amount),
107
+ agentIntent: `${intent.protocol}_payment_control`,
108
+ chain: intent.network,
109
+ }, cfg);
110
+ try {
111
+ options?.onApproval?.(approval, intent);
112
+ }
113
+ catch {
114
+ // observation must never alter the decision path
115
+ }
116
+ return approvalToIntelligence(approval);
117
+ };
118
+ }
119
+ //# sourceMappingURL=intelligence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intelligence.js","sourceRoot":"","sources":["../src/intelligence.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,205 @@
1
+ /**
2
+ * TWZRD Payment Control on the Machine Payments Protocol (MPP) client path.
3
+ *
4
+ * Narrow scope (deliberate): Solana `charge` only. MPP's client SDK (`mppx`)
5
+ * signs AND broadcasts the Solana transaction inside `createCredential()`, so
6
+ * the last deterministic checkpoint before money moves is the `onChallenge`
7
+ * callback of `Mppx.create`. The guard returned by `createTwzrdMppOnChallenge`
8
+ * decides there:
9
+ *
10
+ * - block → the guard THROWS. `createCredential()` is never invoked; nothing
11
+ * is signed, nothing broadcasts. (mppx re-throws onChallenge
12
+ * errors after emitting `payment.failed` — returning `undefined`
13
+ * would proceed to pay, so refusal must be an exception.)
14
+ * - warn → PROCEEDS TO PAY by default; a warn is not a refusal. Set
15
+ * `treatWarnAsBlock: true` to refuse on warn too.
16
+ * - allow → the guard calls `helpers.createCredential()` itself and returns
17
+ * the credential for the exact challenge it evaluated.
18
+ * - other methods/intents (tempo, stripe, session) → fail-closed by default
19
+ * (`UNEVALUATED_METHOD`); opt out with `allowUnevaluated: true`.
20
+ *
21
+ * SCOPE LIMIT (honest): the guard is authoritative only when no
22
+ * `onChallengeReceived` event handler supplies a credential. mppx resolves
23
+ * `eventCredential ?? onChallenge(...)`, so an event handler that returns a
24
+ * credential SHORT-CIRCUITS this callback entirely and pays ungated. Do not
25
+ * register both on one client.
26
+ *
27
+ * PRICING (the load-bearing constraint): `amount` is a base-unit token
28
+ * quantity; the policy runtime enforces ceilings in USD. Converting one to the
29
+ * other is sound ONLY for assets pegged 1:1 to the dollar, so PaymentIntent v1
30
+ * carries USD-pegged charges ONLY. Native SOL and unknown mints fail closed
31
+ * (`UNPRICED_ASSET`) — there is no caller-supplied price escape hatch, because
32
+ * a priced non-stablecoin intent would record `asset: SOL` beside `amount: <USD>`
33
+ * and LOSE the exact token quantity actually being transferred. Binding a
34
+ * quantity the intent does not carry is precisely the divergence this guard
35
+ * exists to prevent. Pricing non-pegged assets needs a future intent version
36
+ * with explicit token-amount + quote fields; until then, refuse.
37
+ *
38
+ * WHAT THE INTENT MUST BIND (verified against the published mppx-solana@0.2.0
39
+ * `charge` request schema — do not infer this from docs):
40
+ *
41
+ * - SPONSORED charges are refused (`SPONSORED_CHARGE`). When `sponsored` /
42
+ * `sponsorPath` / `feeTokenAmount` are present, mppx-solana builds a
43
+ * SECOND transfer — `feeTokenAmount` to the sponsor's fee payer — on top of
44
+ * the advertised `amount`. PaymentIntent v1 binds a single amount to a
45
+ * single payTo, so an approved sponsored charge would move strictly more
46
+ * money than the decision covered.
47
+ * - CLUSTER must be a known cluster name (`UNKNOWN_CLUSTER` otherwise).
48
+ * mppx-solana's `resolveEndpoint` ends in `return cluster`, so a
49
+ * seller-supplied `cluster` is used verbatim AS THE RPC ENDPOINT URL. Our
50
+ * classifier scores any network string containing "solana", so
51
+ * `solana:https://seller-rpc.example` would be scored as mainnet — reputation
52
+ * invented for a chain we never observed. Refuse rather than score a URL.
53
+ * - The DIGEST of the whole normalized challenge is bound into the intent, not
54
+ * just `realm:id`. Every field mppx will act on (amount, currency, decimals,
55
+ * recipient, cluster, memo, expiry) is covered, so any post-approval mutation
56
+ * changes the intent hash.
57
+ *
58
+ * No dependency on `mppx` — challenge types are structural, matching
59
+ * mppx@0.8.6 `Challenge` and mppx-solana@0.2.0's `charge` request schema.
60
+ */
61
+ import type { DecisionSigner, PaymentDecision } from "./decision-token.js";
62
+ import { type PaymentIntent } from "./intent.js";
63
+ import { type IntelligenceProvider, type Mandate, type SpendLedger, type SpendPolicy } from "./policy-runtime.js";
64
+ /** Structural mirror of mppx `Challenge` (WWW-Authenticate: Payment ...). */
65
+ export type MppChallenge = {
66
+ id: string;
67
+ realm: string;
68
+ /** Payment method name (e.g. "solana", "tempo", "stripe"). */
69
+ method: string;
70
+ /** Intent kind (e.g. "charge", "session"). */
71
+ intent: string;
72
+ /** Method-specific request data. */
73
+ request: Record<string, unknown>;
74
+ /** ISO-8601 challenge expiry. */
75
+ expires?: string;
76
+ description?: string;
77
+ };
78
+ /** mppx-solana `charge` request fields the adapter consumes. */
79
+ export type MppSolanaChargeRequest = {
80
+ /** Base-unit token amount (e.g. "50000" = 0.05 USDC at 6dp). */
81
+ amount: string;
82
+ /** Mint address of the payment token, or "solana:native" for SOL. */
83
+ currency: string;
84
+ decimals: number;
85
+ /** Receiving wallet — the payTo. */
86
+ recipient: string;
87
+ cluster?: string;
88
+ memo?: string;
89
+ /**
90
+ * Sponsorship fields. Their presence means a SECOND transfer that
91
+ * PaymentIntent v1 cannot bind — the guard refuses rather than approve a
92
+ * payment larger than the decision covers.
93
+ */
94
+ sponsored?: boolean;
95
+ sponsorPath?: string;
96
+ feeTokenAmount?: string;
97
+ feePayer?: string;
98
+ };
99
+ /** mppx-solana's native-SOL sentinel (NATIVE_SOL_CURRENCY). */
100
+ export declare const NATIVE_SOL_CURRENCY = "solana:native";
101
+ export declare class TwzrdMppBlockError extends Error {
102
+ readonly code: "PAYMENT_CONTROL_BLOCK" | "UNEVALUATED_METHOD" | "MALFORMED_CHALLENGE" | "UNPRICED_ASSET"
103
+ /** Sponsored charge: a second, unbindable transfer to the sponsor. */
104
+ | "SPONSORED_CHARGE"
105
+ /** Cluster is not a known cluster name (i.e. it is a raw RPC endpoint). */
106
+ | "UNKNOWN_CLUSTER";
107
+ readonly reasonCodes?: string[];
108
+ readonly decisionId?: string;
109
+ constructor(code: TwzrdMppBlockError["code"], message: string, detail?: {
110
+ reasonCodes?: string[];
111
+ decisionId?: string;
112
+ });
113
+ }
114
+ export type MppIntentContext = {
115
+ /** Resource URL bound into the intent (the paid request's URL). */
116
+ resourceUrl?: string;
117
+ /** HTTP method of the paid request. */
118
+ method?: string;
119
+ /** Spend purpose (matched against mandate.purposes). */
120
+ purpose?: string;
121
+ };
122
+ /**
123
+ * Digest of the ENTIRE normalized challenge — every field mppx-solana will act
124
+ * on, not just `realm:id`.
125
+ *
126
+ * Binding only the identifiers would let a seller (or a compromised
127
+ * orchestration layer) keep the same challenge id while swapping `recipient`,
128
+ * `amount`, `currency`, or `cluster` after TWZRD approved it, and the intent
129
+ * hash would not move. The digest makes any such mutation a different intent.
130
+ */
131
+ export declare function mppChallengeDigest(challenge: MppChallenge): string;
132
+ /**
133
+ * Normalize an MPP Solana `charge` challenge into PaymentIntent v1.
134
+ *
135
+ * `intent.amount` is always a USD decimal string, because that is what the
136
+ * policy runtime's ceilings mean. Stablecoin charges convert 1:1 from base
137
+ * units; every other asset is refused (UNPRICED_ASSET) rather than priced.
138
+ *
139
+ * Only `method === "solana" && intent === "charge"` is supported. The challenge
140
+ * id + realm are bound into `resource.operation`, so the signed decision covers
141
+ * this exact challenge, not merely an equivalent-looking payment.
142
+ */
143
+ export declare function mppChallengeToIntent(challenge: MppChallenge, ctx?: MppIntentContext): PaymentIntent;
144
+ export type MppOnChallengeOptions = {
145
+ /** Ed25519 decision signer (createLocalDecisionSigner() or a remote signer). */
146
+ signer: DecisionSigner;
147
+ policy?: SpendPolicy;
148
+ mandate?: Mandate;
149
+ ledger?: SpendLedger;
150
+ intelligence?: IntelligenceProvider;
151
+ /** Decision token time-to-live in ms (default 120s). */
152
+ ttlMs?: number;
153
+ /** Clock, Unix ms. Injectable for tests. */
154
+ now?: () => number;
155
+ /** Spend purpose bound into the intent. */
156
+ purpose?: string;
157
+ /** Resource URL bound into the intent (static or derived per challenge). */
158
+ resourceUrl?: string | ((challenge: MppChallenge) => string | undefined);
159
+ /** HTTP method bound into the intent. */
160
+ method?: string;
161
+ /** Refuse on a `warn` verdict too (default false: warn proceeds to pay). */
162
+ treatWarnAsBlock?: boolean;
163
+ /**
164
+ * Non-solana-charge challenges: fail-closed by default (throw
165
+ * UNEVALUATED_METHOD before any credential exists). Set true to let mppx's
166
+ * default flow handle them UNGATED.
167
+ */
168
+ allowUnevaluated?: boolean;
169
+ /** Telemetry after each evaluation. Never throws into the payment path. */
170
+ onDecision?: (detail: {
171
+ challenge: MppChallenge;
172
+ intent?: PaymentIntent;
173
+ decision?: PaymentDecision;
174
+ refusal?: TwzrdMppBlockError;
175
+ }) => void;
176
+ };
177
+ /** Helpers passed by mppx to onChallenge. */
178
+ export type MppOnChallengeHelpers = {
179
+ createCredential: (context?: unknown) => Promise<string>;
180
+ };
181
+ /**
182
+ * TWZRD guard for `Mppx.create({ onChallenge })`.
183
+ *
184
+ * Authoritative at this seat (see the SCOPE LIMIT note at the top of the file:
185
+ * an `onChallengeReceived` handler that returns a credential bypasses it).
186
+ *
187
+ * @example
188
+ * ```ts
189
+ * import { Mppx } from "mppx/client";
190
+ * import { client as solanaClient } from "mppx-solana";
191
+ * import { createTwzrdMppOnChallenge, createLocalDecisionSigner } from "twzrd-x402-gate";
192
+ *
193
+ * const mppx = Mppx.create({
194
+ * methods: [solanaClient({ signer: wallet })],
195
+ * onChallenge: createTwzrdMppOnChallenge({
196
+ * signer: createLocalDecisionSigner(),
197
+ * policy: { maxAmountUsd: "1.00" },
198
+ * // USDC/USDT only. SOL, sponsored charges, and custom clusters are refused.
199
+ * }),
200
+ * });
201
+ * // A blocked seller now throws BEFORE the Solana tx is signed or broadcast.
202
+ * ```
203
+ */
204
+ export declare function createTwzrdMppOnChallenge(options: MppOnChallengeOptions): (challenge: MppChallenge, helpers: MppOnChallengeHelpers) => Promise<string | undefined>;
205
+ //# sourceMappingURL=mpp-hook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mpp-hook.d.ts","sourceRoot":"","sources":["../src/mpp-hook.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,336 @@
1
+ /**
2
+ * TWZRD Payment Control on the Machine Payments Protocol (MPP) client path.
3
+ *
4
+ * Narrow scope (deliberate): Solana `charge` only. MPP's client SDK (`mppx`)
5
+ * signs AND broadcasts the Solana transaction inside `createCredential()`, so
6
+ * the last deterministic checkpoint before money moves is the `onChallenge`
7
+ * callback of `Mppx.create`. The guard returned by `createTwzrdMppOnChallenge`
8
+ * decides there:
9
+ *
10
+ * - block → the guard THROWS. `createCredential()` is never invoked; nothing
11
+ * is signed, nothing broadcasts. (mppx re-throws onChallenge
12
+ * errors after emitting `payment.failed` — returning `undefined`
13
+ * would proceed to pay, so refusal must be an exception.)
14
+ * - warn → PROCEEDS TO PAY by default; a warn is not a refusal. Set
15
+ * `treatWarnAsBlock: true` to refuse on warn too.
16
+ * - allow → the guard calls `helpers.createCredential()` itself and returns
17
+ * the credential for the exact challenge it evaluated.
18
+ * - other methods/intents (tempo, stripe, session) → fail-closed by default
19
+ * (`UNEVALUATED_METHOD`); opt out with `allowUnevaluated: true`.
20
+ *
21
+ * SCOPE LIMIT (honest): the guard is authoritative only when no
22
+ * `onChallengeReceived` event handler supplies a credential. mppx resolves
23
+ * `eventCredential ?? onChallenge(...)`, so an event handler that returns a
24
+ * credential SHORT-CIRCUITS this callback entirely and pays ungated. Do not
25
+ * register both on one client.
26
+ *
27
+ * PRICING (the load-bearing constraint): `amount` is a base-unit token
28
+ * quantity; the policy runtime enforces ceilings in USD. Converting one to the
29
+ * other is sound ONLY for assets pegged 1:1 to the dollar, so PaymentIntent v1
30
+ * carries USD-pegged charges ONLY. Native SOL and unknown mints fail closed
31
+ * (`UNPRICED_ASSET`) — there is no caller-supplied price escape hatch, because
32
+ * a priced non-stablecoin intent would record `asset: SOL` beside `amount: <USD>`
33
+ * and LOSE the exact token quantity actually being transferred. Binding a
34
+ * quantity the intent does not carry is precisely the divergence this guard
35
+ * exists to prevent. Pricing non-pegged assets needs a future intent version
36
+ * with explicit token-amount + quote fields; until then, refuse.
37
+ *
38
+ * WHAT THE INTENT MUST BIND (verified against the published mppx-solana@0.2.0
39
+ * `charge` request schema — do not infer this from docs):
40
+ *
41
+ * - SPONSORED charges are refused (`SPONSORED_CHARGE`). When `sponsored` /
42
+ * `sponsorPath` / `feeTokenAmount` are present, mppx-solana builds a
43
+ * SECOND transfer — `feeTokenAmount` to the sponsor's fee payer — on top of
44
+ * the advertised `amount`. PaymentIntent v1 binds a single amount to a
45
+ * single payTo, so an approved sponsored charge would move strictly more
46
+ * money than the decision covered.
47
+ * - CLUSTER must be a known cluster name (`UNKNOWN_CLUSTER` otherwise).
48
+ * mppx-solana's `resolveEndpoint` ends in `return cluster`, so a
49
+ * seller-supplied `cluster` is used verbatim AS THE RPC ENDPOINT URL. Our
50
+ * classifier scores any network string containing "solana", so
51
+ * `solana:https://seller-rpc.example` would be scored as mainnet — reputation
52
+ * invented for a chain we never observed. Refuse rather than score a URL.
53
+ * - The DIGEST of the whole normalized challenge is bound into the intent, not
54
+ * just `realm:id`. Every field mppx will act on (amount, currency, decimals,
55
+ * recipient, cluster, memo, expiry) is covered, so any post-approval mutation
56
+ * changes the intent hash.
57
+ *
58
+ * No dependency on `mppx` — challenge types are structural, matching
59
+ * mppx@0.8.6 `Challenge` and mppx-solana@0.2.0's `charge` request schema.
60
+ */
61
+ import { createHash } from "node:crypto";
62
+ import { canonicalJson } from "./intent.js";
63
+ import { evaluateIntent, } from "./policy-runtime.js";
64
+ /** mppx-solana's native-SOL sentinel (NATIVE_SOL_CURRENCY). */
65
+ export const NATIVE_SOL_CURRENCY = "solana:native";
66
+ /**
67
+ * Cluster names mppx-solana maps to a real Solana RPC. Anything else is passed
68
+ * through as a raw endpoint URL (`resolveEndpoint` ends in `return cluster`),
69
+ * so it is not a cluster we can identify — and must never be scored.
70
+ */
71
+ const KNOWN_CLUSTERS = new Set([
72
+ "mainnet-beta",
73
+ "mainnet",
74
+ "devnet",
75
+ "testnet",
76
+ "localnet",
77
+ "localhost",
78
+ ]);
79
+ /**
80
+ * Assets we can price at 1:1 USD without an oracle, with their REAL decimals.
81
+ * A challenge that declares different decimals for these mints is lying (or
82
+ * broken) — either way it is not evaluable, so it is refused.
83
+ */
84
+ const USD_PEGGED_ASSETS = {
85
+ // USDC mainnet
86
+ EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v: 6,
87
+ // USDC devnet
88
+ Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr: 6,
89
+ // USDT mainnet
90
+ Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB: 6,
91
+ };
92
+ export class TwzrdMppBlockError extends Error {
93
+ code;
94
+ reasonCodes;
95
+ decisionId;
96
+ constructor(code, message, detail) {
97
+ super(message);
98
+ this.name = "TwzrdMppBlockError";
99
+ this.code = code;
100
+ this.reasonCodes = detail?.reasonCodes;
101
+ this.decisionId = detail?.decisionId;
102
+ }
103
+ }
104
+ /**
105
+ * Base units -> whole-token decimal string. Rejects anything it cannot scale
106
+ * exactly (non-integer amount, non-integer/negative decimals) rather than
107
+ * returning the raw string, which the runtime would misread as a USD figure.
108
+ */
109
+ function baseUnitsToDecimal(units, decimals) {
110
+ const t = String(units).trim();
111
+ if (!/^\d+$/.test(t)) {
112
+ throw new TwzrdMppBlockError("MALFORMED_CHALLENGE", `[twzrd] MPP charge amount is not a base-unit integer: ${JSON.stringify(units)}`);
113
+ }
114
+ if (!Number.isInteger(decimals) || decimals < 0 || decimals > 18) {
115
+ throw new TwzrdMppBlockError("MALFORMED_CHALLENGE", `[twzrd] MPP charge has unusable decimals: ${JSON.stringify(decimals)}`);
116
+ }
117
+ if (decimals === 0)
118
+ return t;
119
+ const scale = 10n ** BigInt(decimals);
120
+ const value = BigInt(t);
121
+ const whole = value / scale;
122
+ const frac = (value % scale).toString().padStart(decimals, "0").replace(/0+$/, "");
123
+ return frac ? `${whole}.${frac}` : `${whole}`;
124
+ }
125
+ /**
126
+ * Digest of the ENTIRE normalized challenge — every field mppx-solana will act
127
+ * on, not just `realm:id`.
128
+ *
129
+ * Binding only the identifiers would let a seller (or a compromised
130
+ * orchestration layer) keep the same challenge id while swapping `recipient`,
131
+ * `amount`, `currency`, or `cluster` after TWZRD approved it, and the intent
132
+ * hash would not move. The digest makes any such mutation a different intent.
133
+ */
134
+ export function mppChallengeDigest(challenge) {
135
+ const req = (challenge.request ?? {});
136
+ const normalized = {
137
+ id: challenge.id,
138
+ realm: challenge.realm,
139
+ method: challenge.method,
140
+ intent: challenge.intent,
141
+ expires: challenge.expires ?? null,
142
+ // Every request field, not a curated subset: an unknown field that mppx
143
+ // acts on must still change the digest.
144
+ request: Object.fromEntries(Object.keys(req)
145
+ .sort()
146
+ .map((k) => [k, req[k] ?? null])),
147
+ };
148
+ return createHash("sha256").update(canonicalJson(normalized), "utf8").digest("hex");
149
+ }
150
+ /** Structural deep-freeze so telemetry cannot mutate the challenge mid-flight. */
151
+ function frozenClone(value) {
152
+ return Object.freeze(JSON.parse(JSON.stringify(value), (_k, v) => v && typeof v === "object" ? Object.freeze(v) : v));
153
+ }
154
+ /**
155
+ * Normalize an MPP Solana `charge` challenge into PaymentIntent v1.
156
+ *
157
+ * `intent.amount` is always a USD decimal string, because that is what the
158
+ * policy runtime's ceilings mean. Stablecoin charges convert 1:1 from base
159
+ * units; every other asset is refused (UNPRICED_ASSET) rather than priced.
160
+ *
161
+ * Only `method === "solana" && intent === "charge"` is supported. The challenge
162
+ * id + realm are bound into `resource.operation`, so the signed decision covers
163
+ * this exact challenge, not merely an equivalent-looking payment.
164
+ */
165
+ export function mppChallengeToIntent(challenge, ctx) {
166
+ if (challenge.method !== "solana" || challenge.intent !== "charge") {
167
+ throw new TwzrdMppBlockError("UNEVALUATED_METHOD", `[twzrd] MPP guard evaluates solana/charge only; got ${challenge.method}/${challenge.intent}`);
168
+ }
169
+ const req = challenge.request;
170
+ if (typeof req.recipient !== "string" ||
171
+ !req.recipient ||
172
+ typeof req.currency !== "string" ||
173
+ !req.currency ||
174
+ (typeof req.amount !== "string" && typeof req.amount !== "number") ||
175
+ typeof req.decimals !== "number") {
176
+ throw new TwzrdMppBlockError("MALFORMED_CHALLENGE", "[twzrd] MPP solana charge challenge missing/mistyped recipient, amount, currency, or decimals");
177
+ }
178
+ // SPONSORSHIP: mppx-solana adds a SECOND transfer of `feeTokenAmount` to the
179
+ // sponsor's fee payer, on top of `amount` to `recipient`. PaymentIntent v1
180
+ // binds one amount to one payTo, so approving this would authorize strictly
181
+ // more money than the decision covers — the exact approve/execute divergence
182
+ // the intent hash exists to prevent. Refuse until an intent version can carry
183
+ // multiple legs.
184
+ if (req.sponsored === true ||
185
+ typeof req.sponsorPath === "string" ||
186
+ typeof req.feeTokenAmount === "string") {
187
+ throw new TwzrdMppBlockError("SPONSORED_CHARGE", "[twzrd] MPP sponsored charge refused: it transfers feeTokenAmount" +
188
+ `${req.feeTokenAmount ? ` (${req.feeTokenAmount})` : ""} to a sponsor in addition to` +
189
+ " the advertised amount, and PaymentIntent v1 binds only a single transfer." +
190
+ " Approving it would authorize more value than the signed decision covers.");
191
+ }
192
+ // CLUSTER: mppx-solana's resolveEndpoint returns an unrecognized cluster
193
+ // verbatim as the RPC endpoint URL. A seller-supplied endpoint is not a
194
+ // cluster we can identify, and our classifier scores anything containing
195
+ // "solana" — so `solana:https://seller-rpc.example` would be scored as
196
+ // mainnet. Never score a URL; refuse it.
197
+ const cluster = req.cluster ?? "mainnet-beta";
198
+ if (!KNOWN_CLUSTERS.has(cluster)) {
199
+ throw new TwzrdMppBlockError("UNKNOWN_CLUSTER", `[twzrd] MPP charge names an unknown cluster ${JSON.stringify(cluster)}.` +
200
+ " mppx-solana uses this verbatim as the RPC endpoint, so it identifies no known" +
201
+ " chain and must not inherit mainnet reputation. Known clusters: " +
202
+ [...KNOWN_CLUSTERS].join(", "));
203
+ }
204
+ const pegDecimals = USD_PEGGED_ASSETS[req.currency];
205
+ // ASSET: PaymentIntent v1 carries USD-pegged assets ONLY. A priced SOL charge
206
+ // would store `asset: solana:native` beside `amount: <USD>` and lose the token
207
+ // quantity actually transferred — binding a number that is not the number the
208
+ // wallet signs. Refuse; a future intent version needs tokenAmount + quote.
209
+ if (pegDecimals === undefined) {
210
+ const raw = String(req.amount);
211
+ throw new TwzrdMppBlockError("UNPRICED_ASSET", `[twzrd] MPP charge in non-USD-pegged asset ${req.currency} (${raw} base units).` +
212
+ " PaymentIntent v1 expresses amounts in USD, so pricing this would record a dollar" +
213
+ " figure while losing the exact token quantity being transferred. Refused by design.");
214
+ }
215
+ // A stablecoin challenge that misdeclares decimals is not evaluable: the
216
+ // declared value scales the amount, so trusting it would let a seller pass
217
+ // 1e9 USDC base units off as "$1" (mppx-solana's transfer_checked would also
218
+ // reject the mismatch on-chain — refuse before signing, not after).
219
+ if (req.decimals !== pegDecimals) {
220
+ throw new TwzrdMppBlockError("MALFORMED_CHALLENGE", `[twzrd] MPP charge declares decimals=${req.decimals} for a mint with ${pegDecimals} decimals`);
221
+ }
222
+ const amountUsd = baseUnitsToDecimal(String(req.amount), req.decimals); // 1 token == 1 USD
223
+ return {
224
+ protocol: "mpp",
225
+ network: `solana:${cluster}`,
226
+ asset: req.currency,
227
+ amount: amountUsd,
228
+ payTo: req.recipient,
229
+ resource: {
230
+ url: ctx?.resourceUrl,
231
+ method: ctx?.method,
232
+ // Bind the WHOLE challenge, not just its identifiers: swapping recipient
233
+ // or amount under the same id changes this digest, hence the intent hash.
234
+ operation: `mpp-charge:${challenge.realm}:${challenge.id}:${mppChallengeDigest(challenge)}`,
235
+ },
236
+ context: {
237
+ purpose: ctx?.purpose,
238
+ expiresAt: challenge.expires,
239
+ },
240
+ };
241
+ }
242
+ /**
243
+ * TWZRD guard for `Mppx.create({ onChallenge })`.
244
+ *
245
+ * Authoritative at this seat (see the SCOPE LIMIT note at the top of the file:
246
+ * an `onChallengeReceived` handler that returns a credential bypasses it).
247
+ *
248
+ * @example
249
+ * ```ts
250
+ * import { Mppx } from "mppx/client";
251
+ * import { client as solanaClient } from "mppx-solana";
252
+ * import { createTwzrdMppOnChallenge, createLocalDecisionSigner } from "twzrd-x402-gate";
253
+ *
254
+ * const mppx = Mppx.create({
255
+ * methods: [solanaClient({ signer: wallet })],
256
+ * onChallenge: createTwzrdMppOnChallenge({
257
+ * signer: createLocalDecisionSigner(),
258
+ * policy: { maxAmountUsd: "1.00" },
259
+ * // USDC/USDT only. SOL, sponsored charges, and custom clusters are refused.
260
+ * }),
261
+ * });
262
+ * // A blocked seller now throws BEFORE the Solana tx is signed or broadcast.
263
+ * ```
264
+ */
265
+ export function createTwzrdMppOnChallenge(options) {
266
+ return async (challenge, helpers) => {
267
+ let intent;
268
+ try {
269
+ intent = mppChallengeToIntent(challenge, {
270
+ resourceUrl: typeof options.resourceUrl === "function"
271
+ ? options.resourceUrl(challenge)
272
+ : options.resourceUrl,
273
+ method: options.method,
274
+ purpose: options.purpose,
275
+ });
276
+ }
277
+ catch (error) {
278
+ const refusal = asBlockError(error, "MALFORMED_CHALLENGE");
279
+ if (refusal.code === "UNEVALUATED_METHOD" && options.allowUnevaluated) {
280
+ emitDecision(options, { challenge });
281
+ return undefined; // explicit opt-out: mppx default flow, ungated
282
+ }
283
+ emitDecision(options, { challenge, refusal });
284
+ throw refusal;
285
+ }
286
+ let decision;
287
+ try {
288
+ decision = await evaluateIntent(intent, {
289
+ signer: options.signer,
290
+ policy: options.policy,
291
+ mandate: options.mandate,
292
+ ledger: options.ledger,
293
+ intelligence: options.intelligence,
294
+ ttlMs: options.ttlMs,
295
+ now: options.now?.(),
296
+ });
297
+ }
298
+ catch (error) {
299
+ // A runtime failure (bad amount, signer error) must never fall through to
300
+ // payment: refuse, exactly as a block would.
301
+ const refusal = asBlockError(error, "MALFORMED_CHALLENGE");
302
+ emitDecision(options, { challenge, intent, refusal });
303
+ throw refusal;
304
+ }
305
+ emitDecision(options, { challenge, intent, decision });
306
+ const refuse = decision.decision === "block" ||
307
+ (decision.decision === "warn" && options.treatWarnAsBlock === true);
308
+ if (refuse) {
309
+ throw new TwzrdMppBlockError("PAYMENT_CONTROL_BLOCK", `[twzrd] mpp_payment_control_${decision.decision}:${decision.reasonCodes.join(",")} payTo=${intent.payTo}`, { reasonCodes: decision.reasonCodes, decisionId: decision.decisionId });
310
+ }
311
+ // allow (or warn, when not treated as block): create the credential for the
312
+ // EXACT challenge evaluated.
313
+ return helpers.createCredential();
314
+ };
315
+ }
316
+ /** Normalize any thrown value into a TwzrdMppBlockError so callers can branch on .code. */
317
+ function asBlockError(error, fallback) {
318
+ if (error instanceof TwzrdMppBlockError)
319
+ return error;
320
+ const message = error instanceof Error ? error.message : String(error);
321
+ return new TwzrdMppBlockError(fallback, `[twzrd] MPP evaluation failed: ${message}`);
322
+ }
323
+ function emitDecision(options, detail) {
324
+ if (!options.onDecision)
325
+ return;
326
+ try {
327
+ // Telemetry runs BEFORE createCredential(). Handing it the live challenge
328
+ // object would let an observer mutate the very fields the decision was
329
+ // signed over, between evaluation and signing. Emit a frozen copy.
330
+ options.onDecision({ ...detail, challenge: frozenClone(detail.challenge) });
331
+ }
332
+ catch {
333
+ // never break the payment path on telemetry
334
+ }
335
+ }
336
+ //# sourceMappingURL=mpp-hook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mpp-hook.js","sourceRoot":"","sources":["../src/mpp-hook.ts"],"names":[],"mappings":"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"}
@@ -11,7 +11,7 @@
11
11
  */
12
12
  import type { TwzrdGateConfig } from "./types.js";
13
13
  import { type Mandate, type SpendLedger, type SpendPolicy } from "./policy-runtime.js";
14
- import type { DecisionSigner, PaymentDecision } from "./decision-token.js";
14
+ import { type DecisionSigner, type PaymentDecision } from "./decision-token.js";
15
15
  import type { PaymentIntent } from "./intent.js";
16
16
  /** Minimal shape of x402 payment requirements used by the hook. */
17
17
  export type X402SelectedRequirements = {
@@ -30,21 +30,27 @@ export type X402SelectedRequirements = {
30
30
  */
31
31
  export type BeforePaymentCreationContext = {
32
32
  selectedRequirements: X402SelectedRequirements;
33
+ /** Full 402 response body; present on the official client, unused by the gate. */
34
+ paymentRequired?: unknown;
33
35
  /** Some client versions may nest under requirements */
34
36
  requirements?: X402SelectedRequirements;
35
37
  };
36
- export type BeforePaymentCreationResult = {
38
+ export type BeforePaymentCreationResult = void | {
37
39
  abort: true;
38
40
  reason: string;
39
- } | {
40
- abort?: false;
41
- } | void;
41
+ };
42
42
  /**
43
43
  * Minimal client surface — no hard dependency on @x402/core at compile time.
44
- * Compatible with x402Client from @x402/core/client.
44
+ *
45
+ * Must stay assignable FROM the official x402Client under strictFunctionTypes:
46
+ * the hook type we claim the client accepts must satisfy the client's own
47
+ * BeforePaymentCreationHook — async-only, returning nothing or
48
+ * `{ abort: true, reason }`. A sync return branch or an `{ abort: false }`
49
+ * variant here makes `new x402Client()` fail to typecheck against this
50
+ * surface. Proven by test/x402-official-compat.test.ts against @x402/fetch.
45
51
  */
46
52
  export type X402ClientLike = {
47
- onBeforePaymentCreation: (hook: (context: BeforePaymentCreationContext) => Promise<BeforePaymentCreationResult> | BeforePaymentCreationResult) => X402ClientLike | void;
53
+ onBeforePaymentCreation: (hook: (context: BeforePaymentCreationContext) => Promise<BeforePaymentCreationResult>) => unknown;
48
54
  };
49
55
  /**
50
56
  * Opt-in TWZRD Payment Control on the client hook. When set, the hook builds a
@@ -59,9 +65,7 @@ export type X402ClientLike = {
59
65
  * even when preflight allowed; it never loosens a legacy denial. Leaving
60
66
  * paymentControl unset preserves the exact prior behavior.
61
67
  */
62
- export type X402PaymentControlOptions = {
63
- /** Ed25519 decision signer (createLocalDecisionSigner() or a remote signer). */
64
- signer: DecisionSigner;
68
+ type X402PaymentControlCommon = {
65
69
  policy?: SpendPolicy;
66
70
  mandate?: Mandate;
67
71
  ledger?: SpendLedger;
@@ -73,6 +77,25 @@ export type X402PaymentControlOptions = {
73
77
  /** Resource method bound into the intent (GET/POST/…). */
74
78
  method?: string;
75
79
  };
80
+ /**
81
+ * Exactly one signing source. Modeled as a union so the type system rejects
82
+ * both-at-once, and checked again at runtime for JS callers: silently
83
+ * preferring one over the other would let an operator believe decisions are
84
+ * signed by a key that is not in fact signing them.
85
+ */
86
+ export type X402PaymentControlOptions = X402PaymentControlCommon & ({
87
+ /** Ed25519 decision signer (createLocalDecisionSigner() or a remote signer). */
88
+ signer: DecisionSigner;
89
+ secret?: never;
90
+ } | {
91
+ /**
92
+ * High-entropy key material (32+ bytes, hex or base64 — `openssl rand -hex 32`)
93
+ * deterministically derived into an Ed25519 signer. Verifiers receive the
94
+ * signer's `publicKeyPem`, never this secret.
95
+ */
96
+ secret: string;
97
+ signer?: never;
98
+ });
76
99
  export type InstallX402ClientHookOptions = TwzrdGateConfig & {
77
100
  /** Opt-in Payment Control: signed intent-bound decisions + local policy/mandate. */
78
101
  paymentControl?: X402PaymentControlOptions;
@@ -122,4 +145,5 @@ export declare function installTwzrdX402ClientHook(client: X402ClientLike, optio
122
145
  * Returns abort result without requiring a client instance.
123
146
  */
124
147
  export declare function twzrdBeforePaymentCreation(selectedRequirements: X402SelectedRequirements, options?: InstallX402ClientHookOptions): Promise<BeforePaymentCreationResult>;
148
+ export {};
125
149
  //# sourceMappingURL=x402-client-hook.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"x402-client-hook.d.ts","sourceRoot":"","sources":["../src/x402-client-hook.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"x402-client-hook.d.ts","sourceRoot":"","sources":["../src/x402-client-hook.ts"],"names":[],"mappings":"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"}
@@ -14,6 +14,8 @@ import { priceUsdcFromAmountMicro } from "./payto.js";
14
14
  import { twzrdApprovePayment } from "./policy.js";
15
15
  import { x402RequirementsToIntent } from "./intent-adapters.js";
16
16
  import { evaluateIntent } from "./policy-runtime.js";
17
+ import { createSeededDecisionSigner, } from "./decision-token.js";
18
+ import { counterpartyKnownFromApproval } from "./intelligence.js";
17
19
  function pickReq(ctx) {
18
20
  return ctx.selectedRequirements ?? ctx.requirements ?? {};
19
21
  }
@@ -37,6 +39,23 @@ function pickReq(ctx) {
37
39
  */
38
40
  export function installTwzrdX402ClientHook(client, options) {
39
41
  const cfg = resolveConfig(options);
42
+ // Resolve the Payment Control signer once at install time (fail fast).
43
+ // EXACTLY one of signer/secret — never silently prefer one when both are set.
44
+ let pcSigner;
45
+ if (options?.paymentControl) {
46
+ const { signer, secret } = options.paymentControl;
47
+ const hasSigner = signer != null;
48
+ const hasSecret = typeof secret === "string" && secret.length > 0;
49
+ if (hasSigner && hasSecret) {
50
+ throw new Error("[twzrd] paymentControl: provide exactly one of `signer` or `secret` — both were given. " +
51
+ "Silently choosing one would sign decisions with a key you did not intend.");
52
+ }
53
+ if (!hasSigner && !hasSecret) {
54
+ throw new Error("[twzrd] paymentControl: provide exactly one of `signer` or `secret` — neither was given. " +
55
+ "Decisions must be signed to be verifiable at the signer boundary.");
56
+ }
57
+ pcSigner = hasSigner ? signer : createSeededDecisionSigner(secret);
58
+ }
40
59
  client.onBeforePaymentCreation(async (context) => {
41
60
  const req = pickReq(context);
42
61
  const payTo = req.payTo ?? req.pay_to;
@@ -65,14 +84,22 @@ export function installTwzrdX402ClientHook(client, options) {
65
84
  purpose: pc.purpose,
66
85
  });
67
86
  decision = await evaluateIntent(intent, {
68
- signer: pc.signer,
87
+ signer: pcSigner,
69
88
  policy: pc.policy,
70
89
  mandate: pc.mandate,
71
90
  ledger: pc.ledger,
72
91
  ttlMs: pc.ttlMs,
73
92
  now: options.now?.(),
93
+ // Ledger hygiene: never record spend for a payment the legacy gate
94
+ // already denied — the hook aborts it regardless of this decision,
95
+ // so recording would pollute cumulative/monthly caps.
96
+ recordSpend: approval.approved,
74
97
  intelligence: () => ({
75
- known: approval.reputationScored ? true : undefined,
98
+ // NOT reputationScored — that flag is true for any scored Solana path,
99
+ // including a wallet we have never observed, which would mark every
100
+ // recipient known:true and disable unknownCounterparty entirely.
101
+ // Same shared mapping as the standalone intelligence provider.
102
+ known: counterpartyKnownFromApproval(approval),
76
103
  washFlagged: approval.washFlagged ?? undefined,
77
104
  decision: approval.verdict === "allow" ||
78
105
  approval.verdict === "warn" ||
@@ -1 +1 @@
1
- {"version":3,"file":"x402-client-hook.js","sourceRoot":"","sources":["../src/x402-client-hook.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"x402-client-hook.js","sourceRoot":"","sources":["../src/x402-client-hook.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "twzrd-x402-gate",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
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 \u2014 blocking the spend on bad paid intel, no human in the loop. 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 \u2014 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 \u2014 set TWZRD_FAIL_OPEN=true to restore legacy allow-on-outage behavior.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -26,8 +26,8 @@
26
26
  "scripts": {
27
27
  "build": "tsc",
28
28
  "prepublishOnly": "tsc",
29
- "typecheck": "tsc --noEmit",
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",
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",
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",