@nevermined-io/core-kit 1.33.0 → 1.34.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.
@@ -323,8 +323,8 @@ export type NeverminedTypedDataMessageV3 = NeverminedTypedDataMessage & {
323
323
  * x402's (#3266).
324
324
  *
325
325
  * `1` is not mintable — it only exists as a verification branch for tokens minted
326
- * before #1678. New tokens are v2 (the default, reusable, pre-#2646 semantics) or
327
- * v3 (seller/resource-bound and single-use).
326
+ * before #1678. New tokens are v3 (the default since #3259 seller/resource-bound
327
+ * and single-use) or v2 (legacy: reusable, unbound, pre-#2646 semantics).
328
328
  *
329
329
  * MPP has NO version ladder and no ordinal of its own: it signs ONE struct —
330
330
  * {@link NeverminedTypedDataTypes}, reused rather than copied — and names no version for it.
@@ -356,12 +356,20 @@ export type GenerateX402TokenOptions = {
356
356
  /** Token expiration timestamp in seconds (Unix epoch) */
357
357
  validUntil?: number;
358
358
  /**
359
- * EIP-712 struct version to sign (#2646). Defaults to `2` the reusable,
360
- * pre-#2646 shape — so existing callers are untouched and there is no flag day.
359
+ * EIP-712 struct version to sign (#2646). **Defaults to `3` since #3259.**
361
360
  *
362
361
  * `3` binds the token to `agentId` / `resource.url` / `httpVerb` and adds a
363
362
  * one-time nonce, which the resource server consumes at settle. A v3 token is
364
- * therefore SINGLE-USE: a caller that opts in must mint one per paid request.
363
+ * therefore SINGLE-USE: the caller mints one per paid request.
364
+ *
365
+ * `2` is the pre-#2646 shape — reusable and unbound — and stays selectable for callers that
366
+ * cannot mint per request. It is the shape a captured token replays forever, so treat it as
367
+ * legacy: it is a deliberate opt-OUT of the nonce, not a neutral choice.
368
+ *
369
+ * ⚠️ The default is the one thing an API caller does NOT control from here: the API pins `2`
370
+ * for clients whose `Nevermined-Version` resolves below 1.34 (the `1.34-x402-default-token-version`
371
+ * gate), so this default is what a 1.34+ client gets. A direct core-kit consumer has no gate and
372
+ * gets `3` outright.
365
373
  *
366
374
  * x402 ONLY (#3266). It used to apply to both protocols, which is exactly how the x402 nonce
367
375
  * reached MPP — where the access token is the buyer's REUSABLE credential and the single-use
@@ -385,8 +393,9 @@ export type GenerateMppTokenOptions = Omit<GenerateX402TokenOptions, 'tokenVersi
385
393
  /**
386
394
  * Generate an x402 access token aligned with x402 v2 spec.
387
395
  *
388
- * Walks x402's OWN version ladder (#3266): v3 when the caller asks for the #2646 binding and
389
- * one-time nonce, the base struct otherwise. Nothing chosen here can reach the MPP minter.
396
+ * Walks x402's OWN version ladder (#3266): v3 the #2646 binding and one-time nonce unless the
397
+ * caller explicitly asks for the legacy v2 struct (#3259). Nothing chosen here can reach the MPP
398
+ * minter.
390
399
  *
391
400
  * @param options - Token generation options
392
401
  * @returns x402 access token with EIP-712 signature
@@ -1 +1 @@
1
- {"version":3,"file":"AgentX402AccessToken.d.ts","sourceRoot":"","sources":["../../src/models/AgentX402AccessToken.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AgentX402AccessToken.d.ts","sourceRoot":"","sources":["../../src/models/AgentX402AccessToken.ts"],"names":[],"mappings":"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"}
@@ -265,8 +265,9 @@ export const NeverminedTypedDataTypesV3 = {
265
265
  /**
266
266
  * Generate an x402 access token aligned with x402 v2 spec.
267
267
  *
268
- * Walks x402's OWN version ladder (#3266): v3 when the caller asks for the #2646 binding and
269
- * one-time nonce, the base struct otherwise. Nothing chosen here can reach the MPP minter.
268
+ * Walks x402's OWN version ladder (#3266): v3 the #2646 binding and one-time nonce unless the
269
+ * caller explicitly asks for the legacy v2 struct (#3259). Nothing chosen here can reach the MPP
270
+ * minter.
270
271
  *
271
272
  * @param options - Token generation options
272
273
  * @returns x402 access token with EIP-712 signature
@@ -276,7 +277,12 @@ export const NeverminedTypedDataTypesV3 = {
276
277
  // left undefined is signed as '' — EIP-712 has no optional members, so "not bound" must itself
277
278
  // be a signed value; `isSignedBindingConsistent` then holds the unsigned envelope copy to the
278
279
  // same absence.
279
- if ((options.tokenVersion ?? 2) === 3) {
280
+ //
281
+ // #3259 — v3 is the DEFAULT, and the absent case is the one that matters: #2646 shipped the
282
+ // nonce and the binding as an opt-in nobody took, so on the default path an x402 token stayed
283
+ // replayable and unbound. Flipping the fallback is the whole control. v2 remains reachable by
284
+ // asking for it explicitly; nothing here infers it.
285
+ if ((options.tokenVersion ?? 3) === 3) {
280
286
  return signAccessToken(options, NEVERMINED_EIP712_DOMAIN_NAME, NeverminedTypedDataTypesV3, {
281
287
  ...message,
282
288
  agentId: options.agentId ?? '',
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/models/AgentX402AccessToken.ts"],"sourcesContent":["import { keccak256, PublicClient, toBytes, TypedDataDefinition } from 'viem'\nimport { SmartAccount } from 'viem/account-abstraction'\n\n/**\n * x402 Resource information\n */\nexport type X402Resource = {\n url: string\n description?: string\n mimeType?: string\n}\n\n/**\n * Supported x402 payment schemes\n */\nexport type X402Scheme = 'nvm:erc4337' | 'nvm:card-delegation'\n\n/**\n * x402 Accepted scheme fields (common to all schemes)\n */\nexport type X402Accepted = {\n scheme: X402Scheme\n network: string\n planId?: string\n extra: {\n version: string\n agentId?: string\n httpVerb?: string\n }\n}\n\n/**\n * Payload specific to the nvm:erc4337 scheme\n */\nexport type X402Erc4337Payload = {\n signature: `0x${string}`\n authorization: {\n from: `0x${string}`\n sessionKeysProvider: string\n sessionKeys: { id: string; data: string }[]\n /**\n * Signed planId (#1678). Present on v2 tokens (minted after #1678) and\n * covered by the EIP-712 signature, so it is tamper-evident on its own.\n * OPTIONAL on the wire type only for backwards-compat: genuinely-old v1\n * tokens carry no `planId` here and verify against the legacy type list.\n */\n planId?: string\n /**\n * Signed seller/resource binding + one-time nonce (#2646). Present on v3\n * tokens and covered by the EIP-712 signature.\n *\n * `agentId` / `resourceUrl` / `httpVerb` are signed as the EMPTY STRING when\n * the mint had no value for them — EIP-712 has no optional members, so\n * \"absent\" has to be a signed value rather than a missing field. The guard\n * (`isSignedBindingConsistent`) then requires the unsigned envelope copy to\n * be absent too, which is what stops anyone ADDING a binding to a token that\n * was signed without one.\n *\n * `nonce` is always a non-empty random value on a v3 token, and is the\n * single v2/v3 discriminator (see `hasSignedNonce`).\n *\n * All four are OPTIONAL on the wire type only for backwards-compat: v1/v2\n * tokens carry none of them and verify against their own type lists.\n */\n agentId?: string\n resourceUrl?: string\n httpVerb?: string\n nonce?: string\n }\n}\n\n/**\n * Payload specific to the nvm:card-delegation scheme\n */\nexport type X402CardDelegationPayload = {\n token: string\n}\n\n/**\n * x402 Access Token aligned with x402 v2 spec\n *\n * Key changes from previous version:\n * - `subscriberAddress` moved to `payload.authorization.from`\n * - `planId` is now in `accepted` (optional — required for erc4337, optional for card-delegation)\n * - `agentId` moved to `accepted.extra.agentId` (optional)\n * - `scheme` and `network` moved to `accepted`\n * - Added `resource` and `extensions` for x402 v2 alignment\n */\nexport type AgentX402AccessToken = {\n x402Version: 2\n resource?: X402Resource\n accepted: X402Accepted\n payload: X402Erc4337Payload | X402CardDelegationPayload\n validUntil?: number\n extensions: Record<string, unknown>\n}\n\n/**\n * EIP-712 domain name for the x402 protocol — the original, unchanged value.\n */\nexport const NEVERMINED_EIP712_DOMAIN_NAME = 'Nevermined' as const\n\n/**\n * EIP-712 domain name for the MPP protocol (#2640).\n *\n * This constant IS the isolation between the two protocols. EIP-712 hashes the domain separator\n * into the signed digest, so a token minted under `Nevermined-MPP` cannot verify against the x402\n * verifier and vice versa — cross-protocol replay and downgrade are closed by construction.\n *\n * A plaintext `scheme`/`protocol` field would NOT do this for the SECURITY boundary:\n * `accepted.scheme` and `accepted.network` sit OUTSIDE the signature (see {@link X402Accepted}), so\n * they are forgeable. Only the domain is covered by the signature without touching the signed\n * struct.\n *\n * That objection does NOT extend to protocol ROUTING. The two envelopes are byte-identical apart\n * from the signature — `accepted.scheme` is `nvm:erc4337` for both — so a dispatcher holding a\n * decoded token has no signal for which verifier to call. If #2641 needs one, add an UNSIGNED hint\n * (`accepted.extra.protocol`) and document it as **routing only — NEVER the security boundary**:\n * forging it can only select the wrong verifier, and the wrong verifier returns `false`.\n * What is forbidden is trying both verifiers in turn — that collapses this isolation to zero.\n *\n * The signed `Authorization` struct is deliberately IDENTICAL for both protocols — do not add a\n * protocol field to it. Changing the struct would fork the type list and break the v1/v2\n * back-compat that `verifyAgentX402AccessToken` depends on, for no security gain.\n */\nexport const NEVERMINED_MPP_EIP712_DOMAIN_NAME = 'Nevermined-MPP' as const\n\n/** The EIP-712 domain name of a Nevermined access token — one per protocol. */\nexport type NeverminedEip712DomainName =\n | typeof NEVERMINED_EIP712_DOMAIN_NAME\n | typeof NEVERMINED_MPP_EIP712_DOMAIN_NAME\n\n/**\n * Defaults to the x402 domain name so the bare `NeverminedTypedDataDomain` keeps resolving to\n * `name: 'Nevermined'` for existing SDK consumers — widening it to the union would be a\n * source-breaking change to a published package (a `const n: 'Nevermined' = domain.name` stops\n * compiling), and `projectsRelationship: \"fixed\"` makes a core-kit major a workspace-wide major.\n */\nexport type NeverminedTypedDataDomain<\n TName extends NeverminedEip712DomainName = typeof NEVERMINED_EIP712_DOMAIN_NAME,\n> = {\n name: TName\n version: '1'\n chainId: number\n verifyingContract: `0x${string}`\n}\n\n/**\n * EIP-712 `Authorization` struct WITH a signed `planId` (#1678).\n *\n * `planId` is appended LAST so the change is purely additive to the EIP-712\n * encoding of the legacy (v1) struct. Signing the planId makes the token's plan\n * tamper-evident on its own — defense-in-depth atop the resource server's\n * `validateAcceptedMatchesRequirements` demand-match, which remains the primary\n * gate. See `NeverminedTypedDataTypesV1` for the legacy struct that pre-#1678\n * tokens were signed over; both shapes verify against the same signer.\n */\nexport type NeverminedTypedData = {\n SessionKey: [{ name: 'id'; type: 'string' }, { name: 'data'; type: 'string' }]\n SessionKeys: [{ name: 'sessionKeys'; type: 'SessionKey[]' }]\n Authorization: [\n { name: 'from'; type: 'address' },\n { name: 'sessionKeysProvider'; type: 'string' },\n { name: 'sessionKeys'; type: 'SessionKey[]' },\n { name: 'planId'; type: 'string' },\n ]\n}\n\nexport const NeverminedTypedDataTypes: NeverminedTypedData = {\n SessionKey: [\n { name: 'id', type: 'string' },\n { name: 'data', type: 'string' },\n ],\n SessionKeys: [{ name: 'sessionKeys', type: 'SessionKey[]' }],\n Authorization: [\n { name: 'from', type: 'address' },\n { name: 'sessionKeysProvider', type: 'string' },\n { name: 'sessionKeys', type: 'SessionKey[]' },\n { name: 'planId', type: 'string' },\n ],\n}\n\n/**\n * Legacy (v1) EIP-712 `Authorization` struct — WITHOUT a signed `planId`.\n *\n * Retained so `verifyAgentX402AccessToken` can still validate genuinely-old\n * tokens minted before #1678 (their `authorization` carries no `planId`, and\n * EIP-712 hashes the type set, so they only verify against THIS type list).\n * Mint always produces the v2 (with-planId) shape going forward.\n */\nexport type NeverminedTypedDataV1 = {\n SessionKey: [{ name: 'id'; type: 'string' }, { name: 'data'; type: 'string' }]\n SessionKeys: [{ name: 'sessionKeys'; type: 'SessionKey[]' }]\n Authorization: [\n { name: 'from'; type: 'address' },\n { name: 'sessionKeysProvider'; type: 'string' },\n { name: 'sessionKeys'; type: 'SessionKey[]' },\n ]\n}\n\nexport const NeverminedTypedDataTypesV1: NeverminedTypedDataV1 = {\n SessionKey: [\n { name: 'id', type: 'string' },\n { name: 'data', type: 'string' },\n ],\n SessionKeys: [{ name: 'sessionKeys', type: 'SessionKey[]' }],\n Authorization: [\n { name: 'from', type: 'address' },\n { name: 'sessionKeysProvider', type: 'string' },\n { name: 'sessionKeys', type: 'SessionKey[]' },\n ],\n}\n\n/**\n * EIP-712 `Authorization` struct v3 (#2646) — WITH the seller/resource binding and\n * a one-time `nonce`, appended after `planId`.\n *\n * Append-only, exactly as #1678 appended `planId` to the v1 struct: the four new\n * members come LAST, so the change is purely additive to the v2 encoding and the\n * older type lists keep verifying the tokens that were signed over them.\n *\n * What each member buys:\n * - `agentId` + `resourceUrl` + `httpVerb` remove the token's CROSS-SELLER\n * property. Before v3 these lived only in `accepted.extra` / `resource`, which\n * sit outside the signature and are demand-matched against a `paymentRequired`\n * the SELLER supplies — so seller A could present a token minted for seller B\n * on the same plan and nothing in the signature contradicted it.\n * - `nonce` removes the BEARER property: a v3 token is single-use at the\n * signature layer, enforced by the replay store in `apps/api` at settle time,\n * independently of any burn-level dedupe.\n *\n * A member the mint had no value for is signed as `''` — EIP-712 has no optional\n * struct members, so absence must itself be a signed value. `isSignedBindingConsistent`\n * pairs that with \"the unsigned copy must be absent too\", which is what prevents\n * ADDING a binding to a token signed without one.\n */\nexport type NeverminedTypedDataV3 = {\n SessionKey: [{ name: 'id'; type: 'string' }, { name: 'data'; type: 'string' }]\n SessionKeys: [{ name: 'sessionKeys'; type: 'SessionKey[]' }]\n Authorization: [\n { name: 'from'; type: 'address' },\n { name: 'sessionKeysProvider'; type: 'string' },\n { name: 'sessionKeys'; type: 'SessionKey[]' },\n { name: 'planId'; type: 'string' },\n { name: 'agentId'; type: 'string' },\n { name: 'resourceUrl'; type: 'string' },\n { name: 'httpVerb'; type: 'string' },\n { name: 'nonce'; type: 'string' },\n ]\n}\n\nexport const NeverminedTypedDataTypesV3: NeverminedTypedDataV3 = {\n SessionKey: [\n { name: 'id', type: 'string' },\n { name: 'data', type: 'string' },\n ],\n SessionKeys: [{ name: 'sessionKeys', type: 'SessionKey[]' }],\n Authorization: [\n { name: 'from', type: 'address' },\n { name: 'sessionKeysProvider', type: 'string' },\n { name: 'sessionKeys', type: 'SessionKey[]' },\n { name: 'planId', type: 'string' },\n { name: 'agentId', type: 'string' },\n { name: 'resourceUrl', type: 'string' },\n { name: 'httpVerb', type: 'string' },\n { name: 'nonce', type: 'string' },\n ],\n}\n\n/**\n * Legacy (v1) signed message shape — no `planId`. Mirrors `NeverminedTypedDataTypesV1`.\n * Only genuinely-old tokens carry this shape; mint never produces it.\n */\nexport type NeverminedTypedDataMessageV1 = {\n from: `0x${string}`\n sessionKeysProvider: string\n sessionKeys: { id: string; data: string }[]\n}\n\n/**\n * The v2 signed message shape — `planId` is REQUIRED. Mint always produces this\n * shape (#1678), so `planId` is non-optional here; the v1 variant above models\n * the legacy no-planId message. Mirrors `NeverminedTypedDataTypes`.\n */\nexport type NeverminedTypedDataMessage = NeverminedTypedDataMessageV1 & {\n /** Signed planId (#1678) — always present on v2 (minted) tokens. */\n planId: string\n}\n\n/**\n * The v3 signed message shape (#2646) — every binding member is REQUIRED, with\n * `''` standing for \"the mint had no value for this\". Mirrors\n * {@link NeverminedTypedDataTypesV3}.\n */\nexport type NeverminedTypedDataMessageV3 = NeverminedTypedDataMessage & {\n /** Signed agentId, or `''` when the token is not bound to an agent. */\n agentId: string\n /** Signed `resource.url`, or `''` when the token is not bound to a resource. */\n resourceUrl: string\n /** Signed HTTP verb, or `''` when the token is not bound to a verb. */\n httpVerb: string\n /** One-time nonce — always a non-empty random value on a v3 token. */\n nonce: string\n}\n\n/**\n * The EIP-712 struct version an **x402** token is signed over — x402's ladder, and only\n * x402's (#3266).\n *\n * `1` is not mintable — it only exists as a verification branch for tokens minted\n * before #1678. New tokens are v2 (the default, reusable, pre-#2646 semantics) or\n * v3 (seller/resource-bound and single-use).\n *\n * MPP has NO version ladder and no ordinal of its own: it signs ONE struct —\n * {@link NeverminedTypedDataTypes}, reused rather than copied — and names no version for it.\n * That is not a temporary state. MPP's own draft (`draft-ryan-httpauth-payment`, §9.2) carries\n * no version on the wire either: the scheme name is the stable identifier, evolution is\n * additive, and what versioning the protocol needs lives on the payment METHOD\n * (`methodDetails.version`). So do not add an MPP rung here, and do not let an x402 rung reach\n * the MPP minter — the two ladders were shared once, and #3258 is what that cost.\n *\n * ⚠️ That draft's \"ignore what you don't recognise\" rule belongs to the HTTP envelope and MUST\n * NOT be carried into this struct: EIP-712 hashes the type set, so an unrecognised signed member\n * is not ignorable — it changes the digest.\n */\nexport type NeverminedTokenVersion = 2 | 3\n\n/**\n * Options for generating an x402 access token\n */\nexport type GenerateX402TokenOptions = {\n subscriber: SmartAccount\n orderSessionKey: string\n redeemSessionKey: string\n publicClient: PublicClient\n planId: string\n /** Scheme version (e.g., '1') - stored in accepted.extra.version */\n schemeVersion?: string\n agentId?: string\n resource?: X402Resource\n httpVerb?: string\n /** Token expiration timestamp in seconds (Unix epoch) */\n validUntil?: number\n /**\n * EIP-712 struct version to sign (#2646). Defaults to `2` — the reusable,\n * pre-#2646 shape — so existing callers are untouched and there is no flag day.\n *\n * `3` binds the token to `agentId` / `resource.url` / `httpVerb` and adds a\n * one-time nonce, which the resource server consumes at settle. A v3 token is\n * therefore SINGLE-USE: a caller that opts in must mint one per paid request.\n *\n * x402 ONLY (#3266). It used to apply to both protocols, which is exactly how the x402 nonce\n * reached MPP — where the access token is the buyer's REUSABLE credential and the single-use\n * unit is the CHALLENGE, so a per-token nonce kills every MPP buyer's second challenge\n * (#3258). {@link GenerateMppTokenOptions} omits this field, and the MPP minter has no\n * parameter that could carry it.\n */\n tokenVersion?: NeverminedTokenVersion\n}\n\n/**\n * Options for minting an MPP access token — {@link GenerateX402TokenOptions} minus the x402\n * version knob (#3266).\n *\n * The omission IS the divergence: MPP signs one struct and the server chooses it, so there is\n * nothing here for a caller to name. Passing `tokenVersion` to\n * {@link generateAgentMppAccessToken} is a compile error rather than a silently honoured\n * request — which also means the guard is invisible to jest, since the suites run through SWC\n * and it strips types without checking them. `nx typecheck` is what enforces it.\n */\nexport type GenerateMppTokenOptions = Omit<GenerateX402TokenOptions, 'tokenVersion'>\n\n/**\n * The domain's `chainId` is a load-bearing part of the separator, and viem drops an `undefined`\n * one from the `EIP712Domain` type list — hashing IDENTICALLY to omitting the field, with no error.\n * A chainless `publicClient` (`createPublicClient({ transport })` with no `chain`, a shape that\n * already exists in this repo) would therefore mint a digest valid on every chain at once. Fail\n * loudly instead: this is a client misconfiguration, never a token defect.\n */\nconst requireChainId = (publicClient: PublicClient, caller: string): number => {\n const chainId = publicClient.chain?.id\n if (typeof chainId !== 'number') {\n throw new Error(`${caller}: publicClient has no chain — the EIP-712 domain needs a chainId`)\n }\n return chainId\n}\n\n/**\n * 32 bytes of CSPRNG output, hex-encoded — the one-time nonce of a v3 token (#2646).\n *\n * `globalThis.crypto` (WebCrypto) rather than node's `crypto` module so core-kit keeps\n * working in the browser, where this package is also consumed. 256 bits makes a\n * collision in the resource server's replay store (a UNIQUE column) unreachable, so a\n * legitimate mint can never be refused as someone else's replay.\n */\nconst generateTokenNonce = (): string => {\n const bytes = new Uint8Array(32)\n globalThis.crypto.getRandomValues(bytes)\n return `0x${Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('')}`\n}\n\n/**\n * Builds the Authorization message BOTH protocols sign.\n *\n * This is the part that deliberately does NOT diverge (#3266): `from`, `sessionKeysProvider`,\n * `sessionKeys` and `planId` mean the same thing on x402 and MPP, so a defect here would be\n * universal — with two copies it would have to be found and fixed twice. Keeping it\n * single-sourced is what bounds the cost of the divergence above it.\n */\nconst buildAuthorizationMessage = (\n options: GenerateMppTokenOptions,\n): NeverminedTypedDataMessage => {\n const { subscriber, orderSessionKey, redeemSessionKey, planId } = options\n\n // A v2 token MUST carry a non-empty signed planId (#1678) — an empty/blank\n // planId would otherwise be signed into `authorization.planId` and could be\n // misread as a \"present but empty\" signed claim, blurring the v1/v2 boundary\n // that verification keys off genuine presence. erc4337 already requires a\n // planId upstream (`validateX402TokenStructure`), so this is a hard invariant.\n if (typeof planId !== 'string' || planId.trim() === '') {\n throw new Error('Nevermined access token: planId is required and must be a non-empty string')\n }\n\n // Including `planId` here puts it inside the EIP-712 digest, so it cannot be\n // altered without invalidating the signature.\n return {\n from: subscriber.address,\n sessionKeysProvider: 'zerodev',\n sessionKeys: [\n { id: 'order', data: keccak256(toBytes(orderSessionKey)) },\n { id: 'redeem', data: keccak256(toBytes(redeemSessionKey)) },\n ],\n planId,\n }\n}\n\n/**\n * Signs an already-chosen struct under an already-chosen domain and wraps it in the envelope.\n *\n * `types` and `message` arrive TOGETHER and already agreed, because EIP-712 hashes the type set\n * — a v3 message signed over the v2 list produces a digest no verifier reproduces. Choosing the\n * pair is each protocol's job; this function never infers one from the other, and has no notion\n * of a version to infer it from.\n *\n * Not exported — callers go through {@link generateAgentX402AccessToken} or\n * {@link generateAgentMppAccessToken}, each with its domain pinned, so a protocol can never be\n * selected by a caller-supplied value.\n */\nconst signAccessToken = async (\n options: GenerateMppTokenOptions,\n domainName: NeverminedEip712DomainName,\n types: NeverminedTypedData | NeverminedTypedDataV3,\n message: NeverminedTypedDataMessage | NeverminedTypedDataMessageV3,\n): Promise<AgentX402AccessToken> => {\n const {\n subscriber,\n publicClient,\n planId,\n schemeVersion = '1',\n agentId,\n resource,\n httpVerb,\n validUntil,\n } = options\n\n const chainId = requireChainId(publicClient, 'Nevermined access token mint')\n\n const domain: NeverminedTypedDataDomain<NeverminedEip712DomainName> = {\n name: domainName,\n version: '1',\n chainId,\n verifyingContract: subscriber.address,\n }\n\n const signature = await subscriber.signTypedData({\n domain,\n types,\n primaryType: 'Authorization',\n message,\n } as TypedDataDefinition<NeverminedTypedData | NeverminedTypedDataV3, 'Authorization'>)\n\n // Network in CAIP-2 format (eip155:chainId) — always resolvable, `requireChainId` already ran.\n const network = `eip155:${chainId}`\n\n return {\n x402Version: 2,\n ...(resource && { resource }),\n accepted: {\n scheme: 'nvm:erc4337',\n network,\n planId,\n extra: {\n version: schemeVersion,\n ...(agentId && { agentId }),\n ...(httpVerb && { httpVerb }),\n },\n },\n payload: {\n signature,\n authorization: message,\n },\n ...(validUntil !== undefined && { validUntil }),\n extensions: {},\n }\n}\n\n/**\n * Generate an x402 access token aligned with x402 v2 spec.\n *\n * Walks x402's OWN version ladder (#3266): v3 when the caller asks for the #2646 binding and\n * one-time nonce, the base struct otherwise. Nothing chosen here can reach the MPP minter.\n *\n * @param options - Token generation options\n * @returns x402 access token with EIP-712 signature\n */\nexport const generateAgentX402AccessToken = async (\n options: GenerateX402TokenOptions,\n): Promise<AgentX402AccessToken> => {\n const message = buildAuthorizationMessage(options)\n\n // v3 (#2646) appends the seller/resource binding and the one-time nonce. A member the caller\n // left undefined is signed as '' — EIP-712 has no optional members, so \"not bound\" must itself\n // be a signed value; `isSignedBindingConsistent` then holds the unsigned envelope copy to the\n // same absence.\n if ((options.tokenVersion ?? 2) === 3) {\n return signAccessToken(options, NEVERMINED_EIP712_DOMAIN_NAME, NeverminedTypedDataTypesV3, {\n ...message,\n agentId: options.agentId ?? '',\n resourceUrl: options.resource?.url ?? '',\n httpVerb: options.httpVerb ?? '',\n nonce: generateTokenNonce(),\n })\n }\n\n return signAccessToken(options, NEVERMINED_EIP712_DOMAIN_NAME, NeverminedTypedDataTypes, message)\n}\n\n/**\n * Generate a NATIVE MPP access token (#2640) — the same struct signed under the\n * `Nevermined-MPP` EIP-712 domain.\n *\n * Native, not a wrapper: the revised Tier A design (#2024) deliberately does NOT embed an x402\n * token inside an MPP credential, because unwrapping it would hand the holder a token that still\n * settles on the public x402 path.\n *\n * ONE struct, NO version (#3266). {@link NeverminedTypedDataTypes} is REUSED rather than copied\n * under an MPP name — the members are identical, and a second table would only drift. What\n * diverges is the CHOICE: this minter has no ladder to walk and no parameter that could make it\n * walk one, so a future x402 struct change cannot reach MPP by default the way #2646's nonce did.\n *\n * @param options - Token generation options, minus x402's `tokenVersion`\n * @returns MPP access token with EIP-712 signature over the MPP domain. The envelope is IDENTICAL\n * to an x402 token's, `accepted.scheme: 'nvm:erc4337'` included — only the signature differs, so\n * the protocol is fixed by the endpoint, not readable off the wire. See\n * {@link NEVERMINED_MPP_EIP712_DOMAIN_NAME} on routing vs. the security boundary.\n */\nexport const generateAgentMppAccessToken = async (\n options: GenerateMppTokenOptions,\n): Promise<AgentX402AccessToken> =>\n signAccessToken(\n options,\n NEVERMINED_MPP_EIP712_DOMAIN_NAME,\n NeverminedTypedDataTypes,\n buildAuthorizationMessage(options),\n )\n\n/**\n * True when `authorization` carries a GENUINE signed planId (#1678) — a present,\n * non-empty string. This is the single v1/v2 discriminator: verification keys off\n * it to choose the matching EIP-712 type list, the handler keys off it to decide\n * whether the signed-vs-unsigned consistency guard fires. Keying off genuine\n * presence (not just `'planId' in authorization`) ensures a `planId: ''` / nullish\n * value can never be mistaken for a real signed claim.\n */\nexport const hasSignedPlanId = (\n authorization: X402Erc4337Payload['authorization'],\n): authorization is X402Erc4337Payload['authorization'] & { planId: string } => {\n return typeof authorization?.planId === 'string' && authorization.planId.trim() !== ''\n}\n\n/**\n * The signed-vs-unsigned planId consistency invariant (#1678), co-located with\n * `hasSignedPlanId` so signer, verifier, and the API handler share ONE\n * definition (no drift between where the planId is signed and where the guard\n * enforces it).\n *\n * For a v2 token (signed planId present) the tamperable unsigned `accepted.planId`\n * MUST exactly equal the signed `authorization.planId` — anything else is a\n * post-signing edit of the outer JSON. Returns `true` for v1 tokens (no signed\n * planId): there is no signed value to be consistent with, so the guard does not\n * apply (the caller handles the legacy fallback separately). The API handler maps\n * a `false` result to its forgery-gated rejection.\n */\nexport const isSignedPlanIdConsistent = (\n authorization: X402Erc4337Payload['authorization'],\n acceptedPlanId: string | null | undefined,\n): boolean => {\n if (!hasSignedPlanId(authorization)) return true\n return acceptedPlanId === authorization.planId\n}\n\n/**\n * True when `authorization` carries a GENUINE one-time nonce (#2646) — a present,\n * non-empty string. This is the single v2/v3 discriminator, the exact counterpart of\n * {@link hasSignedPlanId} for the v1/v2 boundary: verification keys off it to choose\n * the matching EIP-712 type list, and the resource server keys off it to decide\n * whether the binding guard and the single-use replay store apply.\n *\n * `nonce` is the discriminator rather than one of the binding members because it is\n * the only v3 member that is always non-empty — `agentId` / `resourceUrl` / `httpVerb`\n * are legitimately signed as `''` when the mint had no value for them.\n */\nexport const hasSignedNonce = (\n authorization: X402Erc4337Payload['authorization'],\n): authorization is X402Erc4337Payload['authorization'] & { nonce: string } => {\n return typeof authorization?.nonce === 'string' && authorization.nonce.trim() !== ''\n}\n\n/** The unsigned envelope values a v3 binding is checked against. */\nexport type SignedBindingEnvelope = {\n /** `accepted.extra.agentId` */\n agentId: string | null | undefined\n /** `resource.url` */\n resourceUrl: string | null | undefined\n /** `accepted.extra.httpVerb` */\n httpVerb: string | null | undefined\n}\n\n/**\n * The signed-vs-unsigned BINDING invariant (#2646), co-located with\n * {@link hasSignedNonce} so signer, verifier and the API handler share ONE definition —\n * the same reason {@link isSignedPlanIdConsistent} lives here.\n *\n * For a v3 token every binding member must agree with its unsigned envelope copy:\n * - a signed non-empty value must equal the envelope value EXACTLY. Both are our own\n * mint's output, so exact equality is right; the fuzzier, query-insensitive URL\n * comparison belongs to the demand-match against the SELLER-supplied\n * `paymentRequired`, which is a different question.\n * - a signed `''` means \"not bound\", so the envelope copy must be absent (or empty)\n * too. This is the half that stops someone ADDING an `agentId` to a token that was\n * signed without one — without it, `''` would be a hole rather than a claim.\n *\n * Returns `true` for v1/v2 tokens: there is no signed binding to be consistent with,\n * and the caller handles those on the legacy path. The API handler maps a `false`\n * result to its forgery-gated rejection, exactly as it does for the planId guard.\n */\nexport const isSignedBindingConsistent = (\n authorization: X402Erc4337Payload['authorization'],\n envelope: SignedBindingEnvelope,\n): boolean => {\n if (!hasSignedNonce(authorization)) return true\n\n const matches = (signed: string | undefined, unsigned: string | null | undefined): boolean => {\n const signedValue = signed ?? ''\n // Absence and '' are the same claim on both sides: the mint omits an empty member\n // from the envelope entirely, so an omitted field is what a signed '' looks like.\n if (signedValue === '') return unsigned === undefined || unsigned === null || unsigned === ''\n return unsigned === signedValue\n }\n\n return (\n matches(authorization.agentId, envelope.agentId) &&\n matches(authorization.resourceUrl, envelope.resourceUrl) &&\n matches(authorization.httpVerb, envelope.httpVerb)\n )\n}\n\n/**\n * Picks the EIP-712 type list a protocol verifies an authorization against, or `null` to refuse\n * it outright.\n *\n * One selector per protocol IS the divergence (#3266). This used to be a single, protocol-blind\n * field-presence ladder, which made every x402 struct version automatically a verifiable MPP\n * one. Presence detection also cannot distinguish two protocols that want the same field set\n * with different meaning — the next #3258 waiting to happen.\n */\ntype AuthorizationTypesSelector = (\n authorization: X402Erc4337Payload['authorization'],\n) => NeverminedTypedData | NeverminedTypedDataV1 | NeverminedTypedDataV3 | null\n\n/**\n * x402's ladder: a genuine signed nonce (#2646) → v3, else a genuine signed planId (#1678) → v2,\n * else the original v1 list. Selected by GENUINE presence and never by a caller-supplied hint.\n * The branches are mutually exclusive and none falls back to another — trying a second type list\n * on failure would erase exactly the downgrade protection the versioning provides.\n *\n * A v1 (unsigned-planId) authorization leaves `isSignedPlanIdConsistent` inert, so the tamperable\n * `accepted.planId` becomes authoritative. That is a deliberate #1678 back-compat concession, and\n * it is why this selector admits a shape {@link selectMppAuthorizationTypes} refuses.\n */\nconst selectX402AuthorizationTypes: AuthorizationTypesSelector = (authorization) =>\n hasSignedNonce(authorization)\n ? NeverminedTypedDataTypesV3\n : hasSignedPlanId(authorization)\n ? NeverminedTypedDataTypes\n : NeverminedTypedDataTypesV1\n\n/**\n * MPP's table: one entry, no ladder (#3266) — {@link NeverminedTypedDataTypes} reused, not copied.\n *\n * Two consequences, both of them the point:\n * - an authorization carrying a v3 nonce has nowhere to climb to. It is checked against the base\n * list, the digest does not match, and it fails. An x402 struct version is not automatically\n * an MPP one, which is the coupling #3258 came from.\n *\n * ⚠️ This is the one RUNTIME verdict this change flips, and it is retroactive: before #3266 the\n * protocol-blind ladder read a v3 MPP authorization's `planId`, selected the v3 list, and the\n * token VERIFIED. An MPP token already minted at `tokenVersion: 3` therefore stops verifying —\n * it is not merely unmintable from here on. `validUntil` is written at mint but never compared\n * against `now` on this path, so nothing expires such a token out of existence; the holder has\n * to re-mint. No supported client can hold one (`@nevermined-io/payments` has never exposed\n * `tokenVersion`, per #3257) and it was already single-settle in practice, since\n * `consumeTokenNonce` is not MPP-aware and spends the nonce on an MPP settle too.\n * - a legacy (unsigned-planId) authorization is REFUSED rather than checked against the v1 list.\n * MPP is born after #1678 and has no pre-planId tokens to stay compatible with; accepting one\n * would hand authority to the tamperable `accepted.planId`.\n */\nconst selectMppAuthorizationTypes: AuthorizationTypesSelector = (authorization) =>\n hasSignedPlanId(authorization) ? NeverminedTypedDataTypes : null\n\n/**\n * Shared verifier for both protocols, differing only in the EIP-712 domain name and the type\n * list its protocol accepts.\n *\n * EIP-712 hashes the type set, so a token signed over one struct cannot verify against another's\n * type list. `selectTypes` is therefore the protocol's whole verification policy: which shapes it\n * recognises, and which it refuses without asking the chain.\n *\n * Downgrade-safe on every ladder: a v2 token was signed over the with-planId digest, so stripping\n * `authorization.planId` to force the v1 branch changes the digest and the signature fails; a v3\n * token was signed over the with-nonce digest, so stripping the nonce to escape single-use, or\n * stripping `agentId` / `resourceUrl` to escape the seller binding, fails the same way. An\n * attacker cannot demote a signed token to shed a claim.\n *\n * EIP-712 hashes the DOMAIN separator too, which is what makes `domainName` the protocol boundary\n * (#2640) rather than a label. Not exported: callers go through\n * {@link verifyAgentX402AccessToken} or {@link verifyAgentMppAccessToken}, each with its domain\n * and its selector pinned, so no caller-supplied value can pick which protocol a token is checked\n * against.\n */\nconst verifyAgentAccessToken = async (\n accessToken: AgentX402AccessToken,\n publicClient: PublicClient,\n domainName: NeverminedEip712DomainName,\n selectTypes: AuthorizationTypesSelector,\n): Promise<boolean> => {\n // `payload` is a union (erc4337 | card-delegation) and this is a public entry point with no\n // guaranteed pre-validation — `validateX402TokenStructure` runs in `apps/api`, not here. A\n // structural precondition, evaluated BEFORE the await: deliberately NOT a try/catch around the\n // verification itself, which must keep letting an RPC fault propagate rather than laundering it\n // into a `false` the caller reads as a forgery.\n const erc4337Payload = accessToken?.payload as X402Erc4337Payload | undefined\n if (!erc4337Payload?.authorization?.from || !erc4337Payload.signature) return false\n\n const { signature, authorization } = erc4337Payload\n const subscriberAddress = authorization.from\n\n // A shape this protocol does not recognise is refused here, before any chain call.\n const types = selectTypes(authorization)\n if (!types) return false\n\n const domain: NeverminedTypedDataDomain<NeverminedEip712DomainName> = {\n name: domainName,\n version: '1',\n chainId: requireChainId(publicClient, 'Nevermined access token verify'),\n verifyingContract: subscriberAddress,\n }\n const isValid = await publicClient.verifyTypedData({\n address: subscriberAddress,\n signature,\n types,\n domain,\n message: authorization,\n primaryType: 'Authorization',\n })\n return isValid\n}\n\n/**\n * Verify an x402 access token signature (see {@link selectX402AuthorizationTypes} for the\n * v1/v2/v3 type-list detection and its downgrade-safety).\n *\n * Rejects an MPP token: it was signed under a different domain separator, so the digest differs.\n *\n * @param accessToken - The x402 access token to verify\n * @param publicClient - Viem public client\n * @returns true if signature is valid\n */\nexport const verifyAgentX402AccessToken = (\n accessToken: AgentX402AccessToken,\n publicClient: PublicClient,\n): Promise<boolean> =>\n verifyAgentAccessToken(\n accessToken,\n publicClient,\n NEVERMINED_EIP712_DOMAIN_NAME,\n selectX402AuthorizationTypes,\n )\n\n/**\n * Verify an MPP access token signature (#2640).\n *\n * Rejects an x402 token for the same reason the x402 verifier rejects an MPP one — the domain\n * separator is part of the signed digest. This is the property the whole Tier A isolation rests on:\n * a credential harvested from one protocol is inert on the other, closing cross-protocol replay\n * AND downgrade — WHILE the signing key stays server-side. A subscriber holding it can mint under\n * whichever domain they like, so the split constrains the transport, not that holder.\n *\n * One struct, no ladder: {@link selectMppAuthorizationTypes} accepts the base struct and nothing\n * else, so a legacy (unsigned-planId) authorization is refused outright and an x402 struct version\n * is not verifiable here just because x402 added it (#3266).\n *\n * @param accessToken - The MPP access token to verify\n * @param publicClient - Viem public client\n * @returns true if signature is valid\n */\nexport const verifyAgentMppAccessToken = (\n accessToken: AgentX402AccessToken,\n publicClient: PublicClient,\n): Promise<boolean> =>\n verifyAgentAccessToken(\n accessToken,\n publicClient,\n NEVERMINED_MPP_EIP712_DOMAIN_NAME,\n selectMppAuthorizationTypes,\n )\n\n/**\n * Validation result for x402 token structure\n */\nexport type X402TokenValidationResult = {\n valid: boolean\n errors: string[]\n}\n\n/**\n * Validate the structure of an x402 access token\n *\n * @param token - The token to validate (unknown type for safety)\n * @returns Validation result with errors if any\n */\nconst SUPPORTED_SCHEMES: X402Scheme[] = ['nvm:erc4337', 'nvm:card-delegation']\n\nexport const validateX402TokenStructure = (token: unknown): X402TokenValidationResult => {\n const errors: string[] = []\n\n if (!token || typeof token !== 'object') {\n return { valid: false, errors: ['Token must be an object'] }\n }\n\n const t = token as Record<string, unknown>\n\n // Validate x402Version\n if (t.x402Version !== 2) {\n errors.push('x402Version must be 2')\n }\n\n // Validate accepted object\n if (!t.accepted || typeof t.accepted !== 'object') {\n errors.push('accepted is required')\n } else {\n const accepted = t.accepted as Record<string, unknown>\n const scheme = accepted.scheme as string\n\n if (!SUPPORTED_SCHEMES.includes(scheme as X402Scheme)) {\n errors.push(`scheme must be one of: ${SUPPORTED_SCHEMES.join(', ')}`)\n }\n\n if (!accepted.network || typeof accepted.network !== 'string') {\n errors.push('network is required in accepted')\n }\n\n // Validate extra\n if (!accepted.extra || typeof accepted.extra !== 'object') {\n errors.push('extra is required in accepted')\n } else {\n const extra = accepted.extra as Record<string, unknown>\n if (!extra.version || typeof extra.version !== 'string') {\n errors.push('version is required in accepted.extra')\n }\n }\n\n // Scheme-specific accepted validation\n if (scheme === 'nvm:erc4337') {\n if (!accepted.planId || typeof accepted.planId !== 'string') {\n errors.push('planId is required in accepted for nvm:erc4337')\n }\n }\n }\n\n // Validate payload\n if (!t.payload || typeof t.payload !== 'object') {\n errors.push('payload is required')\n } else {\n const accepted = t.accepted as Record<string, unknown> | undefined\n const scheme = accepted?.scheme as string | undefined\n const payload = t.payload as Record<string, unknown>\n\n if (scheme === 'nvm:erc4337') {\n if (!payload.signature || typeof payload.signature !== 'string') {\n errors.push('signature is required in payload')\n }\n\n if (!payload.authorization || typeof payload.authorization !== 'object') {\n errors.push('authorization is required in payload')\n } else {\n const auth = payload.authorization as Record<string, unknown>\n\n if (!auth.from || typeof auth.from !== 'string') {\n errors.push('from address is required in payload.authorization')\n } else if (!auth.from.startsWith('0x')) {\n errors.push('from must be a valid hex address')\n }\n\n if (!auth.sessionKeysProvider || typeof auth.sessionKeysProvider !== 'string') {\n errors.push('sessionKeysProvider is required in payload.authorization')\n }\n\n if (!Array.isArray(auth.sessionKeys)) {\n errors.push('sessionKeys array is required in payload.authorization')\n }\n }\n } else if (scheme === 'nvm:card-delegation') {\n if (!payload.token || typeof payload.token !== 'string') {\n errors.push('token is required in payload for nvm:card-delegation')\n }\n }\n }\n\n // Validate extensions (must be present, even if empty)\n if (t.extensions === undefined) {\n errors.push('extensions is required (can be empty object)')\n }\n\n return { valid: errors.length === 0, errors }\n}\n\nexport const b64EncodeX402AccessToken = (accessToken: AgentX402AccessToken): string => {\n return Buffer.from(JSON.stringify(accessToken)).toString('base64')\n}\n\nexport const b64DecodeX402AccessToken = (encoded: string): AgentX402AccessToken => {\n return JSON.parse(Buffer.from(encoded, 'base64').toString('utf-8'))\n}\n"],"names":["keccak256","toBytes","NEVERMINED_EIP712_DOMAIN_NAME","NEVERMINED_MPP_EIP712_DOMAIN_NAME","NeverminedTypedDataTypes","SessionKey","name","type","SessionKeys","Authorization","NeverminedTypedDataTypesV1","NeverminedTypedDataTypesV3","requireChainId","publicClient","caller","chainId","chain","id","Error","generateTokenNonce","bytes","Uint8Array","globalThis","crypto","getRandomValues","Array","from","b","toString","padStart","join","buildAuthorizationMessage","options","subscriber","orderSessionKey","redeemSessionKey","planId","trim","address","sessionKeysProvider","sessionKeys","data","signAccessToken","domainName","types","message","schemeVersion","agentId","resource","httpVerb","validUntil","domain","version","verifyingContract","signature","signTypedData","primaryType","network","x402Version","accepted","scheme","extra","payload","authorization","undefined","extensions","generateAgentX402AccessToken","tokenVersion","resourceUrl","url","nonce","generateAgentMppAccessToken","hasSignedPlanId","isSignedPlanIdConsistent","acceptedPlanId","hasSignedNonce","isSignedBindingConsistent","envelope","matches","signed","unsigned","signedValue","selectX402AuthorizationTypes","selectMppAuthorizationTypes","verifyAgentAccessToken","accessToken","selectTypes","erc4337Payload","subscriberAddress","isValid","verifyTypedData","verifyAgentX402AccessToken","verifyAgentMppAccessToken","SUPPORTED_SCHEMES","validateX402TokenStructure","token","errors","valid","t","push","includes","auth","startsWith","isArray","length","b64EncodeX402AccessToken","Buffer","JSON","stringify","b64DecodeX402AccessToken","encoded","parse"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/models/AgentX402AccessToken.ts"],"sourcesContent":["import { keccak256, PublicClient, toBytes, TypedDataDefinition } from 'viem'\nimport { SmartAccount } from 'viem/account-abstraction'\n\n/**\n * x402 Resource information\n */\nexport type X402Resource = {\n url: string\n description?: string\n mimeType?: string\n}\n\n/**\n * Supported x402 payment schemes\n */\nexport type X402Scheme = 'nvm:erc4337' | 'nvm:card-delegation'\n\n/**\n * x402 Accepted scheme fields (common to all schemes)\n */\nexport type X402Accepted = {\n scheme: X402Scheme\n network: string\n planId?: string\n extra: {\n version: string\n agentId?: string\n httpVerb?: string\n }\n}\n\n/**\n * Payload specific to the nvm:erc4337 scheme\n */\nexport type X402Erc4337Payload = {\n signature: `0x${string}`\n authorization: {\n from: `0x${string}`\n sessionKeysProvider: string\n sessionKeys: { id: string; data: string }[]\n /**\n * Signed planId (#1678). Present on v2 tokens (minted after #1678) and\n * covered by the EIP-712 signature, so it is tamper-evident on its own.\n * OPTIONAL on the wire type only for backwards-compat: genuinely-old v1\n * tokens carry no `planId` here and verify against the legacy type list.\n */\n planId?: string\n /**\n * Signed seller/resource binding + one-time nonce (#2646). Present on v3\n * tokens and covered by the EIP-712 signature.\n *\n * `agentId` / `resourceUrl` / `httpVerb` are signed as the EMPTY STRING when\n * the mint had no value for them — EIP-712 has no optional members, so\n * \"absent\" has to be a signed value rather than a missing field. The guard\n * (`isSignedBindingConsistent`) then requires the unsigned envelope copy to\n * be absent too, which is what stops anyone ADDING a binding to a token that\n * was signed without one.\n *\n * `nonce` is always a non-empty random value on a v3 token, and is the\n * single v2/v3 discriminator (see `hasSignedNonce`).\n *\n * All four are OPTIONAL on the wire type only for backwards-compat: v1/v2\n * tokens carry none of them and verify against their own type lists.\n */\n agentId?: string\n resourceUrl?: string\n httpVerb?: string\n nonce?: string\n }\n}\n\n/**\n * Payload specific to the nvm:card-delegation scheme\n */\nexport type X402CardDelegationPayload = {\n token: string\n}\n\n/**\n * x402 Access Token aligned with x402 v2 spec\n *\n * Key changes from previous version:\n * - `subscriberAddress` moved to `payload.authorization.from`\n * - `planId` is now in `accepted` (optional — required for erc4337, optional for card-delegation)\n * - `agentId` moved to `accepted.extra.agentId` (optional)\n * - `scheme` and `network` moved to `accepted`\n * - Added `resource` and `extensions` for x402 v2 alignment\n */\nexport type AgentX402AccessToken = {\n x402Version: 2\n resource?: X402Resource\n accepted: X402Accepted\n payload: X402Erc4337Payload | X402CardDelegationPayload\n validUntil?: number\n extensions: Record<string, unknown>\n}\n\n/**\n * EIP-712 domain name for the x402 protocol — the original, unchanged value.\n */\nexport const NEVERMINED_EIP712_DOMAIN_NAME = 'Nevermined' as const\n\n/**\n * EIP-712 domain name for the MPP protocol (#2640).\n *\n * This constant IS the isolation between the two protocols. EIP-712 hashes the domain separator\n * into the signed digest, so a token minted under `Nevermined-MPP` cannot verify against the x402\n * verifier and vice versa — cross-protocol replay and downgrade are closed by construction.\n *\n * A plaintext `scheme`/`protocol` field would NOT do this for the SECURITY boundary:\n * `accepted.scheme` and `accepted.network` sit OUTSIDE the signature (see {@link X402Accepted}), so\n * they are forgeable. Only the domain is covered by the signature without touching the signed\n * struct.\n *\n * That objection does NOT extend to protocol ROUTING. The two envelopes are byte-identical apart\n * from the signature — `accepted.scheme` is `nvm:erc4337` for both — so a dispatcher holding a\n * decoded token has no signal for which verifier to call. If #2641 needs one, add an UNSIGNED hint\n * (`accepted.extra.protocol`) and document it as **routing only — NEVER the security boundary**:\n * forging it can only select the wrong verifier, and the wrong verifier returns `false`.\n * What is forbidden is trying both verifiers in turn — that collapses this isolation to zero.\n *\n * The signed `Authorization` struct is deliberately IDENTICAL for both protocols — do not add a\n * protocol field to it. Changing the struct would fork the type list and break the v1/v2\n * back-compat that `verifyAgentX402AccessToken` depends on, for no security gain.\n */\nexport const NEVERMINED_MPP_EIP712_DOMAIN_NAME = 'Nevermined-MPP' as const\n\n/** The EIP-712 domain name of a Nevermined access token — one per protocol. */\nexport type NeverminedEip712DomainName =\n | typeof NEVERMINED_EIP712_DOMAIN_NAME\n | typeof NEVERMINED_MPP_EIP712_DOMAIN_NAME\n\n/**\n * Defaults to the x402 domain name so the bare `NeverminedTypedDataDomain` keeps resolving to\n * `name: 'Nevermined'` for existing SDK consumers — widening it to the union would be a\n * source-breaking change to a published package (a `const n: 'Nevermined' = domain.name` stops\n * compiling), and `projectsRelationship: \"fixed\"` makes a core-kit major a workspace-wide major.\n */\nexport type NeverminedTypedDataDomain<\n TName extends NeverminedEip712DomainName = typeof NEVERMINED_EIP712_DOMAIN_NAME,\n> = {\n name: TName\n version: '1'\n chainId: number\n verifyingContract: `0x${string}`\n}\n\n/**\n * EIP-712 `Authorization` struct WITH a signed `planId` (#1678).\n *\n * `planId` is appended LAST so the change is purely additive to the EIP-712\n * encoding of the legacy (v1) struct. Signing the planId makes the token's plan\n * tamper-evident on its own — defense-in-depth atop the resource server's\n * `validateAcceptedMatchesRequirements` demand-match, which remains the primary\n * gate. See `NeverminedTypedDataTypesV1` for the legacy struct that pre-#1678\n * tokens were signed over; both shapes verify against the same signer.\n */\nexport type NeverminedTypedData = {\n SessionKey: [{ name: 'id'; type: 'string' }, { name: 'data'; type: 'string' }]\n SessionKeys: [{ name: 'sessionKeys'; type: 'SessionKey[]' }]\n Authorization: [\n { name: 'from'; type: 'address' },\n { name: 'sessionKeysProvider'; type: 'string' },\n { name: 'sessionKeys'; type: 'SessionKey[]' },\n { name: 'planId'; type: 'string' },\n ]\n}\n\nexport const NeverminedTypedDataTypes: NeverminedTypedData = {\n SessionKey: [\n { name: 'id', type: 'string' },\n { name: 'data', type: 'string' },\n ],\n SessionKeys: [{ name: 'sessionKeys', type: 'SessionKey[]' }],\n Authorization: [\n { name: 'from', type: 'address' },\n { name: 'sessionKeysProvider', type: 'string' },\n { name: 'sessionKeys', type: 'SessionKey[]' },\n { name: 'planId', type: 'string' },\n ],\n}\n\n/**\n * Legacy (v1) EIP-712 `Authorization` struct — WITHOUT a signed `planId`.\n *\n * Retained so `verifyAgentX402AccessToken` can still validate genuinely-old\n * tokens minted before #1678 (their `authorization` carries no `planId`, and\n * EIP-712 hashes the type set, so they only verify against THIS type list).\n * Mint always produces the v2 (with-planId) shape going forward.\n */\nexport type NeverminedTypedDataV1 = {\n SessionKey: [{ name: 'id'; type: 'string' }, { name: 'data'; type: 'string' }]\n SessionKeys: [{ name: 'sessionKeys'; type: 'SessionKey[]' }]\n Authorization: [\n { name: 'from'; type: 'address' },\n { name: 'sessionKeysProvider'; type: 'string' },\n { name: 'sessionKeys'; type: 'SessionKey[]' },\n ]\n}\n\nexport const NeverminedTypedDataTypesV1: NeverminedTypedDataV1 = {\n SessionKey: [\n { name: 'id', type: 'string' },\n { name: 'data', type: 'string' },\n ],\n SessionKeys: [{ name: 'sessionKeys', type: 'SessionKey[]' }],\n Authorization: [\n { name: 'from', type: 'address' },\n { name: 'sessionKeysProvider', type: 'string' },\n { name: 'sessionKeys', type: 'SessionKey[]' },\n ],\n}\n\n/**\n * EIP-712 `Authorization` struct v3 (#2646) — WITH the seller/resource binding and\n * a one-time `nonce`, appended after `planId`.\n *\n * Append-only, exactly as #1678 appended `planId` to the v1 struct: the four new\n * members come LAST, so the change is purely additive to the v2 encoding and the\n * older type lists keep verifying the tokens that were signed over them.\n *\n * What each member buys:\n * - `agentId` + `resourceUrl` + `httpVerb` remove the token's CROSS-SELLER\n * property. Before v3 these lived only in `accepted.extra` / `resource`, which\n * sit outside the signature and are demand-matched against a `paymentRequired`\n * the SELLER supplies — so seller A could present a token minted for seller B\n * on the same plan and nothing in the signature contradicted it.\n * - `nonce` removes the BEARER property: a v3 token is single-use at the\n * signature layer, enforced by the replay store in `apps/api` at settle time,\n * independently of any burn-level dedupe.\n *\n * A member the mint had no value for is signed as `''` — EIP-712 has no optional\n * struct members, so absence must itself be a signed value. `isSignedBindingConsistent`\n * pairs that with \"the unsigned copy must be absent too\", which is what prevents\n * ADDING a binding to a token signed without one.\n */\nexport type NeverminedTypedDataV3 = {\n SessionKey: [{ name: 'id'; type: 'string' }, { name: 'data'; type: 'string' }]\n SessionKeys: [{ name: 'sessionKeys'; type: 'SessionKey[]' }]\n Authorization: [\n { name: 'from'; type: 'address' },\n { name: 'sessionKeysProvider'; type: 'string' },\n { name: 'sessionKeys'; type: 'SessionKey[]' },\n { name: 'planId'; type: 'string' },\n { name: 'agentId'; type: 'string' },\n { name: 'resourceUrl'; type: 'string' },\n { name: 'httpVerb'; type: 'string' },\n { name: 'nonce'; type: 'string' },\n ]\n}\n\nexport const NeverminedTypedDataTypesV3: NeverminedTypedDataV3 = {\n SessionKey: [\n { name: 'id', type: 'string' },\n { name: 'data', type: 'string' },\n ],\n SessionKeys: [{ name: 'sessionKeys', type: 'SessionKey[]' }],\n Authorization: [\n { name: 'from', type: 'address' },\n { name: 'sessionKeysProvider', type: 'string' },\n { name: 'sessionKeys', type: 'SessionKey[]' },\n { name: 'planId', type: 'string' },\n { name: 'agentId', type: 'string' },\n { name: 'resourceUrl', type: 'string' },\n { name: 'httpVerb', type: 'string' },\n { name: 'nonce', type: 'string' },\n ],\n}\n\n/**\n * Legacy (v1) signed message shape — no `planId`. Mirrors `NeverminedTypedDataTypesV1`.\n * Only genuinely-old tokens carry this shape; mint never produces it.\n */\nexport type NeverminedTypedDataMessageV1 = {\n from: `0x${string}`\n sessionKeysProvider: string\n sessionKeys: { id: string; data: string }[]\n}\n\n/**\n * The v2 signed message shape — `planId` is REQUIRED. Mint always produces this\n * shape (#1678), so `planId` is non-optional here; the v1 variant above models\n * the legacy no-planId message. Mirrors `NeverminedTypedDataTypes`.\n */\nexport type NeverminedTypedDataMessage = NeverminedTypedDataMessageV1 & {\n /** Signed planId (#1678) — always present on v2 (minted) tokens. */\n planId: string\n}\n\n/**\n * The v3 signed message shape (#2646) — every binding member is REQUIRED, with\n * `''` standing for \"the mint had no value for this\". Mirrors\n * {@link NeverminedTypedDataTypesV3}.\n */\nexport type NeverminedTypedDataMessageV3 = NeverminedTypedDataMessage & {\n /** Signed agentId, or `''` when the token is not bound to an agent. */\n agentId: string\n /** Signed `resource.url`, or `''` when the token is not bound to a resource. */\n resourceUrl: string\n /** Signed HTTP verb, or `''` when the token is not bound to a verb. */\n httpVerb: string\n /** One-time nonce — always a non-empty random value on a v3 token. */\n nonce: string\n}\n\n/**\n * The EIP-712 struct version an **x402** token is signed over — x402's ladder, and only\n * x402's (#3266).\n *\n * `1` is not mintable — it only exists as a verification branch for tokens minted\n * before #1678. New tokens are v3 (the default since #3259 — seller/resource-bound\n * and single-use) or v2 (legacy: reusable, unbound, pre-#2646 semantics).\n *\n * MPP has NO version ladder and no ordinal of its own: it signs ONE struct —\n * {@link NeverminedTypedDataTypes}, reused rather than copied — and names no version for it.\n * That is not a temporary state. MPP's own draft (`draft-ryan-httpauth-payment`, §9.2) carries\n * no version on the wire either: the scheme name is the stable identifier, evolution is\n * additive, and what versioning the protocol needs lives on the payment METHOD\n * (`methodDetails.version`). So do not add an MPP rung here, and do not let an x402 rung reach\n * the MPP minter — the two ladders were shared once, and #3258 is what that cost.\n *\n * ⚠️ That draft's \"ignore what you don't recognise\" rule belongs to the HTTP envelope and MUST\n * NOT be carried into this struct: EIP-712 hashes the type set, so an unrecognised signed member\n * is not ignorable — it changes the digest.\n */\nexport type NeverminedTokenVersion = 2 | 3\n\n/**\n * Options for generating an x402 access token\n */\nexport type GenerateX402TokenOptions = {\n subscriber: SmartAccount\n orderSessionKey: string\n redeemSessionKey: string\n publicClient: PublicClient\n planId: string\n /** Scheme version (e.g., '1') - stored in accepted.extra.version */\n schemeVersion?: string\n agentId?: string\n resource?: X402Resource\n httpVerb?: string\n /** Token expiration timestamp in seconds (Unix epoch) */\n validUntil?: number\n /**\n * EIP-712 struct version to sign (#2646). **Defaults to `3` since #3259.**\n *\n * `3` binds the token to `agentId` / `resource.url` / `httpVerb` and adds a\n * one-time nonce, which the resource server consumes at settle. A v3 token is\n * therefore SINGLE-USE: the caller mints one per paid request.\n *\n * `2` is the pre-#2646 shape — reusable and unbound — and stays selectable for callers that\n * cannot mint per request. It is the shape a captured token replays forever, so treat it as\n * legacy: it is a deliberate opt-OUT of the nonce, not a neutral choice.\n *\n * ⚠️ The default is the one thing an API caller does NOT control from here: the API pins `2`\n * for clients whose `Nevermined-Version` resolves below 1.34 (the `1.34-x402-default-token-version`\n * gate), so this default is what a 1.34+ client gets. A direct core-kit consumer has no gate and\n * gets `3` outright.\n *\n * x402 ONLY (#3266). It used to apply to both protocols, which is exactly how the x402 nonce\n * reached MPP — where the access token is the buyer's REUSABLE credential and the single-use\n * unit is the CHALLENGE, so a per-token nonce kills every MPP buyer's second challenge\n * (#3258). {@link GenerateMppTokenOptions} omits this field, and the MPP minter has no\n * parameter that could carry it.\n */\n tokenVersion?: NeverminedTokenVersion\n}\n\n/**\n * Options for minting an MPP access token — {@link GenerateX402TokenOptions} minus the x402\n * version knob (#3266).\n *\n * The omission IS the divergence: MPP signs one struct and the server chooses it, so there is\n * nothing here for a caller to name. Passing `tokenVersion` to\n * {@link generateAgentMppAccessToken} is a compile error rather than a silently honoured\n * request — which also means the guard is invisible to jest, since the suites run through SWC\n * and it strips types without checking them. `nx typecheck` is what enforces it.\n */\nexport type GenerateMppTokenOptions = Omit<GenerateX402TokenOptions, 'tokenVersion'>\n\n/**\n * The domain's `chainId` is a load-bearing part of the separator, and viem drops an `undefined`\n * one from the `EIP712Domain` type list — hashing IDENTICALLY to omitting the field, with no error.\n * A chainless `publicClient` (`createPublicClient({ transport })` with no `chain`, a shape that\n * already exists in this repo) would therefore mint a digest valid on every chain at once. Fail\n * loudly instead: this is a client misconfiguration, never a token defect.\n */\nconst requireChainId = (publicClient: PublicClient, caller: string): number => {\n const chainId = publicClient.chain?.id\n if (typeof chainId !== 'number') {\n throw new Error(`${caller}: publicClient has no chain — the EIP-712 domain needs a chainId`)\n }\n return chainId\n}\n\n/**\n * 32 bytes of CSPRNG output, hex-encoded — the one-time nonce of a v3 token (#2646).\n *\n * `globalThis.crypto` (WebCrypto) rather than node's `crypto` module so core-kit keeps\n * working in the browser, where this package is also consumed. 256 bits makes a\n * collision in the resource server's replay store (a UNIQUE column) unreachable, so a\n * legitimate mint can never be refused as someone else's replay.\n */\nconst generateTokenNonce = (): string => {\n const bytes = new Uint8Array(32)\n globalThis.crypto.getRandomValues(bytes)\n return `0x${Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('')}`\n}\n\n/**\n * Builds the Authorization message BOTH protocols sign.\n *\n * This is the part that deliberately does NOT diverge (#3266): `from`, `sessionKeysProvider`,\n * `sessionKeys` and `planId` mean the same thing on x402 and MPP, so a defect here would be\n * universal — with two copies it would have to be found and fixed twice. Keeping it\n * single-sourced is what bounds the cost of the divergence above it.\n */\nconst buildAuthorizationMessage = (\n options: GenerateMppTokenOptions,\n): NeverminedTypedDataMessage => {\n const { subscriber, orderSessionKey, redeemSessionKey, planId } = options\n\n // A v2 token MUST carry a non-empty signed planId (#1678) — an empty/blank\n // planId would otherwise be signed into `authorization.planId` and could be\n // misread as a \"present but empty\" signed claim, blurring the v1/v2 boundary\n // that verification keys off genuine presence. erc4337 already requires a\n // planId upstream (`validateX402TokenStructure`), so this is a hard invariant.\n if (typeof planId !== 'string' || planId.trim() === '') {\n throw new Error('Nevermined access token: planId is required and must be a non-empty string')\n }\n\n // Including `planId` here puts it inside the EIP-712 digest, so it cannot be\n // altered without invalidating the signature.\n return {\n from: subscriber.address,\n sessionKeysProvider: 'zerodev',\n sessionKeys: [\n { id: 'order', data: keccak256(toBytes(orderSessionKey)) },\n { id: 'redeem', data: keccak256(toBytes(redeemSessionKey)) },\n ],\n planId,\n }\n}\n\n/**\n * Signs an already-chosen struct under an already-chosen domain and wraps it in the envelope.\n *\n * `types` and `message` arrive TOGETHER and already agreed, because EIP-712 hashes the type set\n * — a v3 message signed over the v2 list produces a digest no verifier reproduces. Choosing the\n * pair is each protocol's job; this function never infers one from the other, and has no notion\n * of a version to infer it from.\n *\n * Not exported — callers go through {@link generateAgentX402AccessToken} or\n * {@link generateAgentMppAccessToken}, each with its domain pinned, so a protocol can never be\n * selected by a caller-supplied value.\n */\nconst signAccessToken = async (\n options: GenerateMppTokenOptions,\n domainName: NeverminedEip712DomainName,\n types: NeverminedTypedData | NeverminedTypedDataV3,\n message: NeverminedTypedDataMessage | NeverminedTypedDataMessageV3,\n): Promise<AgentX402AccessToken> => {\n const {\n subscriber,\n publicClient,\n planId,\n schemeVersion = '1',\n agentId,\n resource,\n httpVerb,\n validUntil,\n } = options\n\n const chainId = requireChainId(publicClient, 'Nevermined access token mint')\n\n const domain: NeverminedTypedDataDomain<NeverminedEip712DomainName> = {\n name: domainName,\n version: '1',\n chainId,\n verifyingContract: subscriber.address,\n }\n\n const signature = await subscriber.signTypedData({\n domain,\n types,\n primaryType: 'Authorization',\n message,\n } as TypedDataDefinition<NeverminedTypedData | NeverminedTypedDataV3, 'Authorization'>)\n\n // Network in CAIP-2 format (eip155:chainId) — always resolvable, `requireChainId` already ran.\n const network = `eip155:${chainId}`\n\n return {\n x402Version: 2,\n ...(resource && { resource }),\n accepted: {\n scheme: 'nvm:erc4337',\n network,\n planId,\n extra: {\n version: schemeVersion,\n ...(agentId && { agentId }),\n ...(httpVerb && { httpVerb }),\n },\n },\n payload: {\n signature,\n authorization: message,\n },\n ...(validUntil !== undefined && { validUntil }),\n extensions: {},\n }\n}\n\n/**\n * Generate an x402 access token aligned with x402 v2 spec.\n *\n * Walks x402's OWN version ladder (#3266): v3 — the #2646 binding and one-time nonce — unless the\n * caller explicitly asks for the legacy v2 struct (#3259). Nothing chosen here can reach the MPP\n * minter.\n *\n * @param options - Token generation options\n * @returns x402 access token with EIP-712 signature\n */\nexport const generateAgentX402AccessToken = async (\n options: GenerateX402TokenOptions,\n): Promise<AgentX402AccessToken> => {\n const message = buildAuthorizationMessage(options)\n\n // v3 (#2646) appends the seller/resource binding and the one-time nonce. A member the caller\n // left undefined is signed as '' — EIP-712 has no optional members, so \"not bound\" must itself\n // be a signed value; `isSignedBindingConsistent` then holds the unsigned envelope copy to the\n // same absence.\n //\n // #3259 — v3 is the DEFAULT, and the absent case is the one that matters: #2646 shipped the\n // nonce and the binding as an opt-in nobody took, so on the default path an x402 token stayed\n // replayable and unbound. Flipping the fallback is the whole control. v2 remains reachable by\n // asking for it explicitly; nothing here infers it.\n if ((options.tokenVersion ?? 3) === 3) {\n return signAccessToken(options, NEVERMINED_EIP712_DOMAIN_NAME, NeverminedTypedDataTypesV3, {\n ...message,\n agentId: options.agentId ?? '',\n resourceUrl: options.resource?.url ?? '',\n httpVerb: options.httpVerb ?? '',\n nonce: generateTokenNonce(),\n })\n }\n\n return signAccessToken(options, NEVERMINED_EIP712_DOMAIN_NAME, NeverminedTypedDataTypes, message)\n}\n\n/**\n * Generate a NATIVE MPP access token (#2640) — the same struct signed under the\n * `Nevermined-MPP` EIP-712 domain.\n *\n * Native, not a wrapper: the revised Tier A design (#2024) deliberately does NOT embed an x402\n * token inside an MPP credential, because unwrapping it would hand the holder a token that still\n * settles on the public x402 path.\n *\n * ONE struct, NO version (#3266). {@link NeverminedTypedDataTypes} is REUSED rather than copied\n * under an MPP name — the members are identical, and a second table would only drift. What\n * diverges is the CHOICE: this minter has no ladder to walk and no parameter that could make it\n * walk one, so a future x402 struct change cannot reach MPP by default the way #2646's nonce did.\n *\n * @param options - Token generation options, minus x402's `tokenVersion`\n * @returns MPP access token with EIP-712 signature over the MPP domain. The envelope is IDENTICAL\n * to an x402 token's, `accepted.scheme: 'nvm:erc4337'` included — only the signature differs, so\n * the protocol is fixed by the endpoint, not readable off the wire. See\n * {@link NEVERMINED_MPP_EIP712_DOMAIN_NAME} on routing vs. the security boundary.\n */\nexport const generateAgentMppAccessToken = async (\n options: GenerateMppTokenOptions,\n): Promise<AgentX402AccessToken> =>\n signAccessToken(\n options,\n NEVERMINED_MPP_EIP712_DOMAIN_NAME,\n NeverminedTypedDataTypes,\n buildAuthorizationMessage(options),\n )\n\n/**\n * True when `authorization` carries a GENUINE signed planId (#1678) — a present,\n * non-empty string. This is the single v1/v2 discriminator: verification keys off\n * it to choose the matching EIP-712 type list, the handler keys off it to decide\n * whether the signed-vs-unsigned consistency guard fires. Keying off genuine\n * presence (not just `'planId' in authorization`) ensures a `planId: ''` / nullish\n * value can never be mistaken for a real signed claim.\n */\nexport const hasSignedPlanId = (\n authorization: X402Erc4337Payload['authorization'],\n): authorization is X402Erc4337Payload['authorization'] & { planId: string } => {\n return typeof authorization?.planId === 'string' && authorization.planId.trim() !== ''\n}\n\n/**\n * The signed-vs-unsigned planId consistency invariant (#1678), co-located with\n * `hasSignedPlanId` so signer, verifier, and the API handler share ONE\n * definition (no drift between where the planId is signed and where the guard\n * enforces it).\n *\n * For a v2 token (signed planId present) the tamperable unsigned `accepted.planId`\n * MUST exactly equal the signed `authorization.planId` — anything else is a\n * post-signing edit of the outer JSON. Returns `true` for v1 tokens (no signed\n * planId): there is no signed value to be consistent with, so the guard does not\n * apply (the caller handles the legacy fallback separately). The API handler maps\n * a `false` result to its forgery-gated rejection.\n */\nexport const isSignedPlanIdConsistent = (\n authorization: X402Erc4337Payload['authorization'],\n acceptedPlanId: string | null | undefined,\n): boolean => {\n if (!hasSignedPlanId(authorization)) return true\n return acceptedPlanId === authorization.planId\n}\n\n/**\n * True when `authorization` carries a GENUINE one-time nonce (#2646) — a present,\n * non-empty string. This is the single v2/v3 discriminator, the exact counterpart of\n * {@link hasSignedPlanId} for the v1/v2 boundary: verification keys off it to choose\n * the matching EIP-712 type list, and the resource server keys off it to decide\n * whether the binding guard and the single-use replay store apply.\n *\n * `nonce` is the discriminator rather than one of the binding members because it is\n * the only v3 member that is always non-empty — `agentId` / `resourceUrl` / `httpVerb`\n * are legitimately signed as `''` when the mint had no value for them.\n */\nexport const hasSignedNonce = (\n authorization: X402Erc4337Payload['authorization'],\n): authorization is X402Erc4337Payload['authorization'] & { nonce: string } => {\n return typeof authorization?.nonce === 'string' && authorization.nonce.trim() !== ''\n}\n\n/** The unsigned envelope values a v3 binding is checked against. */\nexport type SignedBindingEnvelope = {\n /** `accepted.extra.agentId` */\n agentId: string | null | undefined\n /** `resource.url` */\n resourceUrl: string | null | undefined\n /** `accepted.extra.httpVerb` */\n httpVerb: string | null | undefined\n}\n\n/**\n * The signed-vs-unsigned BINDING invariant (#2646), co-located with\n * {@link hasSignedNonce} so signer, verifier and the API handler share ONE definition —\n * the same reason {@link isSignedPlanIdConsistent} lives here.\n *\n * For a v3 token every binding member must agree with its unsigned envelope copy:\n * - a signed non-empty value must equal the envelope value EXACTLY. Both are our own\n * mint's output, so exact equality is right; the fuzzier, query-insensitive URL\n * comparison belongs to the demand-match against the SELLER-supplied\n * `paymentRequired`, which is a different question.\n * - a signed `''` means \"not bound\", so the envelope copy must be absent (or empty)\n * too. This is the half that stops someone ADDING an `agentId` to a token that was\n * signed without one — without it, `''` would be a hole rather than a claim.\n *\n * Returns `true` for v1/v2 tokens: there is no signed binding to be consistent with,\n * and the caller handles those on the legacy path. The API handler maps a `false`\n * result to its forgery-gated rejection, exactly as it does for the planId guard.\n */\nexport const isSignedBindingConsistent = (\n authorization: X402Erc4337Payload['authorization'],\n envelope: SignedBindingEnvelope,\n): boolean => {\n if (!hasSignedNonce(authorization)) return true\n\n const matches = (signed: string | undefined, unsigned: string | null | undefined): boolean => {\n const signedValue = signed ?? ''\n // Absence and '' are the same claim on both sides: the mint omits an empty member\n // from the envelope entirely, so an omitted field is what a signed '' looks like.\n if (signedValue === '') return unsigned === undefined || unsigned === null || unsigned === ''\n return unsigned === signedValue\n }\n\n return (\n matches(authorization.agentId, envelope.agentId) &&\n matches(authorization.resourceUrl, envelope.resourceUrl) &&\n matches(authorization.httpVerb, envelope.httpVerb)\n )\n}\n\n/**\n * Picks the EIP-712 type list a protocol verifies an authorization against, or `null` to refuse\n * it outright.\n *\n * One selector per protocol IS the divergence (#3266). This used to be a single, protocol-blind\n * field-presence ladder, which made every x402 struct version automatically a verifiable MPP\n * one. Presence detection also cannot distinguish two protocols that want the same field set\n * with different meaning — the next #3258 waiting to happen.\n */\ntype AuthorizationTypesSelector = (\n authorization: X402Erc4337Payload['authorization'],\n) => NeverminedTypedData | NeverminedTypedDataV1 | NeverminedTypedDataV3 | null\n\n/**\n * x402's ladder: a genuine signed nonce (#2646) → v3, else a genuine signed planId (#1678) → v2,\n * else the original v1 list. Selected by GENUINE presence and never by a caller-supplied hint.\n * The branches are mutually exclusive and none falls back to another — trying a second type list\n * on failure would erase exactly the downgrade protection the versioning provides.\n *\n * A v1 (unsigned-planId) authorization leaves `isSignedPlanIdConsistent` inert, so the tamperable\n * `accepted.planId` becomes authoritative. That is a deliberate #1678 back-compat concession, and\n * it is why this selector admits a shape {@link selectMppAuthorizationTypes} refuses.\n */\nconst selectX402AuthorizationTypes: AuthorizationTypesSelector = (authorization) =>\n hasSignedNonce(authorization)\n ? NeverminedTypedDataTypesV3\n : hasSignedPlanId(authorization)\n ? NeverminedTypedDataTypes\n : NeverminedTypedDataTypesV1\n\n/**\n * MPP's table: one entry, no ladder (#3266) — {@link NeverminedTypedDataTypes} reused, not copied.\n *\n * Two consequences, both of them the point:\n * - an authorization carrying a v3 nonce has nowhere to climb to. It is checked against the base\n * list, the digest does not match, and it fails. An x402 struct version is not automatically\n * an MPP one, which is the coupling #3258 came from.\n *\n * ⚠️ This is the one RUNTIME verdict this change flips, and it is retroactive: before #3266 the\n * protocol-blind ladder read a v3 MPP authorization's `planId`, selected the v3 list, and the\n * token VERIFIED. An MPP token already minted at `tokenVersion: 3` therefore stops verifying —\n * it is not merely unmintable from here on. `validUntil` is written at mint but never compared\n * against `now` on this path, so nothing expires such a token out of existence; the holder has\n * to re-mint. No supported client can hold one (`@nevermined-io/payments` has never exposed\n * `tokenVersion`, per #3257) and it was already single-settle in practice, since\n * `consumeTokenNonce` is not MPP-aware and spends the nonce on an MPP settle too.\n * - a legacy (unsigned-planId) authorization is REFUSED rather than checked against the v1 list.\n * MPP is born after #1678 and has no pre-planId tokens to stay compatible with; accepting one\n * would hand authority to the tamperable `accepted.planId`.\n */\nconst selectMppAuthorizationTypes: AuthorizationTypesSelector = (authorization) =>\n hasSignedPlanId(authorization) ? NeverminedTypedDataTypes : null\n\n/**\n * Shared verifier for both protocols, differing only in the EIP-712 domain name and the type\n * list its protocol accepts.\n *\n * EIP-712 hashes the type set, so a token signed over one struct cannot verify against another's\n * type list. `selectTypes` is therefore the protocol's whole verification policy: which shapes it\n * recognises, and which it refuses without asking the chain.\n *\n * Downgrade-safe on every ladder: a v2 token was signed over the with-planId digest, so stripping\n * `authorization.planId` to force the v1 branch changes the digest and the signature fails; a v3\n * token was signed over the with-nonce digest, so stripping the nonce to escape single-use, or\n * stripping `agentId` / `resourceUrl` to escape the seller binding, fails the same way. An\n * attacker cannot demote a signed token to shed a claim.\n *\n * EIP-712 hashes the DOMAIN separator too, which is what makes `domainName` the protocol boundary\n * (#2640) rather than a label. Not exported: callers go through\n * {@link verifyAgentX402AccessToken} or {@link verifyAgentMppAccessToken}, each with its domain\n * and its selector pinned, so no caller-supplied value can pick which protocol a token is checked\n * against.\n */\nconst verifyAgentAccessToken = async (\n accessToken: AgentX402AccessToken,\n publicClient: PublicClient,\n domainName: NeverminedEip712DomainName,\n selectTypes: AuthorizationTypesSelector,\n): Promise<boolean> => {\n // `payload` is a union (erc4337 | card-delegation) and this is a public entry point with no\n // guaranteed pre-validation — `validateX402TokenStructure` runs in `apps/api`, not here. A\n // structural precondition, evaluated BEFORE the await: deliberately NOT a try/catch around the\n // verification itself, which must keep letting an RPC fault propagate rather than laundering it\n // into a `false` the caller reads as a forgery.\n const erc4337Payload = accessToken?.payload as X402Erc4337Payload | undefined\n if (!erc4337Payload?.authorization?.from || !erc4337Payload.signature) return false\n\n const { signature, authorization } = erc4337Payload\n const subscriberAddress = authorization.from\n\n // A shape this protocol does not recognise is refused here, before any chain call.\n const types = selectTypes(authorization)\n if (!types) return false\n\n const domain: NeverminedTypedDataDomain<NeverminedEip712DomainName> = {\n name: domainName,\n version: '1',\n chainId: requireChainId(publicClient, 'Nevermined access token verify'),\n verifyingContract: subscriberAddress,\n }\n const isValid = await publicClient.verifyTypedData({\n address: subscriberAddress,\n signature,\n types,\n domain,\n message: authorization,\n primaryType: 'Authorization',\n })\n return isValid\n}\n\n/**\n * Verify an x402 access token signature (see {@link selectX402AuthorizationTypes} for the\n * v1/v2/v3 type-list detection and its downgrade-safety).\n *\n * Rejects an MPP token: it was signed under a different domain separator, so the digest differs.\n *\n * @param accessToken - The x402 access token to verify\n * @param publicClient - Viem public client\n * @returns true if signature is valid\n */\nexport const verifyAgentX402AccessToken = (\n accessToken: AgentX402AccessToken,\n publicClient: PublicClient,\n): Promise<boolean> =>\n verifyAgentAccessToken(\n accessToken,\n publicClient,\n NEVERMINED_EIP712_DOMAIN_NAME,\n selectX402AuthorizationTypes,\n )\n\n/**\n * Verify an MPP access token signature (#2640).\n *\n * Rejects an x402 token for the same reason the x402 verifier rejects an MPP one — the domain\n * separator is part of the signed digest. This is the property the whole Tier A isolation rests on:\n * a credential harvested from one protocol is inert on the other, closing cross-protocol replay\n * AND downgrade — WHILE the signing key stays server-side. A subscriber holding it can mint under\n * whichever domain they like, so the split constrains the transport, not that holder.\n *\n * One struct, no ladder: {@link selectMppAuthorizationTypes} accepts the base struct and nothing\n * else, so a legacy (unsigned-planId) authorization is refused outright and an x402 struct version\n * is not verifiable here just because x402 added it (#3266).\n *\n * @param accessToken - The MPP access token to verify\n * @param publicClient - Viem public client\n * @returns true if signature is valid\n */\nexport const verifyAgentMppAccessToken = (\n accessToken: AgentX402AccessToken,\n publicClient: PublicClient,\n): Promise<boolean> =>\n verifyAgentAccessToken(\n accessToken,\n publicClient,\n NEVERMINED_MPP_EIP712_DOMAIN_NAME,\n selectMppAuthorizationTypes,\n )\n\n/**\n * Validation result for x402 token structure\n */\nexport type X402TokenValidationResult = {\n valid: boolean\n errors: string[]\n}\n\n/**\n * Validate the structure of an x402 access token\n *\n * @param token - The token to validate (unknown type for safety)\n * @returns Validation result with errors if any\n */\nconst SUPPORTED_SCHEMES: X402Scheme[] = ['nvm:erc4337', 'nvm:card-delegation']\n\nexport const validateX402TokenStructure = (token: unknown): X402TokenValidationResult => {\n const errors: string[] = []\n\n if (!token || typeof token !== 'object') {\n return { valid: false, errors: ['Token must be an object'] }\n }\n\n const t = token as Record<string, unknown>\n\n // Validate x402Version\n if (t.x402Version !== 2) {\n errors.push('x402Version must be 2')\n }\n\n // Validate accepted object\n if (!t.accepted || typeof t.accepted !== 'object') {\n errors.push('accepted is required')\n } else {\n const accepted = t.accepted as Record<string, unknown>\n const scheme = accepted.scheme as string\n\n if (!SUPPORTED_SCHEMES.includes(scheme as X402Scheme)) {\n errors.push(`scheme must be one of: ${SUPPORTED_SCHEMES.join(', ')}`)\n }\n\n if (!accepted.network || typeof accepted.network !== 'string') {\n errors.push('network is required in accepted')\n }\n\n // Validate extra\n if (!accepted.extra || typeof accepted.extra !== 'object') {\n errors.push('extra is required in accepted')\n } else {\n const extra = accepted.extra as Record<string, unknown>\n if (!extra.version || typeof extra.version !== 'string') {\n errors.push('version is required in accepted.extra')\n }\n }\n\n // Scheme-specific accepted validation\n if (scheme === 'nvm:erc4337') {\n if (!accepted.planId || typeof accepted.planId !== 'string') {\n errors.push('planId is required in accepted for nvm:erc4337')\n }\n }\n }\n\n // Validate payload\n if (!t.payload || typeof t.payload !== 'object') {\n errors.push('payload is required')\n } else {\n const accepted = t.accepted as Record<string, unknown> | undefined\n const scheme = accepted?.scheme as string | undefined\n const payload = t.payload as Record<string, unknown>\n\n if (scheme === 'nvm:erc4337') {\n if (!payload.signature || typeof payload.signature !== 'string') {\n errors.push('signature is required in payload')\n }\n\n if (!payload.authorization || typeof payload.authorization !== 'object') {\n errors.push('authorization is required in payload')\n } else {\n const auth = payload.authorization as Record<string, unknown>\n\n if (!auth.from || typeof auth.from !== 'string') {\n errors.push('from address is required in payload.authorization')\n } else if (!auth.from.startsWith('0x')) {\n errors.push('from must be a valid hex address')\n }\n\n if (!auth.sessionKeysProvider || typeof auth.sessionKeysProvider !== 'string') {\n errors.push('sessionKeysProvider is required in payload.authorization')\n }\n\n if (!Array.isArray(auth.sessionKeys)) {\n errors.push('sessionKeys array is required in payload.authorization')\n }\n }\n } else if (scheme === 'nvm:card-delegation') {\n if (!payload.token || typeof payload.token !== 'string') {\n errors.push('token is required in payload for nvm:card-delegation')\n }\n }\n }\n\n // Validate extensions (must be present, even if empty)\n if (t.extensions === undefined) {\n errors.push('extensions is required (can be empty object)')\n }\n\n return { valid: errors.length === 0, errors }\n}\n\nexport const b64EncodeX402AccessToken = (accessToken: AgentX402AccessToken): string => {\n return Buffer.from(JSON.stringify(accessToken)).toString('base64')\n}\n\nexport const b64DecodeX402AccessToken = (encoded: string): AgentX402AccessToken => {\n return JSON.parse(Buffer.from(encoded, 'base64').toString('utf-8'))\n}\n"],"names":["keccak256","toBytes","NEVERMINED_EIP712_DOMAIN_NAME","NEVERMINED_MPP_EIP712_DOMAIN_NAME","NeverminedTypedDataTypes","SessionKey","name","type","SessionKeys","Authorization","NeverminedTypedDataTypesV1","NeverminedTypedDataTypesV3","requireChainId","publicClient","caller","chainId","chain","id","Error","generateTokenNonce","bytes","Uint8Array","globalThis","crypto","getRandomValues","Array","from","b","toString","padStart","join","buildAuthorizationMessage","options","subscriber","orderSessionKey","redeemSessionKey","planId","trim","address","sessionKeysProvider","sessionKeys","data","signAccessToken","domainName","types","message","schemeVersion","agentId","resource","httpVerb","validUntil","domain","version","verifyingContract","signature","signTypedData","primaryType","network","x402Version","accepted","scheme","extra","payload","authorization","undefined","extensions","generateAgentX402AccessToken","tokenVersion","resourceUrl","url","nonce","generateAgentMppAccessToken","hasSignedPlanId","isSignedPlanIdConsistent","acceptedPlanId","hasSignedNonce","isSignedBindingConsistent","envelope","matches","signed","unsigned","signedValue","selectX402AuthorizationTypes","selectMppAuthorizationTypes","verifyAgentAccessToken","accessToken","selectTypes","erc4337Payload","subscriberAddress","isValid","verifyTypedData","verifyAgentX402AccessToken","verifyAgentMppAccessToken","SUPPORTED_SCHEMES","validateX402TokenStructure","token","errors","valid","t","push","includes","auth","startsWith","isArray","length","b64EncodeX402AccessToken","Buffer","JSON","stringify","b64DecodeX402AccessToken","encoded","parse"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nevermined-io/core-kit",
3
- "version": "1.33.0",
3
+ "version": "1.34.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",