kawasekit 0.2.0 → 0.4.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.
Files changed (36) hide show
  1. package/dist/{chunk-VXZHS74W.js → chunk-5TTOAVHE.js} +9 -3
  2. package/dist/chunk-5TTOAVHE.js.map +1 -0
  3. package/dist/chunk-FD6Q4NB2.js +293 -0
  4. package/dist/chunk-FD6Q4NB2.js.map +1 -0
  5. package/dist/{chunk-SMAZUZFO.js → chunk-G3UC6SME.js} +3 -3
  6. package/dist/{chunk-SMAZUZFO.js.map → chunk-G3UC6SME.js.map} +1 -1
  7. package/dist/{chunk-XRSZTZVZ.js → chunk-RJLDKDWL.js} +2 -2
  8. package/dist/{chunk-XRSZTZVZ.js.map → chunk-RJLDKDWL.js.map} +1 -1
  9. package/dist/cli/index.cjs +1 -1
  10. package/dist/cli/index.js +5 -5
  11. package/dist/{index-f-Xg86P9.d.ts → index-C9tbaHPF.d.ts} +1 -1
  12. package/dist/{index-Cn6kg7KH.d.cts → index-CAmTA8xR.d.cts} +1 -1
  13. package/dist/index.cjs +239 -4
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.d.cts +4 -4
  16. package/dist/index.d.ts +4 -4
  17. package/dist/index.js +4 -4
  18. package/dist/policy/index.d.cts +2 -2
  19. package/dist/policy/index.d.ts +2 -2
  20. package/dist/signer/index.cjs +235 -0
  21. package/dist/signer/index.cjs.map +1 -1
  22. package/dist/signer/index.d.cts +240 -5
  23. package/dist/signer/index.d.ts +240 -5
  24. package/dist/signer/index.js +2 -2
  25. package/dist/{spending-policy-DKZN3Sg8.d.ts → spending-policy-BD2Mpm-L.d.ts} +1 -1
  26. package/dist/{spending-policy-DaajDg9B.d.cts → spending-policy-CGIaBpg-.d.cts} +1 -1
  27. package/dist/{types-IEl-iOIx.d.cts → types-BLJU67HZ.d.cts} +11 -3
  28. package/dist/{types-IEl-iOIx.d.ts → types-BLJU67HZ.d.ts} +11 -3
  29. package/dist/x402/index.cjs.map +1 -1
  30. package/dist/x402/index.d.cts +2 -2
  31. package/dist/x402/index.d.ts +2 -2
  32. package/dist/x402/index.js +2 -2
  33. package/package.json +1 -1
  34. package/dist/chunk-THTVJZ2Q.js +0 -71
  35. package/dist/chunk-THTVJZ2Q.js.map +0 -1
  36. package/dist/chunk-VXZHS74W.js.map +0 -1
@@ -1,7 +1,7 @@
1
- import { a as PolicyGatedSigner, N as NonBypassableEnforcement } from '../types-IEl-iOIx.cjs';
2
- export { E as EnforcementLevel, P as PaymentIntent, b as PolicyRejection, S as SignResult, c as SignerDescription } from '../types-IEl-iOIx.cjs';
3
- import { Account } from 'viem';
4
- import { a as SpendingPolicy, S as SpendState } from '../spending-policy-DaajDg9B.cjs';
1
+ import { a as PolicyGatedSigner, N as NonBypassableEnforcement, P as PaymentIntent } from '../types-BLJU67HZ.cjs';
2
+ export { E as EnforcementLevel, b as PolicyRejection, S as SignResult, c as SignerDescription } from '../types-BLJU67HZ.cjs';
3
+ import { Account, Hex, Address } from 'viem';
4
+ import { a as SpendingPolicy, S as SpendState } from '../spending-policy-CGIaBpg-.cjs';
5
5
  import { X as X402AssetParam } from '../asset-domain-4Ioxqn28.cjs';
6
6
 
7
7
  /**
@@ -39,6 +39,36 @@ declare class PolicyGatedSignerConfigError extends Error {
39
39
  cause?: unknown;
40
40
  });
41
41
  }
42
+ /**
43
+ * Thrown by the `mpc-2p` cryptographic adapter when the co-signer is
44
+ * **unreachable or the ceremony could not complete** — endpoint down, TLS
45
+ * failure, connection dropped mid-ceremony, timeout, a malformed/missing
46
+ * terminal frame, or an internal protocol anomaly. It is a transient / internal
47
+ * error on the throws channel (M6-0: throws are reserved for internal/config
48
+ * errors), **distinct from a policy denial**.
49
+ *
50
+ * This is the **no-silent-fallback** guarantee (RFC m6-3a constraint 3 / W8):
51
+ * the adapter has no local-signing path, so an unavailable wire NEVER yields an
52
+ * `{ ok: true }` signature and NEVER a {@link PolicyRejection}. A `rejection`
53
+ * means "the owner decided no" (audit-meaningful); a `CoSignUnavailableError`
54
+ * means "the owner did not decide" — the caller may retry the *same* intent
55
+ * (the backend's idempotency keeps a retry safe).
56
+ *
57
+ * @example
58
+ * ```ts
59
+ * try {
60
+ * const result = await mpc2pSigner.sign(intent);
61
+ * if (!result.ok) handleDenial(result.rejection); // owner said no
62
+ * } catch (error) {
63
+ * if (error instanceof CoSignUnavailableError) retryLater(); // wire was down
64
+ * }
65
+ * ```
66
+ */
67
+ declare class CoSignUnavailableError extends Error {
68
+ constructor(message: string, options?: {
69
+ cause?: unknown;
70
+ });
71
+ }
42
72
 
43
73
  /**
44
74
  * The enforcement-level type-gate — the compile-time (and runtime) mechanism
@@ -128,4 +158,209 @@ interface CreateLocalPolicyGatedSignerParams {
128
158
  */
129
159
  declare function createLocalPolicyGatedSigner(params: CreateLocalPolicyGatedSignerParams): PolicyGatedSigner<"advisory">;
130
160
 
131
- export { type CreateLocalPolicyGatedSignerParams, NonBypassableEnforcement, PolicyGatedSigner, PolicyGatedSignerConfigError, assertNonBypassable, createLocalPolicyGatedSigner, requireNonBypassable };
161
+ /**
162
+ * The `mpc-2p` cross-process **wire** (v2) — the versioned `CoSignFrame` control
163
+ * envelope + the A3 canonical-request encoding, as TypeScript source-of-truth.
164
+ *
165
+ * This is the public, TS-interpreted half of the two-layer wire (RFC m6-3a §4.2):
166
+ * a small, versioned envelope carries the decoded {@link PaymentIntent} (never a
167
+ * digest — A4) + a per-ceremony id + ssid + a freshness element, plus the opaque
168
+ * DKLs round payloads (hex, produced/consumed only by the WASM crypto agent). The
169
+ * shapes here mirror the deployed `kawasekit-mpc-2p` Rust serde **byte-for-byte**
170
+ * (snake_case `wire_version`, `session_id`, `ceremony_id`, `ssid`, `freshness_ts`,
171
+ * `freshness_nonce`, `auth_tag`; the string-encoded {@link WireIntent}), so a frame
172
+ * the SDK builds round-trips through the backend's `serde_json`.
173
+ *
174
+ * `canonicalRequestBytes` is the A3 analog of the EIP-712 digest corpus: it
175
+ * reproduces the backend's `auth::canonical_request_bytes` exactly, so the injected
176
+ * authenticator's HMAC equals what the co-signer verifies (RFC §4.6:
177
+ * `HMAC_k(wireVersion ‖ ceremonyId ‖ ssid ‖ canonical(intent) ‖ freshness)`).
178
+ *
179
+ * @packageDocumentation
180
+ */
181
+
182
+ /** The wire protocol version. A frame whose `wire_version` differs is rejected. */
183
+ declare const WIRE_VERSION: 2;
184
+ /**
185
+ * The string-encoded EIP-3009 intent as it crosses the wire — lowercase `0x`
186
+ * addresses, **decimal** integer strings, `0x` hex nonce. Decoupled from any
187
+ * library's native serde so a stdlib client reproduces it trivially; matches the
188
+ * Rust `WireIntent` field names + encoding exactly.
189
+ */
190
+ interface WireIntent {
191
+ readonly token: string;
192
+ readonly chain_id: number;
193
+ readonly from: string;
194
+ readonly to: string;
195
+ readonly value: string;
196
+ readonly valid_after: string;
197
+ readonly valid_before: string;
198
+ readonly nonce: string;
199
+ }
200
+ /** Encode a decoded {@link PaymentIntent} for the wire. */
201
+ declare function toWireIntent(intent: PaymentIntent): WireIntent;
202
+ /**
203
+ * The A3 request envelope the adapter generates per `sign()` and authenticates: a
204
+ * per-ceremony id + ssid (bound into the A3 tag) + the intent + a freshness element
205
+ * (a timestamp + a per-request nonce distinct from the EIP-3009 nonce).
206
+ */
207
+ interface CoSignRequestEnvelope {
208
+ readonly ceremonyId: string;
209
+ readonly ssid: string;
210
+ readonly intent: PaymentIntent;
211
+ /** Unix seconds; the backend checks it against a clock-skew window. */
212
+ readonly freshnessTs: number;
213
+ /** `0x` hex, distinct from the EIP-3009 nonce — the anti-replay key. */
214
+ readonly freshnessNonce: Hex;
215
+ }
216
+ /**
217
+ * A versioned control frame: the only cross-language content of the wire. The
218
+ * DKLs round bytes ride opaque inside `payload`; everything else is the small,
219
+ * pinned envelope. Internally tagged by `kind` (matches the Rust serde).
220
+ */
221
+ type CoSignFrame = {
222
+ readonly wire_version: typeof WIRE_VERSION;
223
+ } & ({
224
+ readonly kind: "request";
225
+ readonly session_id: string;
226
+ readonly ceremony_id: string;
227
+ readonly ssid: string;
228
+ readonly intent: WireIntent;
229
+ readonly freshness_ts: number;
230
+ readonly freshness_nonce: Hex;
231
+ /** A3 authenticator over {@link canonicalRequestBytes}, `0x`-hex. */
232
+ readonly auth_tag: Hex;
233
+ } | {
234
+ readonly kind: "round";
235
+ readonly payload: Hex;
236
+ } | {
237
+ readonly kind: "result";
238
+ readonly r: Hex;
239
+ readonly s: Hex;
240
+ readonly v: number;
241
+ } | {
242
+ readonly kind: "rejection";
243
+ readonly reason: string;
244
+ readonly detail: string;
245
+ } | {
246
+ readonly kind: "error";
247
+ readonly message: string;
248
+ });
249
+ /**
250
+ * The A3 canonical encoding of a request — a byte-exact mirror of the backend's
251
+ * `auth::canonical_request_bytes` (domain-tag `kawasekit-mpc-2p/cosign-request/v3`,
252
+ * one `key=value\n` line per field: `wireVersion ‖ ceremonyId ‖ ssid ‖
253
+ * canonical(intent) ‖ freshness`; lowercase `0x` addresses + freshness nonce,
254
+ * decimal integers, trailing newline). The injected authenticator HMACs these
255
+ * bytes; because the encoding is shared, the tag equals the co-signer's.
256
+ */
257
+ declare function canonicalRequestBytes(env: CoSignRequestEnvelope): Uint8Array;
258
+
259
+ /**
260
+ * The `mpc-2p` PolicyGatedSigner adapter — `enforcement: "cryptographic"`.
261
+ *
262
+ * A 2-of-2 MPC co-signer: the agent holds ONE DKLs share, the owner backend holds
263
+ * the other + the authoritative policy gate. No valid signature exists without a
264
+ * **policy-passing co-sign**, so — unlike `local` — a single key-holder cannot
265
+ * bypass the policy. That is what earns the non-bypassable `"cryptographic"` label
266
+ * and lets the M6-0 type-gate (`requireNonBypassable`) reject an advisory signer at
267
+ * compile time in bounded flows.
268
+ *
269
+ * **Open-core / thin adapter.** This module is pure orchestration over injected
270
+ * interfaces — it ships in the public SDK with **no crypto, no socket, no key**:
271
+ *
272
+ * - {@link Mpc2pCoSignAgent} — the WASM DKLs share (the private package's compiled
273
+ * `crypto-core`); drives the agent's half of the ceremony round-by-round.
274
+ * - {@link CoSignTransport} — the authenticated, encrypted (wss/mTLS) frame channel
275
+ * to the owner backend (the private package's transport).
276
+ * - {@link CoSignRequestAuthenticator} — the A3 HMAC (the pre-shared key never
277
+ * enters this module).
278
+ *
279
+ * The adapter owns the protocol: it pins the EIP-712 domain, **re-derives the
280
+ * digest from the intent (A4)** via the shared `transferWithAuthorizationTypes`
281
+ * source-of-truth, computes the A3 canonical bytes, frames the versioned
282
+ * {@link CoSignFrame} envelope, pumps the ceremony, and maps the terminal frame to
283
+ * a {@link SignResult}. Crucially it has **no local-signing path**: any
284
+ * transport/availability failure throws {@link CoSignUnavailableError}, never an
285
+ * `{ ok: true }` and never a {@link PolicyRejection} (the no-silent-fallback
286
+ * guarantee, RFC m6-3a constraint 3 / W8).
287
+ *
288
+ * @packageDocumentation
289
+ */
290
+
291
+ /** The agent's half of the 2-of-2 ceremony (the injected WASM DKLs share). */
292
+ interface Mpc2pCoSignAgent {
293
+ /** The group 2-of-2 EOA this share controls — must equal the signer's `from`. */
294
+ groupEoa(): Address;
295
+ /** Begin signing the 32-byte EIP-712 `digest`; returns the first outbound round (hex). */
296
+ start(digest: Hex): Hex;
297
+ /** Feed one inbound round (hex); returns the next outbound round, or the final signature. */
298
+ step(incoming: Hex): Mpc2pStepOutcome;
299
+ }
300
+ /** The result of one {@link Mpc2pCoSignAgent.step}. */
301
+ type Mpc2pStepOutcome = {
302
+ readonly outbound: Hex;
303
+ } | {
304
+ readonly signature: {
305
+ readonly r: Hex;
306
+ readonly s: Hex;
307
+ readonly v: number;
308
+ };
309
+ };
310
+ /** One authenticated, encrypted ceremony connection to the owner backend. */
311
+ interface CoSignConnection {
312
+ /** Send one control frame. */
313
+ send(frame: CoSignFrame): Promise<void>;
314
+ /** Receive the next control frame (resolves per round). */
315
+ recv(): Promise<CoSignFrame>;
316
+ /** Release the connection (best-effort; errors here are ignored). */
317
+ close(): void | Promise<void>;
318
+ }
319
+ /** Opens a wss/mTLS {@link CoSignConnection} for a single co-sign ceremony. */
320
+ interface CoSignTransport {
321
+ connect(): Promise<CoSignConnection>;
322
+ }
323
+ /** The A3 request authenticator — HMAC (or signature) over the canonical request bytes. */
324
+ interface CoSignRequestAuthenticator {
325
+ /** Authenticator tag over {@link canonicalRequestBytes}; the key stays inside. */
326
+ tag(canonicalRequest: Uint8Array): Hex | Promise<Hex>;
327
+ }
328
+ /** Parameters for {@link createMpc2pPolicyGatedSigner}. */
329
+ interface Mpc2pSignerParams {
330
+ /** The group 2-of-2 EOA; every `intent.from` must equal this (asserted vs the agent). */
331
+ readonly from: Address;
332
+ /** Asset binding — pins the EIP-712 domain `name`/`version`/`verifyingContract` (A4). */
333
+ readonly asset: X402AssetParam;
334
+ /** The bound policy session, for `describe()` (the backend holds the authoritative policy). */
335
+ readonly session: {
336
+ readonly id: string;
337
+ readonly notAfter: bigint;
338
+ };
339
+ /** The injected WASM DKLs share (private package). */
340
+ readonly agent: Mpc2pCoSignAgent;
341
+ /** The injected wss/mTLS frame channel (private package). */
342
+ readonly transport: CoSignTransport;
343
+ /** The injected A3 authenticator (the pre-shared key never enters the SDK). */
344
+ readonly authenticator: CoSignRequestAuthenticator;
345
+ }
346
+ /**
347
+ * Construct an `mpc-2p` (cryptographic) PolicyGatedSigner over injected agent +
348
+ * transport + authenticator.
349
+ *
350
+ * @example
351
+ * ```ts
352
+ * // The agent, transport and authenticator come from the private `kawasekit-mpc-2p`
353
+ * // package (the WASM share, the wss/mTLS client, the HMAC key) — never bundled here.
354
+ * const signer = createMpc2pPolicyGatedSigner({
355
+ * from: groupEoa,
356
+ * asset: { kind: "known", id: "jpyc-v2" },
357
+ * session: { id: "sess-1", notAfter: 2_000_000_000n },
358
+ * agent, transport, authenticator,
359
+ * });
360
+ * requireNonBypassable(signer); // ✓ "cryptographic" — passes the type-gate
361
+ * const result = await signer.sign(intent);
362
+ * ```
363
+ */
364
+ declare function createMpc2pPolicyGatedSigner(params: Mpc2pSignerParams): PolicyGatedSigner<"cryptographic">;
365
+
366
+ export { type CoSignConnection, type CoSignFrame, type CoSignRequestAuthenticator, type CoSignRequestEnvelope, type CoSignTransport, CoSignUnavailableError, type CreateLocalPolicyGatedSignerParams, type Mpc2pCoSignAgent, type Mpc2pSignerParams, type Mpc2pStepOutcome, NonBypassableEnforcement, PaymentIntent, PolicyGatedSigner, PolicyGatedSignerConfigError, WIRE_VERSION, type WireIntent, assertNonBypassable, canonicalRequestBytes, createLocalPolicyGatedSigner, createMpc2pPolicyGatedSigner, requireNonBypassable, toWireIntent };
@@ -1,7 +1,7 @@
1
- import { a as PolicyGatedSigner, N as NonBypassableEnforcement } from '../types-IEl-iOIx.js';
2
- export { E as EnforcementLevel, P as PaymentIntent, b as PolicyRejection, S as SignResult, c as SignerDescription } from '../types-IEl-iOIx.js';
3
- import { Account } from 'viem';
4
- import { a as SpendingPolicy, S as SpendState } from '../spending-policy-DKZN3Sg8.js';
1
+ import { a as PolicyGatedSigner, N as NonBypassableEnforcement, P as PaymentIntent } from '../types-BLJU67HZ.js';
2
+ export { E as EnforcementLevel, b as PolicyRejection, S as SignResult, c as SignerDescription } from '../types-BLJU67HZ.js';
3
+ import { Account, Hex, Address } from 'viem';
4
+ import { a as SpendingPolicy, S as SpendState } from '../spending-policy-BD2Mpm-L.js';
5
5
  import { X as X402AssetParam } from '../asset-domain-4Ioxqn28.js';
6
6
 
7
7
  /**
@@ -39,6 +39,36 @@ declare class PolicyGatedSignerConfigError extends Error {
39
39
  cause?: unknown;
40
40
  });
41
41
  }
42
+ /**
43
+ * Thrown by the `mpc-2p` cryptographic adapter when the co-signer is
44
+ * **unreachable or the ceremony could not complete** — endpoint down, TLS
45
+ * failure, connection dropped mid-ceremony, timeout, a malformed/missing
46
+ * terminal frame, or an internal protocol anomaly. It is a transient / internal
47
+ * error on the throws channel (M6-0: throws are reserved for internal/config
48
+ * errors), **distinct from a policy denial**.
49
+ *
50
+ * This is the **no-silent-fallback** guarantee (RFC m6-3a constraint 3 / W8):
51
+ * the adapter has no local-signing path, so an unavailable wire NEVER yields an
52
+ * `{ ok: true }` signature and NEVER a {@link PolicyRejection}. A `rejection`
53
+ * means "the owner decided no" (audit-meaningful); a `CoSignUnavailableError`
54
+ * means "the owner did not decide" — the caller may retry the *same* intent
55
+ * (the backend's idempotency keeps a retry safe).
56
+ *
57
+ * @example
58
+ * ```ts
59
+ * try {
60
+ * const result = await mpc2pSigner.sign(intent);
61
+ * if (!result.ok) handleDenial(result.rejection); // owner said no
62
+ * } catch (error) {
63
+ * if (error instanceof CoSignUnavailableError) retryLater(); // wire was down
64
+ * }
65
+ * ```
66
+ */
67
+ declare class CoSignUnavailableError extends Error {
68
+ constructor(message: string, options?: {
69
+ cause?: unknown;
70
+ });
71
+ }
42
72
 
43
73
  /**
44
74
  * The enforcement-level type-gate — the compile-time (and runtime) mechanism
@@ -128,4 +158,209 @@ interface CreateLocalPolicyGatedSignerParams {
128
158
  */
129
159
  declare function createLocalPolicyGatedSigner(params: CreateLocalPolicyGatedSignerParams): PolicyGatedSigner<"advisory">;
130
160
 
131
- export { type CreateLocalPolicyGatedSignerParams, NonBypassableEnforcement, PolicyGatedSigner, PolicyGatedSignerConfigError, assertNonBypassable, createLocalPolicyGatedSigner, requireNonBypassable };
161
+ /**
162
+ * The `mpc-2p` cross-process **wire** (v2) — the versioned `CoSignFrame` control
163
+ * envelope + the A3 canonical-request encoding, as TypeScript source-of-truth.
164
+ *
165
+ * This is the public, TS-interpreted half of the two-layer wire (RFC m6-3a §4.2):
166
+ * a small, versioned envelope carries the decoded {@link PaymentIntent} (never a
167
+ * digest — A4) + a per-ceremony id + ssid + a freshness element, plus the opaque
168
+ * DKLs round payloads (hex, produced/consumed only by the WASM crypto agent). The
169
+ * shapes here mirror the deployed `kawasekit-mpc-2p` Rust serde **byte-for-byte**
170
+ * (snake_case `wire_version`, `session_id`, `ceremony_id`, `ssid`, `freshness_ts`,
171
+ * `freshness_nonce`, `auth_tag`; the string-encoded {@link WireIntent}), so a frame
172
+ * the SDK builds round-trips through the backend's `serde_json`.
173
+ *
174
+ * `canonicalRequestBytes` is the A3 analog of the EIP-712 digest corpus: it
175
+ * reproduces the backend's `auth::canonical_request_bytes` exactly, so the injected
176
+ * authenticator's HMAC equals what the co-signer verifies (RFC §4.6:
177
+ * `HMAC_k(wireVersion ‖ ceremonyId ‖ ssid ‖ canonical(intent) ‖ freshness)`).
178
+ *
179
+ * @packageDocumentation
180
+ */
181
+
182
+ /** The wire protocol version. A frame whose `wire_version` differs is rejected. */
183
+ declare const WIRE_VERSION: 2;
184
+ /**
185
+ * The string-encoded EIP-3009 intent as it crosses the wire — lowercase `0x`
186
+ * addresses, **decimal** integer strings, `0x` hex nonce. Decoupled from any
187
+ * library's native serde so a stdlib client reproduces it trivially; matches the
188
+ * Rust `WireIntent` field names + encoding exactly.
189
+ */
190
+ interface WireIntent {
191
+ readonly token: string;
192
+ readonly chain_id: number;
193
+ readonly from: string;
194
+ readonly to: string;
195
+ readonly value: string;
196
+ readonly valid_after: string;
197
+ readonly valid_before: string;
198
+ readonly nonce: string;
199
+ }
200
+ /** Encode a decoded {@link PaymentIntent} for the wire. */
201
+ declare function toWireIntent(intent: PaymentIntent): WireIntent;
202
+ /**
203
+ * The A3 request envelope the adapter generates per `sign()` and authenticates: a
204
+ * per-ceremony id + ssid (bound into the A3 tag) + the intent + a freshness element
205
+ * (a timestamp + a per-request nonce distinct from the EIP-3009 nonce).
206
+ */
207
+ interface CoSignRequestEnvelope {
208
+ readonly ceremonyId: string;
209
+ readonly ssid: string;
210
+ readonly intent: PaymentIntent;
211
+ /** Unix seconds; the backend checks it against a clock-skew window. */
212
+ readonly freshnessTs: number;
213
+ /** `0x` hex, distinct from the EIP-3009 nonce — the anti-replay key. */
214
+ readonly freshnessNonce: Hex;
215
+ }
216
+ /**
217
+ * A versioned control frame: the only cross-language content of the wire. The
218
+ * DKLs round bytes ride opaque inside `payload`; everything else is the small,
219
+ * pinned envelope. Internally tagged by `kind` (matches the Rust serde).
220
+ */
221
+ type CoSignFrame = {
222
+ readonly wire_version: typeof WIRE_VERSION;
223
+ } & ({
224
+ readonly kind: "request";
225
+ readonly session_id: string;
226
+ readonly ceremony_id: string;
227
+ readonly ssid: string;
228
+ readonly intent: WireIntent;
229
+ readonly freshness_ts: number;
230
+ readonly freshness_nonce: Hex;
231
+ /** A3 authenticator over {@link canonicalRequestBytes}, `0x`-hex. */
232
+ readonly auth_tag: Hex;
233
+ } | {
234
+ readonly kind: "round";
235
+ readonly payload: Hex;
236
+ } | {
237
+ readonly kind: "result";
238
+ readonly r: Hex;
239
+ readonly s: Hex;
240
+ readonly v: number;
241
+ } | {
242
+ readonly kind: "rejection";
243
+ readonly reason: string;
244
+ readonly detail: string;
245
+ } | {
246
+ readonly kind: "error";
247
+ readonly message: string;
248
+ });
249
+ /**
250
+ * The A3 canonical encoding of a request — a byte-exact mirror of the backend's
251
+ * `auth::canonical_request_bytes` (domain-tag `kawasekit-mpc-2p/cosign-request/v3`,
252
+ * one `key=value\n` line per field: `wireVersion ‖ ceremonyId ‖ ssid ‖
253
+ * canonical(intent) ‖ freshness`; lowercase `0x` addresses + freshness nonce,
254
+ * decimal integers, trailing newline). The injected authenticator HMACs these
255
+ * bytes; because the encoding is shared, the tag equals the co-signer's.
256
+ */
257
+ declare function canonicalRequestBytes(env: CoSignRequestEnvelope): Uint8Array;
258
+
259
+ /**
260
+ * The `mpc-2p` PolicyGatedSigner adapter — `enforcement: "cryptographic"`.
261
+ *
262
+ * A 2-of-2 MPC co-signer: the agent holds ONE DKLs share, the owner backend holds
263
+ * the other + the authoritative policy gate. No valid signature exists without a
264
+ * **policy-passing co-sign**, so — unlike `local` — a single key-holder cannot
265
+ * bypass the policy. That is what earns the non-bypassable `"cryptographic"` label
266
+ * and lets the M6-0 type-gate (`requireNonBypassable`) reject an advisory signer at
267
+ * compile time in bounded flows.
268
+ *
269
+ * **Open-core / thin adapter.** This module is pure orchestration over injected
270
+ * interfaces — it ships in the public SDK with **no crypto, no socket, no key**:
271
+ *
272
+ * - {@link Mpc2pCoSignAgent} — the WASM DKLs share (the private package's compiled
273
+ * `crypto-core`); drives the agent's half of the ceremony round-by-round.
274
+ * - {@link CoSignTransport} — the authenticated, encrypted (wss/mTLS) frame channel
275
+ * to the owner backend (the private package's transport).
276
+ * - {@link CoSignRequestAuthenticator} — the A3 HMAC (the pre-shared key never
277
+ * enters this module).
278
+ *
279
+ * The adapter owns the protocol: it pins the EIP-712 domain, **re-derives the
280
+ * digest from the intent (A4)** via the shared `transferWithAuthorizationTypes`
281
+ * source-of-truth, computes the A3 canonical bytes, frames the versioned
282
+ * {@link CoSignFrame} envelope, pumps the ceremony, and maps the terminal frame to
283
+ * a {@link SignResult}. Crucially it has **no local-signing path**: any
284
+ * transport/availability failure throws {@link CoSignUnavailableError}, never an
285
+ * `{ ok: true }` and never a {@link PolicyRejection} (the no-silent-fallback
286
+ * guarantee, RFC m6-3a constraint 3 / W8).
287
+ *
288
+ * @packageDocumentation
289
+ */
290
+
291
+ /** The agent's half of the 2-of-2 ceremony (the injected WASM DKLs share). */
292
+ interface Mpc2pCoSignAgent {
293
+ /** The group 2-of-2 EOA this share controls — must equal the signer's `from`. */
294
+ groupEoa(): Address;
295
+ /** Begin signing the 32-byte EIP-712 `digest`; returns the first outbound round (hex). */
296
+ start(digest: Hex): Hex;
297
+ /** Feed one inbound round (hex); returns the next outbound round, or the final signature. */
298
+ step(incoming: Hex): Mpc2pStepOutcome;
299
+ }
300
+ /** The result of one {@link Mpc2pCoSignAgent.step}. */
301
+ type Mpc2pStepOutcome = {
302
+ readonly outbound: Hex;
303
+ } | {
304
+ readonly signature: {
305
+ readonly r: Hex;
306
+ readonly s: Hex;
307
+ readonly v: number;
308
+ };
309
+ };
310
+ /** One authenticated, encrypted ceremony connection to the owner backend. */
311
+ interface CoSignConnection {
312
+ /** Send one control frame. */
313
+ send(frame: CoSignFrame): Promise<void>;
314
+ /** Receive the next control frame (resolves per round). */
315
+ recv(): Promise<CoSignFrame>;
316
+ /** Release the connection (best-effort; errors here are ignored). */
317
+ close(): void | Promise<void>;
318
+ }
319
+ /** Opens a wss/mTLS {@link CoSignConnection} for a single co-sign ceremony. */
320
+ interface CoSignTransport {
321
+ connect(): Promise<CoSignConnection>;
322
+ }
323
+ /** The A3 request authenticator — HMAC (or signature) over the canonical request bytes. */
324
+ interface CoSignRequestAuthenticator {
325
+ /** Authenticator tag over {@link canonicalRequestBytes}; the key stays inside. */
326
+ tag(canonicalRequest: Uint8Array): Hex | Promise<Hex>;
327
+ }
328
+ /** Parameters for {@link createMpc2pPolicyGatedSigner}. */
329
+ interface Mpc2pSignerParams {
330
+ /** The group 2-of-2 EOA; every `intent.from` must equal this (asserted vs the agent). */
331
+ readonly from: Address;
332
+ /** Asset binding — pins the EIP-712 domain `name`/`version`/`verifyingContract` (A4). */
333
+ readonly asset: X402AssetParam;
334
+ /** The bound policy session, for `describe()` (the backend holds the authoritative policy). */
335
+ readonly session: {
336
+ readonly id: string;
337
+ readonly notAfter: bigint;
338
+ };
339
+ /** The injected WASM DKLs share (private package). */
340
+ readonly agent: Mpc2pCoSignAgent;
341
+ /** The injected wss/mTLS frame channel (private package). */
342
+ readonly transport: CoSignTransport;
343
+ /** The injected A3 authenticator (the pre-shared key never enters the SDK). */
344
+ readonly authenticator: CoSignRequestAuthenticator;
345
+ }
346
+ /**
347
+ * Construct an `mpc-2p` (cryptographic) PolicyGatedSigner over injected agent +
348
+ * transport + authenticator.
349
+ *
350
+ * @example
351
+ * ```ts
352
+ * // The agent, transport and authenticator come from the private `kawasekit-mpc-2p`
353
+ * // package (the WASM share, the wss/mTLS client, the HMAC key) — never bundled here.
354
+ * const signer = createMpc2pPolicyGatedSigner({
355
+ * from: groupEoa,
356
+ * asset: { kind: "known", id: "jpyc-v2" },
357
+ * session: { id: "sess-1", notAfter: 2_000_000_000n },
358
+ * agent, transport, authenticator,
359
+ * });
360
+ * requireNonBypassable(signer); // ✓ "cryptographic" — passes the type-gate
361
+ * const result = await signer.sign(intent);
362
+ * ```
363
+ */
364
+ declare function createMpc2pPolicyGatedSigner(params: Mpc2pSignerParams): PolicyGatedSigner<"cryptographic">;
365
+
366
+ export { type CoSignConnection, type CoSignFrame, type CoSignRequestAuthenticator, type CoSignRequestEnvelope, type CoSignTransport, CoSignUnavailableError, type CreateLocalPolicyGatedSignerParams, type Mpc2pCoSignAgent, type Mpc2pSignerParams, type Mpc2pStepOutcome, NonBypassableEnforcement, PaymentIntent, PolicyGatedSigner, PolicyGatedSignerConfigError, WIRE_VERSION, type WireIntent, assertNonBypassable, canonicalRequestBytes, createLocalPolicyGatedSigner, createMpc2pPolicyGatedSigner, requireNonBypassable, toWireIntent };
@@ -1,5 +1,5 @@
1
- export { createLocalPolicyGatedSigner } from '../chunk-THTVJZ2Q.js';
2
- export { PolicyGatedSignerConfigError, assertNonBypassable, requireNonBypassable } from '../chunk-VXZHS74W.js';
1
+ export { WIRE_VERSION, canonicalRequestBytes, createLocalPolicyGatedSigner, createMpc2pPolicyGatedSigner, toWireIntent } from '../chunk-FD6Q4NB2.js';
2
+ export { CoSignUnavailableError, PolicyGatedSignerConfigError, assertNonBypassable, requireNonBypassable } from '../chunk-5TTOAVHE.js';
3
3
  import '../chunk-WMVJNPX2.js';
4
4
  import '../chunk-6CNAYQOL.js';
5
5
  import '../chunk-KT7XDT2T.js';
@@ -1,5 +1,5 @@
1
1
  import { Address } from 'viem';
2
- import { b as PolicyRejection, P as PaymentIntent } from './types-IEl-iOIx.js';
2
+ import { b as PolicyRejection, P as PaymentIntent } from './types-BLJU67HZ.js';
3
3
 
4
4
  /**
5
5
  * Spending policy — policy-as-data for the x402 / EIP-3009 PolicyGatedSigner
@@ -1,5 +1,5 @@
1
1
  import { Address } from 'viem';
2
- import { b as PolicyRejection, P as PaymentIntent } from './types-IEl-iOIx.cjs';
2
+ import { b as PolicyRejection, P as PaymentIntent } from './types-BLJU67HZ.cjs';
3
3
 
4
4
  /**
5
5
  * Spending policy — policy-as-data for the x402 / EIP-3009 PolicyGatedSigner
@@ -77,11 +77,19 @@ interface PaymentIntent {
77
77
  * The evaluator (`evaluateSpendingPolicy`) emits the `revoked` / `expired` /
78
78
  * `token_not_allowed` / `recipient_not_allowed` / `amount_exceeds_*` reasons;
79
79
  * the adapter additionally emits `from_mismatch` and (for `mpc-2p`)
80
- * `intent_digest_mismatch` / `unauthenticated`. The consumer handles one
81
- * `SignResult` regardless of adapter.
80
+ * `intent_digest_mismatch` / `unauthenticated` / `nonce_reuse_conflict`. The
81
+ * consumer handles one `SignResult` regardless of adapter.
82
82
  */
83
83
  interface PolicyRejection {
84
- readonly reason: "revoked" | "expired" | "token_not_allowed" | "recipient_not_allowed" | "amount_exceeds_per_sign" | "amount_exceeds_cumulative" | "intent_digest_mismatch" | "unauthenticated" | "from_mismatch";
84
+ readonly reason: "revoked" | "expired" | "token_not_allowed" | "recipient_not_allowed" | "amount_exceeds_per_sign" | "amount_exceeds_cumulative" | "intent_digest_mismatch" | "unauthenticated" | "from_mismatch"
85
+ /**
86
+ * (`mpc-2p`) The co-signer was presented a **previously-seen EIP-3009
87
+ * nonce with different intent fields** — the B7 same-nonce/different-fields
88
+ * fund-correctness anomaly. The backend denies + audits it; double-pay
89
+ * protection (same nonce, same fields → cached result) is a separate,
90
+ * non-rejection path (M5 `deriveAuthorizationNonce` + `authorizationState`).
91
+ */
92
+ | "nonce_reuse_conflict";
85
93
  /** Human-readable reason; never contains the nonce or a signature. */
86
94
  readonly detail: string;
87
95
  }
@@ -77,11 +77,19 @@ interface PaymentIntent {
77
77
  * The evaluator (`evaluateSpendingPolicy`) emits the `revoked` / `expired` /
78
78
  * `token_not_allowed` / `recipient_not_allowed` / `amount_exceeds_*` reasons;
79
79
  * the adapter additionally emits `from_mismatch` and (for `mpc-2p`)
80
- * `intent_digest_mismatch` / `unauthenticated`. The consumer handles one
81
- * `SignResult` regardless of adapter.
80
+ * `intent_digest_mismatch` / `unauthenticated` / `nonce_reuse_conflict`. The
81
+ * consumer handles one `SignResult` regardless of adapter.
82
82
  */
83
83
  interface PolicyRejection {
84
- readonly reason: "revoked" | "expired" | "token_not_allowed" | "recipient_not_allowed" | "amount_exceeds_per_sign" | "amount_exceeds_cumulative" | "intent_digest_mismatch" | "unauthenticated" | "from_mismatch";
84
+ readonly reason: "revoked" | "expired" | "token_not_allowed" | "recipient_not_allowed" | "amount_exceeds_per_sign" | "amount_exceeds_cumulative" | "intent_digest_mismatch" | "unauthenticated" | "from_mismatch"
85
+ /**
86
+ * (`mpc-2p`) The co-signer was presented a **previously-seen EIP-3009
87
+ * nonce with different intent fields** — the B7 same-nonce/different-fields
88
+ * fund-correctness anomaly. The backend denies + audits it; double-pay
89
+ * protection (same nonce, same fields → cached result) is a separate,
90
+ * non-rejection path (M5 `deriveAuthorizationNonce` + `authorizationState`).
91
+ */
92
+ | "nonce_reuse_conflict";
85
93
  /** Human-readable reason; never contains the nonce or a signature. */
86
94
  readonly detail: string;
87
95
  }