@insumermodel/mppx-condition-gate 2.0.3 → 3.0.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 CHANGED
@@ -6,16 +6,23 @@ Condition-based access for [mppx](https://github.com/wevm/mppx) routes. One sign
6
6
 
7
7
  ## How it works
8
8
 
9
- mppx embeds the payer's identity in every payment credential as a DID string (`credential.source: "did:pkh:eip155:8453:0xABC..."`). `conditionGate` reads that address, calls [InsumerAPI](https://insumermodel.com) to evaluate the configured conditions, and short-circuits the payment flow for wallets that pass.
9
+ Free access requires a payer your payment method has **proven** controls the request. You supply that payer through `provenPayer`; the gate never infers one.
10
10
 
11
11
  1. Request arrives with a payment credential
12
- 2. `conditionGate` extracts the payer address from `credential.source`
13
- 3. [InsumerAPI](https://insumermodel.com/developers/api-reference/) evaluates the conditions and returns an ECDSA P-256 signed attestation
14
- 4. **Pass** → free receipt returned (`reference: "condition-gate:free:{attestationId}"`)
15
- 5. **Fail** → delegates to the original `verify` (normal payment proceeds)
12
+ 2. The gate calls the method's non-mutating `validate` hook
13
+ 3. Your `provenPayer` resolver receives mppx's method-specific validation `details` and returns the proven payer, or `null`
14
+ 4. [InsumerAPI](https://insumermodel.com/developers/api-reference/) evaluates the conditions for that payer and returns an ECDSA P-256 signed attestation
15
+ 5. **Pass** → free receipt returned (`reference: "condition-gate:free:{attestationId}"`)
16
+ 6. **Fail, or no proven payer** → the normal paid path runs
16
17
 
17
18
  The signed attestation is verifiable offline via [JWKS](https://insumermodel.com/.well-known/jwks.json). The adapter does not re-sign or wrap the result; the signature on the attestation is the one InsumerAPI produced.
18
19
 
20
+ ### Why you must supply the payer
21
+
22
+ mppx credentials carry an optional `source` DID, but mppx documents it as *"an asserted identity, not independent proof of control"* — it is a claim by the caller, not a proof. Versions before 3.0.0 granted free access on it, which let anyone name a qualifying wallet and skip payment ([GHSA-jg6q-3qfh-r9f8](https://github.com/douglasborthwick-crypto/mppx-condition-gate/security/advisories/GHSA-jg6q-3qfh-r9f8)). The gate now refuses to guess.
23
+
24
+ `provenPayer` receives **only** the validation `details` — never the credential and never `source` — so the unproven identity is not reachable from it. Return a payer only if the payment method has actually established control of it. **Every path that cannot justify free access falls through to payment:** no resolver, no `validate` hook on the method, a resolver returning `null` or throwing, a credential that fails validation, conditions not met, or an attestation error.
25
+
19
26
  ## Install
20
27
 
21
28
  ```bash
@@ -35,6 +42,9 @@ const tempoCharge = tempo({
35
42
 
36
43
  const gatedCharge = conditionGate(tempoCharge, {
37
44
  apiKey: process.env.INSUMER_API_KEY,
45
+ // Return only a payer this method has PROVEN for this request, else null.
46
+ // The argument is mppx's method-specific validation `details`.
47
+ provenPayer: (details) => (details as { payer?: string }).payer ?? null,
38
48
  conditions: [{
39
49
  type: 'nft_ownership',
40
50
  contractAddress: '0xYourNFT',
@@ -58,7 +68,7 @@ Mix any of the six in a single call. `matchMode: 'any'` (default) passes when an
58
68
  type: 'token_balance',
59
69
  contractAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
60
70
  chainId: 1,
61
- threshold: 1000,
71
+ threshold: '1000', // decimal string in token units; numbers are converted before sending
62
72
  decimals: 6,
63
73
  label: 'USDC >= 1000',
64
74
  }
@@ -222,6 +232,24 @@ The condition shapes for `token_balance` and `nft_ownership` are unchanged. `eas
222
232
 
223
233
  The `parsXrplDid` typo from v1 is fixed: use `parseXrplDid`. The cache helper renamed: `clearTokenGateCache` is now `clearConditionGateCache`.
224
234
 
235
+ ## Migrating from 2.x (security release)
236
+
237
+ 3.0.0 fixes an authentication bypass ([GHSA-jg6q-3qfh-r9f8](https://github.com/douglasborthwick-crypto/mppx-condition-gate/security/advisories/GHSA-jg6q-3qfh-r9f8)). All 2.x versions, and all versions of the predecessor `@insumermodel/mppx-token-gate`, are affected.
238
+
239
+ Add a `provenPayer` resolver:
240
+
241
+ ```diff
242
+ const gated = conditionGate(server, {
243
+ apiKey: process.env.INSUMER_API_KEY,
244
+ + provenPayer: (details) => (details as { payer?: string }).payer ?? null,
245
+ conditions: [ ... ],
246
+ })
247
+ ```
248
+
249
+ Without it the gate compiles and runs, but never grants free access — every request takes the paid path. That is deliberate: the insecure default is gone, and the safe default is to charge.
250
+
251
+ Your method must expose mppx's `validate` hook. Legacy `verify`-only methods have no non-mutating pre-check, so they are never gated.
252
+
225
253
  ## License
226
254
 
227
255
  MIT
package/dist/index.d.ts CHANGED
@@ -6,8 +6,10 @@ export type TokenBalanceCondition = {
6
6
  /** Token contract address. For XRPL native XRP or Bitcoin, use "native". */
7
7
  contractAddress: string;
8
8
  chainId: ChainId;
9
- /** Minimum balance. Defaults to 1. */
10
- threshold?: number;
9
+ /** Minimum balance in token units. Pass a decimal string (e.g. "1000") for
10
+ * full precision; keys minted today sign under the v2 scheme and reject a
11
+ * JSON number, so numbers are converted to strings before sending. Defaults to "1". */
12
+ threshold?: number | string;
11
13
  /** Token decimals. Auto-detected on most EVM chains if omitted. */
12
14
  decimals?: number;
13
15
  /** XRPL currency code (e.g. "USD", "RLUSD") for trust-line tokens. */
@@ -77,9 +79,42 @@ export type RatioToSupplyCondition = {
77
79
  };
78
80
  /** Any condition accepted by /v1/attest */
79
81
  export type Condition = TokenBalanceCondition | NftOwnershipCondition | EasAttestationCondition | FarcasterIdCondition | RatioToAmountCondition | RatioToSupplyCondition;
82
+ /** Wallet family for a proven payer. */
83
+ export type WalletType = 'evm' | 'solana' | 'xrpl' | 'bitcoin';
84
+ /**
85
+ * A payer the caller has cryptographically proven for this request.
86
+ *
87
+ * Accepts a `did:pkh:...` string, a bare `0x` EVM address, or an explicit
88
+ * `{ address, type }` pair. Bare non-EVM addresses are rejected because their
89
+ * wallet family cannot be inferred unambiguously — pass the object form.
90
+ */
91
+ export type ProvenPayer = string | {
92
+ address: string;
93
+ type: WalletType;
94
+ } | null | undefined;
80
95
  export type ConditionGateOptions = {
81
96
  /** InsumerAPI key. Falls back to INSUMER_API_KEY env var. */
82
97
  apiKey?: string;
98
+ /**
99
+ * Resolves the payer that the payment method has PROVEN controls this
100
+ * request. Required for free access — without it every request takes the
101
+ * paid path.
102
+ *
103
+ * It receives only mppx's method-specific validation `details` (for example
104
+ * a recovered payer address). It is deliberately NOT given the credential or
105
+ * the declared `source`: mppx documents `source` as "an asserted identity,
106
+ * not independent proof of control", and granting on it is the vulnerability
107
+ * fixed in 3.0.0 (GHSA-jg6q-3qfh-r9f8).
108
+ *
109
+ * Return `null` when no payer has been proven. Returning an address you have
110
+ * not proven reintroduces that vulnerability.
111
+ *
112
+ * @example
113
+ * ```ts
114
+ * provenPayer: (details) => (details as { payer?: string }).payer ?? null
115
+ * ```
116
+ */
117
+ provenPayer?: (details: unknown) => ProvenPayer | Promise<ProvenPayer>;
83
118
  /** One or more conditions to evaluate. Mix any of the six types. */
84
119
  conditions: Condition[];
85
120
  /** Whether the wallet must satisfy "any" (default) or "all" conditions. */
@@ -142,20 +177,37 @@ export declare function parseSolanaDid(source: string): string | null;
142
177
  export declare function parseXrplDid(source: string): string | null;
143
178
  /** Extracts a Bitcoin address from a `did:pkh:bip122:{chainId}:{address}` string. */
144
179
  export declare function parseBitcoinDid(source: string): string | null;
180
+ /**
181
+ * Normalizes a caller-supplied proven payer into an address + wallet family.
182
+ *
183
+ * Fail-closed: anything it cannot resolve unambiguously returns null, which
184
+ * sends the request to the paid path.
185
+ */
186
+ export declare function normalizeProvenPayer(payer: ProvenPayer): {
187
+ address: string;
188
+ type: WalletType;
189
+ } | null;
145
190
  /**
146
191
  * Wraps an mppx Method.Server with condition-based access using signed attestations.
147
192
  *
148
- * Extracts the payer address from credential.source (DID), calls /v1/attest to
149
- * evaluate conditions across the 35 chains this adapter reaches (32 EVM + Solana + XRPL + Bitcoin; the engine itself covers 38), and returns a free-access receipt for
150
- * wallets that meet the conditions. Wallets that do not meet them fall through
151
- * to the original payment method.
193
+ * Free access requires a PROVEN payer. The gate calls the method's non-mutating
194
+ * `validate` hook, hands the resulting method-specific `details` to your
195
+ * `provenPayer` resolver, and only then evaluates conditions. It never reads
196
+ * `credential.source` — mppx documents that field as an asserted identity
197
+ * rather than proof of control.
198
+ *
199
+ * The gate falls through to the paid path whenever free access cannot be
200
+ * justified: no `provenPayer` resolver, no `validate` hook on the method
201
+ * (legacy `verify`-only methods included), a resolver returning null, a
202
+ * credential that fails validation, conditions not met, or an attestation
203
+ * error. There is no path from an unproven wallet to a free receipt.
152
204
  *
153
- * Supports six condition types through this adapter's typed surface: token_balance,
154
- * nft_ownership, eas_attestation, farcaster_id, ratio_to_amount (balance >= multiple
155
- * * amount), and ratio_to_supply (balance / totalSupply >= minFraction; EVM + ERC-20
156
- * only). Conditions can be mixed in a single call. InsumerAPI itself also offers
157
- * evm_view_call, erc8004_agent, and erc7710_delegation; those are not yet typed or
158
- * normalized here, so call /v1/attest directly if you need them.
205
+ * Conditions are evaluated across the 35 chains this adapter reaches (32 EVM +
206
+ * Solana + XRPL + Bitcoin; the engine itself covers 38). Six condition types
207
+ * are typed here: token_balance, nft_ownership, eas_attestation, farcaster_id,
208
+ * ratio_to_amount, and ratio_to_supply. InsumerAPI also offers evm_view_call,
209
+ * erc8004_agent, and erc7710_delegation; those are not typed or normalized
210
+ * here, so call /v1/attest directly if you need them.
159
211
  *
160
212
  * The attestation is ECDSA P-256 signed and verifiable offline via the public
161
213
  * JWKS at https://insumermodel.com/.well-known/jwks.json.
@@ -165,6 +217,8 @@ export declare function parseBitcoinDid(source: string): string | null;
165
217
  * import { conditionGate } from '@insumermodel/mppx-condition-gate'
166
218
  *
167
219
  * const gated = conditionGate(tempoCharge, {
220
+ * // Return only a payer this method has proven for THIS request.
221
+ * provenPayer: (details) => (details as { payer?: string }).payer ?? null,
168
222
  * conditions: [
169
223
  * { type: 'eas_attestation', template: 'coinbase_verified_account', chainId: 8453 },
170
224
  * { type: 'farcaster_id' },
@@ -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
@@ -125,7 +125,8 @@ function buildBodyConditions(conditions) {
125
125
  chainId: c.chainId,
126
126
  };
127
127
  if (c.type === 'token_balance') {
128
- cond.threshold = c.threshold ?? 1;
128
+ const threshold = c.threshold ?? '1';
129
+ cond.threshold = typeof threshold === 'string' ? threshold : String(threshold);
129
130
  if (c.decimals !== undefined)
130
131
  cond.decimals = c.decimals;
131
132
  if (c.currency)
@@ -177,20 +178,61 @@ async function callAttest(wallet, walletType, conditions, options) {
177
178
  // ---------------------------------------------------------------------------
178
179
  // conditionGate adapter
179
180
  // ---------------------------------------------------------------------------
181
+ /**
182
+ * Normalizes a caller-supplied proven payer into an address + wallet family.
183
+ *
184
+ * Fail-closed: anything it cannot resolve unambiguously returns null, which
185
+ * sends the request to the paid path.
186
+ */
187
+ export function normalizeProvenPayer(payer) {
188
+ if (!payer)
189
+ return null;
190
+ if (typeof payer === 'object') {
191
+ const { address, type } = payer;
192
+ if (!address || !type)
193
+ return null;
194
+ return { address, type };
195
+ }
196
+ if (typeof payer !== 'string')
197
+ return null;
198
+ const evm = parseDid(payer);
199
+ if (evm)
200
+ return { address: evm, type: 'evm' };
201
+ const sol = parseSolanaDid(payer);
202
+ if (sol)
203
+ return { address: sol, type: 'solana' };
204
+ const xrpl = parseXrplDid(payer);
205
+ if (xrpl)
206
+ return { address: xrpl, type: 'xrpl' };
207
+ const btc = parseBitcoinDid(payer);
208
+ if (btc)
209
+ return { address: btc, type: 'bitcoin' };
210
+ // Bare EVM address is unambiguous; anything else needs the object form.
211
+ if (payer.startsWith('0x'))
212
+ return { address: payer, type: 'evm' };
213
+ return null;
214
+ }
180
215
  /**
181
216
  * Wraps an mppx Method.Server with condition-based access using signed attestations.
182
217
  *
183
- * Extracts the payer address from credential.source (DID), calls /v1/attest to
184
- * evaluate conditions across the 35 chains this adapter reaches (32 EVM + Solana + XRPL + Bitcoin; the engine itself covers 38), and returns a free-access receipt for
185
- * wallets that meet the conditions. Wallets that do not meet them fall through
186
- * to the original payment method.
218
+ * Free access requires a PROVEN payer. The gate calls the method's non-mutating
219
+ * `validate` hook, hands the resulting method-specific `details` to your
220
+ * `provenPayer` resolver, and only then evaluates conditions. It never reads
221
+ * `credential.source` — mppx documents that field as an asserted identity
222
+ * rather than proof of control.
223
+ *
224
+ * The gate falls through to the paid path whenever free access cannot be
225
+ * justified: no `provenPayer` resolver, no `validate` hook on the method
226
+ * (legacy `verify`-only methods included), a resolver returning null, a
227
+ * credential that fails validation, conditions not met, or an attestation
228
+ * error. There is no path from an unproven wallet to a free receipt.
187
229
  *
188
- * Supports six condition types through this adapter's typed surface: token_balance,
189
- * nft_ownership, eas_attestation, farcaster_id, ratio_to_amount (balance >= multiple
190
- * * amount), and ratio_to_supply (balance / totalSupply >= minFraction; EVM + ERC-20
191
- * only). Conditions can be mixed in a single call. InsumerAPI itself also offers
192
- * evm_view_call, erc8004_agent, and erc7710_delegation; those are not yet typed or
193
- * normalized here, so call /v1/attest directly if you need them.
230
+ * Conditions are evaluated across the 35 chains this adapter reaches (32 EVM +
231
+ * Solana + XRPL + Bitcoin; the engine itself covers 38). Six condition types
232
+ * are typed here: token_balance, nft_ownership, eas_attestation, farcaster_id,
233
+ * ratio_to_amount, and ratio_to_supply. InsumerAPI also offers evm_view_call,
234
+ * erc8004_agent, and erc7710_delegation; those are not typed or normalized
235
+ * here, so call /v1/attest directly if you need them.
194
236
  *
195
237
  * The attestation is ECDSA P-256 signed and verifiable offline via the public
196
238
  * JWKS at https://insumermodel.com/.well-known/jwks.json.
@@ -200,6 +242,8 @@ async function callAttest(wallet, walletType, conditions, options) {
200
242
  * import { conditionGate } from '@insumermodel/mppx-condition-gate'
201
243
  *
202
244
  * const gated = conditionGate(tempoCharge, {
245
+ * // Return only a payer this method has proven for THIS request.
246
+ * provenPayer: (details) => (details as { payer?: string }).payer ?? null,
203
247
  * conditions: [
204
248
  * { type: 'eas_attestation', template: 'coinbase_verified_account', chainId: 8453 },
205
249
  * { type: 'farcaster_id' },
@@ -211,87 +255,81 @@ async function callAttest(wallet, walletType, conditions, options) {
211
255
  * ```
212
256
  */
213
257
  export function conditionGate(server, options) {
214
- const { conditions, matchMode = 'any', cacheTtlSeconds = 300 } = options;
215
- const originalVerify = server.verify;
216
- const gatedVerify = async (params) => {
217
- const credential = params.credential;
218
- const source = credential.source;
219
- // No DID → fall through to payment
220
- if (!source)
221
- return originalVerify(params);
222
- // Determine wallet type and address
223
- let wallet = null;
224
- let walletType = 'evm';
225
- wallet = parseDid(source);
226
- if (!wallet) {
227
- wallet = parseSolanaDid(source);
228
- if (wallet)
229
- walletType = 'solana';
258
+ const { conditions, matchMode = 'any', cacheTtlSeconds = 300, provenPayer } = options;
259
+ const anyServer = server;
260
+ const originalVerify = anyServer.verify;
261
+ const originalBroadcast = anyServer.broadcast;
262
+ const originalValidate = anyServer.validate;
263
+ // Free access is only reachable when BOTH exist: a resolver to supply the
264
+ // proven payer, and a non-mutating validate hook to derive it from. A method
265
+ // without `validate` (legacy verify-only, or broadcast-without-validate) has
266
+ // no safe pre-check, so it is never gated.
267
+ const canGate = typeof provenPayer === 'function' && typeof originalValidate === 'function';
268
+ /** Returns a free receipt, or null to take the paid path. */
269
+ async function tryFree(params) {
270
+ if (!canGate)
271
+ return null;
272
+ let details;
273
+ try {
274
+ const validation = await originalValidate(params);
275
+ details = validation?.details;
230
276
  }
231
- if (!wallet) {
232
- wallet = parseXrplDid(source);
233
- if (wallet)
234
- walletType = 'xrpl';
277
+ catch {
278
+ // Credential is not currently acceptable → let the payment method decide.
279
+ return null;
235
280
  }
236
- if (!wallet) {
237
- wallet = parseBitcoinDid(source);
238
- if (wallet)
239
- walletType = 'bitcoin';
281
+ let resolved;
282
+ try {
283
+ resolved = await provenPayer(details);
284
+ }
285
+ catch {
286
+ return null;
240
287
  }
241
- // Unparseable DID → fall through to payment
242
- if (!wallet)
243
- return originalVerify(params);
244
- // Check cache
245
- const key = cacheKey(wallet, conditions);
288
+ const payer = normalizeProvenPayer(resolved);
289
+ if (!payer)
290
+ return null;
291
+ const key = cacheKey(payer.address, conditions);
246
292
  const cached = cache.get(key);
247
293
  if (cached && cached.expiresAt > Date.now()) {
248
- if (cached.pass) {
249
- return {
250
- method: server.name,
251
- reference: `condition-gate:free:${cached.attestationId}`,
252
- status: 'success',
253
- timestamp: new Date().toISOString(),
254
- };
255
- }
256
- // Cached non-holder → fall through
257
- return originalVerify(params);
294
+ if (!cached.pass)
295
+ return null;
296
+ return {
297
+ method: server.name,
298
+ reference: `condition-gate:free:${cached.attestationId}`,
299
+ status: 'success',
300
+ timestamp: new Date().toISOString(),
301
+ };
258
302
  }
259
- // Call InsumerAPI
260
303
  try {
261
- const result = await callAttest(wallet, walletType, conditions, options);
304
+ const result = await callAttest(payer.address, payer.type, conditions, options);
262
305
  const attestation = result.data.attestation;
263
- // Determine pass based on matchMode
264
- let pass;
265
- if (matchMode === 'all') {
266
- pass = attestation.pass; // all conditions must be met
267
- }
268
- else {
269
- // "any" — at least one condition met
270
- pass = attestation.results.some((r) => r.met);
271
- }
272
- // Cache the result
306
+ const pass = matchMode === 'all'
307
+ ? attestation.pass
308
+ : attestation.results.some((r) => r.met);
273
309
  cache.set(key, {
274
310
  pass,
275
311
  attestationId: attestation.id,
276
312
  expiresAt: Date.now() + cacheTtlSeconds * 1000,
277
313
  });
278
- if (pass) {
279
- return {
280
- method: server.name,
281
- reference: `condition-gate:free:${attestation.id}`,
282
- status: 'success',
283
- timestamp: new Date().toISOString(),
284
- };
285
- }
314
+ if (!pass)
315
+ return null;
316
+ return {
317
+ method: server.name,
318
+ reference: `condition-gate:free:${attestation.id}`,
319
+ status: 'success',
320
+ timestamp: new Date().toISOString(),
321
+ };
286
322
  }
287
323
  catch {
288
- // Attestation API error → fall through to payment (fail open)
324
+ // Attestation error → paid path.
325
+ return null;
289
326
  }
290
- return originalVerify(params);
291
- };
292
- return {
293
- ...server,
294
- verify: gatedVerify,
295
- };
327
+ }
328
+ const wrapped = { ...server };
329
+ if (typeof originalBroadcast === 'function') {
330
+ wrapped.broadcast = async (params) => (await tryFree(params)) ?? originalBroadcast(params);
331
+ }
332
+ wrapped.verify = async (params) => (await tryFree(params)) ?? originalVerify(params);
333
+ return wrapped;
296
334
  }
297
335
  //# 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":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@insumermodel/mppx-condition-gate",
3
- "version": "2.0.3",
3
+ "version": "3.0.1",
4
4
  "description": "Condition-based access for mppx routes. Wallet auth via signed attestations. Six condition types: token balance, NFT ownership, EAS attestation, Farcaster ID, ratio_to_amount, ratio_to_supply.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -17,7 +17,8 @@
17
17
  ],
18
18
  "scripts": {
19
19
  "build": "tsc",
20
- "prepublishOnly": "npm run build"
20
+ "prepublishOnly": "npm run build",
21
+ "test": "tsc && node --test test/*.test.mjs"
21
22
  },
22
23
  "keywords": [
23
24
  "condition-based-access",
package/src/index.ts CHANGED
@@ -12,8 +12,10 @@ export type TokenBalanceCondition = {
12
12
  /** Token contract address. For XRPL native XRP or Bitcoin, use "native". */
13
13
  contractAddress: string
14
14
  chainId: ChainId
15
- /** Minimum balance. Defaults to 1. */
16
- threshold?: number
15
+ /** Minimum balance in token units. Pass a decimal string (e.g. "1000") for
16
+ * full precision; keys minted today sign under the v2 scheme and reject a
17
+ * JSON number, so numbers are converted to strings before sending. Defaults to "1". */
18
+ threshold?: number | string
17
19
  /** Token decimals. Auto-detected on most EVM chains if omitted. */
18
20
  decimals?: number
19
21
  /** XRPL currency code (e.g. "USD", "RLUSD") for trust-line tokens. */
@@ -101,9 +103,45 @@ export type Condition =
101
103
  | RatioToAmountCondition
102
104
  | RatioToSupplyCondition
103
105
 
106
+ /** Wallet family for a proven payer. */
107
+ export type WalletType = 'evm' | 'solana' | 'xrpl' | 'bitcoin'
108
+
109
+ /**
110
+ * A payer the caller has cryptographically proven for this request.
111
+ *
112
+ * Accepts a `did:pkh:...` string, a bare `0x` EVM address, or an explicit
113
+ * `{ address, type }` pair. Bare non-EVM addresses are rejected because their
114
+ * wallet family cannot be inferred unambiguously — pass the object form.
115
+ */
116
+ export type ProvenPayer =
117
+ | string
118
+ | { address: string; type: WalletType }
119
+ | null
120
+ | undefined
121
+
104
122
  export type ConditionGateOptions = {
105
123
  /** InsumerAPI key. Falls back to INSUMER_API_KEY env var. */
106
124
  apiKey?: string
125
+ /**
126
+ * Resolves the payer that the payment method has PROVEN controls this
127
+ * request. Required for free access — without it every request takes the
128
+ * paid path.
129
+ *
130
+ * It receives only mppx's method-specific validation `details` (for example
131
+ * a recovered payer address). It is deliberately NOT given the credential or
132
+ * the declared `source`: mppx documents `source` as "an asserted identity,
133
+ * not independent proof of control", and granting on it is the vulnerability
134
+ * fixed in 3.0.0 (GHSA-jg6q-3qfh-r9f8).
135
+ *
136
+ * Return `null` when no payer has been proven. Returning an address you have
137
+ * not proven reintroduces that vulnerability.
138
+ *
139
+ * @example
140
+ * ```ts
141
+ * provenPayer: (details) => (details as { payer?: string }).payer ?? null
142
+ * ```
143
+ */
144
+ provenPayer?: (details: unknown) => ProvenPayer | Promise<ProvenPayer>
107
145
  /** One or more conditions to evaluate. Mix any of the six types. */
108
146
  conditions: Condition[]
109
147
  /** Whether the wallet must satisfy "any" (default) or "all" conditions. */
@@ -283,7 +321,8 @@ function buildBodyConditions(conditions: Condition[]): Array<Record<string, unkn
283
321
  chainId: c.chainId,
284
322
  }
285
323
  if (c.type === 'token_balance') {
286
- cond.threshold = c.threshold ?? 1
324
+ const threshold = c.threshold ?? '1'
325
+ cond.threshold = typeof threshold === 'string' ? threshold : String(threshold)
287
326
  if (c.decimals !== undefined) cond.decimals = c.decimals
288
327
  if (c.currency) cond.currency = c.currency
289
328
  }
@@ -343,20 +382,60 @@ async function callAttest(
343
382
  // conditionGate adapter
344
383
  // ---------------------------------------------------------------------------
345
384
 
385
+ /**
386
+ * Normalizes a caller-supplied proven payer into an address + wallet family.
387
+ *
388
+ * Fail-closed: anything it cannot resolve unambiguously returns null, which
389
+ * sends the request to the paid path.
390
+ */
391
+ export function normalizeProvenPayer(
392
+ payer: ProvenPayer,
393
+ ): { address: string; type: WalletType } | null {
394
+ if (!payer) return null
395
+
396
+ if (typeof payer === 'object') {
397
+ const { address, type } = payer
398
+ if (!address || !type) return null
399
+ return { address, type }
400
+ }
401
+
402
+ if (typeof payer !== 'string') return null
403
+
404
+ const evm = parseDid(payer)
405
+ if (evm) return { address: evm, type: 'evm' }
406
+ const sol = parseSolanaDid(payer)
407
+ if (sol) return { address: sol, type: 'solana' }
408
+ const xrpl = parseXrplDid(payer)
409
+ if (xrpl) return { address: xrpl, type: 'xrpl' }
410
+ const btc = parseBitcoinDid(payer)
411
+ if (btc) return { address: btc, type: 'bitcoin' }
412
+
413
+ // Bare EVM address is unambiguous; anything else needs the object form.
414
+ if (payer.startsWith('0x')) return { address: payer, type: 'evm' }
415
+ return null
416
+ }
417
+
346
418
  /**
347
419
  * Wraps an mppx Method.Server with condition-based access using signed attestations.
348
420
  *
349
- * Extracts the payer address from credential.source (DID), calls /v1/attest to
350
- * evaluate conditions across the 35 chains this adapter reaches (32 EVM + Solana + XRPL + Bitcoin; the engine itself covers 38), and returns a free-access receipt for
351
- * wallets that meet the conditions. Wallets that do not meet them fall through
352
- * to the original payment method.
421
+ * Free access requires a PROVEN payer. The gate calls the method's non-mutating
422
+ * `validate` hook, hands the resulting method-specific `details` to your
423
+ * `provenPayer` resolver, and only then evaluates conditions. It never reads
424
+ * `credential.source` — mppx documents that field as an asserted identity
425
+ * rather than proof of control.
426
+ *
427
+ * The gate falls through to the paid path whenever free access cannot be
428
+ * justified: no `provenPayer` resolver, no `validate` hook on the method
429
+ * (legacy `verify`-only methods included), a resolver returning null, a
430
+ * credential that fails validation, conditions not met, or an attestation
431
+ * error. There is no path from an unproven wallet to a free receipt.
353
432
  *
354
- * Supports six condition types through this adapter's typed surface: token_balance,
355
- * nft_ownership, eas_attestation, farcaster_id, ratio_to_amount (balance >= multiple
356
- * * amount), and ratio_to_supply (balance / totalSupply >= minFraction; EVM + ERC-20
357
- * only). Conditions can be mixed in a single call. InsumerAPI itself also offers
358
- * evm_view_call, erc8004_agent, and erc7710_delegation; those are not yet typed or
359
- * normalized here, so call /v1/attest directly if you need them.
433
+ * Conditions are evaluated across the 35 chains this adapter reaches (32 EVM +
434
+ * Solana + XRPL + Bitcoin; the engine itself covers 38). Six condition types
435
+ * are typed here: token_balance, nft_ownership, eas_attestation, farcaster_id,
436
+ * ratio_to_amount, and ratio_to_supply. InsumerAPI also offers evm_view_call,
437
+ * erc8004_agent, and erc7710_delegation; those are not typed or normalized
438
+ * here, so call /v1/attest directly if you need them.
360
439
  *
361
440
  * The attestation is ECDSA P-256 signed and verifiable offline via the public
362
441
  * JWKS at https://insumermodel.com/.well-known/jwks.json.
@@ -366,6 +445,8 @@ async function callAttest(
366
445
  * import { conditionGate } from '@insumermodel/mppx-condition-gate'
367
446
  *
368
447
  * const gated = conditionGate(tempoCharge, {
448
+ * // Return only a payer this method has proven for THIS request.
449
+ * provenPayer: (details) => (details as { payer?: string }).payer ?? null,
369
450
  * conditions: [
370
451
  * { type: 'eas_attestation', template: 'coinbase_verified_account', chainId: 8453 },
371
452
  * { type: 'farcaster_id' },
@@ -380,92 +461,97 @@ export function conditionGate(
380
461
  server: Method.AnyServer,
381
462
  options: ConditionGateOptions,
382
463
  ): Method.AnyServer {
383
- const { conditions, matchMode = 'any', cacheTtlSeconds = 300 } = options
464
+ const { conditions, matchMode = 'any', cacheTtlSeconds = 300, provenPayer } = options
384
465
 
385
- const originalVerify = server.verify
466
+ const anyServer = server as unknown as {
467
+ verify: (params: any) => Promise<any>
468
+ broadcast?: (params: any) => Promise<any>
469
+ validate?: (params: any) => Promise<any>
470
+ }
386
471
 
387
- const gatedVerify: typeof originalVerify = async (params: any) => {
388
- const credential = params.credential as { source?: string }
389
- const source = credential.source
472
+ const originalVerify = anyServer.verify
473
+ const originalBroadcast = anyServer.broadcast
474
+ const originalValidate = anyServer.validate
390
475
 
391
- // No DID → fall through to payment
392
- if (!source) return originalVerify(params)
476
+ // Free access is only reachable when BOTH exist: a resolver to supply the
477
+ // proven payer, and a non-mutating validate hook to derive it from. A method
478
+ // without `validate` (legacy verify-only, or broadcast-without-validate) has
479
+ // no safe pre-check, so it is never gated.
480
+ const canGate =
481
+ typeof provenPayer === 'function' && typeof originalValidate === 'function'
393
482
 
394
- // Determine wallet type and address
395
- let wallet: string | null = null
396
- let walletType: 'evm' | 'solana' | 'xrpl' | 'bitcoin' = 'evm'
483
+ /** Returns a free receipt, or null to take the paid path. */
484
+ async function tryFree(params: any): Promise<any | null> {
485
+ if (!canGate) return null
397
486
 
398
- wallet = parseDid(source)
399
- if (!wallet) {
400
- wallet = parseSolanaDid(source)
401
- if (wallet) walletType = 'solana'
402
- }
403
- if (!wallet) {
404
- wallet = parseXrplDid(source)
405
- if (wallet) walletType = 'xrpl'
487
+ let details: unknown
488
+ try {
489
+ const validation = await originalValidate!(params)
490
+ details = (validation as { details?: unknown } | undefined)?.details
491
+ } catch {
492
+ // Credential is not currently acceptable → let the payment method decide.
493
+ return null
406
494
  }
407
- if (!wallet) {
408
- wallet = parseBitcoinDid(source)
409
- if (wallet) walletType = 'bitcoin'
495
+
496
+ let resolved: ProvenPayer
497
+ try {
498
+ resolved = await provenPayer!(details)
499
+ } catch {
500
+ return null
410
501
  }
411
502
 
412
- // Unparseable DID → fall through to payment
413
- if (!wallet) return originalVerify(params)
503
+ const payer = normalizeProvenPayer(resolved)
504
+ if (!payer) return null
414
505
 
415
- // Check cache
416
- const key = cacheKey(wallet, conditions)
506
+ const key = cacheKey(payer.address, conditions)
417
507
  const cached = cache.get(key)
418
508
  if (cached && cached.expiresAt > Date.now()) {
419
- if (cached.pass) {
420
- return {
421
- method: server.name,
422
- reference: `condition-gate:free:${cached.attestationId}`,
423
- status: 'success' as const,
424
- timestamp: new Date().toISOString(),
425
- }
509
+ if (!cached.pass) return null
510
+ return {
511
+ method: server.name,
512
+ reference: `condition-gate:free:${cached.attestationId}`,
513
+ status: 'success' as const,
514
+ timestamp: new Date().toISOString(),
426
515
  }
427
- // Cached non-holder → fall through
428
- return originalVerify(params)
429
516
  }
430
517
 
431
- // Call InsumerAPI
432
518
  try {
433
- const result = await callAttest(wallet, walletType, conditions, options)
519
+ const result = await callAttest(payer.address, payer.type, conditions, options)
434
520
  const attestation = result.data.attestation
435
521
 
436
- // Determine pass based on matchMode
437
- let pass: boolean
438
- if (matchMode === 'all') {
439
- pass = attestation.pass // all conditions must be met
440
- } else {
441
- // "any" — at least one condition met
442
- pass = attestation.results.some((r) => r.met)
443
- }
522
+ const pass =
523
+ matchMode === 'all'
524
+ ? attestation.pass
525
+ : attestation.results.some((r) => r.met)
444
526
 
445
- // Cache the result
446
527
  cache.set(key, {
447
528
  pass,
448
529
  attestationId: attestation.id,
449
530
  expiresAt: Date.now() + cacheTtlSeconds * 1000,
450
531
  })
451
532
 
452
- if (pass) {
453
- return {
454
- method: server.name,
455
- reference: `condition-gate:free:${attestation.id}`,
456
- status: 'success' as const,
457
- timestamp: new Date().toISOString(),
458
- }
533
+ if (!pass) return null
534
+ return {
535
+ method: server.name,
536
+ reference: `condition-gate:free:${attestation.id}`,
537
+ status: 'success' as const,
538
+ timestamp: new Date().toISOString(),
459
539
  }
460
540
  } catch {
461
- // Attestation API error → fall through to payment (fail open)
541
+ // Attestation error → paid path.
542
+ return null
462
543
  }
463
-
464
- return originalVerify(params)
465
544
  }
466
545
 
467
- return {
468
- ...server,
469
- verify: gatedVerify,
546
+ const wrapped = { ...server } as unknown as Record<string, unknown>
547
+
548
+ if (typeof originalBroadcast === 'function') {
549
+ wrapped.broadcast = async (params: any) =>
550
+ (await tryFree(params)) ?? originalBroadcast(params)
470
551
  }
552
+
553
+ wrapped.verify = async (params: any) =>
554
+ (await tryFree(params)) ?? originalVerify(params)
555
+
556
+ return wrapped as unknown as Method.AnyServer
471
557
  }