@derec-alliance/react-native 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/primitives.js CHANGED
@@ -35,19 +35,16 @@ function replyTo(value) {
35
35
  return value && value.length > 0 ? encodeTransportList(value) : new Uint8Array(0);
36
36
  }
37
37
  /**
38
- * `ContactMessage` keeps its own dedicated codec rather than going through
39
- * the generic message codec: `encode_contact_message` /
40
- * `decode_contact_message` also enforce the mode/field invariant — an
41
- * `InlineKeys` contact must carry keys, a `HashedKeys` one must carry only
42
- * the commitment — so a malformed contact is rejected here rather than
43
- * travelling.
38
+ * Every contact crossing the native seam goes through the core's contact
39
+ * codec, which also refuses a contact that violates the invariants of its
40
+ * contact mode. Delegates to `pairing.request.encode_contact` /
41
+ * `decode_contact`, defined below.
44
42
  */
45
43
  function encodeContact(contact_message) {
46
- return bytes(call('encode_contact_message', (0, codec_1.jsonToBytes)((0, messages_1.plainMessage)(contact_message))));
44
+ return pairing.request.encode_contact(contact_message);
47
45
  }
48
46
  function decodeContact(wire) {
49
- const json = call('decode_contact_message', wire);
50
- return (0, messages_1.reviveMessage)((0, codec_1.jsonFromBytes)(json));
47
+ return pairing.request.decode_contact(wire);
51
48
  }
52
49
  const discovery = {
53
50
  request: {
@@ -131,23 +128,31 @@ function decodeTransportList(framed) {
131
128
  }
132
129
  const pairing = {
133
130
  request: {
134
- create_contact(channel_id, contact_mode, transport_protocols) {
135
- // The C entry point also accepts a caller-supplied nonce behind a
136
- // presence flag. `@derec-alliance/nodejs` has no such parameter, so the
137
- // flag is 0 and the library generates one — the same behaviour, not a
138
- // default invented here.
139
- const result = call('create_contact_message', channel_id, contact_mode, encodeTransportList(transport_protocols), 0, 0n);
131
+ /** Creates an out-of-band `ContactMessage`. `nonce` omitted or `null`
132
+ * lets the library draw a random one; `ContactMode.NoKeys` requires the
133
+ * caller to supply it. */
134
+ create_contact(channel_id, contact_mode, transport_protocols, nonce) {
135
+ // The C entry point carries `Option<u64>` as a presence flag plus a
136
+ // value; an absent nonce clears the flag and the library draws one.
137
+ const result = call('create_contact_message', channel_id, contact_mode, encodeTransportList(transport_protocols), nonce == null ? 0 : 1, nonce ?? 0n);
140
138
  return {
141
139
  contact_message: decodeContact(result.contact_wire_bytes),
142
140
  secret_key: bytes(result.secret_key_material),
143
141
  };
144
142
  },
145
- /** Proto-encodes a `ContactMessage`. Rejects a contact that violates the
146
- * mode/field invariant rather than serializing it. */
147
- encode_contact: encodeContact,
148
- /** Decodes proto `ContactMessage` bytes. Rejects a contact that violates
149
- * the mode/field invariant rather than returning it. */
150
- decode_contact: decodeContact,
143
+ /** Serializes a `ContactMessage` to the bytes delivered out of band.
144
+ * Refuses a contact that violates the invariants of its contact mode or
145
+ * advertises no endpoint. */
146
+ encode_contact(contact_message) {
147
+ return bytes(call('encode_contact_message', (0, codec_1.jsonToBytes)((0, messages_1.plainMessage)(contact_message))));
148
+ },
149
+ /** Parses out-of-band contact bytes back into a `ContactMessage`.
150
+ * Refuses bytes that are not a contact, or a contact that violates the
151
+ * invariants of its contact mode. */
152
+ decode_contact(bytes) {
153
+ const json = call('decode_contact_message', bytes);
154
+ return (0, messages_1.reviveMessage)((0, codec_1.jsonFromBytes)(json));
155
+ },
151
156
  produce(kind, transport_protocols, contact_message, communication_info, parameter_range) {
152
157
  const result = call('produce_pair_request_message', kind, encodeTransportList(transport_protocols), encodeContact(contact_message), (0, messages_1.encodeOptionalMessage)(messages_1.MessageKind.CommunicationInfo, communication_info), (0, messages_1.encodeOptionalMessage)(messages_1.MessageKind.ParameterRange, parameter_range));
153
158
  return {
@@ -156,8 +161,8 @@ const pairing = {
156
161
  secret_key: bytes(result.secret_key_material),
157
162
  };
158
163
  },
159
- extract(envelope_bytes, secret_key) {
160
- const result = call('extract_pair_request', envelope_bytes, secret_key);
164
+ extract(envelope_bytes, secret_key, parameter_range) {
165
+ const result = call('extract_pair_request', envelope_bytes, secret_key, (0, messages_1.encodeOptionalMessage)(messages_1.MessageKind.ParameterRange, parameter_range));
161
166
  return {
162
167
  request: (0, messages_1.decodeMessage)(messages_1.MessageKind.PairRequest, result.request_proto_bytes),
163
168
  };
@@ -189,8 +194,8 @@ const pairing = {
189
194
  response: (0, messages_1.decodeMessage)(messages_1.MessageKind.PairResponse, result.response_proto_bytes),
190
195
  };
191
196
  },
192
- process(contact_message, response, secret_key) {
193
- const result = call('process_pair_response_message', encodeContact(contact_message), (0, messages_1.encodeMessage)(messages_1.MessageKind.PairResponse, response), secret_key);
197
+ process(contact_message, response, secret_key, parameter_range) {
198
+ const result = call('process_pair_response_message', encodeContact(contact_message), (0, messages_1.encodeMessage)(messages_1.MessageKind.PairResponse, response), secret_key, (0, messages_1.encodeOptionalMessage)(messages_1.MessageKind.ParameterRange, parameter_range));
194
199
  return { shared_key: bytes(result.shared_key), channel_id: result.channel_id };
195
200
  },
196
201
  produce_pre_pair(channel_id, request, secret_key) {
@@ -211,6 +216,24 @@ const pairing = {
211
216
  nonce: result.nonce,
212
217
  };
213
218
  },
219
+ produce_pre_pair_no_keys(channel_id, request) {
220
+ const result = call('produce_pre_pair_no_keys_response_message', channel_id, (0, messages_1.encodeMessage)(messages_1.MessageKind.PrePairRequest, request));
221
+ return {
222
+ envelope: bytes(result.envelope_wire_bytes),
223
+ secret_key_material: bytes(result.secret_key_material),
224
+ };
225
+ },
226
+ process_pre_pair_no_keys(contact_message, response) {
227
+ const result = call('process_pre_pair_no_keys_response_message', encodeContact(contact_message), (0, messages_1.encodeMessage)(messages_1.MessageKind.PrePairResponse, response));
228
+ return {
229
+ mlkem_encapsulation_key: bytes(result.mlkem_encapsulation_key),
230
+ ecies_public_key: bytes(result.ecies_public_key),
231
+ nonce: result.nonce,
232
+ };
233
+ },
234
+ },
235
+ fingerprint(shared_key) {
236
+ return call('pairing_fingerprint', shared_key);
214
237
  },
215
238
  };
216
239
  const recovery = {
package/lib/protocol.d.ts CHANGED
@@ -1,19 +1,10 @@
1
1
  import { FlowKind } from './types';
2
- import type { AutoAcceptPolicy, ChannelStore, ContactMessage, ContactMode, DeRecEvent, DiscoveryParams, PairingParams, ParameterRange, ProtectSecretParams, RecoverSecretParams, UnpairReplicaParams, SecretStore, ShareStore, StateStore, ReplicaDiscoveryParams, Timeouts, Transport, UnpairAck, UnpairParams, UpdateChannelInfoParams, UserSecretStore, VerifySharesParams } from './types';
2
+ import type { AutoAcceptPolicy, ChannelStore, ContactMessage, ContactMode, DeRecEvent, Endpoint, DiscoveryParams, PairingParams, ParameterRange, ProtectSecretParams, RecoverSecretParams, UnpairReplicaParams, SecretStore, ShareStore, StateStore, StatusEnum, ReplicaDiscoveryParams, Timeouts, Transport, UnpairAck, UnpairParams, UpdateChannelInfoParams, UserSecretStore, VerifySharesParams } from './types';
3
3
  /** Shape of the `__DeRec` host object as seen from this file: every member is
4
4
  * a plain callable, since the JSI layer exposes host functions this way and
5
5
  * TypeScript has no static knowledge of them (see `primitives.ts`'s `call`
6
6
  * helper, which uses the same escape hatch). */
7
7
  type NativeHost = Record<string, (...args: any[]) => any>;
8
- /**
9
- * Maps a transport protocol name to the `derec_proto::Protocol` discriminant.
10
- * The shared enum fixture every other numeric mapping in this SDK is checked
11
- * against does not carry this enum (it
12
- * only covers the Rust-internal serde enums listed under its `"enums"` key);
13
- * the transport `Protocol` enum lives in `protobufs/transportprotocol.proto`
14
- * instead, where `HTTPS = 0` and `GRPC = 1` are defined.
15
- */
16
- export declare function protocolDiscriminant(protocol: string): number;
17
8
  /**
18
9
  * `ProtectSecretParamsJson` (`library/src/interop/ffi/protocol/flow.rs`): every
19
10
  * `UserSecret.id`/`.data` byte array travels as a bare JSON array of decimal
@@ -58,7 +49,6 @@ export declare class DeRecProtocolBuilder {
58
49
  private readonly secretIdValue;
59
50
  private config;
60
51
  private stores;
61
- private communicationInfo;
62
52
  constructor(secretId: bigint | number);
63
53
  withChannelStore(store: ChannelStore): this;
64
54
  withShareStore(store: ShareStore): this;
@@ -66,21 +56,10 @@ export declare class DeRecProtocolBuilder {
66
56
  withUserSecretStore(store: UserSecretStore): this;
67
57
  withStateStore(store: StateStore): this;
68
58
  withTransport(transport: Transport): this;
69
- /**
70
- * @deprecated Use {@link withOwnTransports}, which takes the whole
71
- * preference list — `withOwnTransports([endpoint])` is the direct
72
- * replacement. Removed at 0.0.5.
73
- */
74
- withOwnTransport(endpoint: {
75
- uri: string;
76
- protocol: string;
77
- }): this;
78
59
  /**
79
60
  * Set every transport endpoint this application serves, in preference
80
- * order. Written to the config's `own_transports` array, which takes
81
- * precedence over `own_transport_uri` / `own_transport_protocol` on the
82
- * Rust side when non-empty — see `ProtocolConfig` in
83
- * `library/src/interop/ffi/protocol/handle/mod.rs`.
61
+ * order. Written to the config's `own_transports` array — see
62
+ * `ProtocolConfig` in `library/src/interop/ffi/protocol/handle/mod.rs`.
84
63
  *
85
64
  * The order given is forwarded verbatim: it is not sorted, deduplicated,
86
65
  * or reordered here. It is this application's own preference and
@@ -89,14 +68,10 @@ export declare class DeRecProtocolBuilder {
89
68
  * listing an endpoint this application does not serve makes pairing
90
69
  * succeed and replies vanish.
91
70
  *
92
- * Supersedes {@link withOwnTransport} for applications serving more
93
- * than one transport; the single-endpoint setter remains fully
94
- * supported.
71
+ * Required: `build()` with no own transport is refused by the library,
72
+ * since a node with no endpoint cannot be reached by any peer.
95
73
  */
96
- withOwnTransports(transports: {
97
- uri: string;
98
- protocol: string;
99
- }[]): this;
74
+ withOwnTransports(transports: Endpoint[]): this;
100
75
  /** Default: 3. */
101
76
  withThreshold(threshold: number): this;
102
77
  /** Default: 3. */
@@ -109,38 +84,14 @@ export declare class DeRecProtocolBuilder {
109
84
  * `snake_case` keys one for one.
110
85
  */
111
86
  withTimeouts(timeouts: Timeouts): this;
112
- /**
113
- * @deprecated Use {@link withUnsafeConnection}, which names both gated
114
- * schemes. Removed at 0.0.5. Default: false.
115
- */
116
- withUnsafeHttp(allow: boolean): this;
117
87
  /**
118
88
  * Accept plaintext `http://` and `grpc://` transport endpoints.
119
- * **Development only.** Default: false. Supersedes
120
- * {@link withUnsafeHttp}, which names only the HTTP scheme.
121
- *
122
- * Either flag alone is honored. Setting both to disagreeing values fails
123
- * construction with the error code `CONFLICTING_PLAINTEXT_OPT_IN` rather
124
- * than resolving silently, because precedence would hand the decision to
125
- * the flag being removed.
89
+ * **Development only.** Default: false.
126
90
  */
127
91
  withUnsafeConnection(allow: boolean): this;
128
92
  /**
129
- * Default: empty. `derec_protocol_new`'s own `communication_info` argument
130
- * is a pre-encoded `CommunicationInfo` protobuf message, and this SDK has
131
- * no encoder for that message — the C ABI exposes one only for
132
- * `ContactMessage`. Hand-rolling one here would be SDK-side protocol logic
133
- * with no test coverage — exactly what this codebase's "Rust decides, the
134
- * SDK only marshals" rule forbids. Instead,
135
- * `build()` constructs the protocol with an empty `communication_info`
136
- * (a legitimate, always-accepted value — see `decode_communication_info`
137
- * in `library/src/interop/ffi/protocol/handle/mod.rs`, which treats a zero-length
138
- * buffer as "no entries") and then calls the already-bound
139
- * {@link DeRecProtocol.setCommunicationInfo}, which takes the same map as
140
- * plain JSON (`derec_protocol_set_communication_info` in
141
- * `library/src/interop/ffi/protocol/handle/config.rs`). That setter is queued on
142
- * the protocol's serial worker before `build()` returns, so it is ordered
143
- * ahead of every call the caller can subsequently make.
93
+ * Default: empty. Written to the config's `communication_info` key, so the
94
+ * map is part of the protocol from construction.
144
95
  */
145
96
  withCommunicationInfo(info: Record<string, string>): this;
146
97
  /** Default: false. */
@@ -149,7 +100,10 @@ export declare class DeRecProtocolBuilder {
149
100
  withUnpairAck(ack: UnpairAck): this;
150
101
  /** Default: false. */
151
102
  withAutoReplyTo(enabled: boolean): this;
152
- /** Default: empty policy (every flow off). */
103
+ /**
104
+ * Default: empty policy (every flow off). A flow left out of `policy` is
105
+ * left out of the config, and the library applies its own default to it.
106
+ */
153
107
  withAutoAccept(policy: AutoAcceptPolicy): this;
154
108
  /** Default: unset. */
155
109
  withReplicaId(replicaId: bigint | number): this;
@@ -160,6 +114,9 @@ export declare class DeRecProtocolBuilder {
160
114
  * against the peer's range on inbound ones: a range that fails to
161
115
  * intersect rejects the pairing. Every bound is optional and defaults to
162
116
  * `0`, which the protocol reads as "no constraint on this dimension".
117
+ * Bounds cross to the library as decimal strings, so the full `i64` range
118
+ * survives; a bound left out is left out of the config, and the library
119
+ * applies its default.
163
120
  *
164
121
  * Default: unset — no constraints advertised, every peer range accepted.
165
122
  */
@@ -169,9 +126,8 @@ export declare class DeRecProtocolBuilder {
169
126
  /**
170
127
  * Thin wrapper around the `ProtocolHost` JSI host object, mirroring
171
128
  * `@derec-alliance/nodejs`'s `DeRecProtocol` — same methods, and the same
172
- * sync/async split except for `setCommunicationInfo` and `setOwnTransport`,
173
- * which return a `Promise` here (see their own doc comments for why);
174
- * `secretId` is synchronous and everything else returns a `Promise`. Every method encodes its
129
+ * sync/async split: `secretId` is synchronous and everything else returns a
130
+ * `Promise`. Every method encodes its
175
131
  * arguments into the wire shape the host function expects and decodes its
176
132
  * result back into the typed value declared here; no protocol decision is
177
133
  * made in this class.
@@ -191,53 +147,32 @@ export declare class DeRecProtocol {
191
147
  static fromHost(host: NativeHost): DeRecProtocol;
192
148
  secretId(): bigint;
193
149
  /**
194
- * Returns a `Promise`, where `@derec-alliance/nodejs` declares this
195
- * `void`. The native setter takes the same handle mutex a running flow
196
- * holds across its store callbacks, so calling it on the JavaScript thread
197
- * would block that thread until the flow released the mutex — which it
198
- * cannot do while it is waiting on the JavaScript thread. The binding
199
- * therefore queues the setter onto the same serial worker every flow runs
200
- * on, which orders it after any call already in flight. The nodejs SDK is
201
- * WASM and single-threaded, so it has no such hazard.
150
+ * Replaces this node's local communication info.
202
151
  *
203
- * Callers that ignore the result behave exactly as before, so this stays
204
- * source-compatible with nodejs-shaped code; awaiting it additionally
205
- * surfaces a failure that would otherwise be swallowed.
152
+ * The native setter takes the same handle mutex a running flow holds
153
+ * across its store callbacks, so calling it on the JavaScript thread would
154
+ * block that thread until the flow released the mutex — which it cannot do
155
+ * while it is waiting on the JavaScript thread. The binding therefore
156
+ * queues the setter onto the same serial worker every flow runs on, which
157
+ * orders it after any call already in flight. Awaiting the returned
158
+ * `Promise` surfaces a failure that would otherwise be swallowed.
206
159
  */
207
160
  setCommunicationInfo(info: Record<string, string>): Promise<void>;
208
- /**
209
- * Replace this node's endpoint for one protocol, leaving the others
210
- * alone. A node serves at most one endpoint per protocol, so the
211
- * `(uri, protocol)` pair identifies the entry it replaces; an entry for a
212
- * protocol not yet served is appended, and a replaced one keeps its
213
- * position in the preference order.
214
- *
215
- * Returns a `Promise` for the same reason {@link setCommunicationInfo} does.
216
- *
217
- * @deprecated Use {@link setOwnTransports}, which takes the whole
218
- * preference list and is the only way to change which protocols this node
219
- * serves, or their order. Removed at 0.0.5.
220
- */
221
- setOwnTransport(uri: string, protocol: string): Promise<void>;
222
161
  /**
223
162
  * Replaces every endpoint this node advertises, in preference order —
224
- * the runtime counterpart to `withOwnTransports`, and the only way to
225
- * change a multi-endpoint node's set ({@link setOwnTransport} collapses
226
- * it to the one endpoint it is given).
163
+ * the runtime counterpart to `withOwnTransports`.
227
164
  *
228
165
  * Every entry is validated before any is stored, so a malformed URI
229
166
  * leaves the previous set intact. An empty array is rejected.
230
167
  *
231
- * Returns a `Promise` for the same reason {@link setCommunicationInfo} does.
168
+ * Queued onto the serial worker for the same reason as
169
+ * {@link setCommunicationInfo}.
232
170
  */
233
- setOwnTransports(transports: {
234
- uri: string;
235
- protocol: string;
236
- }[]): Promise<void>;
171
+ setOwnTransports(transports: Endpoint[]): Promise<void>;
237
172
  /**
238
173
  * Decodes the `contact_wire_bytes` `derec_protocol_create_contact`
239
174
  * produces into a typed `ContactMessage`, so an application can read the
240
- * contact's `nonce`, `transport_protocol` and mode without a protobuf
175
+ * contact's `nonce`, `supported_transports` and mode without a protobuf
241
176
  * codec of its own. Feed the returned object straight back into
242
177
  * `start(FlowKind.Pairing, { contact })`, which re-encodes it.
243
178
  */
@@ -254,14 +189,31 @@ export declare class DeRecProtocol {
254
189
  process(message: Uint8Array): Promise<DeRecEvent[]>;
255
190
  tick(): Promise<DeRecEvent[]>;
256
191
  accept(actionBytes: Uint8Array): Promise<DeRecEvent[]>;
257
- reject(actionBytes: Uint8Array, status: number, memo: string): Promise<void>;
192
+ reject(actionBytes: Uint8Array, status: StatusEnum, memo: string): Promise<void>;
258
193
  getFingerprint(channelId: bigint | number): Promise<string>;
259
194
  verifyFingerprint(channelId: bigint | number, fingerprint: string): Promise<boolean>;
260
195
  removeExpiredChannels(olderThanSecs: number): Promise<string[]>;
196
+ /**
197
+ * Rebuild this protocol's `secret_id` namespace from a recovered `Secret`.
198
+ * Pass the `secret` carried by the `SecretRecovered` event verbatim.
199
+ * A helper or member whose `transports` is empty gets no channel: it is
200
+ * reported as a `PeerNotRestored` event in the returned array and the rest
201
+ * of the roster is restored.
202
+ *
203
+ * Rejects with a `DeRecError`; among its codes:
204
+ *
205
+ * | code | meaning |
206
+ * |--------------------|-------------------------------------------------------------|
207
+ * | `already_restored` | A user-secret snapshot already exists for this `secret_id`. |
208
+ * | `restore_conflict` | Channels live at ids restore is about to write. The error |
209
+ * | | carries `channel_ids: string[]` listing the collisions. |
210
+ */
261
211
  restore(recoveredSecret: Extract<DeRecEvent, {
262
212
  type: 'SecretRecovered';
263
213
  }>['secret'], version: number): Promise<DeRecEvent[]>;
264
214
  /** Release the native handle. Safe to call more than once. */
265
215
  free(): void;
216
+ /** Same as {@link DeRecProtocol.free}, for `using`. */
217
+ [Symbol.dispose](): void;
266
218
  }
267
219
  export {};