tersign 0.6.1 → 0.6.2

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.
@@ -8,6 +8,6 @@ export declare function envDeps(env?: Record<string, string | undefined>): McpDe
8
8
  * every client; mcp.test.ts pins it against package.json so a release bump can't drift it. */
9
9
  export declare const MCP_SERVER_IDENTITY: {
10
10
  readonly name: "tersign";
11
- readonly version: "0.6.1";
11
+ readonly version: "0.6.2";
12
12
  };
13
13
  export declare function buildServer(deps: McpDeps): McpServer;
@@ -53,7 +53,7 @@ function json(value) {
53
53
  }
54
54
  /** MUST match package.json name/version — the MCP handshake self-reports this identity to
55
55
  * every client; mcp.test.ts pins it against package.json so a release bump can't drift it. */
56
- export const MCP_SERVER_IDENTITY = { name: 'tersign', version: '0.6.1' };
56
+ export const MCP_SERVER_IDENTITY = { name: 'tersign', version: '0.6.2' };
57
57
  export function buildServer(deps) {
58
58
  const server = new McpServer(MCP_SERVER_IDENTITY);
59
59
  server.registerTool('issue_receipt', {
@@ -51,7 +51,7 @@ export declare function bindSigner(signer: `0x${string}`, expected: string | und
51
51
  *
52
52
  * Scope: verifyReceipt, verifyComplianceRecord and the CLI and MCP tools built on them. The
53
53
  * action-record, dispute and evidence verifiers (evidence/action.ts, dispute/sign.ts) do NOT call
54
- * this and still accept what viem accepts (PUNT-REGISTER R8). Neither does the ledger's ingest
54
+ * this and still accept what viem accepts. Neither does the ledger's ingest
55
55
  * (SECURITY-AUDIT A8), so a receipt the ledger counter-signed with a non-canonical signature is
56
56
  * refused here. The reasons are package text only: nothing from the file is echoed. */
57
57
  export declare function signatureError(sig: unknown): string | undefined;
@@ -2,7 +2,7 @@
2
2
  * verifyComplianceRecord, the `tersign verify` CLI and the MCP verify tools, so those four
3
3
  * surfaces cannot drift apart on the one question a verify result is read for. verifyActionRecord,
4
4
  * verifyDispute and verifyEvidence do NOT use it: they have no signer binding and no canonical
5
- * signature check (PUNT-REGISTER R8).
5
+ * signature check.
6
6
  *
7
7
  * ECDSA recovery yields an address for ANY payload and ANY well-formed signature. An edited
8
8
  * receipt therefore still "verifies" — it recovers a different address. A recovered signer is
@@ -67,7 +67,7 @@ const SECP256K1_N = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0
67
67
  *
68
68
  * Scope: verifyReceipt, verifyComplianceRecord and the CLI and MCP tools built on them. The
69
69
  * action-record, dispute and evidence verifiers (evidence/action.ts, dispute/sign.ts) do NOT call
70
- * this and still accept what viem accepts (PUNT-REGISTER R8). Neither does the ledger's ingest
70
+ * this and still accept what viem accepts. Neither does the ledger's ingest
71
71
  * (SECURITY-AUDIT A8), so a receipt the ledger counter-signed with a non-canonical signature is
72
72
  * refused here. The reasons are package text only: nothing from the file is echoed. */
73
73
  export function signatureError(sig) {
@@ -118,6 +118,17 @@ function signedFieldError(p) {
118
118
  }
119
119
  return undefined;
120
120
  }
121
+ /** x402 offer-and-receipt §5.5 step 2: payload.version selects the EIP-712 types, and "currently
122
+ * only version 1 is defined". Without this a version-2 payload recovered under the version-1
123
+ * types and verified valid. Runs after signedFieldError, so version is already a JSON integer
124
+ * (a string "1" is refused there with its own reason); the comparison is strict anyway, so it
125
+ * does not lean on that order. The Python twin raises the same text. */
126
+ function receiptVersionError(p) {
127
+ const v = p.version;
128
+ if (v === 1 || v === 1n)
129
+ return undefined;
130
+ return `payload.version ${String(v)} is not supported: version 1 is the only receipt version the x402 offer-and-receipt extension defines`;
131
+ }
121
132
  /** Verify an EIP-712 receipt. `expectedSigner` implements the spec's payTo-key authorization
122
133
  * model; pass the seller's payTo address (or a registry-resolved key), obtained out-of-band,
123
134
  * to enforce it. Without it the recovered signer is UNAUTHENTICATED (signerBound:false). */
@@ -136,6 +147,9 @@ export async function verifyReceipt(artifact, expectedSigner) {
136
147
  const badField = signedFieldError(artifact.payload);
137
148
  if (badField)
138
149
  return { valid: false, signerBound: false, reason: badField };
150
+ const badVersion = receiptVersionError(artifact.payload);
151
+ if (badVersion)
152
+ return { valid: false, signerBound: false, reason: badVersion };
139
153
  const badSig = signatureError(artifact.signature);
140
154
  if (badSig)
141
155
  return { valid: false, signerBound: false, reason: badSig };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tersign",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "description": "Tersign \u2014 the evidence layer for the agent economy. Counter-signed receipts, agent action records, idempotency enforcement, refunds, disputes, and jury-ready evidence envelopes for x402/agent-commerce sellers.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",