@derec-alliance/react-native 0.0.4 → 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/lib/types.d.ts CHANGED
@@ -2,11 +2,12 @@ export interface SecretStore {
2
2
  load(secretId: string, channelId: string, kind: 0 | 1 | 2): Promise<Uint8Array | null | undefined>;
3
3
  /**
4
4
  * Load secrets of the same `kind` for several channels in one call,
5
- * scoped to `secretId`. Must return an array with one entry per input
6
- * id, in the same order, using `null` (or `undefined`) for channels
7
- * with no stored secret of `kind`.
5
+ * scoped to `secretId`. Must return an array with exactly one entry per
6
+ * input id, in the same order, using `null` (or `undefined`) for channels
7
+ * with no stored secret of `kind`. Whether a missing entry is an error is
8
+ * decided by the library.
8
9
  */
9
- loadMany(secretId: string, channelIds: string[], kind: 0 | 1 | 2, missingPolicy: "skip" | "fail"): Promise<Array<Uint8Array | null | undefined>>;
10
+ loadMany(secretId: string, channelIds: string[], kind: 0 | 1 | 2): Promise<Array<Uint8Array | null | undefined>>;
10
11
  save(secretId: string, channelId: string, kind: 0 | 1 | 2, value: Uint8Array): Promise<void>;
11
12
  remove(secretId: string, channelId: string, kind: 0 | 1 | 2): Promise<void>;
12
13
  }
@@ -78,19 +79,11 @@ export declare function channelFilterMatches(filter: HelperFilter | ReplicaFilte
78
79
  /**
79
80
  * The endpoints a peer-supplied message advertises, in the peer's own order.
80
81
  *
81
- * Yields `supported_transports` when it is non-empty, and otherwise the
82
- * singular `transport_protocol` — which is how every implementation predating
83
- * the offer list advertises, and the reason this is a function rather than a
84
- * field read. Reading `transport_protocol` directly is a bug: its meaning
85
- * narrowed to "one entry of a list, and possibly absent", so a peer that has
86
- * moved past it looks unreachable to a reader that was correct before 0.0.3.
87
- *
88
82
  * Reports what was advertised, not what is acceptable — nothing here is
89
83
  * validated, and the protocol still applies its own transport policy to
90
84
  * whatever it records.
91
85
  */
92
86
  export declare function advertisedEndpoints(message: {
93
- transport_protocol?: TransportProtocol;
94
87
  supported_transports?: TransportProtocol[];
95
88
  } | null | undefined): TransportProtocol[];
96
89
  /**
@@ -172,7 +165,7 @@ export interface ChannelStore {
172
165
  * Order explicitly to make succession predictable.
173
166
  */
174
167
  listReplicas(secretId: string, filter: ReplicaFilter): Promise<Uint8Array | null | undefined>;
175
- linkChannel(secretId: string, channelId: string, linkedChannelId: string): Promise<void>;
168
+ linkChannel(secretId: string, a: string, b: string): Promise<void>;
176
169
  linkedChannels(secretId: string, channelId: string): Promise<string[]>;
177
170
  }
178
171
  export interface Share {
@@ -180,6 +173,17 @@ export interface Share {
180
173
  version: number;
181
174
  bytes: Uint8Array;
182
175
  }
176
+ /**
177
+ * Share-record persistence.
178
+ *
179
+ * Rows are keyed by `(secretId, channelId, version)` where `secretId` is
180
+ * the partition passed to every method. `Share.secretId` is a different
181
+ * value: it names the secret the bytes belong to, which on a helper is
182
+ * the owner's id and routinely differs from the partition this device
183
+ * stores under. Key on the argument and carry `share.secretId` alongside
184
+ * as data — keying on it instead puts rows where no `load` looks, since
185
+ * every read filters on the partition.
186
+ */
183
187
  export interface ShareStore {
184
188
  load(secretId: string, channelId: string, versions: number[]): Promise<Share[]>;
185
189
  loadMany(secretId: string, channelIds: string[], versions: number[]): Promise<Share[]>;
@@ -197,6 +201,10 @@ export interface UserSecrets {
197
201
  version: number;
198
202
  secrets: UserSecretEntry[];
199
203
  description?: string;
204
+ /** Decimal `replica_id` of the member that published `version`. Absent
205
+ * when none is recorded. Store and return it unchanged: replica members
206
+ * compare it to detect a conflicting copy of the same version. */
207
+ author_replica_id?: string;
200
208
  }
201
209
  /**
202
210
  * Persistence for the user-facing secret contents, keyed by `secretId`.
@@ -234,6 +242,16 @@ export interface StateStore {
234
242
  remove(secretId: string, keyJson: Uint8Array): Promise<boolean>;
235
243
  loadAll(secretId: string, kind: 0 | 1 | 2 | 3 | 4): Promise<Uint8Array[]>;
236
244
  }
245
+ /** A transport protocol, by name. */
246
+ export type TransportProtocolName = "https" | "grpc";
247
+ /**
248
+ * One endpoint a node serves or a peer advertised, as every app-facing call
249
+ * and event carries it.
250
+ */
251
+ export interface Endpoint {
252
+ uri: string;
253
+ protocol: TransportProtocolName;
254
+ }
237
255
  /**
238
256
  * Outbound message delivery.
239
257
  *
@@ -278,10 +296,7 @@ export interface Transport {
278
296
  * provide — if that is genuinely wanted, say so with
279
297
  * {@link singleEndpointTransport} rather than by indexing.
280
298
  */
281
- send(endpoints: ReadonlyArray<{
282
- protocol: string;
283
- uri: string;
284
- }>, message: Uint8Array): Promise<void>;
299
+ send(endpoints: ReadonlyArray<Endpoint>, message: Uint8Array): Promise<void>;
285
300
  }
286
301
  /**
287
302
  * Delivers one message to one endpoint.
@@ -297,10 +312,22 @@ export interface Transport {
297
312
  * which is the safe reading. Trying an endpoint that would have refused costs
298
313
  * a round trip; skipping one that would have worked costs the delivery.
299
314
  */
300
- export type SendOne = (endpoint: {
301
- protocol: string;
302
- uri: string;
303
- }, message: Uint8Array) => Promise<void>;
315
+ export type SendOne = (endpoint: Endpoint, message: Uint8Array) => Promise<void>;
316
+ /**
317
+ * The DeRec protocol version this build speaks — the `protocolVersionMajor` /
318
+ * `protocolVersionMinor` it writes into every envelope it produces. Not the
319
+ * package version.
320
+ */
321
+ export declare function protocol_version(): {
322
+ major: number;
323
+ minor: number;
324
+ };
325
+ /**
326
+ * A fresh, random replica id — never `0`. Generate it once per device,
327
+ * persist it, and pass the same value to
328
+ * `DeRecProtocolBuilder.withReplicaId` on every init.
329
+ */
330
+ export declare function generate_replica_id(): bigint;
304
331
  /**
305
332
  * Builds a {@link Transport} that tries each endpoint in the order the peer
306
333
  * offered it and stops at the first success.
@@ -342,7 +369,7 @@ export declare enum SenderKind {
342
369
  * the scanner must fetch the actual keys over the wire via the `PrePair`
343
370
  * round-trip and verify them against the commitment before pairing.
344
371
  * - `NoKeys`: no key material and no commitment. The contact carries only
345
- * `channel_id`, `nonce`, and `transport_protocol` — small enough to be
372
+ * `channel_id`, `nonce`, and `supported_transports` — small enough to be
346
373
  * hand-typed or dictated. Keys are generated on the fly by the contact
347
374
  * creator when the `PrePairRequest` arrives; the scanner accepts them
348
375
  * without cryptographic verification. Trust rests entirely on the OOB
@@ -382,19 +409,31 @@ export declare enum FlowKind {
382
409
  * string so ids above 2^53 survive JS number handling. */
383
410
  UnpairReplica = 8
384
411
  }
412
+ /** Result status carried in every protocol response (`result.proto`). Passed
413
+ * to `reject()` to say why an inbound request was refused. */
414
+ export declare enum StatusEnum {
415
+ Ok = 0,
416
+ Partial = 1,
417
+ Fail = 2,
418
+ SizeLimitExceeded = 3,
419
+ TooFrequent = 4,
420
+ UnknownSecretId = 5,
421
+ UnknownShareVersion = 6,
422
+ DecryptionFailed = 7,
423
+ VerificationFailed = 8,
424
+ FormatError = 9,
425
+ Rejected = 10,
426
+ IncompatibleParameterRange = 11,
427
+ UnsupportedTransportProtocol = 12,
428
+ VersionConflict = 13,
429
+ ReplicaIdConflict = 14,
430
+ RequestToClose = 99
431
+ }
385
432
  export type UnpairAck = "required" | "not_required";
386
433
  export interface ContactMessage {
387
434
  channel_id: bigint;
388
435
  /** `ContactMode` numeric value (0 = INLINE_KEYS, 1 = HASHED_KEYS, 2 = NO_KEYS). */
389
436
  contact_mode: number;
390
- /**
391
- * @deprecated Reading this field directly is incorrect: its meaning narrowed
392
- * to "one entry of a list, and possibly absent", so a peer advertising only
393
- * `supported_transports` looks unreachable to a reader that was correct
394
- * before 0.0.3. Call {@link advertisedEndpoints}, which resolves both
395
- * spellings. Removed at 0.0.5.
396
- */
397
- transport_protocol?: TransportProtocol;
398
437
  nonce: bigint;
399
438
  /** Present only when `contact_mode === ContactMode.InlineKeys`. */
400
439
  mlkem_encapsulation_key?: Uint8Array;
@@ -404,8 +443,7 @@ export interface ContactMessage {
404
443
  contact_binding_hash?: Uint8Array;
405
444
  timestamp?: Timestamp;
406
445
  /** Every transport endpoint the creator of this contact can be reached
407
- * on, in its own preference order. Empty means "only
408
- * `transport_protocol` is offered". */
446
+ * on, in its own preference order. */
409
447
  supported_transports: TransportProtocol[];
410
448
  }
411
449
  export interface UserSecret {
@@ -444,23 +482,11 @@ export interface UpdateChannelInfoParams {
444
482
  /** New communication-info map. `null`/absent leaves the peer's stored
445
483
  * map untouched; pass an empty object to clear it. */
446
484
  communication_info?: Record<string, string>;
447
- /**
448
- * New transport endpoint. Absent leaves it untouched.
449
- *
450
- * @deprecated Use `own_transports`, which carries every endpoint this node
451
- * now serves; its first entry also fills this field for peers predating the
452
- * list. Removed at 0.0.5.
453
- */
454
- transport_protocol?: {
455
- uri: string;
456
- protocol: number;
457
- };
458
485
  /**
459
486
  * Every endpoint this node now serves, in its own preference order.
460
- * Omitted leaves the target(s)' stored set untouched. Takes precedence
461
- * over `transport_protocol`, whose first entry it also fills.
487
+ * Omitted leaves the target(s)' stored set untouched.
462
488
  */
463
- own_transports?: TransportProtocol[];
489
+ own_transports?: Endpoint[];
464
490
  }
465
491
  /**
466
492
  * How long the protocol waits on each thing that can keep it waiting. Every
@@ -513,11 +539,30 @@ export type DeRecEvent = {
513
539
  channel_id: string;
514
540
  action: Uint8Array;
515
541
  action_kind: PendingActionKind;
542
+ /** Correlation token of the inbound request, decimal-encoded. */
543
+ trace_id: string;
544
+ /** Pairing only. */
516
545
  peer_communication_info?: Record<string, string>;
546
+ /** `sender_kind` of the inbound pair request (Pairing only). */
517
547
  sender_kind?: SenderKind;
548
+ /** Share version (StoreShare / VerifyShare / GetShare). */
518
549
  version?: number;
550
+ /** Description of the secret version (StoreShare only). */
519
551
  share_description?: string;
552
+ /** Secret identifier, decimal-encoded (StoreShare / VerifyShare /
553
+ * GetShare). On GetShare, with `version`, names the requested share. */
520
554
  share_secret_id?: string;
555
+ /** Length in bytes of the share the helper would store (StoreShare
556
+ * only) — what a size or quota decision is made on. */
557
+ share_size?: number;
558
+ /** The peer's memo (Unpair only). */
559
+ unpair_memo?: string;
560
+ /** Communication info the peer replaces its stored map with
561
+ * (UpdateChannelInfo only). Absent: unchanged. Empty: cleared. */
562
+ updated_communication_info?: Record<string, string>;
563
+ /** Endpoints the peer is moving to (UpdateChannelInfo only). Absent:
564
+ * unchanged. */
565
+ updated_transports?: Endpoint[];
521
566
  } | {
522
567
  type: "ShareStored";
523
568
  channel_id: string;
@@ -530,7 +575,7 @@ export type DeRecEvent = {
530
575
  type: "ShareRejected";
531
576
  channel_id: string;
532
577
  version: number;
533
- status: number;
578
+ status: StatusEnum;
534
579
  memo: string;
535
580
  }
536
581
  /** A publishing round finished — every targeted helper confirmed,
@@ -563,7 +608,7 @@ export type DeRecEvent = {
563
608
  replica_id: string;
564
609
  secret_id: string;
565
610
  version: number;
566
- status: number;
611
+ status: StatusEnum;
567
612
  memo: string;
568
613
  }
569
614
  /** A secret sync could not be delivered to a member at all — distinct from
@@ -649,12 +694,9 @@ export type DeRecEvent = {
649
694
  helpers: Array<{
650
695
  channel_id: string;
651
696
  /** Every endpoint this peer advertised, in the order it offered them. */
652
- transports: Array<{
653
- uri: string;
654
- protocol: number;
655
- }>;
697
+ transports: Endpoint[];
656
698
  shared_key: Uint8Array;
657
- communication_info: Record<string, string>;
699
+ communication_info?: Record<string, string>;
658
700
  }>;
659
701
  secrets: Array<{
660
702
  id: Uint8Array;
@@ -674,12 +716,9 @@ export type DeRecEvent = {
674
716
  members: Array<{
675
717
  replica_id: string;
676
718
  /** Every endpoint this peer advertised, in the order it offered them. */
677
- transports: Array<{
678
- uri: string;
679
- protocol: number;
680
- }>;
719
+ transports: Endpoint[];
681
720
  role: "Source" | "Destination";
682
- communication_info: Record<string, string>;
721
+ communication_info?: Record<string, string>;
683
722
  }>;
684
723
  shared_key: Uint8Array;
685
724
  };
@@ -690,7 +729,7 @@ export type DeRecEvent = {
690
729
  } | {
691
730
  type: "UnpairRejected";
692
731
  channel_id: string;
693
- status: number;
732
+ status: StatusEnum;
694
733
  memo: string;
695
734
  }
696
735
  /** Contact creator answered the scanner's `PrePairRequest` with a
@@ -699,7 +738,7 @@ export type DeRecEvent = {
699
738
  | {
700
739
  type: "PrePairRejected";
701
740
  channel_id: string;
702
- status: number;
741
+ status: StatusEnum;
703
742
  memo: string;
704
743
  }
705
744
  /** Fires alongside `PairingCompleted` on replica-mode pair handshakes.
@@ -718,25 +757,28 @@ export type DeRecEvent = {
718
757
  /** A `ReplicaSource` peer pushed a secret sync on a
719
758
  * `ReplicaDestination` channel. The library decoded the
720
759
  * `ReplicaSecretPayload`; the app installs `secret.secrets` and
721
- * optionally uses `shares` for recovery. `from_replica_id` and the
722
- * `replica_id` fields inside `secret` are `u64` as **decimal**
723
- * strings. */
760
+ * optionally uses `shares` for recovery. `from_replica_id`,
761
+ * `author_replica_id` and the `replica_id` fields inside `secret` are
762
+ * `u64` as **decimal** strings.
763
+ *
764
+ * `from_replica_id` is the member this copy came from: the publisher on
765
+ * a push, the serving member on a catch-up. `author_replica_id` is the
766
+ * member that published `version`, or `null` when the serving member's
767
+ * snapshot records none. */
724
768
  | {
725
769
  type: "ReplicaSecretReceived";
726
770
  channel_id: string;
727
771
  from_replica_id: string;
772
+ author_replica_id: string | null;
728
773
  secret_id: string;
729
774
  version: number;
730
775
  secret: {
731
776
  helpers: Array<{
732
777
  channel_id: string;
733
778
  /** Every endpoint this peer advertised, in the order it offered them. */
734
- transports: Array<{
735
- uri: string;
736
- protocol: number;
737
- }>;
779
+ transports: Endpoint[];
738
780
  shared_key: Uint8Array;
739
- communication_info: Record<string, string>;
781
+ communication_info?: Record<string, string>;
740
782
  }>;
741
783
  secrets: Array<{
742
784
  id: Uint8Array;
@@ -754,12 +796,9 @@ export type DeRecEvent = {
754
796
  members: Array<{
755
797
  replica_id: string;
756
798
  /** Every endpoint this peer advertised, in the order it offered them. */
757
- transports: Array<{
758
- uri: string;
759
- protocol: number;
760
- }>;
799
+ transports: Endpoint[];
761
800
  role: "Source" | "Destination";
762
- communication_info: Record<string, string>;
801
+ communication_info?: Record<string, string>;
763
802
  }>;
764
803
  shared_key: Uint8Array;
765
804
  };
@@ -782,18 +821,16 @@ export type DeRecEvent = {
782
821
  type: "ReplicaSecretInstalled";
783
822
  channel_id: string;
784
823
  from_replica_id: string;
824
+ author_replica_id: string | null;
785
825
  secret_id: string;
786
826
  version: number;
787
827
  secret: {
788
828
  helpers: Array<{
789
829
  channel_id: string;
790
830
  /** Every endpoint this peer advertised, in the order it offered them. */
791
- transports: Array<{
792
- uri: string;
793
- protocol: number;
794
- }>;
831
+ transports: Endpoint[];
795
832
  shared_key: Uint8Array;
796
- communication_info: Record<string, string>;
833
+ communication_info?: Record<string, string>;
797
834
  }>;
798
835
  secrets: Array<{
799
836
  id: Uint8Array;
@@ -811,12 +848,9 @@ export type DeRecEvent = {
811
848
  members: Array<{
812
849
  replica_id: string;
813
850
  /** Every endpoint this peer advertised, in the order it offered them. */
814
- transports: Array<{
815
- uri: string;
816
- protocol: number;
817
- }>;
851
+ transports: Endpoint[];
818
852
  role: "Source" | "Destination";
819
- communication_info: Record<string, string>;
853
+ communication_info?: Record<string, string>;
820
854
  }>;
821
855
  shared_key: Uint8Array;
822
856
  };
@@ -826,6 +860,56 @@ export type DeRecEvent = {
826
860
  committed_share: Uint8Array;
827
861
  }>;
828
862
  }
863
+ /** A member offered a different copy of the version this device holds.
864
+ * Nothing was written: this device keeps its own copy and refuses the
865
+ * incoming one with `VERSION_CONFLICT`, so the publisher sees
866
+ * `ReplicaSyncRejected`. Both copies are complete states — the held one
867
+ * is in the local stores, the incoming one is `secret`. Resolve by
868
+ * publishing the chosen state with `start(FlowKind.ProtectSecret)`; the
869
+ * next version supersedes both on every member and helper.
870
+ *
871
+ * `held_author_replica_id` / `incoming_author_replica_id` are the
872
+ * decimal `replica_id` of each copy's publisher, or `null` when that
873
+ * copy records none. */
874
+ | {
875
+ type: "ReplicaVersionConflict";
876
+ channel_id: string;
877
+ from_replica_id: string;
878
+ secret_id: string;
879
+ version: number;
880
+ held_author_replica_id: string | null;
881
+ incoming_author_replica_id: string | null;
882
+ secret: {
883
+ helpers: Array<{
884
+ channel_id: string;
885
+ /** Every endpoint this peer advertised, in the order it offered them. */
886
+ transports: Endpoint[];
887
+ shared_key: Uint8Array;
888
+ communication_info?: Record<string, string>;
889
+ }>;
890
+ secrets: Array<{
891
+ id: Uint8Array;
892
+ name: string;
893
+ data: Uint8Array;
894
+ }>;
895
+ /** The same shape as `SecretRecovered.secret.replicas`. */
896
+ replicas?: {
897
+ /** The one channel every member is addressed on. */
898
+ channel_id: string;
899
+ /** Every member of the group, including the writer. Exactly one
900
+ * carries `role: "Source"` — that member is where the secret
901
+ * originated, which is why no separate owner field is needed. */
902
+ members: Array<{
903
+ replica_id: string;
904
+ /** Every endpoint this peer advertised, in the order it offered them. */
905
+ transports: Endpoint[];
906
+ role: "Source" | "Destination";
907
+ communication_info?: Record<string, string>;
908
+ }>;
909
+ shared_key: Uint8Array;
910
+ };
911
+ };
912
+ }
829
913
  /** Peer's ack of a secret sync we sent. `status` is the `StatusEnum`
830
914
  * integer (0 = Ok), `memo` is the peer's explanation. */
831
915
  | {
@@ -834,7 +918,7 @@ export type DeRecEvent = {
834
918
  from_replica_id: string;
835
919
  secret_id: string;
836
920
  version: number;
837
- status: number;
921
+ status: StatusEnum;
838
922
  memo: string;
839
923
  }
840
924
  /** A peer announced an updated `communication_info` map and/or
@@ -851,7 +935,7 @@ export type DeRecEvent = {
851
935
  | {
852
936
  type: "ChannelInfoUpdateRejected";
853
937
  channel_id: string;
854
- status: number;
938
+ status: StatusEnum;
855
939
  memo: string;
856
940
  }
857
941
  /** Emitted by `process()` in place of `ActionRequired` when the
@@ -868,6 +952,38 @@ export type DeRecEvent = {
868
952
  } | {
869
953
  type: "NoOp";
870
954
  }
955
+ /** An inbound message was dropped untouched: no store was written and
956
+ * nothing was sent back. `reason` says why.
957
+ *
958
+ * `"PendingVerification"` means the peer sent something before this
959
+ * device confirmed the channel's fingerprint — typically a replica source
960
+ * pushing its first copy while this destination still shows the code.
961
+ * Confirming does not replay it: after `verifyFingerprint` succeeds, a
962
+ * replica destination calls `start(FlowKind.ReplicaDiscovery)` to pull
963
+ * the copy itself. `"Expired"` means the message was older than the
964
+ * inbound timeout. `trace_id` matches the peer's `*Started` event for
965
+ * the same round (`"0"` when the sender set none). */
966
+ | {
967
+ type: "MessageIgnored";
968
+ channel_id: string;
969
+ reason: IgnoreReason;
970
+ trace_id: string;
971
+ }
972
+ /** Returned by `restore`: a roster entry got no channel, so this device
973
+ * cannot reach that peer. Every other entry and the user-secret snapshot
974
+ * were restored; `reason` says why this one was not. `"NoTransports"`
975
+ * means the recovered roster names no endpoint for it.
976
+ *
977
+ * For a helper, `channel_id` is its channel and `replica_id` is absent.
978
+ * For a replica group member, `channel_id` is the group's channel and
979
+ * `replica_id` names the member. The peer itself is untouched — a helper
980
+ * still holds its share — and pairing with it again makes it reachable. */
981
+ | {
982
+ type: "PeerNotRestored";
983
+ channel_id: string;
984
+ replica_id?: string;
985
+ reason: NotRestoredReason;
986
+ }
871
987
  /** A pairing handshake was dispatched successfully. `kind` is the
872
988
  * local party's role — same value the subsequent `PairingCompleted`
873
989
  * will carry. Emitted by `start(Pairing)`. */
@@ -978,8 +1094,8 @@ export type DeRecEvent = {
978
1094
  * inbound shares. The protocol enforces no size, quota or rate limit
979
1095
  * of its own, and `maxShareSize` is checked for range overlap at
980
1096
  * pairing time only, never against an actual share. While this is
981
- * `false`, `ActionRequired` carries the decoded request, so the
982
- * application can inspect the share and call `reject()` with
1097
+ * `false`, `ActionRequired` carries `share_size`, so the application
1098
+ * can compare it to its quota and call `reject()` with
983
1099
  * `StatusEnum.SizeLimitExceeded`. Setting it `true` removes that
984
1100
  * opportunity entirely: every share from every paired Owner is stored
985
1101
  * unconditionally, at whatever size it arrives. Keep off in any
@@ -1055,6 +1171,12 @@ export interface CommunicationInfoKeyValue {
1055
1171
  export interface CommunicationInfo {
1056
1172
  communication_info_entries: CommunicationInfoKeyValue[];
1057
1173
  }
1174
+ /** Why a `MessageIgnored` event dropped a message. Matches the Rust
1175
+ * `IgnoreReason` discriminants one-for-one. */
1176
+ export type IgnoreReason = "PendingVerification" | "Expired";
1177
+ /** Why a `PeerNotRestored` event left a roster entry without a channel.
1178
+ * Matches the Rust `NotRestoredReason` discriminants one-for-one. */
1179
+ export type NotRestoredReason = "NoTransports";
1058
1180
  /**
1059
1181
  * The label vocabulary for `ActionRequired.action_kind` and
1060
1182
  * `AutoAccepted.action_kind` — one value per pending-action kind the
@@ -1081,17 +1203,9 @@ export interface PairRequestMessage {
1081
1203
  nonce: bigint;
1082
1204
  communication_info?: CommunicationInfo;
1083
1205
  parameter_range?: ParameterRange;
1084
- /**
1085
- * @deprecated Reading this field directly is incorrect: its meaning narrowed
1086
- * to "one entry of a list, and possibly absent", so a peer advertising only
1087
- * `supported_transports` looks unreachable to a reader that was correct
1088
- * before 0.0.3. Call {@link advertisedEndpoints}, which resolves both
1089
- * spellings. Removed at 0.0.5.
1090
- */
1091
- transport_protocol?: TransportProtocol;
1092
1206
  timestamp?: Timestamp;
1093
1207
  /** Every transport endpoint the initiator can be reached on, in its own
1094
- * preference order. Empty means "only `transport_protocol` is offered". */
1208
+ * preference order. */
1095
1209
  supported_transports: TransportProtocol[];
1096
1210
  }
1097
1211
  export interface PairResponseMessage {
@@ -1111,21 +1225,12 @@ export interface PairResponseMessage {
1111
1225
  }
1112
1226
  export interface PrePairRequestMessage {
1113
1227
  nonce: bigint;
1114
- /**
1115
- * @deprecated Reading this field directly is incorrect: its meaning narrowed
1116
- * to "one entry of a list, and possibly absent", so a peer advertising only
1117
- * `supported_transports` looks unreachable to a reader that was correct
1118
- * before 0.0.3. Call {@link advertisedEndpoints}, which resolves both
1119
- * spellings. Removed at 0.0.5.
1120
- */
1121
- transport_protocol?: TransportProtocol;
1122
1228
  timestamp?: Timestamp;
1123
1229
  /**
1124
1230
  * Every endpoint the sender can be reached on for the PrePair reply, in
1125
- * its own preference order. At least one of this and `transport_protocol`
1126
- * must be present.
1231
+ * its own preference order.
1127
1232
  */
1128
- supported_transports?: TransportProtocol[];
1233
+ supported_transports: TransportProtocol[];
1129
1234
  }
1130
1235
  export interface PrePairResponseMessage {
1131
1236
  result?: DeRecResult;
@@ -1281,6 +1386,12 @@ export interface PairingProcessResult {
1281
1386
  export interface ProducePrePairResult {
1282
1387
  envelope: Uint8Array;
1283
1388
  }
1389
+ export interface ProducePrePairNoKeysResult {
1390
+ envelope: Uint8Array;
1391
+ /** Secret key material generated for this pairing. The caller MUST persist
1392
+ * it: the `PairRequest` that follows is encrypted to it. */
1393
+ secret_key_material: Uint8Array;
1394
+ }
1284
1395
  export interface PrePairRequestExtractResult {
1285
1396
  request: PrePairRequestMessage;
1286
1397
  }
package/lib/types.js CHANGED
@@ -2,11 +2,14 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
  // Copyright (c) 2026 DeRec Alliance. All rights reserved.
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.FlowKind = exports.ContactMode = exports.SenderKind = void 0;
5
+ exports.StatusEnum = exports.FlowKind = exports.ContactMode = exports.SenderKind = void 0;
6
6
  exports.channelFilterMatches = channelFilterMatches;
7
7
  exports.advertisedEndpoints = advertisedEndpoints;
8
+ exports.protocol_version = protocol_version;
9
+ exports.generate_replica_id = generate_replica_id;
8
10
  exports.sequentialFailover = sequentialFailover;
9
11
  exports.singleEndpointTransport = singleEndpointTransport;
12
+ const native_1 = require("./native");
10
13
  /**
11
14
  * Whether a channel or member with these attributes survives `filter`.
12
15
  *
@@ -37,13 +40,6 @@ function channelFilterMatches(filter, id, status, role) {
37
40
  /**
38
41
  * The endpoints a peer-supplied message advertises, in the peer's own order.
39
42
  *
40
- * Yields `supported_transports` when it is non-empty, and otherwise the
41
- * singular `transport_protocol` — which is how every implementation predating
42
- * the offer list advertises, and the reason this is a function rather than a
43
- * field read. Reading `transport_protocol` directly is a bug: its meaning
44
- * narrowed to "one entry of a list, and possibly absent", so a peer that has
45
- * moved past it looks unreachable to a reader that was correct before 0.0.3.
46
- *
47
43
  * Reports what was advertised, not what is acceptable — nothing here is
48
44
  * validated, and the protocol still applies its own transport policy to
49
45
  * whatever it records.
@@ -51,10 +47,23 @@ function channelFilterMatches(filter, id, status, role) {
51
47
  function advertisedEndpoints(message) {
52
48
  if (!message)
53
49
  return [];
54
- const offers = message.supported_transports ?? [];
55
- if (offers.length > 0)
56
- return offers;
57
- return message.transport_protocol ? [message.transport_protocol] : [];
50
+ return message.supported_transports ?? [];
51
+ }
52
+ /**
53
+ * The DeRec protocol version this build speaks — the `protocolVersionMajor` /
54
+ * `protocolVersionMinor` it writes into every envelope it produces. Not the
55
+ * package version.
56
+ */
57
+ function protocol_version() {
58
+ return (0, native_1.getNative)().version();
59
+ }
60
+ /**
61
+ * A fresh, random replica id — never `0`. Generate it once per device,
62
+ * persist it, and pass the same value to
63
+ * `DeRecProtocolBuilder.withReplicaId` on every init.
64
+ */
65
+ function generate_replica_id() {
66
+ return (0, native_1.getNative)().generate_replica_id();
58
67
  }
59
68
  /**
60
69
  * Builds a {@link Transport} that tries each endpoint in the order the peer
@@ -126,7 +135,7 @@ var SenderKind;
126
135
  * the scanner must fetch the actual keys over the wire via the `PrePair`
127
136
  * round-trip and verify them against the commitment before pairing.
128
137
  * - `NoKeys`: no key material and no commitment. The contact carries only
129
- * `channel_id`, `nonce`, and `transport_protocol` — small enough to be
138
+ * `channel_id`, `nonce`, and `supported_transports` — small enough to be
130
139
  * hand-typed or dictated. Keys are generated on the fly by the contact
131
140
  * creator when the `PrePairRequest` arrives; the scanner accepts them
132
141
  * without cryptographic verification. Trust rests entirely on the OOB
@@ -168,3 +177,24 @@ var FlowKind;
168
177
  * string so ids above 2^53 survive JS number handling. */
169
178
  FlowKind[FlowKind["UnpairReplica"] = 8] = "UnpairReplica";
170
179
  })(FlowKind || (exports.FlowKind = FlowKind = {}));
180
+ /** Result status carried in every protocol response (`result.proto`). Passed
181
+ * to `reject()` to say why an inbound request was refused. */
182
+ var StatusEnum;
183
+ (function (StatusEnum) {
184
+ StatusEnum[StatusEnum["Ok"] = 0] = "Ok";
185
+ StatusEnum[StatusEnum["Partial"] = 1] = "Partial";
186
+ StatusEnum[StatusEnum["Fail"] = 2] = "Fail";
187
+ StatusEnum[StatusEnum["SizeLimitExceeded"] = 3] = "SizeLimitExceeded";
188
+ StatusEnum[StatusEnum["TooFrequent"] = 4] = "TooFrequent";
189
+ StatusEnum[StatusEnum["UnknownSecretId"] = 5] = "UnknownSecretId";
190
+ StatusEnum[StatusEnum["UnknownShareVersion"] = 6] = "UnknownShareVersion";
191
+ StatusEnum[StatusEnum["DecryptionFailed"] = 7] = "DecryptionFailed";
192
+ StatusEnum[StatusEnum["VerificationFailed"] = 8] = "VerificationFailed";
193
+ StatusEnum[StatusEnum["FormatError"] = 9] = "FormatError";
194
+ StatusEnum[StatusEnum["Rejected"] = 10] = "Rejected";
195
+ StatusEnum[StatusEnum["IncompatibleParameterRange"] = 11] = "IncompatibleParameterRange";
196
+ StatusEnum[StatusEnum["UnsupportedTransportProtocol"] = 12] = "UnsupportedTransportProtocol";
197
+ StatusEnum[StatusEnum["VersionConflict"] = 13] = "VersionConflict";
198
+ StatusEnum[StatusEnum["ReplicaIdConflict"] = 14] = "ReplicaIdConflict";
199
+ StatusEnum[StatusEnum["RequestToClose"] = 99] = "RequestToClose";
200
+ })(StatusEnum || (exports.StatusEnum = StatusEnum = {}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@derec-alliance/react-native",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "description": "React Native bindings for derec-library, the Rust SDK for the DeRec protocol.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {