@derec-alliance/nodejs 0.0.5 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +77 -21
- package/derec_descriptor.bin +0 -0
- package/derec_library.d.ts +110 -121
- package/derec_library.js +171 -169
- package/derec_library_bg.wasm +0 -0
- package/derec_library_bg.wasm.d.ts +35 -35
- package/index.d.ts +462 -168
- package/index.js +33 -3
- package/package.json +1 -1
- package/proto/contact.proto +15 -48
- package/proto/getshare.proto +4 -14
- package/proto/pair.proto +5 -29
- package/proto/prepair.proto +14 -39
- package/proto/secretidsversions.proto +4 -14
- package/proto/storeshare.proto +8 -39
- package/proto/unpair.proto +4 -14
- package/proto/updatechannelinfo.proto +16 -45
- package/proto/verify.proto +4 -14
package/README.md
CHANGED
|
@@ -126,7 +126,7 @@ const request = primitives.pairing.request.produce(
|
|
|
126
126
|
|
|
127
127
|
// Step 3: Initiator extracts the request and produces the response.
|
|
128
128
|
const { request: pairRequest } =
|
|
129
|
-
primitives.pairing.request.extract(request.envelope, contact.secret_key);
|
|
129
|
+
primitives.pairing.request.extract(request.envelope, contact.secret_key, null);
|
|
130
130
|
const produced = primitives.pairing.response.produce(
|
|
131
131
|
channelId,
|
|
132
132
|
pairRequest,
|
|
@@ -141,6 +141,7 @@ const processed = primitives.pairing.response.process(
|
|
|
141
141
|
request.initiator_contact_message,
|
|
142
142
|
pairResponse,
|
|
143
143
|
request.secret_key,
|
|
144
|
+
null,
|
|
144
145
|
);
|
|
145
146
|
|
|
146
147
|
// Both sides hold the same shared key and rekeyed channel id.
|
|
@@ -227,7 +228,7 @@ The orchestrator handles the whole chain automatically:
|
|
|
227
228
|
`ActionRequired` event with `action_kind: "PrePair"`. Call
|
|
228
229
|
`protocol.accept(action)` to publish the keys (the library builds the
|
|
229
230
|
response and routes it), or `protocol.reject(action, status, memo)` to
|
|
230
|
-
refuse.
|
|
231
|
+
refuse — `status` is a `StatusEnum` value such as `StatusEnum.Rejected`.
|
|
231
232
|
- **Scanner** — `protocol.start(FlowKind.Pairing, { kind, contact })` kicks
|
|
232
233
|
off the plaintext PrePair leg. `start()` returns a `DeRecEvent[]`
|
|
233
234
|
containing one `PairingStarted { channel_id, kind }` event that
|
|
@@ -316,12 +317,22 @@ const recovered = primitives.recovery.response.recover(
|
|
|
316
317
|
// `recovered` is a Uint8Array carrying the reconstructed secret payload.
|
|
317
318
|
```
|
|
318
319
|
|
|
319
|
-
When driving the protocol layer instead of the primitives,
|
|
320
|
-
|
|
320
|
+
When driving the protocol layer instead of the primitives, a helper that
|
|
321
|
+
answers with a share that cannot be part of the secret is reported as a
|
|
322
|
+
`RecoveryShareCorrupted` event (`reason`: `"Malformed"`, `"InvalidProof"` or
|
|
323
|
+
`"Inconsistent"`); the share is set aside and never blocks the recovery from
|
|
324
|
+
the others. An honest helper never sends one, so treat it as a sign of a
|
|
325
|
+
damaged or compromised helper — for example, offer to unpair it.
|
|
326
|
+
|
|
327
|
+
The recovering device receives a `SecretRecovered` event carrying the typed
|
|
328
|
+
`secret`. Pass it
|
|
321
329
|
to `protocol.restore(secret, version)` on a fresh `DeRecProtocol` instance to
|
|
322
330
|
commit canonical helper / replica state and wipe the throwaway recovery-mode
|
|
323
331
|
channels — at that point the device resumes normal operation as if the secret
|
|
324
332
|
had been protected here originally.
|
|
333
|
+
A helper or member with no endpoint in the recovered roster gets no channel;
|
|
334
|
+
`restore` returns a `PeerNotRestored` event for it (`reason: "NoTransports"`)
|
|
335
|
+
and restores the rest.
|
|
325
336
|
|
|
326
337
|
```ts
|
|
327
338
|
const events = await protocol.process(responseBytes);
|
|
@@ -332,8 +343,10 @@ for (const ev of events) {
|
|
|
332
343
|
}
|
|
333
344
|
```
|
|
334
345
|
|
|
335
|
-
Errors surface as
|
|
336
|
-
`
|
|
346
|
+
Errors surface as a `DeRecError` with a `category` and `code` —
|
|
347
|
+
`already_restored`, `restore_conflict` (with `channel_ids`), `invariant`,
|
|
348
|
+
`invalid_recovered_secret` (a malformed `secret`), or `store_error` (a store call failed; `category`
|
|
349
|
+
names the store).
|
|
337
350
|
|
|
338
351
|
> **Secret format:** the recoverable secret (the bytes helpers store and
|
|
339
352
|
> recovery reconstructs) is `[version byte] · payload` — v1's payload is
|
|
@@ -380,6 +393,12 @@ console.log("Valid:", isValid);
|
|
|
380
393
|
- No protobuf types are exposed
|
|
381
394
|
- No cryptographic operations occur in JavaScript
|
|
382
395
|
- Rust is the single source of truth
|
|
396
|
+
- Every `DeRecProtocol` method that touches protocol state returns a
|
|
397
|
+
`Promise`, including the `set*` setters. Overlapping calls on one
|
|
398
|
+
instance — a `tick()` timer firing while `process()` handles a message —
|
|
399
|
+
queue and run in the order they were made; they never collide. A store
|
|
400
|
+
or transport callback must not await a call on the instance that
|
|
401
|
+
invoked it, since that call waits behind the callback's own caller.
|
|
383
402
|
|
|
384
403
|
---
|
|
385
404
|
|
|
@@ -392,14 +411,18 @@ side runs as `SenderKind.ReplicaSource` (owns the secret), the other as
|
|
|
392
411
|
with a stable `replicaId`:
|
|
393
412
|
|
|
394
413
|
```ts
|
|
395
|
-
const owner = new
|
|
396
|
-
channelStore
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
)
|
|
414
|
+
const owner = new DeRecProtocolBuilder(secretId)
|
|
415
|
+
.withChannelStore(channelStore)
|
|
416
|
+
.withShareStore(shareStore)
|
|
417
|
+
.withSecretStore(secretStore)
|
|
418
|
+
.withUserSecretStore(userSecretStore)
|
|
419
|
+
.withStateStore(stateStore)
|
|
420
|
+
.withTransport(transport)
|
|
421
|
+
.withOwnTransports([{ uri: "https://owner.example.com", protocol: "https" }])
|
|
422
|
+
.withThreshold(2)
|
|
423
|
+
.withCommunicationInfo({ name: "Owner" })
|
|
424
|
+
.withReplicaId(0xAAAA_AAAA_AAAA_AAAAn)
|
|
425
|
+
.build();
|
|
403
426
|
```
|
|
404
427
|
|
|
405
428
|
A typical Source↔Destination handshake:
|
|
@@ -452,6 +475,27 @@ End-to-end coverage lives in the repository's tests — see
|
|
|
452
475
|
|
|
453
476
|
---
|
|
454
477
|
|
|
478
|
+
## When `process()` fails
|
|
479
|
+
|
|
480
|
+
`process()` settles expired deadlines (sharing-round and unpair timeouts)
|
|
481
|
+
before it handles the message, and those are never reported again. So when
|
|
482
|
+
the message then fails, the thrown `DeRecError` carries them: `events` holds
|
|
483
|
+
every event produced before the failure, and `channel_id` names the channel
|
|
484
|
+
the message came from (absent when the bytes were not a decodable envelope).
|
|
485
|
+
Handle the events as you would a successful call's, then the error:
|
|
486
|
+
|
|
487
|
+
```ts
|
|
488
|
+
try {
|
|
489
|
+
handle(await protocol.process(bytes));
|
|
490
|
+
} catch (error) {
|
|
491
|
+
const failure = error as DeRecError;
|
|
492
|
+
handle(failure.events ?? []);
|
|
493
|
+
report(failure.channel_id, failure);
|
|
494
|
+
}
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
---
|
|
498
|
+
|
|
455
499
|
## Correlation and routing
|
|
456
500
|
|
|
457
501
|
Two cross-cutting metadata fields appear on every channel-mode exchange:
|
|
@@ -461,13 +505,13 @@ Two cross-cutting metadata fields appear on every channel-mode exchange:
|
|
|
461
505
|
end-to-end (random token on every outbound request, echo on every
|
|
462
506
|
response). Primitive-only callers can manipulate it directly via
|
|
463
507
|
`envelope.apply_trace_id(bytes, traceId)` and `envelope.read_trace_id(bytes)`.
|
|
464
|
-
- **`replyTo`** — optional `TransportProtocol` on request bodies, telling
|
|
465
|
-
the responder to route this exchange's response to
|
|
508
|
+
- **`replyTo`** — optional `TransportProtocol` list on request bodies, telling
|
|
509
|
+
the responder to route this exchange's response to alternate endpoints.
|
|
466
510
|
Set it per call (every `primitives.*.request.produce` takes a trailing
|
|
467
511
|
`reply_to` arg) or protocol-wide with the `autoReplyTo` constructor flag
|
|
468
|
-
on `DeRecProtocol` (stamps
|
|
469
|
-
request). Excludes pairing and `UpdateChannelInfo`, which
|
|
470
|
-
their own `
|
|
512
|
+
on `DeRecProtocol` (stamps this node's own transports into `replyTo` on
|
|
513
|
+
every outbound request). Excludes pairing and `UpdateChannelInfo`, which
|
|
514
|
+
already carry their own `supportedTransports` field.
|
|
471
515
|
|
|
472
516
|
The motivating case for `replyTo` is replicas: when Replica A sends a
|
|
473
517
|
request on a channel the helper paired with sibling Replica B, the
|
|
@@ -554,13 +598,16 @@ that you can retire as soon as the PrePair leg completes.
|
|
|
554
598
|
|
|
555
599
|
The recommended pattern is: pair on the ephemeral URI, then — as soon
|
|
556
600
|
as the pairing completes on the contact creator side — call
|
|
557
|
-
`setOwnTransports` with the permanent endpoint
|
|
558
|
-
deprecated and removed at 0.0.5) and start an
|
|
601
|
+
`setOwnTransports` with the permanent endpoint and start an
|
|
559
602
|
`UpdateChannelInfo` flow against the peer to announce the swap. Once
|
|
560
603
|
the peer acknowledges, retire the ephemeral URI. This keeps the
|
|
561
604
|
plaintext PrePair window tight while letting subsequent traffic ride
|
|
562
605
|
on the long-lived endpoint.
|
|
563
606
|
|
|
607
|
+
`UpdateChannelInfo` reaches helper channels only. A replica member that
|
|
608
|
+
changes its endpoint or `communication_info` publishes a new version first,
|
|
609
|
+
then updates its helpers; see [On a replica member](https://github.com/derecalliance/lib-derec/tree/main/library#on-a-replica-member).
|
|
610
|
+
|
|
564
611
|
### Replica fingerprint verification is mandatory
|
|
565
612
|
|
|
566
613
|
Replica channels are created with `status: "Pending"` and remain there
|
|
@@ -571,6 +618,15 @@ target is still `Pending`. Treat verification as a required step in
|
|
|
571
618
|
the pairing UX — a scanner that auto-pairs without it accepts a
|
|
572
619
|
MITM-vulnerable replica.
|
|
573
620
|
|
|
621
|
+
Until a device confirms, it ignores everything the peer sends on that
|
|
622
|
+
channel: `process` changes no store, sends nothing back, and returns
|
|
623
|
+
`{ type: "MessageIgnored", channel_id, reason: "PendingVerification",
|
|
624
|
+
trace_id }`. This matters most for a replica destination. The source's own
|
|
625
|
+
confirmation publishes the vault immediately, so that copy usually arrives
|
|
626
|
+
before the destination's user has confirmed. Confirming does not replay it:
|
|
627
|
+
once the destination's `verifyFingerprint` resolves `true`, call
|
|
628
|
+
`start(FlowKind.ReplicaDiscovery)` to pull the copy from the source.
|
|
629
|
+
|
|
574
630
|
### The `derec.*` namespace in `communicationInfo` is library-owned
|
|
575
631
|
|
|
576
632
|
`communicationInfo` is otherwise an opaque app-defined map, but every
|
package/derec_descriptor.bin
CHANGED
|
Binary file
|
package/derec_library.d.ts
CHANGED
|
@@ -9,11 +9,12 @@
|
|
|
9
9
|
* docs.
|
|
10
10
|
*
|
|
11
11
|
* Required setters: `withChannelStore`, `withShareStore`,
|
|
12
|
-
* `withSecretStore`, `
|
|
13
|
-
* `withOwnTransports`. Calling `build()` without all
|
|
12
|
+
* `withSecretStore`, `withUserSecretStore`, `withStateStore`,
|
|
13
|
+
* `withTransport`, and `withOwnTransports`. Calling `build()` without all
|
|
14
|
+
* seven throws.
|
|
14
15
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
16
|
+
* An optional setter that is never called leaves the Rust builder's default
|
|
17
|
+
* in force: the value is forwarded only when the application supplied one.
|
|
17
18
|
*/
|
|
18
19
|
export class DeRecProtocolBuilder {
|
|
19
20
|
free(): void;
|
|
@@ -43,7 +44,7 @@ export class DeRecProtocolBuilder {
|
|
|
43
44
|
*/
|
|
44
45
|
withAutoAccept(policy: any): DeRecProtocolBuilder;
|
|
45
46
|
/**
|
|
46
|
-
* Whether outbound requests
|
|
47
|
+
* Whether outbound requests carry this node's own transports as their reply-to list.
|
|
47
48
|
* Default: false.
|
|
48
49
|
*/
|
|
49
50
|
withAutoReplyTo(enabled: boolean): DeRecProtocolBuilder;
|
|
@@ -57,34 +58,17 @@ export class DeRecProtocolBuilder {
|
|
|
57
58
|
* `info` shape: `Record<string, string>`. Default: empty.
|
|
58
59
|
*/
|
|
59
60
|
withCommunicationInfo(info: any): DeRecProtocolBuilder;
|
|
60
|
-
/**
|
|
61
|
-
* Number of recent versions each helper must retain. Default: 3.
|
|
62
|
-
*/
|
|
63
|
-
withKeepVersionsCount(count: number): DeRecProtocolBuilder;
|
|
64
|
-
/**
|
|
65
|
-
* `endpoint` shape: `{ uri: string, protocol: string }`.
|
|
66
|
-
* `protocol` is `"https"` or `"grpc"` (case-insensitive).
|
|
67
|
-
*
|
|
68
|
-
* @deprecated Use `withOwnTransports`, which takes the whole preference
|
|
69
|
-
* list — `withOwnTransports([endpoint])` is the direct replacement.
|
|
70
|
-
* Removed at 0.0.5.
|
|
71
|
-
*/
|
|
72
|
-
withOwnTransport(endpoint: any): DeRecProtocolBuilder;
|
|
73
61
|
/**
|
|
74
62
|
* Every transport endpoint this application serves, in preference
|
|
75
63
|
* order. `transports` is an array of `{ uri: string, protocol: string
|
|
76
64
|
* }` objects, `protocol` being `"https"` or `"grpc"`
|
|
77
|
-
* (case-insensitive)
|
|
65
|
+
* (case-insensitive).
|
|
78
66
|
*
|
|
79
67
|
* The order is the application's own preference and decides which of
|
|
80
68
|
* a peer's offered endpoints is used. Every listed transport must
|
|
81
69
|
* actually be served, because delivery is push-only — listing an
|
|
82
70
|
* endpoint this application does not serve makes pairing succeed and
|
|
83
71
|
* replies vanish.
|
|
84
|
-
*
|
|
85
|
-
* Supersedes [`Self::with_own_transport`] for applications serving
|
|
86
|
-
* more than one transport; the single-endpoint setter remains fully
|
|
87
|
-
* supported.
|
|
88
72
|
*/
|
|
89
73
|
withOwnTransports(transports: any[]): DeRecProtocolBuilder;
|
|
90
74
|
/**
|
|
@@ -108,7 +92,7 @@ export class DeRecProtocolBuilder {
|
|
|
108
92
|
withStateStore(store: any): DeRecProtocolBuilder;
|
|
109
93
|
/**
|
|
110
94
|
* Minimum number of shares required to reconstruct the secret.
|
|
111
|
-
* Default:
|
|
95
|
+
* Default: [`crate::protocol::DEFAULT_THRESHOLD`].
|
|
112
96
|
*/
|
|
113
97
|
withThreshold(threshold: number): DeRecProtocolBuilder;
|
|
114
98
|
/**
|
|
@@ -133,18 +117,13 @@ export class DeRecProtocolBuilder {
|
|
|
133
117
|
withTimeouts(timeouts: any): DeRecProtocolBuilder;
|
|
134
118
|
withTransport(transport: any): DeRecProtocolBuilder;
|
|
135
119
|
/**
|
|
136
|
-
* `ack` is `"required"` (default) or `"not_required"
|
|
120
|
+
* `ack` is exactly `"required"` (default) or `"not_required"`, naming
|
|
121
|
+
* [`UnpairAck::Required`] and [`UnpairAck::NotRequired`].
|
|
137
122
|
*/
|
|
138
123
|
withUnpairAck(ack: string): DeRecProtocolBuilder;
|
|
139
124
|
/**
|
|
140
125
|
* Accept plaintext transport endpoints — `http://` and `grpc://`.
|
|
141
|
-
* **Development only.** Default `false`.
|
|
142
|
-
* conflict rule when both are set.
|
|
143
|
-
*/
|
|
144
|
-
withUnsafeConnection(allow: boolean): DeRecProtocolBuilder;
|
|
145
|
-
/**
|
|
146
|
-
* Accept plaintext `http://` transport endpoints. **Development only.**
|
|
147
|
-
* Default `false`.
|
|
126
|
+
* **Development only.** Default `false`.
|
|
148
127
|
*
|
|
149
128
|
* With it `false`, plaintext is accepted only for an endpoint this
|
|
150
129
|
* device configured for *itself* that names loopback (`localhost`,
|
|
@@ -152,11 +131,8 @@ export class DeRecProtocolBuilder {
|
|
|
152
131
|
* With it `true`, plaintext is accepted for any host on any path,
|
|
153
132
|
* including endpoints a peer supplies. That is what makes the LAN case
|
|
154
133
|
* work (a phone against a laptop), and why the name is blunt.
|
|
155
|
-
*
|
|
156
|
-
* Superseded by `withUnsafeConnection`; still honored, and wins on
|
|
157
|
-
* conflict. Removed at 0.0.5.
|
|
158
134
|
*/
|
|
159
|
-
|
|
135
|
+
withUnsafeConnection(allow: boolean): DeRecProtocolBuilder;
|
|
160
136
|
withUserSecretStore(store: any): DeRecProtocolBuilder;
|
|
161
137
|
}
|
|
162
138
|
|
|
@@ -164,31 +140,46 @@ export class DeRecProtocolBuilder {
|
|
|
164
140
|
* Higher-level DeRec protocol orchestrator for TypeScript/JavaScript consumers.
|
|
165
141
|
*
|
|
166
142
|
* Wraps [`crate::protocol::DeRecProtocol`] with JS-side store
|
|
167
|
-
* and transport adapters so that a TypeScript application can drive
|
|
168
|
-
* protocol
|
|
143
|
+
* and transport adapters so that a TypeScript application can drive every
|
|
144
|
+
* protocol flow without routing raw bytes manually. Built with
|
|
145
|
+
* [`DeRecProtocolBuilderWasm`] (`DeRecProtocolBuilder` in JS).
|
|
169
146
|
*
|
|
170
147
|
* # Stores
|
|
171
148
|
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
149
|
+
* The five stores and the transport are JS objects implementing the
|
|
150
|
+
* `ChannelStore`, `ShareStore`, `SecretStore`, `UserSecretStore`,
|
|
151
|
+
* `StateStore` and `Transport` interfaces in `index.d.ts`. All their methods
|
|
152
|
+
* must return `Promise`s — synchronous implementations can wrap their result
|
|
153
|
+
* with `Promise.resolve(...)`.
|
|
175
154
|
*
|
|
176
|
-
* #
|
|
155
|
+
* # Concurrency
|
|
177
156
|
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
157
|
+
* Every method that touches protocol state is `async` and runs under one
|
|
158
|
+
* lock per instance, so overlapping calls on the same instance — a
|
|
159
|
+
* `tick` timer firing while `process` handles an inbound message — queue
|
|
160
|
+
* and run one at a time, in the order they were made. Distinct instances
|
|
161
|
+
* do not share the lock: two instances bound to the same `secret_id` and
|
|
162
|
+
* the same stores must still be serialized by the caller.
|
|
180
163
|
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
* | `ShareConfirmed` | `channel_id: string`, `version: number` |
|
|
186
|
-
* | `ShareVerified` | `channel_id: string`, `version: number` |
|
|
187
|
-
* | `SecretsDiscovered`| `channel_id: string`, `secrets: SecretVersionEntry[]` |
|
|
188
|
-
* | `SecretRecovered` | `secret: { helpers, secrets, replicas }` (same nested shape as `ReplicaSecretReceived.secret`) |
|
|
189
|
-
* | `NoOp` | _(none)_ |
|
|
164
|
+
* A store or transport callback must not await a call on the instance
|
|
165
|
+
* that invoked it: that call queues behind the one waiting on the
|
|
166
|
+
* callback, and neither settles. Calling `free()` while a call is in
|
|
167
|
+
* flight throws.
|
|
190
168
|
*
|
|
191
|
-
*
|
|
169
|
+
* Methods take `&self` for this reason: wasm-bindgen holds the borrow of
|
|
170
|
+
* the instance for an async call's whole lifetime, so under `&mut self` an
|
|
171
|
+
* overlapping call fails that borrow outside its promise and never
|
|
172
|
+
* settles.
|
|
173
|
+
*
|
|
174
|
+
* # Events
|
|
175
|
+
*
|
|
176
|
+
* [`process`](DeRecProtocolWasm::process), [`start`](DeRecProtocolWasm::start),
|
|
177
|
+
* [`accept`](DeRecProtocolWasm::accept), [`tick`](DeRecProtocolWasm::tick)
|
|
178
|
+
* and [`restore`](DeRecProtocolWasm::restore) return an `Array` of plain JS
|
|
179
|
+
* objects, one per [`crate::protocol::DeRecEvent`], each tagged by a `type`
|
|
180
|
+
* field naming the variant. Every `u64` identifier (`channel_id`,
|
|
181
|
+
* `secret_id`, `replica_id`, `trace_id`) is a decimal string. The full set of
|
|
182
|
+
* shapes is the `DeRecEvent` union in `index.d.ts`.
|
|
192
183
|
*/
|
|
193
184
|
export class DeRecProtocolWasm {
|
|
194
185
|
private constructor();
|
|
@@ -261,46 +252,36 @@ export class DeRecProtocolWasm {
|
|
|
261
252
|
* # Returns
|
|
262
253
|
*
|
|
263
254
|
* An `Array` of removed channel ids as decimal strings.
|
|
255
|
+
*
|
|
256
|
+
* `older_than_secs` is a `u64`: a `bigint`, a non-negative safe-integer
|
|
257
|
+
* `number`, or a decimal string.
|
|
264
258
|
*/
|
|
265
|
-
removeExpiredChannels(older_than_secs:
|
|
259
|
+
removeExpiredChannels(older_than_secs: any): Promise<any>;
|
|
266
260
|
/**
|
|
267
261
|
* Rebuild this protocol's `secret_id` namespace from a recovered
|
|
268
262
|
* `Secret`. Mirrors [`crate::protocol::DeRecProtocol::restore`] —
|
|
269
263
|
* see that method for the full contract.
|
|
270
264
|
*
|
|
271
265
|
* `recoveredSecret` is the typed `Secret` object carried by the
|
|
272
|
-
* `SecretRecovered` event; pass it verbatim.
|
|
266
|
+
* `SecretRecovered` event; pass it verbatim. A helper or member whose
|
|
267
|
+
* `transports` is empty, `null` or absent gets no channel; it is
|
|
268
|
+
* reported as a `PeerNotRestored` event in the returned array and the
|
|
269
|
+
* rest of the roster is restored.
|
|
273
270
|
*
|
|
274
|
-
* Errors surface as
|
|
271
|
+
* Errors surface as a `DeRecError` (`category`, `code`, `message`):
|
|
275
272
|
*
|
|
276
273
|
* | code | meaning |
|
|
277
274
|
* |--------------------|------------------------------------------------------------------|
|
|
278
|
-
* | `
|
|
279
|
-
* | `
|
|
275
|
+
* | `already_restored` | A user-secret snapshot already exists for this `secret_id`. |
|
|
276
|
+
* | `restore_conflict` | Channels live at ids restore is about to write. The error |
|
|
280
277
|
* | | carries `channel_ids: string[]` listing the collisions. |
|
|
281
|
-
* | `
|
|
282
|
-
* | `
|
|
278
|
+
* | `invariant` | The recovered `Secret` is internally inconsistent. |
|
|
279
|
+
* | `invalid_recovered_secret` | `recoveredSecret` is malformed — e.g. a missing or |
|
|
280
|
+
* | | non-decimal `channel_id` / `replica_id`. |
|
|
281
|
+
* | `store_error` | A store call failed mid-restore; `category` names the store. |
|
|
283
282
|
*/
|
|
284
283
|
restore(recovered_secret: any, version: number): Promise<any>;
|
|
285
284
|
/**
|
|
286
|
-
* Generate an out-of-band contact message (QR code payload, deep link, …).
|
|
287
|
-
*
|
|
288
|
-
* Returns a plain JS `ContactMessage` object. The `channel_id` field identifies
|
|
289
|
-
* the pairing session and will match the `channel_id` in the eventual
|
|
290
|
-
* `PairingCompleted` event — read it directly from the returned object.
|
|
291
|
-
*
|
|
292
|
-
* The caller is responsible for serializing the contact for out-of-band
|
|
293
|
-
* delivery (QR code, deep link, etc.). The peer passes the deserialized object
|
|
294
|
-
* to [`start`](Self::start) with `FlowKind::Pairing`.
|
|
295
|
-
*
|
|
296
|
-
* # Arguments
|
|
297
|
-
*
|
|
298
|
-
* * `channel_id` — Optional `BigInt` channel identifier. Pass `null` or
|
|
299
|
-
* `undefined` to have the library generate a random one.
|
|
300
|
-
* * `contact_mode` — `0` for `InlineKeys` (keys embedded directly), `1`
|
|
301
|
-
* for `HashedKeys` (contact carries only a SHA-384 binding hash; the
|
|
302
|
-
* scanner fetches keys via a `PrePair` round-trip). `HashedKeys`
|
|
303
|
-
* requires the protocol's `own_transport` to be ephemeral.
|
|
304
285
|
* The secret identifier this protocol instance is bound to.
|
|
305
286
|
*/
|
|
306
287
|
secretId(): bigint;
|
|
@@ -308,32 +289,13 @@ export class DeRecProtocolWasm {
|
|
|
308
289
|
* Replace this node's local communication info. Does not contact peers —
|
|
309
290
|
* follow up with a `start(UpdateChannelInfo, ...)` to propagate.
|
|
310
291
|
*/
|
|
311
|
-
setCommunicationInfo(info: any): void
|
|
312
|
-
/**
|
|
313
|
-
* Replace this node's endpoint for one protocol, leaving the others
|
|
314
|
-
* alone. A node serves at most one endpoint per protocol, so the
|
|
315
|
-
* `(uri, protocol)` pair identifies the entry it replaces; an entry for
|
|
316
|
-
* a protocol not yet served is appended, and a replaced one keeps its
|
|
317
|
-
* position in the preference order.
|
|
318
|
-
*
|
|
319
|
-
* @deprecated Use `setOwnTransports`, which takes the whole preference
|
|
320
|
-
* list and is the only way to change which protocols this node serves,
|
|
321
|
-
* or their order. Removed at 0.0.5.
|
|
322
|
-
*
|
|
323
|
-
* See `setCommunicationInfo` for the matching update-propagation
|
|
324
|
-
* flow, and `setOwnTransports` to keep more than one endpoint.
|
|
325
|
-
* IMPORTANT: keep the old endpoint operational during the changeover —
|
|
326
|
-
* see the Rust docs on `set_own_transport` for the discipline.
|
|
327
|
-
*/
|
|
328
|
-
setOwnTransport(uri: string, protocol: string): void;
|
|
292
|
+
setCommunicationInfo(info: any): Promise<void>;
|
|
329
293
|
/**
|
|
330
294
|
* Replace every endpoint this node advertises, in preference order.
|
|
331
295
|
*
|
|
332
296
|
* `transports` is an array of `{ uri: string, protocol: string }`
|
|
333
|
-
* objects, same shape as `withOwnTransports
|
|
334
|
-
*
|
|
335
|
-
* `setOwnTransport` replaces only the entry for the protocol its URI
|
|
336
|
-
* names. A node serves at most one endpoint per protocol, so this list
|
|
297
|
+
* objects, same shape as `withOwnTransports`, and is its runtime
|
|
298
|
+
* counterpart. A node serves at most one endpoint per protocol, so this list
|
|
337
299
|
* is a preference order over distinct protocols and two entries of the
|
|
338
300
|
* same protocol are rejected.
|
|
339
301
|
*
|
|
@@ -342,18 +304,17 @@ export class DeRecProtocolWasm {
|
|
|
342
304
|
* operational during the changeover — see the Rust docs on
|
|
343
305
|
* `set_own_transports` for the discipline.
|
|
344
306
|
*/
|
|
345
|
-
setOwnTransports(transports: any[]): void
|
|
307
|
+
setOwnTransports(transports: any[]): Promise<void>;
|
|
346
308
|
/**
|
|
347
309
|
* Unified entry point for initiating any protocol flow.
|
|
348
310
|
*
|
|
349
311
|
* # Arguments
|
|
350
312
|
*
|
|
351
|
-
* * `flow_kind` —
|
|
352
|
-
*
|
|
353
|
-
*
|
|
354
|
-
*
|
|
355
|
-
*
|
|
356
|
-
* - `4` = RecoverSecret (params: `{ secretId: Uint8Array, version: number }`)
|
|
313
|
+
* * `flow_kind` — `FlowKind` discriminant: `0` Pairing, `1` Discovery,
|
|
314
|
+
* `2` ProtectSecret, `3` VerifyShares, `4` RecoverSecret, `5` Unpair,
|
|
315
|
+
* `6` UpdateChannelInfo, `7` ReplicaDiscovery, `8` UnpairReplica.
|
|
316
|
+
* * `params` — the flow's parameters, declared per kind in `index.d.ts`
|
|
317
|
+
* as `PairingParams`, `DiscoveryParams`, … `UnpairReplicaParams`.
|
|
357
318
|
*
|
|
358
319
|
* # Returns
|
|
359
320
|
*
|
|
@@ -411,30 +372,33 @@ export function envelope_apply_trace_id(envelope_bytes: Uint8Array, trace_id: bi
|
|
|
411
372
|
export function envelope_read_trace_id(envelope_bytes: Uint8Array): bigint;
|
|
412
373
|
|
|
413
374
|
/**
|
|
414
|
-
*
|
|
415
|
-
*
|
|
416
|
-
*
|
|
375
|
+
* A fresh replica identity. See [`crate::generate_replica_id`]: the caller
|
|
376
|
+
* persists it once per device and passes the same value on every protocol
|
|
377
|
+
* init. Never `0`.
|
|
417
378
|
*/
|
|
418
|
-
export function
|
|
379
|
+
export function generate_replica_id(): bigint;
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* The human-readable fingerprint of a pairing's shared key. Both ends derive
|
|
383
|
+
* the same value; comparing it out of band confirms the pairing.
|
|
384
|
+
*/
|
|
385
|
+
export function pairing_fingerprint(shared_key: Uint8Array): string;
|
|
419
386
|
|
|
420
387
|
export function pairing_request_create_contact(channel_id: bigint, contact_mode: number, transport_protocols: any, nonce: any): any;
|
|
421
388
|
|
|
422
389
|
/**
|
|
423
|
-
* Decodes
|
|
424
|
-
*
|
|
425
|
-
* trust the mode/field invariants documented on the wire format.
|
|
390
|
+
* Decodes proto `ContactMessage` wire bytes. See
|
|
391
|
+
* [`crate::primitives::pairing::request::decode_contact`].
|
|
426
392
|
*/
|
|
427
393
|
export function pairing_request_decode_contact(bytes: Uint8Array): any;
|
|
428
394
|
|
|
429
395
|
/**
|
|
430
|
-
* Encodes a [`ContactMessage`] to proto wire bytes.
|
|
431
|
-
*
|
|
432
|
-
* mode/field invariant is rejected at the boundary rather than silently
|
|
433
|
-
* serialized.
|
|
396
|
+
* Encodes a [`ContactMessage`] to proto wire bytes. See
|
|
397
|
+
* [`crate::primitives::pairing::request::encode_contact`].
|
|
434
398
|
*/
|
|
435
399
|
export function pairing_request_encode_contact(contact_message: any): Uint8Array;
|
|
436
400
|
|
|
437
|
-
export function pairing_request_extract(envelope_bytes: Uint8Array, secret_key: Uint8Array): any;
|
|
401
|
+
export function pairing_request_extract(envelope_bytes: Uint8Array, secret_key: Uint8Array, parameter_range: any): any;
|
|
438
402
|
|
|
439
403
|
/**
|
|
440
404
|
* Initiator-side: decode an inbound plaintext `PrePairRequest` envelope.
|
|
@@ -456,7 +420,7 @@ export function pairing_response_extract(envelope_bytes: Uint8Array, secret_key:
|
|
|
456
420
|
*/
|
|
457
421
|
export function pairing_response_extract_pre_pair(envelope_bytes: Uint8Array): any;
|
|
458
422
|
|
|
459
|
-
export function pairing_response_process(contact_message: any, response: any, secret_key: Uint8Array): any;
|
|
423
|
+
export function pairing_response_process(contact_message: any, response: any, secret_key: Uint8Array, parameter_range: any): any;
|
|
460
424
|
|
|
461
425
|
/**
|
|
462
426
|
* Scanner-side: validate the `PrePairResponse` against the contact's
|
|
@@ -464,6 +428,14 @@ export function pairing_response_process(contact_message: any, response: any, se
|
|
|
464
428
|
*/
|
|
465
429
|
export function pairing_response_process_pre_pair(contact_message: any, response: any): any;
|
|
466
430
|
|
|
431
|
+
/**
|
|
432
|
+
* Scanner side of a `NO_KEYS` pairing: accept the contact creator's public
|
|
433
|
+
* keys. There is no binding hash to check them against, so the channel this
|
|
434
|
+
* leads to MUST stay unusable until both sides confirm `pairing_fingerprint`
|
|
435
|
+
* out of band.
|
|
436
|
+
*/
|
|
437
|
+
export function pairing_response_process_pre_pair_no_keys(contact_message: any, response: any): any;
|
|
438
|
+
|
|
467
439
|
export function pairing_response_produce(channel_id: bigint, request: any, secret_key: Uint8Array, communication_info: any, parameter_range: any, unsafe_connection: boolean): any;
|
|
468
440
|
|
|
469
441
|
/**
|
|
@@ -471,6 +443,23 @@ export function pairing_response_produce(channel_id: bigint, request: any, secre
|
|
|
471
443
|
*/
|
|
472
444
|
export function pairing_response_produce_pre_pair(channel_id: bigint, request: any, secret_key: Uint8Array): any;
|
|
473
445
|
|
|
446
|
+
/**
|
|
447
|
+
* Contact-creator side of a `NO_KEYS` pairing: generate key material and
|
|
448
|
+
* answer the `PrePairRequest` with its public half.
|
|
449
|
+
*
|
|
450
|
+
* The caller MUST first match the request's `nonce` against the contact it
|
|
451
|
+
* issued, and MUST keep the resulting channel unusable until both sides
|
|
452
|
+
* confirm `pairing_fingerprint` out of band.
|
|
453
|
+
*/
|
|
454
|
+
export function pairing_response_produce_pre_pair_no_keys(channel_id: bigint, request: any): any;
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* The DeRec protocol version this build speaks — the `protocolVersionMajor`
|
|
458
|
+
* / `protocolVersionMinor` it writes into every envelope it produces —
|
|
459
|
+
* as `{ major, minor }`.
|
|
460
|
+
*/
|
|
461
|
+
export function protocol_version(): any;
|
|
462
|
+
|
|
474
463
|
export function recovery_request_extract(envelope_bytes: Uint8Array, shared_key: Uint8Array): any;
|
|
475
464
|
|
|
476
465
|
export function recovery_request_produce(channel_id: bigint, secret_id: bigint, version: number, shared_key: Uint8Array, reply_to: any): any;
|