@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 +46 -10
- package/derec_library.d.ts +0 -5
- package/derec_library.js +1 -12
- package/derec_library_bg.wasm +0 -0
- package/derec_library_bg.wasm.d.ts +34 -35
- package/index.d.ts +92 -6
- package/package.json +1 -1
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,
|
|
321
|
-
|
|
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
|
|
408
|
-
channelStore
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
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
|
package/derec_library.d.ts
CHANGED
|
@@ -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:
|
|
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
|
},
|
package/derec_library_bg.wasm
CHANGED
|
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
|
|
64
|
-
export const
|
|
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
|
|
79
|
-
export const
|
|
80
|
-
export const
|
|
81
|
-
export const
|
|
82
|
-
export const
|
|
83
|
-
export const
|
|
84
|
-
export const
|
|
85
|
-
export const
|
|
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
|
|
690
|
-
*
|
|
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