@derec-alliance/nodejs 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -317,8 +317,15 @@ const recovered = primitives.recovery.response.recover(
317
317
  // `recovered` is a Uint8Array carrying the reconstructed secret payload.
318
318
  ```
319
319
 
320
- When driving the protocol layer instead of the primitives, the recovering
321
- device receives a `SecretRecovered` event carrying the typed `secret`. Pass it
320
+ When driving the protocol layer instead of the primitives, a helper that
321
+ answers with a share that cannot be part of the secret is reported as a
322
+ `RecoveryShareCorrupted` event (`reason`: `"Malformed"`, `"InvalidProof"` or
323
+ `"Inconsistent"`); the share is set aside and never blocks the recovery from
324
+ the others. An honest helper never sends one, so treat it as a sign of a
325
+ damaged or compromised helper — for example, offer to unpair it.
326
+
327
+ The recovering device receives a `SecretRecovered` event carrying the typed
328
+ `secret`. Pass it
322
329
  to `protocol.restore(secret, version)` on a fresh `DeRecProtocol` instance to
323
330
  commit canonical helper / replica state and wipe the throwaway recovery-mode
324
331
  channels — at that point the device resumes normal operation as if the secret
@@ -404,14 +411,18 @@ side runs as `SenderKind.ReplicaSource` (owns the secret), the other as
404
411
  with a stable `replicaId`:
405
412
 
406
413
  ```ts
407
- const owner = new DeRecProtocol(
408
- channelStore, shareStore, secretStore, transport,
409
- "https://owner.example.com", "https",
410
- /* threshold */ 2, /* keepVersionsCount */ 3,
411
- { name: "Owner" },
412
- null, null, null, null,
413
- /* replicaId */ 0xAAAA_AAAA_AAAA_AAAAn,
414
- );
414
+ const owner = new DeRecProtocolBuilder(secretId)
415
+ .withChannelStore(channelStore)
416
+ .withShareStore(shareStore)
417
+ .withSecretStore(secretStore)
418
+ .withUserSecretStore(userSecretStore)
419
+ .withStateStore(stateStore)
420
+ .withTransport(transport)
421
+ .withOwnTransports([{ uri: "https://owner.example.com", protocol: "https" }])
422
+ .withThreshold(2)
423
+ .withCommunicationInfo({ name: "Owner" })
424
+ .withReplicaId(0xAAAA_AAAA_AAAA_AAAAn)
425
+ .build();
415
426
  ```
416
427
 
417
428
  A typical Source↔Destination handshake:
@@ -464,6 +475,27 @@ End-to-end coverage lives in the repository's tests — see
464
475
 
465
476
  ---
466
477
 
478
+ ## When `process()` fails
479
+
480
+ `process()` settles expired deadlines (sharing-round and unpair timeouts)
481
+ before it handles the message, and those are never reported again. So when
482
+ the message then fails, the thrown `DeRecError` carries them: `events` holds
483
+ every event produced before the failure, and `channel_id` names the channel
484
+ the message came from (absent when the bytes were not a decodable envelope).
485
+ Handle the events as you would a successful call's, then the error:
486
+
487
+ ```ts
488
+ try {
489
+ handle(await protocol.process(bytes));
490
+ } catch (error) {
491
+ const failure = error as DeRecError;
492
+ handle(failure.events ?? []);
493
+ report(failure.channel_id, failure);
494
+ }
495
+ ```
496
+
497
+ ---
498
+
467
499
  ## Correlation and routing
468
500
 
469
501
  Two cross-cutting metadata fields appear on every channel-mode exchange:
@@ -572,6 +604,10 @@ the peer acknowledges, retire the ephemeral URI. This keeps the
572
604
  plaintext PrePair window tight while letting subsequent traffic ride
573
605
  on the long-lived endpoint.
574
606
 
607
+ `UpdateChannelInfo` reaches helper channels only. A replica member that
608
+ changes its endpoint or `communication_info` publishes a new version first,
609
+ then updates its helpers; see [On a replica member](https://github.com/derecalliance/lib-derec/tree/main/library#on-a-replica-member).
610
+
575
611
  ### Replica fingerprint verification is mandatory
576
612
 
577
613
  Replica channels are created with `status: "Pending"` and remain there
@@ -58,11 +58,6 @@ export class DeRecProtocolBuilder {
58
58
  * `info` shape: `Record<string, string>`. Default: empty.
59
59
  */
60
60
  withCommunicationInfo(info: any): DeRecProtocolBuilder;
61
- /**
62
- * Number of recent versions each helper must retain.
63
- * Default: [`crate::protocol::DEFAULT_KEEP_VERSIONS_COUNT`].
64
- */
65
- withKeepVersionsCount(count: number): DeRecProtocolBuilder;
66
61
  /**
67
62
  * Every transport endpoint this application serves, in preference
68
63
  * order. `transports` is an array of `{ uri: string, protocol: string
package/derec_library.js CHANGED
@@ -126,17 +126,6 @@ class DeRecProtocolBuilder {
126
126
  }
127
127
  return DeRecProtocolBuilder.__wrap(ret[0]);
128
128
  }
129
- /**
130
- * Number of recent versions each helper must retain.
131
- * Default: [`crate::protocol::DEFAULT_KEEP_VERSIONS_COUNT`].
132
- * @param {number} count
133
- * @returns {DeRecProtocolBuilder}
134
- */
135
- withKeepVersionsCount(count) {
136
- const ptr = this.__destroy_into_raw();
137
- const ret = wasm.derecprotocolbuilder_withKeepVersionsCount(ptr, count);
138
- return DeRecProtocolBuilder.__wrap(ret);
139
- }
140
129
  /**
141
130
  * Every transport endpoint this application serves, in preference
142
131
  * order. `transports` is an array of `{ uri: string, protocol: string
@@ -1824,7 +1813,7 @@ function __wbg_get_imports() {
1824
1813
  return ret;
1825
1814
  },
1826
1815
  __wbindgen_cast_0000000000000001: function(arg0, arg1) {
1827
- // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 395, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
1816
+ // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 404, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
1828
1817
  const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h379e0770a020d351);
1829
1818
  return ret;
1830
1819
  },
Binary file
@@ -1,30 +1,6 @@
1
1
  /* tslint:disable */
2
2
  /* eslint-disable */
3
3
  export const memory: WebAssembly.Memory;
4
- export const verification_response_extract: (a: number, b: number, c: number, d: number) => [number, number, number];
5
- export const verification_response_process: (a: any, b: any, c: number, d: number) => [number, number, number];
6
- export const verification_response_produce: (a: bigint, b: any, c: number, d: number, e: number, f: number) => [number, number, number];
7
- export const discovery_response_extract: (a: number, b: number, c: number, d: number) => [number, number, number];
8
- export const discovery_response_process: (a: any) => [number, number, number];
9
- export const discovery_response_produce: (a: bigint, b: any, c: number, d: number) => [number, number, number];
10
- export const envelope_apply_trace_id: (a: number, b: number, c: bigint) => [number, number, number, number];
11
- export const envelope_read_trace_id: (a: number, b: number) => [bigint, number, number];
12
- export const sharing_response_extract: (a: number, b: number, c: number, d: number) => [number, number, number];
13
- export const sharing_response_process: (a: number, b: any) => [number, number];
14
- export const sharing_response_produce: (a: bigint, b: any, c: number, d: number) => [number, number, number];
15
- export const wasm_start: () => void;
16
- export const sharing_request_extract: (a: number, b: number, c: number, d: number) => [number, number, number];
17
- export const sharing_request_produce: (a: bigint, b: number, c: bigint, d: any, e: any, f: number, g: number, h: number, i: number, j: any) => [number, number, number];
18
- export const sharing_request_split: (a: any, b: bigint, c: number, d: number, e: number, f: number) => [number, number, number];
19
- export const pairing_fingerprint: (a: number, b: number) => [number, number, number, number];
20
- export const pairing_response_extract: (a: number, b: number, c: number, d: number) => [number, number, number];
21
- export const pairing_response_extract_pre_pair: (a: number, b: number) => [number, number, number];
22
- export const pairing_response_process: (a: any, b: any, c: number, d: number, e: any) => [number, number, number];
23
- export const pairing_response_process_pre_pair: (a: any, b: any) => [number, number, number];
24
- export const pairing_response_process_pre_pair_no_keys: (a: any, b: any) => [number, number, number];
25
- export const pairing_response_produce: (a: bigint, b: any, c: number, d: number, e: any, f: any, g: number) => [number, number, number];
26
- export const pairing_response_produce_pre_pair: (a: bigint, b: any, c: number, d: number) => [number, number, number];
27
- export const pairing_response_produce_pre_pair_no_keys: (a: bigint, b: any) => [number, number, number];
28
4
  export const __wbg_derecprotocolbuilder_free: (a: number, b: number) => void;
29
5
  export const __wbg_derecprotocolwasm_free: (a: number, b: number) => void;
30
6
  export const derecprotocolbuilder_build: (a: number) => [number, number, number];
@@ -34,7 +10,6 @@ export const derecprotocolbuilder_withAutoReplyTo: (a: number, b: number) => num
34
10
  export const derecprotocolbuilder_withAutoRespondOnFailure: (a: number, b: number) => number;
35
11
  export const derecprotocolbuilder_withChannelStore: (a: number, b: any) => number;
36
12
  export const derecprotocolbuilder_withCommunicationInfo: (a: number, b: any) => [number, number, number];
37
- export const derecprotocolbuilder_withKeepVersionsCount: (a: number, b: number) => number;
38
13
  export const derecprotocolbuilder_withOwnTransports: (a: number, b: number, c: number) => [number, number, number];
39
14
  export const derecprotocolbuilder_withParameterRange: (a: number, b: any) => [number, number, number];
40
15
  export const derecprotocolbuilder_withReplicaId: (a: number, b: any) => [number, number, number];
@@ -60,8 +35,11 @@ export const derecprotocolwasm_setOwnTransports: (a: number, b: number, c: numbe
60
35
  export const derecprotocolwasm_start: (a: number, b: number, c: any) => any;
61
36
  export const derecprotocolwasm_tick: (a: number) => any;
62
37
  export const derecprotocolwasm_verifyFingerprint: (a: number, b: any, c: number, d: number) => any;
63
- export const discovery_request_extract: (a: number, b: number, c: number, d: number) => [number, number, number];
64
- export const discovery_request_produce: (a: bigint, b: number, c: number, d: any) => [number, number, number];
38
+ export const envelope_apply_trace_id: (a: number, b: number, c: bigint) => [number, number, number, number];
39
+ export const envelope_read_trace_id: (a: number, b: number) => [bigint, number, number];
40
+ export const recovery_response_extract: (a: number, b: number, c: number, d: number) => [number, number, number];
41
+ export const recovery_response_produce: (a: bigint, b: any, c: any, d: number, e: number) => [number, number, number];
42
+ export const recovery_response_recover: (a: bigint, b: number, c: any) => [number, number, number];
65
43
  export const pairing_request_create_contact: (a: bigint, b: number, c: any, d: any) => [number, number, number];
66
44
  export const pairing_request_decode_contact: (a: number, b: number) => [number, number, number];
67
45
  export const pairing_request_encode_contact: (a: any) => [number, number, number, number];
@@ -69,20 +47,41 @@ export const pairing_request_extract: (a: number, b: number, c: number, d: numbe
69
47
  export const pairing_request_extract_pre_pair: (a: number, b: number) => [number, number, number];
70
48
  export const pairing_request_produce: (a: number, b: any, c: any, d: any, e: any) => [number, number, number];
71
49
  export const pairing_request_produce_pre_pair: (a: any, b: any) => [number, number, number];
50
+ export const unpairing_response_extract: (a: number, b: number, c: number, d: number) => [number, number, number];
51
+ export const unpairing_response_process: (a: any) => [number, number, number];
52
+ export const unpairing_response_produce: (a: bigint, b: number, c: number) => [number, number, number];
53
+ export const discovery_response_extract: (a: number, b: number, c: number, d: number) => [number, number, number];
54
+ export const discovery_response_process: (a: any) => [number, number, number];
55
+ export const discovery_response_produce: (a: bigint, b: any, c: number, d: number) => [number, number, number];
72
56
  export const protocol_version: () => [number, number, number];
57
+ export const sharing_response_extract: (a: number, b: number, c: number, d: number) => [number, number, number];
58
+ export const sharing_response_process: (a: number, b: any) => [number, number];
59
+ export const sharing_response_produce: (a: bigint, b: any, c: number, d: number) => [number, number, number];
60
+ export const wasm_start: () => void;
61
+ export const discovery_request_extract: (a: number, b: number, c: number, d: number) => [number, number, number];
62
+ export const discovery_request_produce: (a: bigint, b: number, c: number, d: any) => [number, number, number];
63
+ export const sharing_request_extract: (a: number, b: number, c: number, d: number) => [number, number, number];
64
+ export const sharing_request_produce: (a: bigint, b: number, c: bigint, d: any, e: any, f: number, g: number, h: number, i: number, j: any) => [number, number, number];
65
+ export const sharing_request_split: (a: any, b: bigint, c: number, d: number, e: number, f: number) => [number, number, number];
66
+ export const recovery_request_extract: (a: number, b: number, c: number, d: number) => [number, number, number];
67
+ export const recovery_request_produce: (a: bigint, b: bigint, c: number, d: number, e: number, f: any) => [number, number, number];
73
68
  export const unpairing_request_extract: (a: number, b: number, c: number, d: number) => [number, number, number];
74
69
  export const unpairing_request_produce: (a: bigint, b: number, c: number, d: number, e: number, f: any) => [number, number, number];
75
70
  export const verification_request_extract: (a: number, b: number, c: number, d: number) => [number, number, number];
76
71
  export const verification_request_produce: (a: bigint, b: bigint, c: number, d: number, e: number, f: any) => [number, number, number];
77
72
  export const generate_replica_id: () => bigint;
78
- export const recovery_response_extract: (a: number, b: number, c: number, d: number) => [number, number, number];
79
- export const recovery_response_produce: (a: bigint, b: any, c: any, d: number, e: number) => [number, number, number];
80
- export const recovery_response_recover: (a: bigint, b: number, c: any) => [number, number, number];
81
- export const unpairing_response_extract: (a: number, b: number, c: number, d: number) => [number, number, number];
82
- export const unpairing_response_process: (a: any) => [number, number, number];
83
- export const unpairing_response_produce: (a: bigint, b: number, c: number) => [number, number, number];
84
- export const recovery_request_extract: (a: number, b: number, c: number, d: number) => [number, number, number];
85
- export const recovery_request_produce: (a: bigint, b: bigint, c: number, d: number, e: number, f: any) => [number, number, number];
73
+ export const pairing_fingerprint: (a: number, b: number) => [number, number, number, number];
74
+ export const pairing_response_extract: (a: number, b: number, c: number, d: number) => [number, number, number];
75
+ export const pairing_response_extract_pre_pair: (a: number, b: number) => [number, number, number];
76
+ export const pairing_response_process: (a: any, b: any, c: number, d: number, e: any) => [number, number, number];
77
+ export const pairing_response_process_pre_pair: (a: any, b: any) => [number, number, number];
78
+ export const pairing_response_process_pre_pair_no_keys: (a: any, b: any) => [number, number, number];
79
+ export const pairing_response_produce: (a: bigint, b: any, c: number, d: number, e: any, f: any, g: number) => [number, number, number];
80
+ export const pairing_response_produce_pre_pair: (a: bigint, b: any, c: number, d: number) => [number, number, number];
81
+ export const pairing_response_produce_pre_pair_no_keys: (a: bigint, b: any) => [number, number, number];
82
+ export const verification_response_extract: (a: number, b: number, c: number, d: number) => [number, number, number];
83
+ export const verification_response_process: (a: any, b: any, c: number, d: number) => [number, number, number];
84
+ export const verification_response_produce: (a: bigint, b: any, c: number, d: number, e: number, f: number) => [number, number, number];
86
85
  export const wasm_bindgen__convert__closures_____invoke__h379e0770a020d351: (a: number, b: number, c: any) => [number, number];
87
86
  export const wasm_bindgen__convert__closures_____invoke__h037700d3f721a480: (a: number, b: number, c: any, d: any) => void;
88
87
  export const __wbindgen_malloc: (a: number, b: number) => number;
package/index.d.ts CHANGED
@@ -253,6 +253,35 @@ export interface ShareStore {
253
253
  save(secretId: string, channelId: string, share: Share): Promise<void>;
254
254
  latestVersion(secretId: string): Promise<number | null>;
255
255
  removeChannel(secretId: string, channelId: string): Promise<void>;
256
+ /**
257
+ * Drop the shares stored under `(secretId, channelId)` at each of
258
+ * `versions`. Idempotent: a version that is not stored is skipped, and
259
+ * an empty array is a no-op.
260
+ *
261
+ * A helper calls this to apply `StoreShareRequestMessage.keepList`, the
262
+ * complete set of versions the owner wants retained: every stored
263
+ * version outside it is removed once the incoming share is persisted.
264
+ * Shares under other channels or partitions must be left untouched.
265
+ */
266
+ removeVersions(secretId: string, channelId: string, versions: number[]): Promise<void>;
267
+ /**
268
+ * Owner only: the versions every helper keeps after the owner distributes
269
+ * `version`. Asked once per sharing round, before anything is sent,
270
+ * including the rounds the library starts itself; the answer becomes
271
+ * `keepList` for every helper.
272
+ *
273
+ * Return `null` or `undefined` to send no `keepList` (it goes out empty):
274
+ * helpers then keep every version they hold. An app that wants to cap how
275
+ * many versions helpers retain returns that cap here. A returned list is
276
+ * used as is, plus `version`, which the library always adds. Helpers
277
+ * delete every version that is not listed, so list every version that
278
+ * could still become the latest: those that committed (for example, whose
279
+ * `SharingComplete` reported `threshold_met`) and those whose round is
280
+ * still open. Leave out only versions whose round failed or that the user
281
+ * rolled back; a list that leaves out too much can make the secret
282
+ * unrecoverable.
283
+ */
284
+ keepList(secretId: string, version: number): Promise<number[] | null | undefined>;
256
285
  }
257
286
 
258
287
  export interface UserSecretEntry {
@@ -615,6 +644,15 @@ export interface Timeouts {
615
644
  * are both read from the stores. The argument may be omitted entirely. */
616
645
  export type ReplicaDiscoveryParams = Record<string, never>;
617
646
 
647
+ /** Any member may remove any member, the source included: a lost or stolen
648
+ * source must be removable by the devices that remain, and the library
649
+ * checks no role. Ask the user before starting this flow, above all when it
650
+ * names the source. Removing the source promotes the first remaining member
651
+ * in the order the channel store's `listReplicas` returns. The removed
652
+ * member is not asked and gets no event when told to leave: when a roster
653
+ * excluding it arrives it drops its whole `secret_id` partition and emits
654
+ * `SelfRemovedFromGroup`. The secret survives on the remaining members and
655
+ * the helpers. */
618
656
  export interface UnpairReplicaParams {
619
657
  /** The member to remove, as a **decimal** `u64` string — the same form
620
658
  * `ReplicaPaired.peer_replica_id` hands back. A value naming no current
@@ -686,8 +724,11 @@ export type DeRecEvent =
686
724
  | { type: "SharingComplete"; version: number; confirmed_count: number; failed_count: number; threshold_met: boolean }
687
725
  /** A group member refused a secret sync. Keyed by `replica_id`, not
688
726
  * `channel_id`: every member answers on the one group channel. A
689
- * `VERSION_CONFLICT` status means the round must be resolved and
690
- * republished at a new version. */
727
+ * `VERSION_CONFLICT` status means another member holds a different copy
728
+ * of this version: do not publish from this device again until the
729
+ * conflict is resolved. Run `start(FlowKind.ReplicaDiscovery)` to receive
730
+ * the group's copy as `ReplicaVersionConflict`, merge, and publish the
731
+ * result once with `start(FlowKind.ProtectSecret)`. */
691
732
  | {
692
733
  type: "ReplicaSyncRejected";
693
734
  replica_id: string;
@@ -710,7 +751,8 @@ export type DeRecEvent =
710
751
  /** This device left the group and dropped its whole `secret_id` partition —
711
752
  * group channel, helper channels, shares, secrets and the snapshot. Fires
712
753
  * only once it was told to leave *and* has since seen a roster excluding
713
- * it; absence alone never destroys a copy of the secret. */
754
+ * it; absence alone never destroys a copy of the secret. The teardown is
755
+ * automatic: this device is not asked first and gets no earlier event. */
714
756
  | { type: "SelfRemovedFromGroup"; version: number }
715
757
  /** A replica catch-up finished. `fetched_from` is absent when this device
716
758
  * was already current, in which case no hydration event follows. */
@@ -726,6 +768,10 @@ export type DeRecEvent =
726
768
  * library keeps no durable per-member sync state. */
727
769
  | { type: "ReplicaSyncComplete"; version: number; synced: string[]; behind: string[] }
728
770
  | { type: "ShareVerified"; channel_id: string; version: number }
771
+ /** A helper refused a verification challenge: its response carried a
772
+ * non-OK `status` instead of a proof. The challenge is spent; a new
773
+ * `VerifyShares` round challenges the helper again. */
774
+ | { type: "ShareVerifyRejected"; channel_id: string; version: number; status: StatusEnum; memo: string }
729
775
  | {
730
776
  type: "SecretsDiscovered";
731
777
  channel_id: string;
@@ -734,6 +780,22 @@ export type DeRecEvent =
734
780
  }
735
781
  | { type: "RecoveryShareReceived"; channel_id: string; shares_received: number }
736
782
  | { type: "RecoveryShareError"; channel_id: string; shares_received: number; error: string }
783
+ /** A helper refused a recovery share request: its response carried a
784
+ * non-OK `status` (e.g. `UNKNOWN_SHARE_VERSION`) instead of a share. The
785
+ * refusal is not collected — it does not count towards `shares_received`
786
+ * and the recovery stays open for the other helpers' shares — but it does
787
+ * answer that helper's `RecoverSecretStarted`. */
788
+ | { type: "RecoveryShareRefused"; channel_id: string; version: number; status: StatusEnum; memo: string }
789
+ /** A helper answered with a share that cannot be part of the secret;
790
+ * `reason` says how it failed. `Malformed` and `InvalidProof` are judged
791
+ * on arrival; `Inconsistent` (valid on its own but disagreeing with the
792
+ * shares the secret was rebuilt from) is reported alongside
793
+ * `SecretRecovered`, once per helper. The share is set aside — it does
794
+ * not count towards `shares_received` and never blocks the recovery. An
795
+ * honest helper never sends one, so the app may treat it as a sign of a
796
+ * damaged or compromised helper, e.g. offer to unpair it. It also
797
+ * answers that helper's `RecoverSecretStarted`. */
798
+ | { type: "RecoveryShareCorrupted"; channel_id: string; version: number; reason: CorruptionReason }
737
799
  /** Recovery completed — the typed `Secret` snapshot the owner
738
800
  * originally protected. Mirrors `ReplicaSecretReceived.secret`:
739
801
  * `secrets` is the user-facing `Vec<UserSecret>` the application
@@ -911,7 +973,10 @@ export type DeRecEvent =
911
973
  * `ReplicaSyncRejected`. Both copies are complete states — the held one
912
974
  * is in the local stores, the incoming one is `secret`. Resolve by
913
975
  * publishing the chosen state with `start(FlowKind.ProtectSecret)`; the
914
- * next version supersedes both on every member and helper.
976
+ * next version supersedes both on every member and helper. Until then,
977
+ * do not publish from this device: any further `ProtectSecret` is a
978
+ * higher version that every other member applies over its own copy,
979
+ * losing the change it never merged.
915
980
  *
916
981
  * `held_author_replica_id` / `incoming_author_replica_id` are the
917
982
  * decimal `replica_id` of each copy's publisher, or `null` when that
@@ -1167,8 +1232,6 @@ export declare class DeRecProtocolBuilder {
1167
1232
 
1168
1233
  /** Minimum number of shares required to reconstruct the secret. Default: 3. */
1169
1234
  withThreshold(threshold: number): DeRecProtocolBuilder;
1170
- /** Number of recent versions each helper must retain. Default: 3. */
1171
- withKeepVersionsCount(count: number): DeRecProtocolBuilder;
1172
1235
  /**
1173
1236
  * Configure how long the protocol waits on each thing that can keep it
1174
1237
  * waiting. Every field is optional and **absent means "keep the library
@@ -1388,6 +1451,11 @@ export declare class DeRecProtocol {
1388
1451
  * Verify `fingerprint` against the channel's locally-derived one. On
1389
1452
  * match, the channel transitions from `Pending` to `Paired`. Returns
1390
1453
  * `true` on confirmation, `false` on mismatch.
1454
+ *
1455
+ * On a replica destination, confirming is also the decision to adopt the
1456
+ * group's vault: the source's publish is then installed as it arrives,
1457
+ * with no further prompt. Ask the user before calling this; to decline,
1458
+ * never confirm.
1391
1459
  */
1392
1460
  verifyFingerprint(channelId: bigint | number, fingerprint: string): Promise<boolean>;
1393
1461
  /**
@@ -1409,6 +1477,10 @@ export declare class DeRecProtocol {
1409
1477
  * `Secret`. Mirrors the Rust `DeRecProtocol::restore` — pass the
1410
1478
  * typed `secret` carried by the `SecretRecovered` event verbatim.
1411
1479
  *
1480
+ * Recovery and restore are separate steps on purpose: `SecretRecovered`
1481
+ * writes nothing. Show the user what was recovered, or ask them, before
1482
+ * calling `restore`, which commits it to this device.
1483
+ *
1412
1484
  * A helper or member whose `transports` is empty gets no channel: it is
1413
1485
  * reported as a `PeerNotRestored` event in the returned array and the rest
1414
1486
  * of the roster is restored.
@@ -1538,6 +1610,14 @@ export type IgnoreReason = "PendingVerification" | "Expired";
1538
1610
  * Matches the Rust `NotRestoredReason` discriminants one-for-one. */
1539
1611
  export type NotRestoredReason = "NoTransports";
1540
1612
 
1613
+ /** Why a `RecoveryShareCorrupted` event set a helper's share aside.
1614
+ * Matches the Rust `CorruptionReason` discriminants one-for-one:
1615
+ * `Malformed` — no decodable share for the requested secret and version;
1616
+ * `InvalidProof` — the share fails its own Merkle proof;
1617
+ * `Inconsistent` — valid on its own, but its commitment root or ciphertext
1618
+ * disagrees with the shares the secret was rebuilt from. */
1619
+ export type CorruptionReason = "Malformed" | "InvalidProof" | "Inconsistent";
1620
+
1541
1621
  export type PendingActionKind =
1542
1622
  | "Pairing"
1543
1623
  | "PrePair"
@@ -1860,6 +1940,12 @@ export interface DeRecError {
1860
1940
  got?: number;
1861
1941
  /** The channel the failing inbound message arrived on, when `process()` could tell. */
1862
1942
  channel_id?: string;
1943
+ /**
1944
+ * On a failed `process()`: the events it produced before failing, such as
1945
+ * sharing-round and unpair timeouts. They are not reported again, so
1946
+ * handle them as you would a successful call's events.
1947
+ */
1948
+ events?: DeRecEvent[];
1863
1949
  /** On a `restore` `CONFLICT`: the pre-existing channels at canonical ids. */
1864
1950
  channel_ids?: string[];
1865
1951
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@derec-alliance/nodejs",
3
3
  "description": "Node.js WebAssembly bindings for derec-library, the Rust SDK for the DeRec protocol.",
4
- "version": "0.0.6",
4
+ "version": "0.0.7",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",