kawasekit 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-G3UC6SME.js → chunk-P5563RGP.js} +3 -3
- package/dist/{chunk-G3UC6SME.js.map → chunk-P5563RGP.js.map} +1 -1
- package/dist/{chunk-EUW7AZ4P.js → chunk-S2ZSX2VS.js} +158 -36
- package/dist/chunk-S2ZSX2VS.js.map +1 -0
- package/dist/{chunk-5TTOAVHE.js → chunk-VJUXTVSW.js} +11 -3
- package/dist/chunk-VJUXTVSW.js.map +1 -0
- package/dist/cli/index.cjs +1 -1
- package/dist/cli/index.js +4 -4
- package/dist/index.cjs +163 -33
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -3
- package/dist/signer/index.cjs +164 -33
- package/dist/signer/index.cjs.map +1 -1
- package/dist/signer/index.d.cts +96 -20
- package/dist/signer/index.d.ts +96 -20
- package/dist/signer/index.js +2 -2
- package/dist/x402/index.cjs.map +1 -1
- package/dist/x402/index.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-5TTOAVHE.js.map +0 -1
- package/dist/chunk-EUW7AZ4P.js.map +0 -1
package/dist/signer/index.d.cts
CHANGED
|
@@ -65,8 +65,16 @@ declare class PolicyGatedSignerConfigError extends Error {
|
|
|
65
65
|
* ```
|
|
66
66
|
*/
|
|
67
67
|
declare class CoSignUnavailableError extends Error {
|
|
68
|
+
/**
|
|
69
|
+
* `true` when the failure is the **transient transport class** (connect failed /
|
|
70
|
+
* connection dropped) — the only class the adapter's bounded retry replays
|
|
71
|
+
* (RFC m6-3a §4.7: never a delivered rejection, never a ban/identifiable-abort,
|
|
72
|
+
* never a protocol anomaly or timeout). Defaults to `false`.
|
|
73
|
+
*/
|
|
74
|
+
readonly transient: boolean;
|
|
68
75
|
constructor(message: string, options?: {
|
|
69
76
|
cause?: unknown;
|
|
77
|
+
transient?: boolean;
|
|
70
78
|
});
|
|
71
79
|
}
|
|
72
80
|
|
|
@@ -159,27 +167,37 @@ interface CreateLocalPolicyGatedSignerParams {
|
|
|
159
167
|
declare function createLocalPolicyGatedSigner(params: CreateLocalPolicyGatedSignerParams): PolicyGatedSigner<"advisory">;
|
|
160
168
|
|
|
161
169
|
/**
|
|
162
|
-
* The `mpc-2p` cross-process **wire** — the versioned `CoSignFrame` control
|
|
170
|
+
* The `mpc-2p` cross-process **wire** (v2) — the versioned `CoSignFrame` control
|
|
163
171
|
* envelope + the A3 canonical-request encoding, as TypeScript source-of-truth.
|
|
164
172
|
*
|
|
165
173
|
* This is the public, TS-interpreted half of the two-layer wire (RFC m6-3a §4.2):
|
|
166
174
|
* a small, versioned envelope carries the decoded {@link PaymentIntent} (never a
|
|
167
|
-
* digest — A4)
|
|
168
|
-
* by the WASM crypto agent). The
|
|
169
|
-
* `kawasekit-mpc-2p` Rust serde **byte-for-byte**
|
|
170
|
-
* `session_id`, `
|
|
171
|
-
*
|
|
172
|
-
*
|
|
175
|
+
* digest — A4) + a per-ceremony id + ssid + a freshness element, plus the opaque
|
|
176
|
+
* DKLs round payloads (hex, produced/consumed only by the WASM crypto agent). The
|
|
177
|
+
* shapes here mirror the deployed `kawasekit-mpc-2p` Rust serde **byte-for-byte**
|
|
178
|
+
* (snake_case `wire_version`, `session_id`, `ceremony_id`, `ssid`, `freshness_ts`,
|
|
179
|
+
* `freshness_nonce`, `auth_tag`; the string-encoded {@link WireIntent}), so a frame
|
|
180
|
+
* the SDK builds round-trips through the backend's `serde_json`.
|
|
173
181
|
*
|
|
174
|
-
* `
|
|
175
|
-
* reproduces the backend's `auth::
|
|
176
|
-
*
|
|
182
|
+
* `canonicalRequestBytes` is the A3 analog of the EIP-712 digest corpus: it
|
|
183
|
+
* reproduces the backend's `auth::canonical_request_bytes` exactly, so the injected
|
|
184
|
+
* authenticator's HMAC equals what the co-signer verifies (RFC §4.6:
|
|
185
|
+
* `HMAC_k(wireVersion ‖ ceremonyId ‖ ssid ‖ canonical(intent) ‖ freshness)`).
|
|
177
186
|
*
|
|
178
187
|
* @packageDocumentation
|
|
179
188
|
*/
|
|
180
189
|
|
|
181
190
|
/** The wire protocol version. A frame whose `wire_version` differs is rejected. */
|
|
182
|
-
declare const WIRE_VERSION:
|
|
191
|
+
declare const WIRE_VERSION: 2;
|
|
192
|
+
/**
|
|
193
|
+
* The inbound round-payload bound, in bytes — mirrors the backend's
|
|
194
|
+
* `crypto-core/src/transport.rs` `MAX_FRAME_BYTES` (8 MiB) so the agent side
|
|
195
|
+
* enforces the same pre-decode cap the backend does (RFC m6-3a §4.2/M3). The
|
|
196
|
+
* adapter refuses an over-bound `round` payload **before** hex-decoding it into
|
|
197
|
+
* the WASM boundary; the private transport should additionally cap raw
|
|
198
|
+
* websocket messages (e.g. the `ws` client's `maxPayload`).
|
|
199
|
+
*/
|
|
200
|
+
declare const MAX_FRAME_BYTES: number;
|
|
183
201
|
/**
|
|
184
202
|
* The string-encoded EIP-3009 intent as it crosses the wire — lowercase `0x`
|
|
185
203
|
* addresses, **decimal** integer strings, `0x` hex nonce. Decoupled from any
|
|
@@ -198,6 +216,20 @@ interface WireIntent {
|
|
|
198
216
|
}
|
|
199
217
|
/** Encode a decoded {@link PaymentIntent} for the wire. */
|
|
200
218
|
declare function toWireIntent(intent: PaymentIntent): WireIntent;
|
|
219
|
+
/**
|
|
220
|
+
* The A3 request envelope the adapter generates per `sign()` and authenticates: a
|
|
221
|
+
* per-ceremony id + ssid (bound into the A3 tag) + the intent + a freshness element
|
|
222
|
+
* (a timestamp + a per-request nonce distinct from the EIP-3009 nonce).
|
|
223
|
+
*/
|
|
224
|
+
interface CoSignRequestEnvelope {
|
|
225
|
+
readonly ceremonyId: string;
|
|
226
|
+
readonly ssid: string;
|
|
227
|
+
readonly intent: PaymentIntent;
|
|
228
|
+
/** Unix seconds; the backend checks it against a clock-skew window. */
|
|
229
|
+
readonly freshnessTs: number;
|
|
230
|
+
/** `0x` hex, distinct from the EIP-3009 nonce — the anti-replay key. */
|
|
231
|
+
readonly freshnessNonce: Hex;
|
|
232
|
+
}
|
|
201
233
|
/**
|
|
202
234
|
* A versioned control frame: the only cross-language content of the wire. The
|
|
203
235
|
* DKLs round bytes ride opaque inside `payload`; everything else is the small,
|
|
@@ -208,8 +240,12 @@ type CoSignFrame = {
|
|
|
208
240
|
} & ({
|
|
209
241
|
readonly kind: "request";
|
|
210
242
|
readonly session_id: string;
|
|
243
|
+
readonly ceremony_id: string;
|
|
244
|
+
readonly ssid: string;
|
|
211
245
|
readonly intent: WireIntent;
|
|
212
|
-
|
|
246
|
+
readonly freshness_ts: number;
|
|
247
|
+
readonly freshness_nonce: Hex;
|
|
248
|
+
/** A3 authenticator over {@link canonicalRequestBytes}, `0x`-hex. */
|
|
213
249
|
readonly auth_tag: Hex;
|
|
214
250
|
} | {
|
|
215
251
|
readonly kind: "round";
|
|
@@ -228,13 +264,14 @@ type CoSignFrame = {
|
|
|
228
264
|
readonly message: string;
|
|
229
265
|
});
|
|
230
266
|
/**
|
|
231
|
-
* The A3 canonical encoding of
|
|
232
|
-
* `auth::
|
|
233
|
-
* one `key=value\n` line per field
|
|
234
|
-
*
|
|
235
|
-
*
|
|
267
|
+
* The A3 canonical encoding of a request — a byte-exact mirror of the backend's
|
|
268
|
+
* `auth::canonical_request_bytes` (domain-tag `kawasekit-mpc-2p/cosign-request/v3`,
|
|
269
|
+
* one `key=value\n` line per field: `wireVersion ‖ ceremonyId ‖ ssid ‖
|
|
270
|
+
* canonical(intent) ‖ freshness`; lowercase `0x` addresses + freshness nonce,
|
|
271
|
+
* decimal integers, trailing newline). The injected authenticator HMACs these
|
|
272
|
+
* bytes; because the encoding is shared, the tag equals the co-signer's.
|
|
236
273
|
*/
|
|
237
|
-
declare function
|
|
274
|
+
declare function canonicalRequestBytes(env: CoSignRequestEnvelope): Uint8Array;
|
|
238
275
|
|
|
239
276
|
/**
|
|
240
277
|
* The `mpc-2p` PolicyGatedSigner adapter — `enforcement: "cryptographic"`.
|
|
@@ -265,6 +302,14 @@ declare function canonicalIntentBytes(intent: PaymentIntent): Uint8Array;
|
|
|
265
302
|
* `{ ok: true }` and never a {@link PolicyRejection} (the no-silent-fallback
|
|
266
303
|
* guarantee, RFC m6-3a constraint 3 / W8).
|
|
267
304
|
*
|
|
305
|
+
* **Wire hardening (RFC §4.7/§4.8, Track C):** a bounded **transient-only retry**
|
|
306
|
+
* replays the byte-identical intent (nonce included — idempotency-by-nonce is the
|
|
307
|
+
* safety net) under a fresh A3 envelope and accepts the backend's **roundless
|
|
308
|
+
* idempotent-replay result** via an ecrecover/low-S self-check; the **ceremony
|
|
309
|
+
* deadline always fires before `validBefore`** (minus a clock-skew budget, W11),
|
|
310
|
+
* and inbound round payloads are **bounded** before the WASM boundary (M3). Tuning
|
|
311
|
+
* via {@link Mpc2pWireOptions}.
|
|
312
|
+
*
|
|
268
313
|
* @packageDocumentation
|
|
269
314
|
*/
|
|
270
315
|
|
|
@@ -302,9 +347,38 @@ interface CoSignTransport {
|
|
|
302
347
|
}
|
|
303
348
|
/** The A3 request authenticator — HMAC (or signature) over the canonical request bytes. */
|
|
304
349
|
interface CoSignRequestAuthenticator {
|
|
305
|
-
/** Authenticator tag over {@link
|
|
350
|
+
/** Authenticator tag over {@link canonicalRequestBytes}; the key stays inside. */
|
|
306
351
|
tag(canonicalRequest: Uint8Array): Hex | Promise<Hex>;
|
|
307
352
|
}
|
|
353
|
+
/**
|
|
354
|
+
* Wire liveness / retry tuning (RFC m6-3a §4.7 + §4.8). Every field is optional
|
|
355
|
+
* with a safe default. The invariants these enforce:
|
|
356
|
+
*
|
|
357
|
+
* - **Retry (4b/H2):** only the **transient transport class** is retried (connect
|
|
358
|
+
* failed / connection dropped), replaying the **byte-identical intent** — nonce
|
|
359
|
+
* included, so the backend's idempotency-by-nonce is the safety net — under a
|
|
360
|
+
* fresh A3 envelope (the freshness guard rejects a replayed envelope by design).
|
|
361
|
+
* A delivered rejection, a ban/identifiable-abort, a protocol anomaly, or a
|
|
362
|
+
* timeout is never retried.
|
|
363
|
+
* - **Liveness (4c/W11/M1+M3):** the ceremony deadline always fires **before**
|
|
364
|
+
* `intent.validBefore − clockSkewBudgetSecs` (a co-signature must never be born
|
|
365
|
+
* expired), and a `sign()` whose remaining window is under
|
|
366
|
+
* `minWindowSecs + clockSkewBudgetSecs` is refused up front.
|
|
367
|
+
* - **Inbound bound (4c/M3):** a `round` payload over `maxFrameBytes` is refused
|
|
368
|
+
* before it reaches the WASM boundary (mirrors the backend's bound).
|
|
369
|
+
*/
|
|
370
|
+
interface Mpc2pWireOptions {
|
|
371
|
+
/** Max ceremony attempts for transient transport failures (default 2 = one retry). */
|
|
372
|
+
readonly maxAttempts?: number;
|
|
373
|
+
/** Overall per-`sign()` budget in ms, across ALL attempts (default 30_000). */
|
|
374
|
+
readonly ceremonyTimeoutMs?: number;
|
|
375
|
+
/** Minimum remaining validity window required at `sign()` start, in seconds (default 30). */
|
|
376
|
+
readonly minWindowSecs?: number;
|
|
377
|
+
/** Max tolerated agent-host clock skew, in seconds (default 30). */
|
|
378
|
+
readonly clockSkewBudgetSecs?: number;
|
|
379
|
+
/** Inbound round-payload bound in bytes (default {@link MAX_FRAME_BYTES} = 8 MiB). */
|
|
380
|
+
readonly maxFrameBytes?: number;
|
|
381
|
+
}
|
|
308
382
|
/** Parameters for {@link createMpc2pPolicyGatedSigner}. */
|
|
309
383
|
interface Mpc2pSignerParams {
|
|
310
384
|
/** The group 2-of-2 EOA; every `intent.from` must equal this (asserted vs the agent). */
|
|
@@ -322,6 +396,8 @@ interface Mpc2pSignerParams {
|
|
|
322
396
|
readonly transport: CoSignTransport;
|
|
323
397
|
/** The injected A3 authenticator (the pre-shared key never enters the SDK). */
|
|
324
398
|
readonly authenticator: CoSignRequestAuthenticator;
|
|
399
|
+
/** Wire liveness / retry tuning (optional; safe defaults — {@link Mpc2pWireOptions}). */
|
|
400
|
+
readonly wire?: Mpc2pWireOptions;
|
|
325
401
|
}
|
|
326
402
|
/**
|
|
327
403
|
* Construct an `mpc-2p` (cryptographic) PolicyGatedSigner over injected agent +
|
|
@@ -343,4 +419,4 @@ interface Mpc2pSignerParams {
|
|
|
343
419
|
*/
|
|
344
420
|
declare function createMpc2pPolicyGatedSigner(params: Mpc2pSignerParams): PolicyGatedSigner<"cryptographic">;
|
|
345
421
|
|
|
346
|
-
export { type CoSignConnection, type CoSignFrame, type CoSignRequestAuthenticator, type CoSignTransport, CoSignUnavailableError, type CreateLocalPolicyGatedSignerParams, type Mpc2pCoSignAgent, type Mpc2pSignerParams, type Mpc2pStepOutcome, NonBypassableEnforcement, PaymentIntent, PolicyGatedSigner, PolicyGatedSignerConfigError, WIRE_VERSION, type WireIntent, assertNonBypassable,
|
|
422
|
+
export { type CoSignConnection, type CoSignFrame, type CoSignRequestAuthenticator, type CoSignRequestEnvelope, type CoSignTransport, CoSignUnavailableError, type CreateLocalPolicyGatedSignerParams, MAX_FRAME_BYTES, type Mpc2pCoSignAgent, type Mpc2pSignerParams, type Mpc2pStepOutcome, type Mpc2pWireOptions, NonBypassableEnforcement, PaymentIntent, PolicyGatedSigner, PolicyGatedSignerConfigError, WIRE_VERSION, type WireIntent, assertNonBypassable, canonicalRequestBytes, createLocalPolicyGatedSigner, createMpc2pPolicyGatedSigner, requireNonBypassable, toWireIntent };
|
package/dist/signer/index.d.ts
CHANGED
|
@@ -65,8 +65,16 @@ declare class PolicyGatedSignerConfigError extends Error {
|
|
|
65
65
|
* ```
|
|
66
66
|
*/
|
|
67
67
|
declare class CoSignUnavailableError extends Error {
|
|
68
|
+
/**
|
|
69
|
+
* `true` when the failure is the **transient transport class** (connect failed /
|
|
70
|
+
* connection dropped) — the only class the adapter's bounded retry replays
|
|
71
|
+
* (RFC m6-3a §4.7: never a delivered rejection, never a ban/identifiable-abort,
|
|
72
|
+
* never a protocol anomaly or timeout). Defaults to `false`.
|
|
73
|
+
*/
|
|
74
|
+
readonly transient: boolean;
|
|
68
75
|
constructor(message: string, options?: {
|
|
69
76
|
cause?: unknown;
|
|
77
|
+
transient?: boolean;
|
|
70
78
|
});
|
|
71
79
|
}
|
|
72
80
|
|
|
@@ -159,27 +167,37 @@ interface CreateLocalPolicyGatedSignerParams {
|
|
|
159
167
|
declare function createLocalPolicyGatedSigner(params: CreateLocalPolicyGatedSignerParams): PolicyGatedSigner<"advisory">;
|
|
160
168
|
|
|
161
169
|
/**
|
|
162
|
-
* The `mpc-2p` cross-process **wire** — the versioned `CoSignFrame` control
|
|
170
|
+
* The `mpc-2p` cross-process **wire** (v2) — the versioned `CoSignFrame` control
|
|
163
171
|
* envelope + the A3 canonical-request encoding, as TypeScript source-of-truth.
|
|
164
172
|
*
|
|
165
173
|
* This is the public, TS-interpreted half of the two-layer wire (RFC m6-3a §4.2):
|
|
166
174
|
* a small, versioned envelope carries the decoded {@link PaymentIntent} (never a
|
|
167
|
-
* digest — A4)
|
|
168
|
-
* by the WASM crypto agent). The
|
|
169
|
-
* `kawasekit-mpc-2p` Rust serde **byte-for-byte**
|
|
170
|
-
* `session_id`, `
|
|
171
|
-
*
|
|
172
|
-
*
|
|
175
|
+
* digest — A4) + a per-ceremony id + ssid + a freshness element, plus the opaque
|
|
176
|
+
* DKLs round payloads (hex, produced/consumed only by the WASM crypto agent). The
|
|
177
|
+
* shapes here mirror the deployed `kawasekit-mpc-2p` Rust serde **byte-for-byte**
|
|
178
|
+
* (snake_case `wire_version`, `session_id`, `ceremony_id`, `ssid`, `freshness_ts`,
|
|
179
|
+
* `freshness_nonce`, `auth_tag`; the string-encoded {@link WireIntent}), so a frame
|
|
180
|
+
* the SDK builds round-trips through the backend's `serde_json`.
|
|
173
181
|
*
|
|
174
|
-
* `
|
|
175
|
-
* reproduces the backend's `auth::
|
|
176
|
-
*
|
|
182
|
+
* `canonicalRequestBytes` is the A3 analog of the EIP-712 digest corpus: it
|
|
183
|
+
* reproduces the backend's `auth::canonical_request_bytes` exactly, so the injected
|
|
184
|
+
* authenticator's HMAC equals what the co-signer verifies (RFC §4.6:
|
|
185
|
+
* `HMAC_k(wireVersion ‖ ceremonyId ‖ ssid ‖ canonical(intent) ‖ freshness)`).
|
|
177
186
|
*
|
|
178
187
|
* @packageDocumentation
|
|
179
188
|
*/
|
|
180
189
|
|
|
181
190
|
/** The wire protocol version. A frame whose `wire_version` differs is rejected. */
|
|
182
|
-
declare const WIRE_VERSION:
|
|
191
|
+
declare const WIRE_VERSION: 2;
|
|
192
|
+
/**
|
|
193
|
+
* The inbound round-payload bound, in bytes — mirrors the backend's
|
|
194
|
+
* `crypto-core/src/transport.rs` `MAX_FRAME_BYTES` (8 MiB) so the agent side
|
|
195
|
+
* enforces the same pre-decode cap the backend does (RFC m6-3a §4.2/M3). The
|
|
196
|
+
* adapter refuses an over-bound `round` payload **before** hex-decoding it into
|
|
197
|
+
* the WASM boundary; the private transport should additionally cap raw
|
|
198
|
+
* websocket messages (e.g. the `ws` client's `maxPayload`).
|
|
199
|
+
*/
|
|
200
|
+
declare const MAX_FRAME_BYTES: number;
|
|
183
201
|
/**
|
|
184
202
|
* The string-encoded EIP-3009 intent as it crosses the wire — lowercase `0x`
|
|
185
203
|
* addresses, **decimal** integer strings, `0x` hex nonce. Decoupled from any
|
|
@@ -198,6 +216,20 @@ interface WireIntent {
|
|
|
198
216
|
}
|
|
199
217
|
/** Encode a decoded {@link PaymentIntent} for the wire. */
|
|
200
218
|
declare function toWireIntent(intent: PaymentIntent): WireIntent;
|
|
219
|
+
/**
|
|
220
|
+
* The A3 request envelope the adapter generates per `sign()` and authenticates: a
|
|
221
|
+
* per-ceremony id + ssid (bound into the A3 tag) + the intent + a freshness element
|
|
222
|
+
* (a timestamp + a per-request nonce distinct from the EIP-3009 nonce).
|
|
223
|
+
*/
|
|
224
|
+
interface CoSignRequestEnvelope {
|
|
225
|
+
readonly ceremonyId: string;
|
|
226
|
+
readonly ssid: string;
|
|
227
|
+
readonly intent: PaymentIntent;
|
|
228
|
+
/** Unix seconds; the backend checks it against a clock-skew window. */
|
|
229
|
+
readonly freshnessTs: number;
|
|
230
|
+
/** `0x` hex, distinct from the EIP-3009 nonce — the anti-replay key. */
|
|
231
|
+
readonly freshnessNonce: Hex;
|
|
232
|
+
}
|
|
201
233
|
/**
|
|
202
234
|
* A versioned control frame: the only cross-language content of the wire. The
|
|
203
235
|
* DKLs round bytes ride opaque inside `payload`; everything else is the small,
|
|
@@ -208,8 +240,12 @@ type CoSignFrame = {
|
|
|
208
240
|
} & ({
|
|
209
241
|
readonly kind: "request";
|
|
210
242
|
readonly session_id: string;
|
|
243
|
+
readonly ceremony_id: string;
|
|
244
|
+
readonly ssid: string;
|
|
211
245
|
readonly intent: WireIntent;
|
|
212
|
-
|
|
246
|
+
readonly freshness_ts: number;
|
|
247
|
+
readonly freshness_nonce: Hex;
|
|
248
|
+
/** A3 authenticator over {@link canonicalRequestBytes}, `0x`-hex. */
|
|
213
249
|
readonly auth_tag: Hex;
|
|
214
250
|
} | {
|
|
215
251
|
readonly kind: "round";
|
|
@@ -228,13 +264,14 @@ type CoSignFrame = {
|
|
|
228
264
|
readonly message: string;
|
|
229
265
|
});
|
|
230
266
|
/**
|
|
231
|
-
* The A3 canonical encoding of
|
|
232
|
-
* `auth::
|
|
233
|
-
* one `key=value\n` line per field
|
|
234
|
-
*
|
|
235
|
-
*
|
|
267
|
+
* The A3 canonical encoding of a request — a byte-exact mirror of the backend's
|
|
268
|
+
* `auth::canonical_request_bytes` (domain-tag `kawasekit-mpc-2p/cosign-request/v3`,
|
|
269
|
+
* one `key=value\n` line per field: `wireVersion ‖ ceremonyId ‖ ssid ‖
|
|
270
|
+
* canonical(intent) ‖ freshness`; lowercase `0x` addresses + freshness nonce,
|
|
271
|
+
* decimal integers, trailing newline). The injected authenticator HMACs these
|
|
272
|
+
* bytes; because the encoding is shared, the tag equals the co-signer's.
|
|
236
273
|
*/
|
|
237
|
-
declare function
|
|
274
|
+
declare function canonicalRequestBytes(env: CoSignRequestEnvelope): Uint8Array;
|
|
238
275
|
|
|
239
276
|
/**
|
|
240
277
|
* The `mpc-2p` PolicyGatedSigner adapter — `enforcement: "cryptographic"`.
|
|
@@ -265,6 +302,14 @@ declare function canonicalIntentBytes(intent: PaymentIntent): Uint8Array;
|
|
|
265
302
|
* `{ ok: true }` and never a {@link PolicyRejection} (the no-silent-fallback
|
|
266
303
|
* guarantee, RFC m6-3a constraint 3 / W8).
|
|
267
304
|
*
|
|
305
|
+
* **Wire hardening (RFC §4.7/§4.8, Track C):** a bounded **transient-only retry**
|
|
306
|
+
* replays the byte-identical intent (nonce included — idempotency-by-nonce is the
|
|
307
|
+
* safety net) under a fresh A3 envelope and accepts the backend's **roundless
|
|
308
|
+
* idempotent-replay result** via an ecrecover/low-S self-check; the **ceremony
|
|
309
|
+
* deadline always fires before `validBefore`** (minus a clock-skew budget, W11),
|
|
310
|
+
* and inbound round payloads are **bounded** before the WASM boundary (M3). Tuning
|
|
311
|
+
* via {@link Mpc2pWireOptions}.
|
|
312
|
+
*
|
|
268
313
|
* @packageDocumentation
|
|
269
314
|
*/
|
|
270
315
|
|
|
@@ -302,9 +347,38 @@ interface CoSignTransport {
|
|
|
302
347
|
}
|
|
303
348
|
/** The A3 request authenticator — HMAC (or signature) over the canonical request bytes. */
|
|
304
349
|
interface CoSignRequestAuthenticator {
|
|
305
|
-
/** Authenticator tag over {@link
|
|
350
|
+
/** Authenticator tag over {@link canonicalRequestBytes}; the key stays inside. */
|
|
306
351
|
tag(canonicalRequest: Uint8Array): Hex | Promise<Hex>;
|
|
307
352
|
}
|
|
353
|
+
/**
|
|
354
|
+
* Wire liveness / retry tuning (RFC m6-3a §4.7 + §4.8). Every field is optional
|
|
355
|
+
* with a safe default. The invariants these enforce:
|
|
356
|
+
*
|
|
357
|
+
* - **Retry (4b/H2):** only the **transient transport class** is retried (connect
|
|
358
|
+
* failed / connection dropped), replaying the **byte-identical intent** — nonce
|
|
359
|
+
* included, so the backend's idempotency-by-nonce is the safety net — under a
|
|
360
|
+
* fresh A3 envelope (the freshness guard rejects a replayed envelope by design).
|
|
361
|
+
* A delivered rejection, a ban/identifiable-abort, a protocol anomaly, or a
|
|
362
|
+
* timeout is never retried.
|
|
363
|
+
* - **Liveness (4c/W11/M1+M3):** the ceremony deadline always fires **before**
|
|
364
|
+
* `intent.validBefore − clockSkewBudgetSecs` (a co-signature must never be born
|
|
365
|
+
* expired), and a `sign()` whose remaining window is under
|
|
366
|
+
* `minWindowSecs + clockSkewBudgetSecs` is refused up front.
|
|
367
|
+
* - **Inbound bound (4c/M3):** a `round` payload over `maxFrameBytes` is refused
|
|
368
|
+
* before it reaches the WASM boundary (mirrors the backend's bound).
|
|
369
|
+
*/
|
|
370
|
+
interface Mpc2pWireOptions {
|
|
371
|
+
/** Max ceremony attempts for transient transport failures (default 2 = one retry). */
|
|
372
|
+
readonly maxAttempts?: number;
|
|
373
|
+
/** Overall per-`sign()` budget in ms, across ALL attempts (default 30_000). */
|
|
374
|
+
readonly ceremonyTimeoutMs?: number;
|
|
375
|
+
/** Minimum remaining validity window required at `sign()` start, in seconds (default 30). */
|
|
376
|
+
readonly minWindowSecs?: number;
|
|
377
|
+
/** Max tolerated agent-host clock skew, in seconds (default 30). */
|
|
378
|
+
readonly clockSkewBudgetSecs?: number;
|
|
379
|
+
/** Inbound round-payload bound in bytes (default {@link MAX_FRAME_BYTES} = 8 MiB). */
|
|
380
|
+
readonly maxFrameBytes?: number;
|
|
381
|
+
}
|
|
308
382
|
/** Parameters for {@link createMpc2pPolicyGatedSigner}. */
|
|
309
383
|
interface Mpc2pSignerParams {
|
|
310
384
|
/** The group 2-of-2 EOA; every `intent.from` must equal this (asserted vs the agent). */
|
|
@@ -322,6 +396,8 @@ interface Mpc2pSignerParams {
|
|
|
322
396
|
readonly transport: CoSignTransport;
|
|
323
397
|
/** The injected A3 authenticator (the pre-shared key never enters the SDK). */
|
|
324
398
|
readonly authenticator: CoSignRequestAuthenticator;
|
|
399
|
+
/** Wire liveness / retry tuning (optional; safe defaults — {@link Mpc2pWireOptions}). */
|
|
400
|
+
readonly wire?: Mpc2pWireOptions;
|
|
325
401
|
}
|
|
326
402
|
/**
|
|
327
403
|
* Construct an `mpc-2p` (cryptographic) PolicyGatedSigner over injected agent +
|
|
@@ -343,4 +419,4 @@ interface Mpc2pSignerParams {
|
|
|
343
419
|
*/
|
|
344
420
|
declare function createMpc2pPolicyGatedSigner(params: Mpc2pSignerParams): PolicyGatedSigner<"cryptographic">;
|
|
345
421
|
|
|
346
|
-
export { type CoSignConnection, type CoSignFrame, type CoSignRequestAuthenticator, type CoSignTransport, CoSignUnavailableError, type CreateLocalPolicyGatedSignerParams, type Mpc2pCoSignAgent, type Mpc2pSignerParams, type Mpc2pStepOutcome, NonBypassableEnforcement, PaymentIntent, PolicyGatedSigner, PolicyGatedSignerConfigError, WIRE_VERSION, type WireIntent, assertNonBypassable,
|
|
422
|
+
export { type CoSignConnection, type CoSignFrame, type CoSignRequestAuthenticator, type CoSignRequestEnvelope, type CoSignTransport, CoSignUnavailableError, type CreateLocalPolicyGatedSignerParams, MAX_FRAME_BYTES, type Mpc2pCoSignAgent, type Mpc2pSignerParams, type Mpc2pStepOutcome, type Mpc2pWireOptions, NonBypassableEnforcement, PaymentIntent, PolicyGatedSigner, PolicyGatedSignerConfigError, WIRE_VERSION, type WireIntent, assertNonBypassable, canonicalRequestBytes, createLocalPolicyGatedSigner, createMpc2pPolicyGatedSigner, requireNonBypassable, toWireIntent };
|
package/dist/signer/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { WIRE_VERSION,
|
|
2
|
-
export { CoSignUnavailableError, PolicyGatedSignerConfigError, assertNonBypassable, requireNonBypassable } from '../chunk-
|
|
1
|
+
export { MAX_FRAME_BYTES, WIRE_VERSION, canonicalRequestBytes, createLocalPolicyGatedSigner, createMpc2pPolicyGatedSigner, toWireIntent } from '../chunk-S2ZSX2VS.js';
|
|
2
|
+
export { CoSignUnavailableError, PolicyGatedSignerConfigError, assertNonBypassable, requireNonBypassable } from '../chunk-VJUXTVSW.js';
|
|
3
3
|
import '../chunk-WMVJNPX2.js';
|
|
4
4
|
import '../chunk-6CNAYQOL.js';
|
|
5
5
|
import '../chunk-KT7XDT2T.js';
|