@derec-alliance/react-native 0.0.2 → 0.0.4
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 -2
- 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/Primitives.cpp +27 -18
- package/cpp/ProtocolHost.cpp +37 -0
- package/cpp/StoreCallbacks.cpp +127 -19
- package/cpp/derec_ffi.h +145 -24
- package/ios/DeRecFFI.xcframework/ios-arm64/Headers/derec_ffi.h +145 -24
- package/ios/DeRecFFI.xcframework/ios-arm64/libderec_library.a +0 -0
- package/ios/DeRecFFI.xcframework/ios-arm64_x86_64-simulator/Headers/derec_ffi.h +145 -24
- package/ios/DeRecFFI.xcframework/ios-arm64_x86_64-simulator/libderec_library.a +2 -2
- package/lib/primitives.d.ts +9 -9
- package/lib/primitives.js +63 -13
- package/lib/protocol.d.ts +85 -6
- package/lib/protocol.js +119 -8
- package/lib/types.d.ts +313 -29
- package/lib/types.js +109 -2
- package/package.json +2 -1
- package/src/primitives.ts +77 -21
- package/src/protocol.ts +138 -13
- package/src/types.ts +379 -35
package/src/types.ts
CHANGED
|
@@ -28,6 +28,136 @@ export interface SecretStore {
|
|
|
28
28
|
remove(secretId: string, channelId: string, kind: 0 | 1 | 2): Promise<void>;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* A channel's lifecycle status, as the Rust variant name the core emits.
|
|
34
|
+
*/
|
|
35
|
+
export type ChannelStatusName = "Pending" | "Paired" | "Unpairing";
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* A peer's role on a helper channel, as the Rust variant name.
|
|
39
|
+
*/
|
|
40
|
+
export type SenderKindName =
|
|
41
|
+
| "Owner"
|
|
42
|
+
| "Helper"
|
|
43
|
+
| "ReplicaSource"
|
|
44
|
+
| "ReplicaDestination";
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* A member's role within a replica group, as the Rust variant name.
|
|
48
|
+
*/
|
|
49
|
+
export type ReplicaRoleName = "Source" | "Destination";
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Narrows a listing from {@link ChannelStore}.
|
|
53
|
+
*
|
|
54
|
+
* Every field is a restriction, and every field's empty value means "do not
|
|
55
|
+
* restrict on this" — a filter of all-empties selects everything.
|
|
56
|
+
* Restrictions combine with AND, and `exclude` is applied last, overriding
|
|
57
|
+
* `ids`.
|
|
58
|
+
*
|
|
59
|
+
* **Returning everything under the `secretId` and ignoring the filter is
|
|
60
|
+
* correct**, and the implementation to write unless there is a measured reason
|
|
61
|
+
* not to. The library re-applies the filter to whatever you return and drops
|
|
62
|
+
* what it excludes, so a superset is trimmed before anything acts on it.
|
|
63
|
+
*
|
|
64
|
+
* Pushing the filter into your query — a `WHERE` clause, a key-condition
|
|
65
|
+
* expression — is an optimization you opt into. It saves transferring rows the
|
|
66
|
+
* caller discards, which costs bandwidth everywhere and real money on a metered
|
|
67
|
+
* backing that bills by bytes read. Verify one against
|
|
68
|
+
* `library/tests/fixtures/channel_filter.json`.
|
|
69
|
+
*
|
|
70
|
+
* The asymmetry is what makes pushdown worth verifying: the re-check can drop
|
|
71
|
+
* rows but cannot recover one that was never returned, so selecting too *few*
|
|
72
|
+
* is undetectable at runtime — no exception, no event, just a share that was
|
|
73
|
+
* never published. That matters most here, because TypeScript accepts a
|
|
74
|
+
* function of fewer parameters where more are declared: a store written before
|
|
75
|
+
* this parameter existed still satisfies the interface and compiles clean under
|
|
76
|
+
* `--strict`, so the type system cannot see the gap either.
|
|
77
|
+
*
|
|
78
|
+
* Ids are decimal strings, like every other `u64` on this bridge.
|
|
79
|
+
*/
|
|
80
|
+
export interface ChannelFilter<Role> {
|
|
81
|
+
/** Restrict to these ids. Empty selects every record. */
|
|
82
|
+
ids: string[];
|
|
83
|
+
/** Restrict to these statuses. Empty selects any status. */
|
|
84
|
+
status: ChannelStatusName[];
|
|
85
|
+
/** Restrict to this role. `null` selects any role. */
|
|
86
|
+
role: Role | null;
|
|
87
|
+
/** Omit these ids, applied after `ids`. Empty omits nothing. */
|
|
88
|
+
exclude: string[];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Whether a channel or member with these attributes survives `filter`.
|
|
93
|
+
*
|
|
94
|
+
* Every empty field means "do not restrict", `exclude` is applied after `ids`,
|
|
95
|
+
* and the restrictions combine with AND — the same contract the core states on
|
|
96
|
+
* `ChannelFilter`. A store whose backing cannot express the filter as a query
|
|
97
|
+
* can list and call this; that is correct but transfers the rows the filter
|
|
98
|
+
* exists to leave behind.
|
|
99
|
+
*
|
|
100
|
+
* `id` is a decimal string, as ids are everywhere on this bridge. `role` is the
|
|
101
|
+
* peer's `SenderKind` name for `listHelpers` and the member's `ReplicaRole`
|
|
102
|
+
* name for `listReplicas`.
|
|
103
|
+
*/
|
|
104
|
+
export function channelFilterMatches(
|
|
105
|
+
filter: HelperFilter | ReplicaFilter | null | undefined,
|
|
106
|
+
id: string,
|
|
107
|
+
status: ChannelStatusName,
|
|
108
|
+
role: SenderKindName | ReplicaRoleName,
|
|
109
|
+
): boolean {
|
|
110
|
+
if (!filter) return true;
|
|
111
|
+
const ids = filter.ids ?? [];
|
|
112
|
+
const statuses = filter.status ?? [];
|
|
113
|
+
const exclude = filter.exclude ?? [];
|
|
114
|
+
if (ids.length > 0 && !ids.includes(id)) return false;
|
|
115
|
+
if (statuses.length > 0 && !statuses.includes(status)) return false;
|
|
116
|
+
if (filter.role != null && filter.role !== role) return false;
|
|
117
|
+
return !exclude.includes(id);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* The endpoints a peer-supplied message advertises, in the peer's own order.
|
|
122
|
+
*
|
|
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
|
+
* Reports what was advertised, not what is acceptable — nothing here is
|
|
131
|
+
* validated, and the protocol still applies its own transport policy to
|
|
132
|
+
* whatever it records.
|
|
133
|
+
*/
|
|
134
|
+
export function advertisedEndpoints(
|
|
135
|
+
message:
|
|
136
|
+
| {
|
|
137
|
+
transport_protocol?: TransportProtocol;
|
|
138
|
+
supported_transports?: TransportProtocol[];
|
|
139
|
+
}
|
|
140
|
+
| null
|
|
141
|
+
| undefined,
|
|
142
|
+
): TransportProtocol[] {
|
|
143
|
+
if (!message) return [];
|
|
144
|
+
const offers = message.supported_transports ?? [];
|
|
145
|
+
if (offers.length > 0) return offers;
|
|
146
|
+
return message.transport_protocol ? [message.transport_protocol] : [];
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Narrows `listHelpers`. Ids are the channel's `channel_id` and the role is
|
|
151
|
+
* the **peer's** `peer_role`.
|
|
152
|
+
*/
|
|
153
|
+
export type HelperFilter = ChannelFilter<SenderKindName>;
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Narrows `listReplicas`. Ids are the member's `replica_id` and the role is
|
|
157
|
+
* the member's `role`.
|
|
158
|
+
*/
|
|
159
|
+
export type ReplicaFilter = ChannelFilter<ReplicaRoleName>;
|
|
160
|
+
|
|
31
161
|
/**
|
|
32
162
|
* Channel-record persistence.
|
|
33
163
|
*
|
|
@@ -48,7 +178,7 @@ export interface SecretStore {
|
|
|
48
178
|
*
|
|
49
179
|
* `listHelpers` and `listReplicas` are **not** arrays of that union — they
|
|
50
180
|
* return a JSON array of the **inner** records with the tag stripped:
|
|
51
|
-
* `[{ channel_id,
|
|
181
|
+
* `[{ schema_version, channel_id, transports, ... }, ...]`, `HelperChannel` for the first and
|
|
52
182
|
* `ReplicaMember` for the second. Wrapping each element back in
|
|
53
183
|
* `{ "Helper": ... }` will not decode.
|
|
54
184
|
*
|
|
@@ -77,8 +207,19 @@ export interface ChannelStore {
|
|
|
77
207
|
bytes: Uint8Array,
|
|
78
208
|
): Promise<void>;
|
|
79
209
|
remove(secretId: string, channelId: string, replicaId: string): Promise<boolean>;
|
|
80
|
-
/**
|
|
81
|
-
|
|
210
|
+
/**
|
|
211
|
+
* JSON array of the helper channels stored under `secretId` that `filter`
|
|
212
|
+
* selects.
|
|
213
|
+
*
|
|
214
|
+
* Apply the filter in your query rather than listing everything and
|
|
215
|
+
* discarding rows; see {@link ChannelFilter}. The library re-applies it to
|
|
216
|
+
* whatever you return, so ignoring it is slow rather than wrong — but
|
|
217
|
+
* returning fewer rows than it selects is wrong, and undetectable.
|
|
218
|
+
*/
|
|
219
|
+
listHelpers(
|
|
220
|
+
secretId: string,
|
|
221
|
+
filter: HelperFilter,
|
|
222
|
+
): Promise<Uint8Array | null | undefined>;
|
|
82
223
|
/**
|
|
83
224
|
* JSON array of the replica-group members stored under `secretId`,
|
|
84
225
|
* including this device's own row.
|
|
@@ -97,7 +238,10 @@ export interface ChannelStore {
|
|
|
97
238
|
* insertion order after arbitrary edits are both effectively arbitrary.
|
|
98
239
|
* Order explicitly to make succession predictable.
|
|
99
240
|
*/
|
|
100
|
-
listReplicas(
|
|
241
|
+
listReplicas(
|
|
242
|
+
secretId: string,
|
|
243
|
+
filter: ReplicaFilter,
|
|
244
|
+
): Promise<Uint8Array | null | undefined>;
|
|
101
245
|
linkChannel(
|
|
102
246
|
secretId: string,
|
|
103
247
|
channelId: string,
|
|
@@ -155,7 +299,7 @@ export interface UserSecretStore {
|
|
|
155
299
|
* returns the exact blob it received, `remove` drops the row, and
|
|
156
300
|
* `loadAll` returns every blob whose `kind` matches the requested
|
|
157
301
|
* category (`0` = PendingVerification, `1` = PendingRecovery,
|
|
158
|
-
* `2` = PendingUnpair, `3` = SharingRound, `4` =
|
|
302
|
+
* `2` = PendingUnpair, `3` = SharingRound, `4` = PendingReplicaDiscovery).
|
|
159
303
|
*
|
|
160
304
|
* Rows are keyed by `(secretId, StateKey)` — the `keyJson` buffer is
|
|
161
305
|
* a JSON object `{ kind, channel_id?, version? }` matching the `kind`
|
|
@@ -197,7 +341,109 @@ export interface StateStore {
|
|
|
197
341
|
* DeRec over request/response transports" in the Rust SDK README.
|
|
198
342
|
*/
|
|
199
343
|
export interface Transport {
|
|
200
|
-
|
|
344
|
+
/**
|
|
345
|
+
* Delivers `message` to a peer reachable at any of `endpoints`.
|
|
346
|
+
*
|
|
347
|
+
* `endpoints` are the addresses that peer advertised, in the order it
|
|
348
|
+
* offered them, already filtered to those the library will record. The
|
|
349
|
+
* library does not rank them: which to dial, and whether to fall back when
|
|
350
|
+
* one is unreachable, is this implementation's choice. Never empty.
|
|
351
|
+
*
|
|
352
|
+
* Delivery to any one endpoint is success. Reject only when the message
|
|
353
|
+
* reached none of them.
|
|
354
|
+
*
|
|
355
|
+
* **Deliver once.** Every entry addresses the same peer, so sending to all
|
|
356
|
+
* of them delivers one authenticated message several times. Stop at the
|
|
357
|
+
* first success. The protocol's handlers are idempotent, so a duplicate
|
|
358
|
+
* does not corrupt state, but it is still a duplicate to anything counting
|
|
359
|
+
* messages, and a peer entitled to treat re-delivery as a replay will.
|
|
360
|
+
*
|
|
361
|
+
* **Prefer an adapter to writing this by hand.** Choosing which endpoint to
|
|
362
|
+
* dial is yours and stays here; the bookkeeping around it is the same
|
|
363
|
+
* everywhere and is already written and tested. Write a {@link SendOne} and
|
|
364
|
+
* wrap it in {@link sequentialFailover}. Taking `endpoints[0]` type-checks,
|
|
365
|
+
* passes every test, and silently gives up the failover the list exists to
|
|
366
|
+
* provide — if that is genuinely wanted, say so with
|
|
367
|
+
* {@link singleEndpointTransport} rather than by indexing.
|
|
368
|
+
*/
|
|
369
|
+
send(
|
|
370
|
+
endpoints: ReadonlyArray<{ protocol: string; uri: string }>,
|
|
371
|
+
message: Uint8Array,
|
|
372
|
+
): Promise<void>;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Delivers one message to one endpoint.
|
|
377
|
+
*
|
|
378
|
+
* The narrow half of a transport: everything genuinely about dialing, and
|
|
379
|
+
* nothing about which endpoint to dial. Pass one of these to
|
|
380
|
+
* {@link sequentialFailover} or {@link singleEndpointTransport} to get a
|
|
381
|
+
* {@link Transport}.
|
|
382
|
+
*
|
|
383
|
+
* Rejecting means the endpoint did not receive the message. The rejection
|
|
384
|
+
* reason need not distinguish "unreachable" from "rejected":
|
|
385
|
+
* {@link sequentialFailover} treats both as a reason to try the next endpoint,
|
|
386
|
+
* which is the safe reading. Trying an endpoint that would have refused costs
|
|
387
|
+
* a round trip; skipping one that would have worked costs the delivery.
|
|
388
|
+
*/
|
|
389
|
+
export type SendOne = (
|
|
390
|
+
endpoint: { protocol: string; uri: string },
|
|
391
|
+
message: Uint8Array,
|
|
392
|
+
) => Promise<void>;
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Builds a {@link Transport} that tries each endpoint in the order the peer
|
|
396
|
+
* offered it and stops at the first success.
|
|
397
|
+
*
|
|
398
|
+
* An error is thrown only when every endpoint failed. The message is delivered
|
|
399
|
+
* at most once.
|
|
400
|
+
*
|
|
401
|
+
* This is the right default. A peer advertising several endpoints is saying it
|
|
402
|
+
* can be reached at any of them, and the reason 0.0.3 records the whole list is
|
|
403
|
+
* so one being down does not end the conversation.
|
|
404
|
+
*/
|
|
405
|
+
export function sequentialFailover(dialer: SendOne): Transport {
|
|
406
|
+
return {
|
|
407
|
+
async send(endpoints, message) {
|
|
408
|
+
let last: unknown;
|
|
409
|
+
for (const endpoint of endpoints) {
|
|
410
|
+
try {
|
|
411
|
+
await dialer(endpoint, message);
|
|
412
|
+
return;
|
|
413
|
+
} catch (e) {
|
|
414
|
+
last = e;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
// `endpoints` is never empty — the library refuses to record a peer
|
|
418
|
+
// whose endpoints were all filtered away — so reaching here means at
|
|
419
|
+
// least one attempt was made and `last` is populated.
|
|
420
|
+
throw last ?? new Error('send was called with no endpoints');
|
|
421
|
+
},
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Builds a {@link Transport} that uses the first endpoint only.
|
|
427
|
+
*
|
|
428
|
+
* Reproduces the pre-0.0.3 behaviour exactly, for an application that genuinely
|
|
429
|
+
* serves one endpoint or has a reason not to fail over.
|
|
430
|
+
*
|
|
431
|
+
* It exists so that choosing it is visible. `endpoints[0]` written inline looks
|
|
432
|
+
* like an implementation detail and reads as finished; naming this records that
|
|
433
|
+
* failover was considered and declined, which is a claim a reviewer can
|
|
434
|
+
* disagree with. If the peers this application talks to advertise more than one
|
|
435
|
+
* endpoint, prefer {@link sequentialFailover} — every endpoint after the first
|
|
436
|
+
* is reachability being thrown away.
|
|
437
|
+
*/
|
|
438
|
+
export function singleEndpointTransport(dialer: SendOne): Transport {
|
|
439
|
+
return {
|
|
440
|
+
async send(endpoints, message) {
|
|
441
|
+
if (endpoints.length === 0) {
|
|
442
|
+
throw new Error('send was called with no endpoints');
|
|
443
|
+
}
|
|
444
|
+
await dialer(endpoints[0]!, message);
|
|
445
|
+
},
|
|
446
|
+
};
|
|
201
447
|
}
|
|
202
448
|
|
|
203
449
|
export enum SenderKind {
|
|
@@ -250,12 +496,12 @@ export enum FlowKind {
|
|
|
250
496
|
/** Ask the replica group whether this device is behind, and catch up if it
|
|
251
497
|
* is. Replica-only, and takes no parameters — the group and this device's
|
|
252
498
|
* own version both come from the stores. */
|
|
253
|
-
|
|
499
|
+
ReplicaDiscovery = 7,
|
|
254
500
|
/** Remove a member from the replica group. Replica-only. Naming this device
|
|
255
501
|
* is a voluntary departure; naming another is an eviction. Params:
|
|
256
502
|
* `{ replica_id: string; memo?: string }` — `replica_id` is a decimal
|
|
257
503
|
* string so ids above 2^53 survive JS number handling. */
|
|
258
|
-
|
|
504
|
+
UnpairReplica = 8,
|
|
259
505
|
}
|
|
260
506
|
|
|
261
507
|
export type UnpairAck = "required" | "not_required";
|
|
@@ -264,6 +510,13 @@ export interface ContactMessage {
|
|
|
264
510
|
channel_id: bigint;
|
|
265
511
|
/** `ContactMode` numeric value (0 = INLINE_KEYS, 1 = HASHED_KEYS, 2 = NO_KEYS). */
|
|
266
512
|
contact_mode: number;
|
|
513
|
+
/**
|
|
514
|
+
* @deprecated Reading this field directly is incorrect: its meaning narrowed
|
|
515
|
+
* to "one entry of a list, and possibly absent", so a peer advertising only
|
|
516
|
+
* `supported_transports` looks unreachable to a reader that was correct
|
|
517
|
+
* before 0.0.3. Call {@link advertisedEndpoints}, which resolves both
|
|
518
|
+
* spellings. Removed at 0.0.5.
|
|
519
|
+
*/
|
|
267
520
|
transport_protocol?: TransportProtocol;
|
|
268
521
|
nonce: bigint;
|
|
269
522
|
/** Present only when `contact_mode === ContactMode.InlineKeys`. */
|
|
@@ -273,6 +526,10 @@ export interface ContactMessage {
|
|
|
273
526
|
/** Present only when `contact_mode === ContactMode.HashedKeys`. SHA-384 digest (48 bytes). */
|
|
274
527
|
contact_binding_hash?: Uint8Array;
|
|
275
528
|
timestamp?: Timestamp;
|
|
529
|
+
/** Every transport endpoint the creator of this contact can be reached
|
|
530
|
+
* on, in its own preference order. Empty means "only
|
|
531
|
+
* `transport_protocol` is offered". */
|
|
532
|
+
supported_transports: TransportProtocol[];
|
|
276
533
|
}
|
|
277
534
|
|
|
278
535
|
export interface UserSecret {
|
|
@@ -319,8 +576,20 @@ export interface UpdateChannelInfoParams {
|
|
|
319
576
|
* map untouched; pass an empty object to clear it. */
|
|
320
577
|
communication_info?: Record<string, string>;
|
|
321
578
|
|
|
322
|
-
/**
|
|
579
|
+
/**
|
|
580
|
+
* New transport endpoint. Absent leaves it untouched.
|
|
581
|
+
*
|
|
582
|
+
* @deprecated Use `own_transports`, which carries every endpoint this node
|
|
583
|
+
* now serves; its first entry also fills this field for peers predating the
|
|
584
|
+
* list. Removed at 0.0.5.
|
|
585
|
+
*/
|
|
323
586
|
transport_protocol?: { uri: string; protocol: number };
|
|
587
|
+
/**
|
|
588
|
+
* Every endpoint this node now serves, in its own preference order.
|
|
589
|
+
* Omitted leaves the target(s)' stored set untouched. Takes precedence
|
|
590
|
+
* over `transport_protocol`, whose first entry it also fills.
|
|
591
|
+
*/
|
|
592
|
+
own_transports?: TransportProtocol[];
|
|
324
593
|
}
|
|
325
594
|
|
|
326
595
|
/**
|
|
@@ -349,11 +618,11 @@ export interface Timeouts {
|
|
|
349
618
|
expired_channels?: { enabled: boolean; timeout_in_secs: number };
|
|
350
619
|
}
|
|
351
620
|
|
|
352
|
-
/** `
|
|
621
|
+
/** `ReplicaDiscovery` takes no parameters: the group and this device's own version
|
|
353
622
|
* are both read from the stores. The argument may be omitted entirely. */
|
|
354
|
-
export type
|
|
623
|
+
export type ReplicaDiscoveryParams = Record<string, never>;
|
|
355
624
|
|
|
356
|
-
export interface
|
|
625
|
+
export interface UnpairReplicaParams {
|
|
357
626
|
/** The member to remove, as a **decimal** `u64` string — the same form
|
|
358
627
|
* `ReplicaPaired.peer_replica_id` hands back. A value naming no current
|
|
359
628
|
* member is rejected; it is not silently ignored. */
|
|
@@ -378,7 +647,7 @@ export type DeRecEvent =
|
|
|
378
647
|
|
|
379
648
|
action: Uint8Array;
|
|
380
649
|
|
|
381
|
-
action_kind:
|
|
650
|
+
action_kind: PendingActionKind;
|
|
382
651
|
peer_communication_info?: Record<string, string>;
|
|
383
652
|
|
|
384
653
|
sender_kind?: SenderKind;
|
|
@@ -437,7 +706,7 @@ export type DeRecEvent =
|
|
|
437
706
|
/** A replica catch-up finished. `fetched_from` is absent when this device
|
|
438
707
|
* was already current, in which case no hydration event follows. */
|
|
439
708
|
| {
|
|
440
|
-
type: "
|
|
709
|
+
type: "ReplicaDiscoveryComplete";
|
|
441
710
|
local_version: number;
|
|
442
711
|
group_version: number;
|
|
443
712
|
fetched_from?: string;
|
|
@@ -467,7 +736,8 @@ export type DeRecEvent =
|
|
|
467
736
|
secret: {
|
|
468
737
|
helpers: Array<{
|
|
469
738
|
channel_id: string;
|
|
470
|
-
|
|
739
|
+
/** Every endpoint this peer advertised, in the order it offered them. */
|
|
740
|
+
transports: Array<{ uri: string; protocol: number }>;
|
|
471
741
|
shared_key: Uint8Array;
|
|
472
742
|
communication_info: Record<string, string>;
|
|
473
743
|
}>;
|
|
@@ -488,7 +758,8 @@ export type DeRecEvent =
|
|
|
488
758
|
* originated, which is why no separate owner field is needed. */
|
|
489
759
|
members: Array<{
|
|
490
760
|
replica_id: string;
|
|
491
|
-
|
|
761
|
+
/** Every endpoint this peer advertised, in the order it offered them. */
|
|
762
|
+
transports: Array<{ uri: string; protocol: number }>;
|
|
492
763
|
role: "Source" | "Destination";
|
|
493
764
|
communication_info: Record<string, string>;
|
|
494
765
|
}>;
|
|
@@ -509,7 +780,7 @@ export type DeRecEvent =
|
|
|
509
780
|
/** Fires alongside `PairingCompleted` on replica-mode pair handshakes.
|
|
510
781
|
* `peer_replica_id` is the peer's `u64` as a **decimal** string,
|
|
511
782
|
* matching the wire `derec.replica_id` representation and every other
|
|
512
|
-
* id across this boundary. Pass it back verbatim — `
|
|
783
|
+
* id across this boundary. Pass it back verbatim — `UnpairReplica`
|
|
513
784
|
* expects the same decimal form. The local side's role
|
|
514
785
|
* (`ReplicaSource` vs `ReplicaDestination`) is on the persisted
|
|
515
786
|
* channel record — replica pairings are unidirectional, so there is
|
|
@@ -534,7 +805,8 @@ export type DeRecEvent =
|
|
|
534
805
|
secret: {
|
|
535
806
|
helpers: Array<{
|
|
536
807
|
channel_id: string;
|
|
537
|
-
|
|
808
|
+
/** Every endpoint this peer advertised, in the order it offered them. */
|
|
809
|
+
transports: Array<{ uri: string; protocol: number }>;
|
|
538
810
|
shared_key: Uint8Array;
|
|
539
811
|
communication_info: Record<string, string>;
|
|
540
812
|
}>;
|
|
@@ -553,7 +825,8 @@ export type DeRecEvent =
|
|
|
553
825
|
* originated, which is why no separate owner field is needed. */
|
|
554
826
|
members: Array<{
|
|
555
827
|
replica_id: string;
|
|
556
|
-
|
|
828
|
+
/** Every endpoint this peer advertised, in the order it offered them. */
|
|
829
|
+
transports: Array<{ uri: string; protocol: number }>;
|
|
557
830
|
role: "Source" | "Destination";
|
|
558
831
|
communication_info: Record<string, string>;
|
|
559
832
|
}>;
|
|
@@ -583,7 +856,8 @@ export type DeRecEvent =
|
|
|
583
856
|
secret: {
|
|
584
857
|
helpers: Array<{
|
|
585
858
|
channel_id: string;
|
|
586
|
-
|
|
859
|
+
/** Every endpoint this peer advertised, in the order it offered them. */
|
|
860
|
+
transports: Array<{ uri: string; protocol: number }>;
|
|
587
861
|
shared_key: Uint8Array;
|
|
588
862
|
communication_info: Record<string, string>;
|
|
589
863
|
}>;
|
|
@@ -602,7 +876,8 @@ export type DeRecEvent =
|
|
|
602
876
|
* originated, which is why no separate owner field is needed. */
|
|
603
877
|
members: Array<{
|
|
604
878
|
replica_id: string;
|
|
605
|
-
|
|
879
|
+
/** Every endpoint this peer advertised, in the order it offered them. */
|
|
880
|
+
transports: Array<{ uri: string; protocol: number }>;
|
|
606
881
|
role: "Source" | "Destination";
|
|
607
882
|
communication_info: Record<string, string>;
|
|
608
883
|
}>;
|
|
@@ -649,21 +924,21 @@ export type DeRecEvent =
|
|
|
649
924
|
* for observability — no further action is required. `action_kind`
|
|
650
925
|
* is the same label vocabulary as `ActionRequired.action_kind`
|
|
651
926
|
* (`"Pairing"`, `"StoreShare"`, …). */
|
|
652
|
-
| { type: "AutoAccepted"; channel_id: string; action_kind:
|
|
927
|
+
| { type: "AutoAccepted"; channel_id: string; action_kind: PendingActionKind }
|
|
653
928
|
| { type: "NoOp" }
|
|
654
929
|
/** A pairing handshake was dispatched successfully. `kind` is the
|
|
655
930
|
* local party's role — same value the subsequent `PairingCompleted`
|
|
656
931
|
* will carry. Emitted by `start(Pairing)`. */
|
|
657
|
-
| { type: "PairingStarted"; channel_id: string; kind: SenderKind }
|
|
932
|
+
| { type: "PairingStarted"; channel_id: string; kind: SenderKind; trace_id: string }
|
|
658
933
|
/** A discovery request was dispatched to `channel_id`. Emitted per
|
|
659
934
|
* targeted helper by `start(Discovery)`. */
|
|
660
|
-
| { type: "DiscoveryStarted"; channel_id: string }
|
|
935
|
+
| { type: "DiscoveryStarted"; channel_id: string; trace_id: string }
|
|
661
936
|
/** A discovery request could not be dispatched to `channel_id`. Other
|
|
662
937
|
* targeted channels are unaffected. */
|
|
663
938
|
| { type: "DiscoveryFailed"; channel_id: string; error: string }
|
|
664
939
|
/** A share-storage request was dispatched to `channel_id`. Emitted per
|
|
665
940
|
* targeted peer by `start(ProtectSecret)`. */
|
|
666
|
-
| { type: "ProtectSecretStarted"; channel_id: string; version: number }
|
|
941
|
+
| { type: "ProtectSecretStarted"; channel_id: string; version: number; trace_id: string }
|
|
667
942
|
/** A share-storage request could not be dispatched to `channel_id`. */
|
|
668
943
|
| {
|
|
669
944
|
type: "ProtectSecretFailed";
|
|
@@ -672,7 +947,7 @@ export type DeRecEvent =
|
|
|
672
947
|
error: string;
|
|
673
948
|
}
|
|
674
949
|
/** A verify-share challenge was dispatched to `channel_id`. */
|
|
675
|
-
| { type: "VerifySharesStarted"; channel_id: string; version: number }
|
|
950
|
+
| { type: "VerifySharesStarted"; channel_id: string; version: number; trace_id: string }
|
|
676
951
|
/** A verify-share challenge could not be dispatched to `channel_id`. */
|
|
677
952
|
| {
|
|
678
953
|
type: "VerifySharesFailed";
|
|
@@ -681,7 +956,7 @@ export type DeRecEvent =
|
|
|
681
956
|
error: string;
|
|
682
957
|
}
|
|
683
958
|
/** A recovery share request was dispatched to `channel_id`. */
|
|
684
|
-
| { type: "RecoverSecretStarted"; channel_id: string; version: number }
|
|
959
|
+
| { type: "RecoverSecretStarted"; channel_id: string; version: number; trace_id: string }
|
|
685
960
|
/** A recovery share request could not be dispatched to `channel_id`. */
|
|
686
961
|
| {
|
|
687
962
|
type: "RecoverSecretFailed";
|
|
@@ -693,9 +968,9 @@ export type DeRecEvent =
|
|
|
693
968
|
* `Unpaired` event once the peer acknowledges (or in the same event
|
|
694
969
|
* vec, under `UnpairAck.NotRequired`). */
|
|
695
970
|
| { type: "UnpairFailed"; channel_id: string; error: string }
|
|
696
|
-
| { type: "UnpairStarted"; channel_id: string }
|
|
971
|
+
| { type: "UnpairStarted"; channel_id: string; trace_id: string }
|
|
697
972
|
/** An update-channel-info request was dispatched to `channel_id`. */
|
|
698
|
-
| { type: "UpdateChannelInfoStarted"; channel_id: string }
|
|
973
|
+
| { type: "UpdateChannelInfoStarted"; channel_id: string; trace_id: string }
|
|
699
974
|
/** An update-channel-info request could not be dispatched to
|
|
700
975
|
* `channel_id`. */
|
|
701
976
|
| { type: "UpdateChannelInfoFailed"; channel_id: string; error: string };
|
|
@@ -756,7 +1031,12 @@ export interface GetSecretIdsVersionsRequestMessage {
|
|
|
756
1031
|
timestamp?: Timestamp;
|
|
757
1032
|
/** Ephemeral endpoint where the requester wants the response routed.
|
|
758
1033
|
* Absent means "use the channel's stored peer endpoint". */
|
|
759
|
-
|
|
1034
|
+
/**
|
|
1035
|
+
* Every endpoint the requester can be answered on for this exchange, in
|
|
1036
|
+
* its own preference order. Omitted means route to the endpoints already
|
|
1037
|
+
* recorded for the channel.
|
|
1038
|
+
*/
|
|
1039
|
+
reply_to?: TransportProtocol[];
|
|
760
1040
|
/** Replica-group member that sent this; see `replicaId` semantics. */
|
|
761
1041
|
replica_id?: bigint;
|
|
762
1042
|
}
|
|
@@ -808,6 +1088,22 @@ export interface CommunicationInfo {
|
|
|
808
1088
|
// `ContactMessage` is defined once above and covers both `INLINE_KEYS` and
|
|
809
1089
|
// `HASHED_KEYS` modes.
|
|
810
1090
|
|
|
1091
|
+
/**
|
|
1092
|
+
* The label vocabulary for `ActionRequired.action_kind` and
|
|
1093
|
+
* `AutoAccepted.action_kind` — one value per pending-action kind the
|
|
1094
|
+
* protocol can raise. Matches the Rust `PendingActionKind` discriminants
|
|
1095
|
+
* one-for-one.
|
|
1096
|
+
*/
|
|
1097
|
+
export type PendingActionKind =
|
|
1098
|
+
| "Pairing"
|
|
1099
|
+
| "PrePair"
|
|
1100
|
+
| "StoreShare"
|
|
1101
|
+
| "VerifyShare"
|
|
1102
|
+
| "Discovery"
|
|
1103
|
+
| "GetShare"
|
|
1104
|
+
| "Unpair"
|
|
1105
|
+
| "UpdateChannelInfo";
|
|
1106
|
+
|
|
811
1107
|
export interface ParameterRange {
|
|
812
1108
|
min_share_size: bigint;
|
|
813
1109
|
max_share_size: bigint;
|
|
@@ -828,8 +1124,18 @@ export interface PairRequestMessage {
|
|
|
828
1124
|
nonce: bigint;
|
|
829
1125
|
communication_info?: CommunicationInfo;
|
|
830
1126
|
parameter_range?: ParameterRange;
|
|
1127
|
+
/**
|
|
1128
|
+
* @deprecated Reading this field directly is incorrect: its meaning narrowed
|
|
1129
|
+
* to "one entry of a list, and possibly absent", so a peer advertising only
|
|
1130
|
+
* `supported_transports` looks unreachable to a reader that was correct
|
|
1131
|
+
* before 0.0.3. Call {@link advertisedEndpoints}, which resolves both
|
|
1132
|
+
* spellings. Removed at 0.0.5.
|
|
1133
|
+
*/
|
|
831
1134
|
transport_protocol?: TransportProtocol;
|
|
832
1135
|
timestamp?: Timestamp;
|
|
1136
|
+
/** Every transport endpoint the initiator can be reached on, in its own
|
|
1137
|
+
* preference order. Empty means "only `transport_protocol` is offered". */
|
|
1138
|
+
supported_transports: TransportProtocol[];
|
|
833
1139
|
}
|
|
834
1140
|
|
|
835
1141
|
export interface PairResponseMessage {
|
|
@@ -850,8 +1156,21 @@ export interface PairResponseMessage {
|
|
|
850
1156
|
|
|
851
1157
|
export interface PrePairRequestMessage {
|
|
852
1158
|
nonce: bigint;
|
|
1159
|
+
/**
|
|
1160
|
+
* @deprecated Reading this field directly is incorrect: its meaning narrowed
|
|
1161
|
+
* to "one entry of a list, and possibly absent", so a peer advertising only
|
|
1162
|
+
* `supported_transports` looks unreachable to a reader that was correct
|
|
1163
|
+
* before 0.0.3. Call {@link advertisedEndpoints}, which resolves both
|
|
1164
|
+
* spellings. Removed at 0.0.5.
|
|
1165
|
+
*/
|
|
853
1166
|
transport_protocol?: TransportProtocol;
|
|
854
1167
|
timestamp?: Timestamp;
|
|
1168
|
+
/**
|
|
1169
|
+
* Every endpoint the sender can be reached on for the PrePair reply, in
|
|
1170
|
+
* its own preference order. At least one of this and `transport_protocol`
|
|
1171
|
+
* must be present.
|
|
1172
|
+
*/
|
|
1173
|
+
supported_transports?: TransportProtocol[];
|
|
855
1174
|
}
|
|
856
1175
|
|
|
857
1176
|
export interface PrePairResponseMessage {
|
|
@@ -869,7 +1188,12 @@ export interface GetShareRequestMessage {
|
|
|
869
1188
|
version: number;
|
|
870
1189
|
timestamp?: Timestamp;
|
|
871
1190
|
/** Ephemeral response endpoint; see `replyTo` semantics. */
|
|
872
|
-
|
|
1191
|
+
/**
|
|
1192
|
+
* Every endpoint the requester can be answered on for this exchange, in
|
|
1193
|
+
* its own preference order. Omitted means route to the endpoints already
|
|
1194
|
+
* recorded for the channel.
|
|
1195
|
+
*/
|
|
1196
|
+
reply_to?: TransportProtocol[];
|
|
873
1197
|
/** Replica-group member that sent this; see `replicaId` semantics. */
|
|
874
1198
|
replica_id?: bigint;
|
|
875
1199
|
}
|
|
@@ -911,7 +1235,12 @@ export interface StoreShareRequestMessage {
|
|
|
911
1235
|
timestamp?: Timestamp;
|
|
912
1236
|
secret_id: bigint;
|
|
913
1237
|
/** Ephemeral response endpoint; see `replyTo` semantics. */
|
|
914
|
-
|
|
1238
|
+
/**
|
|
1239
|
+
* Every endpoint the requester can be answered on for this exchange, in
|
|
1240
|
+
* its own preference order. Omitted means route to the endpoints already
|
|
1241
|
+
* recorded for the channel.
|
|
1242
|
+
*/
|
|
1243
|
+
reply_to?: TransportProtocol[];
|
|
915
1244
|
/** Replica-group member that sent this; see `replicaId` semantics. */
|
|
916
1245
|
replica_id?: bigint;
|
|
917
1246
|
}
|
|
@@ -929,7 +1258,12 @@ export interface UnpairRequestMessage {
|
|
|
929
1258
|
memo: string;
|
|
930
1259
|
timestamp?: Timestamp;
|
|
931
1260
|
/** Ephemeral response endpoint; see `replyTo` semantics. */
|
|
932
|
-
|
|
1261
|
+
/**
|
|
1262
|
+
* Every endpoint the requester can be answered on for this exchange, in
|
|
1263
|
+
* its own preference order. Omitted means route to the endpoints already
|
|
1264
|
+
* recorded for the channel.
|
|
1265
|
+
*/
|
|
1266
|
+
reply_to?: TransportProtocol[];
|
|
933
1267
|
/** Replica-group member that sent this; see `replicaId` semantics. */
|
|
934
1268
|
replica_id?: bigint;
|
|
935
1269
|
}
|
|
@@ -945,7 +1279,12 @@ export interface VerifyShareRequestMessage {
|
|
|
945
1279
|
nonce: bigint;
|
|
946
1280
|
timestamp?: Timestamp;
|
|
947
1281
|
/** Ephemeral response endpoint; see `replyTo` semantics. */
|
|
948
|
-
|
|
1282
|
+
/**
|
|
1283
|
+
* Every endpoint the requester can be answered on for this exchange, in
|
|
1284
|
+
* its own preference order. Omitted means route to the endpoints already
|
|
1285
|
+
* recorded for the channel.
|
|
1286
|
+
*/
|
|
1287
|
+
reply_to?: TransportProtocol[];
|
|
949
1288
|
}
|
|
950
1289
|
|
|
951
1290
|
export interface VerifyShareResponseMessage {
|
|
@@ -981,7 +1320,12 @@ export interface PairingRequestProduceResult extends ProduceResult {
|
|
|
981
1320
|
}
|
|
982
1321
|
|
|
983
1322
|
export interface PairingResponseProduceResult extends ProduceResult {
|
|
984
|
-
|
|
1323
|
+
/**
|
|
1324
|
+
* Every endpoint the requester advertised, in the order it offered them,
|
|
1325
|
+
* filtered to those the library will record. Never empty. Choosing which
|
|
1326
|
+
* to dial, and failing over when one is unreachable, is the application's.
|
|
1327
|
+
*/
|
|
1328
|
+
peer_transports: TransportProtocol[];
|
|
985
1329
|
|
|
986
1330
|
shared_key: Uint8Array;
|
|
987
1331
|
|