@derec-alliance/react-native 0.0.5 → 0.0.6
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 +9 -15
- package/android/CMakeLists.txt +1 -1
- package/android/src/main/jniLibs/arm64-v8a/libderec_library.a +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/libderec_library.a +0 -0
- package/android/src/main/jniLibs/x86_64/libderec_library.a +0 -0
- package/cpp/Convert.cpp +125 -0
- package/cpp/Convert.h +35 -0
- package/cpp/DeRecInstaller.cpp +0 -12
- package/cpp/Primitives.cpp +159 -26
- package/cpp/Primitives.h +16 -0
- package/cpp/ProtocolHost.cpp +22 -47
- package/cpp/StoreCallbacks.cpp +97 -304
- package/cpp/UserSecretsJson.cpp +109 -0
- package/cpp/UserSecretsJson.h +28 -0
- package/cpp/derec_ffi.h +256 -120
- package/ios/DeRecFFI.xcframework/ios-arm64/Headers/derec_ffi.h +256 -120
- package/ios/DeRecFFI.xcframework/ios-arm64/libderec_library.a +0 -0
- package/ios/DeRecFFI.xcframework/ios-arm64_x86_64-simulator/Headers/derec_ffi.h +256 -120
- package/ios/DeRecFFI.xcframework/ios-arm64_x86_64-simulator/libderec_library.a +2 -2
- package/lib/errors.d.ts +7 -0
- package/lib/native.d.ts +5 -1
- package/lib/primitives.d.ts +18 -21
- package/lib/primitives.js +48 -25
- package/lib/protocol.d.ts +49 -97
- package/lib/protocol.js +71 -162
- package/lib/types.d.ts +207 -107
- package/lib/types.js +43 -13
- package/package.json +1 -1
- package/src/errors.ts +7 -0
- package/src/native.ts +2 -1
- package/src/primitives.ts +82 -25
- package/src/protocol.ts +79 -179
- package/src/types.ts +221 -96
package/src/types.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// Copyright (c) 2026 DeRec Alliance. All rights reserved.
|
|
3
3
|
|
|
4
|
+
import { getNative } from './native';
|
|
5
|
+
|
|
4
6
|
export interface SecretStore {
|
|
5
7
|
load(
|
|
6
8
|
secretId: string,
|
|
@@ -9,15 +11,15 @@ export interface SecretStore {
|
|
|
9
11
|
): Promise<Uint8Array | null | undefined>;
|
|
10
12
|
/**
|
|
11
13
|
* Load secrets of the same `kind` for several channels in one call,
|
|
12
|
-
* scoped to `secretId`. Must return an array with one entry per
|
|
13
|
-
* id, in the same order, using `null` (or `undefined`) for channels
|
|
14
|
-
* with no stored secret of `kind`.
|
|
14
|
+
* scoped to `secretId`. Must return an array with exactly one entry per
|
|
15
|
+
* input id, in the same order, using `null` (or `undefined`) for channels
|
|
16
|
+
* with no stored secret of `kind`. Whether a missing entry is an error is
|
|
17
|
+
* decided by the library.
|
|
15
18
|
*/
|
|
16
19
|
loadMany(
|
|
17
20
|
secretId: string,
|
|
18
21
|
channelIds: string[],
|
|
19
22
|
kind: 0 | 1 | 2,
|
|
20
|
-
missingPolicy: "skip" | "fail",
|
|
21
23
|
): Promise<Array<Uint8Array | null | undefined>>;
|
|
22
24
|
save(
|
|
23
25
|
secretId: string,
|
|
@@ -120,30 +122,15 @@ export function channelFilterMatches(
|
|
|
120
122
|
/**
|
|
121
123
|
* The endpoints a peer-supplied message advertises, in the peer's own order.
|
|
122
124
|
*
|
|
123
|
-
* Yields `supported_transports` when it is non-empty, and otherwise the
|
|
124
|
-
* singular `transport_protocol` — which is how every implementation predating
|
|
125
|
-
* the offer list advertises, and the reason this is a function rather than a
|
|
126
|
-
* field read. Reading `transport_protocol` directly is a bug: its meaning
|
|
127
|
-
* narrowed to "one entry of a list, and possibly absent", so a peer that has
|
|
128
|
-
* moved past it looks unreachable to a reader that was correct before 0.0.3.
|
|
129
|
-
*
|
|
130
125
|
* Reports what was advertised, not what is acceptable — nothing here is
|
|
131
126
|
* validated, and the protocol still applies its own transport policy to
|
|
132
127
|
* whatever it records.
|
|
133
128
|
*/
|
|
134
129
|
export function advertisedEndpoints(
|
|
135
|
-
message:
|
|
136
|
-
| {
|
|
137
|
-
transport_protocol?: TransportProtocol;
|
|
138
|
-
supported_transports?: TransportProtocol[];
|
|
139
|
-
}
|
|
140
|
-
| null
|
|
141
|
-
| undefined,
|
|
130
|
+
message: { supported_transports?: TransportProtocol[] } | null | undefined,
|
|
142
131
|
): TransportProtocol[] {
|
|
143
132
|
if (!message) return [];
|
|
144
|
-
|
|
145
|
-
if (offers.length > 0) return offers;
|
|
146
|
-
return message.transport_protocol ? [message.transport_protocol] : [];
|
|
133
|
+
return message.supported_transports ?? [];
|
|
147
134
|
}
|
|
148
135
|
|
|
149
136
|
/**
|
|
@@ -242,11 +229,7 @@ export interface ChannelStore {
|
|
|
242
229
|
secretId: string,
|
|
243
230
|
filter: ReplicaFilter,
|
|
244
231
|
): Promise<Uint8Array | null | undefined>;
|
|
245
|
-
linkChannel(
|
|
246
|
-
secretId: string,
|
|
247
|
-
channelId: string,
|
|
248
|
-
linkedChannelId: string,
|
|
249
|
-
): Promise<void>;
|
|
232
|
+
linkChannel(secretId: string, a: string, b: string): Promise<void>;
|
|
250
233
|
linkedChannels(secretId: string, channelId: string): Promise<string[]>;
|
|
251
234
|
}
|
|
252
235
|
|
|
@@ -290,6 +273,10 @@ export interface UserSecrets {
|
|
|
290
273
|
version: number;
|
|
291
274
|
secrets: UserSecretEntry[];
|
|
292
275
|
description?: string;
|
|
276
|
+
/** Decimal `replica_id` of the member that published `version`. Absent
|
|
277
|
+
* when none is recorded. Store and return it unchanged: replica members
|
|
278
|
+
* compare it to detect a conflicting copy of the same version. */
|
|
279
|
+
author_replica_id?: string;
|
|
293
280
|
}
|
|
294
281
|
|
|
295
282
|
/**
|
|
@@ -333,6 +320,18 @@ export interface StateStore {
|
|
|
333
320
|
loadAll(secretId: string, kind: 0 | 1 | 2 | 3 | 4): Promise<Uint8Array[]>;
|
|
334
321
|
}
|
|
335
322
|
|
|
323
|
+
/** A transport protocol, by name. */
|
|
324
|
+
export type TransportProtocolName = "https" | "grpc";
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* One endpoint a node serves or a peer advertised, as every app-facing call
|
|
328
|
+
* and event carries it.
|
|
329
|
+
*/
|
|
330
|
+
export interface Endpoint {
|
|
331
|
+
uri: string;
|
|
332
|
+
protocol: TransportProtocolName;
|
|
333
|
+
}
|
|
334
|
+
|
|
336
335
|
/**
|
|
337
336
|
* Outbound message delivery.
|
|
338
337
|
*
|
|
@@ -378,7 +377,7 @@ export interface Transport {
|
|
|
378
377
|
* {@link singleEndpointTransport} rather than by indexing.
|
|
379
378
|
*/
|
|
380
379
|
send(
|
|
381
|
-
endpoints: ReadonlyArray<
|
|
380
|
+
endpoints: ReadonlyArray<Endpoint>,
|
|
382
381
|
message: Uint8Array,
|
|
383
382
|
): Promise<void>;
|
|
384
383
|
}
|
|
@@ -398,10 +397,28 @@ export interface Transport {
|
|
|
398
397
|
* a round trip; skipping one that would have worked costs the delivery.
|
|
399
398
|
*/
|
|
400
399
|
export type SendOne = (
|
|
401
|
-
endpoint:
|
|
400
|
+
endpoint: Endpoint,
|
|
402
401
|
message: Uint8Array,
|
|
403
402
|
) => Promise<void>;
|
|
404
403
|
|
|
404
|
+
/**
|
|
405
|
+
* The DeRec protocol version this build speaks — the `protocolVersionMajor` /
|
|
406
|
+
* `protocolVersionMinor` it writes into every envelope it produces. Not the
|
|
407
|
+
* package version.
|
|
408
|
+
*/
|
|
409
|
+
export function protocol_version(): { major: number; minor: number } {
|
|
410
|
+
return getNative().version();
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* A fresh, random replica id — never `0`. Generate it once per device,
|
|
415
|
+
* persist it, and pass the same value to
|
|
416
|
+
* `DeRecProtocolBuilder.withReplicaId` on every init.
|
|
417
|
+
*/
|
|
418
|
+
export function generate_replica_id(): bigint {
|
|
419
|
+
return getNative().generate_replica_id();
|
|
420
|
+
}
|
|
421
|
+
|
|
405
422
|
/**
|
|
406
423
|
* Builds a {@link Transport} that tries each endpoint in the order the peer
|
|
407
424
|
* offered it and stops at the first success.
|
|
@@ -473,7 +490,7 @@ export enum SenderKind {
|
|
|
473
490
|
* the scanner must fetch the actual keys over the wire via the `PrePair`
|
|
474
491
|
* round-trip and verify them against the commitment before pairing.
|
|
475
492
|
* - `NoKeys`: no key material and no commitment. The contact carries only
|
|
476
|
-
* `channel_id`, `nonce`, and `
|
|
493
|
+
* `channel_id`, `nonce`, and `supported_transports` — small enough to be
|
|
477
494
|
* hand-typed or dictated. Keys are generated on the fly by the contact
|
|
478
495
|
* creator when the `PrePairRequest` arrives; the scanner accepts them
|
|
479
496
|
* without cryptographic verification. Trust rests entirely on the OOB
|
|
@@ -515,20 +532,33 @@ export enum FlowKind {
|
|
|
515
532
|
UnpairReplica = 8,
|
|
516
533
|
}
|
|
517
534
|
|
|
535
|
+
/** Result status carried in every protocol response (`result.proto`). Passed
|
|
536
|
+
* to `reject()` to say why an inbound request was refused. */
|
|
537
|
+
export enum StatusEnum {
|
|
538
|
+
Ok = 0,
|
|
539
|
+
Partial = 1,
|
|
540
|
+
Fail = 2,
|
|
541
|
+
SizeLimitExceeded = 3,
|
|
542
|
+
TooFrequent = 4,
|
|
543
|
+
UnknownSecretId = 5,
|
|
544
|
+
UnknownShareVersion = 6,
|
|
545
|
+
DecryptionFailed = 7,
|
|
546
|
+
VerificationFailed = 8,
|
|
547
|
+
FormatError = 9,
|
|
548
|
+
Rejected = 10,
|
|
549
|
+
IncompatibleParameterRange = 11,
|
|
550
|
+
UnsupportedTransportProtocol = 12,
|
|
551
|
+
VersionConflict = 13,
|
|
552
|
+
ReplicaIdConflict = 14,
|
|
553
|
+
RequestToClose = 99,
|
|
554
|
+
}
|
|
555
|
+
|
|
518
556
|
export type UnpairAck = "required" | "not_required";
|
|
519
557
|
|
|
520
558
|
export interface ContactMessage {
|
|
521
559
|
channel_id: bigint;
|
|
522
560
|
/** `ContactMode` numeric value (0 = INLINE_KEYS, 1 = HASHED_KEYS, 2 = NO_KEYS). */
|
|
523
561
|
contact_mode: number;
|
|
524
|
-
/**
|
|
525
|
-
* @deprecated Reading this field directly is incorrect: its meaning narrowed
|
|
526
|
-
* to "one entry of a list, and possibly absent", so a peer advertising only
|
|
527
|
-
* `supported_transports` looks unreachable to a reader that was correct
|
|
528
|
-
* before 0.0.3. Call {@link advertisedEndpoints}, which resolves both
|
|
529
|
-
* spellings. Removed at 0.0.5.
|
|
530
|
-
*/
|
|
531
|
-
transport_protocol?: TransportProtocol;
|
|
532
562
|
nonce: bigint;
|
|
533
563
|
/** Present only when `contact_mode === ContactMode.InlineKeys`. */
|
|
534
564
|
mlkem_encapsulation_key?: Uint8Array;
|
|
@@ -538,8 +568,7 @@ export interface ContactMessage {
|
|
|
538
568
|
contact_binding_hash?: Uint8Array;
|
|
539
569
|
timestamp?: Timestamp;
|
|
540
570
|
/** Every transport endpoint the creator of this contact can be reached
|
|
541
|
-
* on, in its own preference order.
|
|
542
|
-
* `transport_protocol` is offered". */
|
|
571
|
+
* on, in its own preference order. */
|
|
543
572
|
supported_transports: TransportProtocol[];
|
|
544
573
|
}
|
|
545
574
|
|
|
@@ -587,20 +616,11 @@ export interface UpdateChannelInfoParams {
|
|
|
587
616
|
* map untouched; pass an empty object to clear it. */
|
|
588
617
|
communication_info?: Record<string, string>;
|
|
589
618
|
|
|
590
|
-
/**
|
|
591
|
-
* New transport endpoint. Absent leaves it untouched.
|
|
592
|
-
*
|
|
593
|
-
* @deprecated Use `own_transports`, which carries every endpoint this node
|
|
594
|
-
* now serves; its first entry also fills this field for peers predating the
|
|
595
|
-
* list. Removed at 0.0.5.
|
|
596
|
-
*/
|
|
597
|
-
transport_protocol?: { uri: string; protocol: number };
|
|
598
619
|
/**
|
|
599
620
|
* Every endpoint this node now serves, in its own preference order.
|
|
600
|
-
* Omitted leaves the target(s)' stored set untouched.
|
|
601
|
-
* over `transport_protocol`, whose first entry it also fills.
|
|
621
|
+
* Omitted leaves the target(s)' stored set untouched.
|
|
602
622
|
*/
|
|
603
|
-
own_transports?:
|
|
623
|
+
own_transports?: Endpoint[];
|
|
604
624
|
}
|
|
605
625
|
|
|
606
626
|
/**
|
|
@@ -659,18 +679,34 @@ export type DeRecEvent =
|
|
|
659
679
|
action: Uint8Array;
|
|
660
680
|
|
|
661
681
|
action_kind: PendingActionKind;
|
|
682
|
+
/** Correlation token of the inbound request, decimal-encoded. */
|
|
683
|
+
trace_id: string;
|
|
684
|
+
/** Pairing only. */
|
|
662
685
|
peer_communication_info?: Record<string, string>;
|
|
663
|
-
|
|
686
|
+
/** `sender_kind` of the inbound pair request (Pairing only). */
|
|
664
687
|
sender_kind?: SenderKind;
|
|
665
|
-
|
|
688
|
+
/** Share version (StoreShare / VerifyShare / GetShare). */
|
|
666
689
|
version?: number;
|
|
690
|
+
/** Description of the secret version (StoreShare only). */
|
|
667
691
|
share_description?: string;
|
|
668
|
-
|
|
692
|
+
/** Secret identifier, decimal-encoded (StoreShare / VerifyShare /
|
|
693
|
+
* GetShare). On GetShare, with `version`, names the requested share. */
|
|
669
694
|
share_secret_id?: string;
|
|
695
|
+
/** Length in bytes of the share the helper would store (StoreShare
|
|
696
|
+
* only) — what a size or quota decision is made on. */
|
|
697
|
+
share_size?: number;
|
|
698
|
+
/** The peer's memo (Unpair only). */
|
|
699
|
+
unpair_memo?: string;
|
|
700
|
+
/** Communication info the peer replaces its stored map with
|
|
701
|
+
* (UpdateChannelInfo only). Absent: unchanged. Empty: cleared. */
|
|
702
|
+
updated_communication_info?: Record<string, string>;
|
|
703
|
+
/** Endpoints the peer is moving to (UpdateChannelInfo only). Absent:
|
|
704
|
+
* unchanged. */
|
|
705
|
+
updated_transports?: Endpoint[];
|
|
670
706
|
}
|
|
671
707
|
| { type: "ShareStored"; channel_id: string; version: number }
|
|
672
708
|
| { type: "ShareConfirmed"; channel_id: string; version: number }
|
|
673
|
-
| { type: "ShareRejected"; channel_id: string; version: number; status:
|
|
709
|
+
| { type: "ShareRejected"; channel_id: string; version: number; status: StatusEnum; memo: string }
|
|
674
710
|
/** A publishing round finished — every targeted helper confirmed,
|
|
675
711
|
* rejected, or timed out.
|
|
676
712
|
*
|
|
@@ -695,7 +731,7 @@ export type DeRecEvent =
|
|
|
695
731
|
replica_id: string;
|
|
696
732
|
secret_id: string;
|
|
697
733
|
version: number;
|
|
698
|
-
status:
|
|
734
|
+
status: StatusEnum;
|
|
699
735
|
memo: string;
|
|
700
736
|
}
|
|
701
737
|
/** A secret sync could not be delivered to a member at all — distinct from
|
|
@@ -748,9 +784,9 @@ export type DeRecEvent =
|
|
|
748
784
|
helpers: Array<{
|
|
749
785
|
channel_id: string;
|
|
750
786
|
/** Every endpoint this peer advertised, in the order it offered them. */
|
|
751
|
-
transports:
|
|
787
|
+
transports: Endpoint[];
|
|
752
788
|
shared_key: Uint8Array;
|
|
753
|
-
communication_info
|
|
789
|
+
communication_info?: Record<string, string>;
|
|
754
790
|
}>;
|
|
755
791
|
secrets: Array<{
|
|
756
792
|
id: Uint8Array;
|
|
@@ -770,9 +806,9 @@ export type DeRecEvent =
|
|
|
770
806
|
members: Array<{
|
|
771
807
|
replica_id: string;
|
|
772
808
|
/** Every endpoint this peer advertised, in the order it offered them. */
|
|
773
|
-
transports:
|
|
809
|
+
transports: Endpoint[];
|
|
774
810
|
role: "Source" | "Destination";
|
|
775
|
-
communication_info
|
|
811
|
+
communication_info?: Record<string, string>;
|
|
776
812
|
}>;
|
|
777
813
|
shared_key: Uint8Array;
|
|
778
814
|
};
|
|
@@ -781,12 +817,12 @@ export type DeRecEvent =
|
|
|
781
817
|
|
|
782
818
|
| { type: "Unpaired"; channel_id: string }
|
|
783
819
|
|
|
784
|
-
| { type: "UnpairRejected"; channel_id: string; status:
|
|
820
|
+
| { type: "UnpairRejected"; channel_id: string; status: StatusEnum; memo: string }
|
|
785
821
|
|
|
786
822
|
/** Contact creator answered the scanner's `PrePairRequest` with a
|
|
787
823
|
* non-Ok status (HashedKeys flow). Distinct from a cryptographic
|
|
788
824
|
* hash mismatch, which surfaces as a thrown error from `process()`. */
|
|
789
|
-
| { type: "PrePairRejected"; channel_id: string; status:
|
|
825
|
+
| { type: "PrePairRejected"; channel_id: string; status: StatusEnum; memo: string }
|
|
790
826
|
|
|
791
827
|
/** Fires alongside `PairingCompleted` on replica-mode pair handshakes.
|
|
792
828
|
* `peer_replica_id` is the peer's `u64` as a **decimal** string,
|
|
@@ -804,22 +840,28 @@ export type DeRecEvent =
|
|
|
804
840
|
/** A `ReplicaSource` peer pushed a secret sync on a
|
|
805
841
|
* `ReplicaDestination` channel. The library decoded the
|
|
806
842
|
* `ReplicaSecretPayload`; the app installs `secret.secrets` and
|
|
807
|
-
* optionally uses `shares` for recovery. `from_replica_id
|
|
808
|
-
* `replica_id` fields inside `secret` are
|
|
809
|
-
* strings.
|
|
843
|
+
* optionally uses `shares` for recovery. `from_replica_id`,
|
|
844
|
+
* `author_replica_id` and the `replica_id` fields inside `secret` are
|
|
845
|
+
* `u64` as **decimal** strings.
|
|
846
|
+
*
|
|
847
|
+
* `from_replica_id` is the member this copy came from: the publisher on
|
|
848
|
+
* a push, the serving member on a catch-up. `author_replica_id` is the
|
|
849
|
+
* member that published `version`, or `null` when the serving member's
|
|
850
|
+
* snapshot records none. */
|
|
810
851
|
| {
|
|
811
852
|
type: "ReplicaSecretReceived";
|
|
812
853
|
channel_id: string;
|
|
813
854
|
from_replica_id: string;
|
|
855
|
+
author_replica_id: string | null;
|
|
814
856
|
secret_id: string;
|
|
815
857
|
version: number;
|
|
816
858
|
secret: {
|
|
817
859
|
helpers: Array<{
|
|
818
860
|
channel_id: string;
|
|
819
861
|
/** Every endpoint this peer advertised, in the order it offered them. */
|
|
820
|
-
transports:
|
|
862
|
+
transports: Endpoint[];
|
|
821
863
|
shared_key: Uint8Array;
|
|
822
|
-
communication_info
|
|
864
|
+
communication_info?: Record<string, string>;
|
|
823
865
|
}>;
|
|
824
866
|
secrets: Array<{
|
|
825
867
|
id: Uint8Array;
|
|
@@ -837,9 +879,9 @@ export type DeRecEvent =
|
|
|
837
879
|
members: Array<{
|
|
838
880
|
replica_id: string;
|
|
839
881
|
/** Every endpoint this peer advertised, in the order it offered them. */
|
|
840
|
-
transports:
|
|
882
|
+
transports: Endpoint[];
|
|
841
883
|
role: "Source" | "Destination";
|
|
842
|
-
communication_info
|
|
884
|
+
communication_info?: Record<string, string>;
|
|
843
885
|
}>;
|
|
844
886
|
shared_key: Uint8Array;
|
|
845
887
|
};
|
|
@@ -862,15 +904,16 @@ export type DeRecEvent =
|
|
|
862
904
|
type: "ReplicaSecretInstalled";
|
|
863
905
|
channel_id: string;
|
|
864
906
|
from_replica_id: string;
|
|
907
|
+
author_replica_id: string | null;
|
|
865
908
|
secret_id: string;
|
|
866
909
|
version: number;
|
|
867
910
|
secret: {
|
|
868
911
|
helpers: Array<{
|
|
869
912
|
channel_id: string;
|
|
870
913
|
/** Every endpoint this peer advertised, in the order it offered them. */
|
|
871
|
-
transports:
|
|
914
|
+
transports: Endpoint[];
|
|
872
915
|
shared_key: Uint8Array;
|
|
873
|
-
communication_info
|
|
916
|
+
communication_info?: Record<string, string>;
|
|
874
917
|
}>;
|
|
875
918
|
secrets: Array<{
|
|
876
919
|
id: Uint8Array;
|
|
@@ -888,9 +931,9 @@ export type DeRecEvent =
|
|
|
888
931
|
members: Array<{
|
|
889
932
|
replica_id: string;
|
|
890
933
|
/** Every endpoint this peer advertised, in the order it offered them. */
|
|
891
|
-
transports:
|
|
934
|
+
transports: Endpoint[];
|
|
892
935
|
role: "Source" | "Destination";
|
|
893
|
-
communication_info
|
|
936
|
+
communication_info?: Record<string, string>;
|
|
894
937
|
}>;
|
|
895
938
|
shared_key: Uint8Array;
|
|
896
939
|
};
|
|
@@ -900,6 +943,56 @@ export type DeRecEvent =
|
|
|
900
943
|
committed_share: Uint8Array;
|
|
901
944
|
}>;
|
|
902
945
|
}
|
|
946
|
+
/** A member offered a different copy of the version this device holds.
|
|
947
|
+
* Nothing was written: this device keeps its own copy and refuses the
|
|
948
|
+
* incoming one with `VERSION_CONFLICT`, so the publisher sees
|
|
949
|
+
* `ReplicaSyncRejected`. Both copies are complete states — the held one
|
|
950
|
+
* is in the local stores, the incoming one is `secret`. Resolve by
|
|
951
|
+
* publishing the chosen state with `start(FlowKind.ProtectSecret)`; the
|
|
952
|
+
* next version supersedes both on every member and helper.
|
|
953
|
+
*
|
|
954
|
+
* `held_author_replica_id` / `incoming_author_replica_id` are the
|
|
955
|
+
* decimal `replica_id` of each copy's publisher, or `null` when that
|
|
956
|
+
* copy records none. */
|
|
957
|
+
| {
|
|
958
|
+
type: "ReplicaVersionConflict";
|
|
959
|
+
channel_id: string;
|
|
960
|
+
from_replica_id: string;
|
|
961
|
+
secret_id: string;
|
|
962
|
+
version: number;
|
|
963
|
+
held_author_replica_id: string | null;
|
|
964
|
+
incoming_author_replica_id: string | null;
|
|
965
|
+
secret: {
|
|
966
|
+
helpers: Array<{
|
|
967
|
+
channel_id: string;
|
|
968
|
+
/** Every endpoint this peer advertised, in the order it offered them. */
|
|
969
|
+
transports: Endpoint[];
|
|
970
|
+
shared_key: Uint8Array;
|
|
971
|
+
communication_info?: Record<string, string>;
|
|
972
|
+
}>;
|
|
973
|
+
secrets: Array<{
|
|
974
|
+
id: Uint8Array;
|
|
975
|
+
name: string;
|
|
976
|
+
data: Uint8Array;
|
|
977
|
+
}>;
|
|
978
|
+
/** The same shape as `SecretRecovered.secret.replicas`. */
|
|
979
|
+
replicas?: {
|
|
980
|
+
/** The one channel every member is addressed on. */
|
|
981
|
+
channel_id: string;
|
|
982
|
+
/** Every member of the group, including the writer. Exactly one
|
|
983
|
+
* carries `role: "Source"` — that member is where the secret
|
|
984
|
+
* originated, which is why no separate owner field is needed. */
|
|
985
|
+
members: Array<{
|
|
986
|
+
replica_id: string;
|
|
987
|
+
/** Every endpoint this peer advertised, in the order it offered them. */
|
|
988
|
+
transports: Endpoint[];
|
|
989
|
+
role: "Source" | "Destination";
|
|
990
|
+
communication_info?: Record<string, string>;
|
|
991
|
+
}>;
|
|
992
|
+
shared_key: Uint8Array;
|
|
993
|
+
};
|
|
994
|
+
};
|
|
995
|
+
}
|
|
903
996
|
/** Peer's ack of a secret sync we sent. `status` is the `StatusEnum`
|
|
904
997
|
* integer (0 = Ok), `memo` is the peer's explanation. */
|
|
905
998
|
| {
|
|
@@ -908,7 +1001,7 @@ export type DeRecEvent =
|
|
|
908
1001
|
from_replica_id: string;
|
|
909
1002
|
secret_id: string;
|
|
910
1003
|
version: number;
|
|
911
|
-
status:
|
|
1004
|
+
status: StatusEnum;
|
|
912
1005
|
memo: string;
|
|
913
1006
|
}
|
|
914
1007
|
/** A peer announced an updated `communication_info` map and/or
|
|
@@ -925,7 +1018,7 @@ export type DeRecEvent =
|
|
|
925
1018
|
| {
|
|
926
1019
|
type: "ChannelInfoUpdateRejected";
|
|
927
1020
|
channel_id: string;
|
|
928
|
-
status:
|
|
1021
|
+
status: StatusEnum;
|
|
929
1022
|
memo: string;
|
|
930
1023
|
}
|
|
931
1024
|
/** Emitted by `process()` in place of `ActionRequired` when the
|
|
@@ -937,6 +1030,38 @@ export type DeRecEvent =
|
|
|
937
1030
|
* (`"Pairing"`, `"StoreShare"`, …). */
|
|
938
1031
|
| { type: "AutoAccepted"; channel_id: string; action_kind: PendingActionKind }
|
|
939
1032
|
| { type: "NoOp" }
|
|
1033
|
+
/** An inbound message was dropped untouched: no store was written and
|
|
1034
|
+
* nothing was sent back. `reason` says why.
|
|
1035
|
+
*
|
|
1036
|
+
* `"PendingVerification"` means the peer sent something before this
|
|
1037
|
+
* device confirmed the channel's fingerprint — typically a replica source
|
|
1038
|
+
* pushing its first copy while this destination still shows the code.
|
|
1039
|
+
* Confirming does not replay it: after `verifyFingerprint` succeeds, a
|
|
1040
|
+
* replica destination calls `start(FlowKind.ReplicaDiscovery)` to pull
|
|
1041
|
+
* the copy itself. `"Expired"` means the message was older than the
|
|
1042
|
+
* inbound timeout. `trace_id` matches the peer's `*Started` event for
|
|
1043
|
+
* the same round (`"0"` when the sender set none). */
|
|
1044
|
+
| {
|
|
1045
|
+
type: "MessageIgnored";
|
|
1046
|
+
channel_id: string;
|
|
1047
|
+
reason: IgnoreReason;
|
|
1048
|
+
trace_id: string;
|
|
1049
|
+
}
|
|
1050
|
+
/** Returned by `restore`: a roster entry got no channel, so this device
|
|
1051
|
+
* cannot reach that peer. Every other entry and the user-secret snapshot
|
|
1052
|
+
* were restored; `reason` says why this one was not. `"NoTransports"`
|
|
1053
|
+
* means the recovered roster names no endpoint for it.
|
|
1054
|
+
*
|
|
1055
|
+
* For a helper, `channel_id` is its channel and `replica_id` is absent.
|
|
1056
|
+
* For a replica group member, `channel_id` is the group's channel and
|
|
1057
|
+
* `replica_id` names the member. The peer itself is untouched — a helper
|
|
1058
|
+
* still holds its share — and pairing with it again makes it reachable. */
|
|
1059
|
+
| {
|
|
1060
|
+
type: "PeerNotRestored";
|
|
1061
|
+
channel_id: string;
|
|
1062
|
+
replica_id?: string;
|
|
1063
|
+
reason: NotRestoredReason;
|
|
1064
|
+
}
|
|
940
1065
|
/** A pairing handshake was dispatched successfully. `kind` is the
|
|
941
1066
|
* local party's role — same value the subsequent `PairingCompleted`
|
|
942
1067
|
* will carry. Emitted by `start(Pairing)`. */
|
|
@@ -1005,8 +1130,8 @@ export type DeRecEvent =
|
|
|
1005
1130
|
* inbound shares. The protocol enforces no size, quota or rate limit
|
|
1006
1131
|
* of its own, and `maxShareSize` is checked for range overlap at
|
|
1007
1132
|
* pairing time only, never against an actual share. While this is
|
|
1008
|
-
* `false`, `ActionRequired` carries
|
|
1009
|
-
*
|
|
1133
|
+
* `false`, `ActionRequired` carries `share_size`, so the application
|
|
1134
|
+
* can compare it to its quota and call `reject()` with
|
|
1010
1135
|
* `StatusEnum.SizeLimitExceeded`. Setting it `true` removes that
|
|
1011
1136
|
* opportunity entirely: every share from every paired Owner is stored
|
|
1012
1137
|
* unconditionally, at whatever size it arrives. Keep off in any
|
|
@@ -1099,6 +1224,14 @@ export interface CommunicationInfo {
|
|
|
1099
1224
|
// `ContactMessage` is defined once above and covers both `INLINE_KEYS` and
|
|
1100
1225
|
// `HASHED_KEYS` modes.
|
|
1101
1226
|
|
|
1227
|
+
/** Why a `MessageIgnored` event dropped a message. Matches the Rust
|
|
1228
|
+
* `IgnoreReason` discriminants one-for-one. */
|
|
1229
|
+
export type IgnoreReason = "PendingVerification" | "Expired";
|
|
1230
|
+
|
|
1231
|
+
/** Why a `PeerNotRestored` event left a roster entry without a channel.
|
|
1232
|
+
* Matches the Rust `NotRestoredReason` discriminants one-for-one. */
|
|
1233
|
+
export type NotRestoredReason = "NoTransports";
|
|
1234
|
+
|
|
1102
1235
|
/**
|
|
1103
1236
|
* The label vocabulary for `ActionRequired.action_kind` and
|
|
1104
1237
|
* `AutoAccepted.action_kind` — one value per pending-action kind the
|
|
@@ -1135,17 +1268,9 @@ export interface PairRequestMessage {
|
|
|
1135
1268
|
nonce: bigint;
|
|
1136
1269
|
communication_info?: CommunicationInfo;
|
|
1137
1270
|
parameter_range?: ParameterRange;
|
|
1138
|
-
/**
|
|
1139
|
-
* @deprecated Reading this field directly is incorrect: its meaning narrowed
|
|
1140
|
-
* to "one entry of a list, and possibly absent", so a peer advertising only
|
|
1141
|
-
* `supported_transports` looks unreachable to a reader that was correct
|
|
1142
|
-
* before 0.0.3. Call {@link advertisedEndpoints}, which resolves both
|
|
1143
|
-
* spellings. Removed at 0.0.5.
|
|
1144
|
-
*/
|
|
1145
|
-
transport_protocol?: TransportProtocol;
|
|
1146
1271
|
timestamp?: Timestamp;
|
|
1147
1272
|
/** Every transport endpoint the initiator can be reached on, in its own
|
|
1148
|
-
* preference order.
|
|
1273
|
+
* preference order. */
|
|
1149
1274
|
supported_transports: TransportProtocol[];
|
|
1150
1275
|
}
|
|
1151
1276
|
|
|
@@ -1167,21 +1292,12 @@ export interface PairResponseMessage {
|
|
|
1167
1292
|
|
|
1168
1293
|
export interface PrePairRequestMessage {
|
|
1169
1294
|
nonce: bigint;
|
|
1170
|
-
/**
|
|
1171
|
-
* @deprecated Reading this field directly is incorrect: its meaning narrowed
|
|
1172
|
-
* to "one entry of a list, and possibly absent", so a peer advertising only
|
|
1173
|
-
* `supported_transports` looks unreachable to a reader that was correct
|
|
1174
|
-
* before 0.0.3. Call {@link advertisedEndpoints}, which resolves both
|
|
1175
|
-
* spellings. Removed at 0.0.5.
|
|
1176
|
-
*/
|
|
1177
|
-
transport_protocol?: TransportProtocol;
|
|
1178
1295
|
timestamp?: Timestamp;
|
|
1179
1296
|
/**
|
|
1180
1297
|
* Every endpoint the sender can be reached on for the PrePair reply, in
|
|
1181
|
-
* its own preference order.
|
|
1182
|
-
* must be present.
|
|
1298
|
+
* its own preference order.
|
|
1183
1299
|
*/
|
|
1184
|
-
supported_transports
|
|
1300
|
+
supported_transports: TransportProtocol[];
|
|
1185
1301
|
}
|
|
1186
1302
|
|
|
1187
1303
|
export interface PrePairResponseMessage {
|
|
@@ -1367,6 +1483,15 @@ export interface ProducePrePairResult {
|
|
|
1367
1483
|
envelope: Uint8Array;
|
|
1368
1484
|
}
|
|
1369
1485
|
|
|
1486
|
+
export interface ProducePrePairNoKeysResult {
|
|
1487
|
+
|
|
1488
|
+
envelope: Uint8Array;
|
|
1489
|
+
|
|
1490
|
+
/** Secret key material generated for this pairing. The caller MUST persist
|
|
1491
|
+
* it: the `PairRequest` that follows is encrypted to it. */
|
|
1492
|
+
secret_key_material: Uint8Array;
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1370
1495
|
export interface PrePairRequestExtractResult {
|
|
1371
1496
|
|
|
1372
1497
|
request: PrePairRequestMessage;
|