@derec-alliance/react-native 0.0.1

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.
Files changed (65) hide show
  1. package/DeRec.podspec +25 -0
  2. package/LICENSE +201 -0
  3. package/README.md +222 -0
  4. package/android/CMakeLists.txt +38 -0
  5. package/android/build.gradle +79 -0
  6. package/android/src/main/AndroidManifest.xml +12 -0
  7. package/android/src/main/java/org/derec/DeRecModule.kt +56 -0
  8. package/android/src/main/java/org/derec/DeRecPackage.kt +24 -0
  9. package/android/src/main/jni/OnLoad.cpp +39 -0
  10. package/android/src/main/jniLibs/arm64-v8a/libderec_library.a +0 -0
  11. package/android/src/main/jniLibs/armeabi-v7a/libderec_library.a +0 -0
  12. package/android/src/main/jniLibs/x86_64/libderec_library.a +0 -0
  13. package/cpp/Convert.cpp +50 -0
  14. package/cpp/Convert.h +38 -0
  15. package/cpp/DeRecInstaller.cpp +186 -0
  16. package/cpp/DeRecInstaller.h +28 -0
  17. package/cpp/Invoker.h +20 -0
  18. package/cpp/JsCallbackBridge.cpp +144 -0
  19. package/cpp/JsCallbackBridge.h +148 -0
  20. package/cpp/Primitives.cpp +1193 -0
  21. package/cpp/Primitives.h +39 -0
  22. package/cpp/ProtocolHost.cpp +613 -0
  23. package/cpp/ProtocolHost.h +88 -0
  24. package/cpp/RuntimeInvoker.h +29 -0
  25. package/cpp/StoreCallbacks.cpp +1293 -0
  26. package/cpp/StoreCallbacks.h +111 -0
  27. package/cpp/WorkerThread.cpp +74 -0
  28. package/cpp/WorkerThread.h +54 -0
  29. package/cpp/derec_ffi.h +2145 -0
  30. package/ios/DeRec.h +23 -0
  31. package/ios/DeRec.mm +39 -0
  32. package/ios/DeRecFFI.xcframework/Info.plist +48 -0
  33. package/ios/DeRecFFI.xcframework/ios-arm64/Headers/derec_ffi.h +2145 -0
  34. package/ios/DeRecFFI.xcframework/ios-arm64/libderec_library.a +0 -0
  35. package/ios/DeRecFFI.xcframework/ios-arm64_x86_64-simulator/Headers/derec_ffi.h +2145 -0
  36. package/ios/DeRecFFI.xcframework/ios-arm64_x86_64-simulator/libderec_library.a +0 -0
  37. package/lib/binary.d.ts +19 -0
  38. package/lib/binary.js +164 -0
  39. package/lib/codec.d.ts +16 -0
  40. package/lib/codec.js +80 -0
  41. package/lib/errors.d.ts +23 -0
  42. package/lib/errors.js +35 -0
  43. package/lib/index.d.ts +4 -0
  44. package/lib/index.js +27 -0
  45. package/lib/messages.d.ts +41 -0
  46. package/lib/messages.js +192 -0
  47. package/lib/native.d.ts +11 -0
  48. package/lib/native.js +40 -0
  49. package/lib/primitives.d.ts +137 -0
  50. package/lib/primitives.js +329 -0
  51. package/lib/protocol.d.ts +188 -0
  52. package/lib/protocol.js +514 -0
  53. package/lib/types.d.ts +1014 -0
  54. package/lib/types.js +63 -0
  55. package/package.json +55 -0
  56. package/react-native.config.js +19 -0
  57. package/src/binary.ts +182 -0
  58. package/src/codec.ts +79 -0
  59. package/src/errors.ts +45 -0
  60. package/src/index.ts +7 -0
  61. package/src/messages.ts +192 -0
  62. package/src/native.ts +52 -0
  63. package/src/primitives.ts +770 -0
  64. package/src/protocol.ts +621 -0
  65. package/src/types.ts +1040 -0
@@ -0,0 +1,137 @@
1
+ import type { CommittedDeRecShare, CommunicationInfo, ContactMessage, ContactMode, CreateContactResult, DiscoveryProcessResult, GetSecretIdsVersionsRequestMessage, GetSecretIdsVersionsResponseMessage, GetShareRequestMessage, GetShareResponseMessage, PairRequestMessage, PairResponseMessage, PairingProcessResult, PairingRequestProduceResult, PairingResponseProduceResult, ParameterRange, PrePairRequestExtractResult, PrePairRequestMessage, PrePairResponseExtractResult, PrePairResponseMessage, ProcessPrePairResult, ProducePrePairResult, ProduceResult, RecoverResult, SecretVersionEntry, SenderKind, SharingResponseProduceResult, SplitResult, StoreShareRequestMessage, StoreShareResponseMessage, TransportProtocol, UnpairRequestMessage, UnpairResponseMessage, UnpairingProcessResult, VerifyShareRequestMessage, VerifyShareResponseMessage } from './types';
2
+ /**
3
+ * `ContactMessage` keeps its own dedicated codec rather than going through
4
+ * the generic message codec: `encode_contact_message` /
5
+ * `decode_contact_message` also enforce the mode/field invariant — an
6
+ * `InlineKeys` contact must carry keys, a `HashedKeys` one must carry only
7
+ * the commitment — so a malformed contact is rejected here rather than
8
+ * travelling.
9
+ */
10
+ declare function encodeContact(contact_message: ContactMessage): Uint8Array;
11
+ declare function decodeContact(wire: Uint8Array | ArrayBuffer): ContactMessage;
12
+ export declare const primitives: {
13
+ discovery: {
14
+ request: {
15
+ produce(channel_id: bigint, shared_key: Uint8Array, reply_to?: TransportProtocol | null): ProduceResult;
16
+ extract(envelope_bytes: Uint8Array, shared_key: Uint8Array): {
17
+ request: GetSecretIdsVersionsRequestMessage;
18
+ };
19
+ };
20
+ response: {
21
+ produce(channel_id: bigint, secret_list: SecretVersionEntry[], shared_key: Uint8Array): ProduceResult;
22
+ extract(envelope_bytes: Uint8Array, shared_key: Uint8Array): {
23
+ response: GetSecretIdsVersionsResponseMessage;
24
+ };
25
+ process(response: GetSecretIdsVersionsResponseMessage): DiscoveryProcessResult;
26
+ };
27
+ };
28
+ pairing: {
29
+ request: {
30
+ create_contact(channel_id: bigint, contact_mode: ContactMode | number, transport_protocol: TransportProtocol): CreateContactResult;
31
+ /** Proto-encodes a `ContactMessage`. Rejects a contact that violates the
32
+ * mode/field invariant rather than serializing it. */
33
+ encode_contact: typeof encodeContact;
34
+ /** Decodes proto `ContactMessage` bytes. Rejects a contact that violates
35
+ * the mode/field invariant rather than returning it. */
36
+ decode_contact: typeof decodeContact;
37
+ produce(kind: SenderKind, transport_protocol: TransportProtocol, contact_message: ContactMessage, communication_info: CommunicationInfo | null, parameter_range: ParameterRange | null): PairingRequestProduceResult;
38
+ extract(envelope_bytes: Uint8Array, secret_key: Uint8Array): {
39
+ request: PairRequestMessage;
40
+ };
41
+ produce_pre_pair(transport_protocol: TransportProtocol, contact_message: ContactMessage): ProducePrePairResult;
42
+ extract_pre_pair(envelope_bytes: Uint8Array): PrePairRequestExtractResult;
43
+ };
44
+ response: {
45
+ produce(channel_id: bigint, request: PairRequestMessage, secret_key: Uint8Array, communication_info: CommunicationInfo | null, parameter_range: ParameterRange | null): PairingResponseProduceResult;
46
+ extract(envelope_bytes: Uint8Array, secret_key: Uint8Array): {
47
+ response: PairResponseMessage;
48
+ };
49
+ process(contact_message: ContactMessage, response: PairResponseMessage, secret_key: Uint8Array): PairingProcessResult;
50
+ produce_pre_pair(channel_id: bigint, request: PrePairRequestMessage, secret_key: Uint8Array): ProducePrePairResult;
51
+ extract_pre_pair(envelope_bytes: Uint8Array): PrePairResponseExtractResult;
52
+ process_pre_pair(contact_message: ContactMessage, response: PrePairResponseMessage): ProcessPrePairResult;
53
+ };
54
+ };
55
+ recovery: {
56
+ request: {
57
+ produce(channel_id: bigint, secret_id: bigint, version: number, shared_key: Uint8Array, reply_to?: TransportProtocol | null): ProduceResult;
58
+ extract(envelope_bytes: Uint8Array, shared_key: Uint8Array): {
59
+ request: GetShareRequestMessage;
60
+ };
61
+ };
62
+ response: {
63
+ produce(channel_id: bigint, request: GetShareRequestMessage, stored_share_request: StoreShareRequestMessage, shared_key: Uint8Array): ProduceResult;
64
+ extract(envelope_bytes: Uint8Array, shared_key: Uint8Array): {
65
+ response: GetShareResponseMessage;
66
+ };
67
+ recover(secret_id: bigint, version: number, responses: GetShareResponseMessage[]): RecoverResult;
68
+ };
69
+ };
70
+ sharing: {
71
+ request: {
72
+ split(channels: bigint[], secret_id: bigint, version: number, secret_data: Uint8Array, threshold: number): SplitResult;
73
+ produce(channel_id: bigint, version: number, secret_id: bigint, committed_share: CommittedDeRecShare, keep_list: number[], description: string, shared_key: Uint8Array, reply_to?: TransportProtocol | null): ProduceResult;
74
+ extract(envelope_bytes: Uint8Array, shared_key: Uint8Array): {
75
+ request: StoreShareRequestMessage;
76
+ };
77
+ };
78
+ response: {
79
+ produce(channel_id: bigint, request: StoreShareRequestMessage, shared_key: Uint8Array): SharingResponseProduceResult;
80
+ extract(envelope_bytes: Uint8Array, shared_key: Uint8Array): {
81
+ response: StoreShareResponseMessage;
82
+ };
83
+ process(version: number, response: StoreShareResponseMessage): void;
84
+ };
85
+ };
86
+ unpairing: {
87
+ request: {
88
+ produce(channel_id: bigint, memo: string, shared_key: Uint8Array, reply_to?: TransportProtocol | null): ProduceResult;
89
+ extract(envelope_bytes: Uint8Array, shared_key: Uint8Array): {
90
+ request: UnpairRequestMessage;
91
+ };
92
+ };
93
+ response: {
94
+ produce(channel_id: bigint, shared_key: Uint8Array): ProduceResult;
95
+ extract(envelope_bytes: Uint8Array, shared_key: Uint8Array): {
96
+ response: UnpairResponseMessage;
97
+ };
98
+ /**
99
+ * `acknowledged` is `true` for every value this can return. The library's
100
+ * `unpairing::response::process` yields `ProcessResult { acknowledged:
101
+ * true }` on success and an error on a non-Ok peer status, and the C ABI
102
+ * carries only the error — so a refusal arrives as a thrown `DeRecError`,
103
+ * never as `acknowledged: false`. The field exists because
104
+ * `@derec-alliance/nodejs` surfaces it, where serde serializes the same
105
+ * constant.
106
+ */
107
+ process(response: UnpairResponseMessage): UnpairingProcessResult;
108
+ };
109
+ };
110
+ verification: {
111
+ request: {
112
+ produce(channel_id: bigint, secret_id: bigint, version: number, shared_key: Uint8Array, reply_to?: TransportProtocol | null): ProduceResult;
113
+ extract(envelope_bytes: Uint8Array, shared_key: Uint8Array): {
114
+ request: VerifyShareRequestMessage;
115
+ };
116
+ };
117
+ response: {
118
+ produce(channel_id: bigint, request: VerifyShareRequestMessage, shared_key: Uint8Array, share_content: Uint8Array): ProduceResult;
119
+ extract(envelope_bytes: Uint8Array, shared_key: Uint8Array): {
120
+ response: VerifyShareResponseMessage;
121
+ };
122
+ /** `request` must be the request the owner previously produced for this
123
+ * challenge. Responses whose `(nonce, secret_id, version)` triple does
124
+ * not match are rejected — that is the anti-replay gate. */
125
+ process(request: VerifyShareRequestMessage, response: VerifyShareResponseMessage, share_content: Uint8Array): boolean;
126
+ };
127
+ };
128
+ };
129
+ /**
130
+ * Envelope-level helpers that operate on raw `DeRecMessage` bytes without
131
+ * touching the encrypted inner payload.
132
+ */
133
+ export declare const envelope: {
134
+ apply_trace_id(envelope_bytes: Uint8Array, trace_id: bigint): Uint8Array;
135
+ read_trace_id(envelope_bytes: Uint8Array): bigint;
136
+ };
137
+ export {};
@@ -0,0 +1,329 @@
1
+ "use strict";
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ // Copyright (c) 2026 DeRec Alliance. All rights reserved.
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.envelope = exports.primitives = void 0;
6
+ /**
7
+ * The stateless primitive surface, shaped identically to
8
+ * `@derec-alliance/nodejs`.
9
+ *
10
+ * Primitives are synchronous: they are pure byte transforms with no store or
11
+ * transport callbacks, so they run on the JavaScript thread. `sharing.request.
12
+ * split` does real cryptographic work, which is why an application that needs
13
+ * it off-thread should drive it through `DeRecProtocol` instead.
14
+ *
15
+ * Each function marshals between the typed surface and the C ABI's own shapes
16
+ * — protobuf wire bytes for messages, hand-packed little-endian containers for
17
+ * the three set-valued arguments. See `./messages` and `./binary`. Nothing
18
+ * here interprets a protocol value: no defaulting, no clamping, no branching
19
+ * on what a field contains.
20
+ */
21
+ const binary_1 = require("./binary");
22
+ const codec_1 = require("./codec");
23
+ const messages_1 = require("./messages");
24
+ const native_1 = require("./native");
25
+ function call(name, ...args) {
26
+ return (0, native_1.getNative)()[name](...args);
27
+ }
28
+ function bytes(value) {
29
+ return new Uint8Array(value);
30
+ }
31
+ /** `null` and `undefined` both mean "no override" for every optional
32
+ * `TransportProtocol` argument; the C ABI reads a zero-length buffer as
33
+ * absent. */
34
+ function replyTo(value) {
35
+ return (0, messages_1.encodeOptionalMessage)(messages_1.MessageKind.TransportProtocol, value);
36
+ }
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.
44
+ */
45
+ function encodeContact(contact_message) {
46
+ return bytes(call('encode_contact_message', (0, codec_1.jsonToBytes)((0, messages_1.plainMessage)(contact_message))));
47
+ }
48
+ function decodeContact(wire) {
49
+ const json = call('decode_contact_message', wire);
50
+ return (0, messages_1.reviveMessage)((0, codec_1.jsonFromBytes)(json));
51
+ }
52
+ const discovery = {
53
+ request: {
54
+ produce(channel_id, shared_key, reply_to) {
55
+ const envelope = call('produce_get_secret_ids_versions_request_message', channel_id, shared_key, replyTo(reply_to));
56
+ return { envelope: bytes(envelope) };
57
+ },
58
+ extract(envelope_bytes, shared_key) {
59
+ const result = call('extract_get_secret_ids_versions_request', envelope_bytes, shared_key);
60
+ return {
61
+ request: (0, messages_1.decodeMessage)(messages_1.MessageKind.GetSecretIdsVersionsRequest, result.request_proto_bytes),
62
+ };
63
+ },
64
+ },
65
+ response: {
66
+ produce(channel_id, secret_list, shared_key) {
67
+ const envelope = call('produce_get_secret_ids_versions_response_message', channel_id, (0, binary_1.encodeSecretList)(secret_list), shared_key);
68
+ return { envelope: bytes(envelope) };
69
+ },
70
+ extract(envelope_bytes, shared_key) {
71
+ const result = call('extract_get_secret_ids_versions_response', envelope_bytes, shared_key);
72
+ return {
73
+ response: (0, messages_1.decodeMessage)(messages_1.MessageKind.GetSecretIdsVersionsResponse, result.response_proto_bytes),
74
+ };
75
+ },
76
+ process(response) {
77
+ const packed = call('process_get_secret_ids_versions_response_message', (0, messages_1.encodeMessage)(messages_1.MessageKind.GetSecretIdsVersionsResponse, response));
78
+ return { secret_list: (0, binary_1.decodeSecretList)(packed) };
79
+ },
80
+ },
81
+ };
82
+ const pairing = {
83
+ request: {
84
+ create_contact(channel_id, contact_mode, transport_protocol) {
85
+ // The C entry point also accepts a caller-supplied nonce behind a
86
+ // presence flag. `@derec-alliance/nodejs` has no such parameter, so the
87
+ // flag is 0 and the library generates one — the same behaviour, not a
88
+ // default invented here.
89
+ const result = call('create_contact_message', channel_id, contact_mode, (0, messages_1.encodeMessage)(messages_1.MessageKind.TransportProtocol, transport_protocol), 0, 0n);
90
+ return {
91
+ contact_message: decodeContact(result.contact_wire_bytes),
92
+ secret_key: bytes(result.secret_key_material),
93
+ };
94
+ },
95
+ /** Proto-encodes a `ContactMessage`. Rejects a contact that violates the
96
+ * mode/field invariant rather than serializing it. */
97
+ encode_contact: encodeContact,
98
+ /** Decodes proto `ContactMessage` bytes. Rejects a contact that violates
99
+ * the mode/field invariant rather than returning it. */
100
+ decode_contact: decodeContact,
101
+ produce(kind, transport_protocol, contact_message, communication_info, parameter_range) {
102
+ const result = call('produce_pair_request_message', kind, (0, messages_1.encodeMessage)(messages_1.MessageKind.TransportProtocol, transport_protocol), encodeContact(contact_message), (0, messages_1.encodeOptionalMessage)(messages_1.MessageKind.CommunicationInfo, communication_info), (0, messages_1.encodeOptionalMessage)(messages_1.MessageKind.ParameterRange, parameter_range));
103
+ return {
104
+ envelope: bytes(result.request_wire_bytes),
105
+ initiator_contact_message: decodeContact(result.initiator_contact_message_wire_bytes),
106
+ secret_key: bytes(result.secret_key_material),
107
+ };
108
+ },
109
+ extract(envelope_bytes, secret_key) {
110
+ const result = call('extract_pair_request', envelope_bytes, secret_key);
111
+ return {
112
+ request: (0, messages_1.decodeMessage)(messages_1.MessageKind.PairRequest, result.request_proto_bytes),
113
+ };
114
+ },
115
+ produce_pre_pair(transport_protocol, contact_message) {
116
+ const envelope = call('produce_pre_pair_request_message', (0, messages_1.encodeMessage)(messages_1.MessageKind.TransportProtocol, transport_protocol), encodeContact(contact_message));
117
+ return { envelope: bytes(envelope) };
118
+ },
119
+ extract_pre_pair(envelope_bytes) {
120
+ const result = call('extract_pre_pair_request', envelope_bytes);
121
+ return {
122
+ request: (0, messages_1.decodeMessage)(messages_1.MessageKind.PrePairRequest, result.request_proto_bytes),
123
+ };
124
+ },
125
+ },
126
+ response: {
127
+ produce(channel_id, request, secret_key, communication_info, parameter_range) {
128
+ const result = call('produce_pair_response_message', channel_id, (0, messages_1.encodeMessage)(messages_1.MessageKind.PairRequest, request), secret_key, (0, messages_1.encodeOptionalMessage)(messages_1.MessageKind.CommunicationInfo, communication_info), (0, messages_1.encodeOptionalMessage)(messages_1.MessageKind.ParameterRange, parameter_range));
129
+ return {
130
+ envelope: bytes(result.response_wire_bytes),
131
+ peer_transport_protocol: (0, messages_1.decodeMessage)(messages_1.MessageKind.TransportProtocol, result.peer_transport_protocol),
132
+ shared_key: bytes(result.shared_key),
133
+ channel_id: result.channel_id,
134
+ };
135
+ },
136
+ extract(envelope_bytes, secret_key) {
137
+ const result = call('extract_pair_response', envelope_bytes, secret_key);
138
+ return {
139
+ response: (0, messages_1.decodeMessage)(messages_1.MessageKind.PairResponse, result.response_proto_bytes),
140
+ };
141
+ },
142
+ process(contact_message, response, secret_key) {
143
+ const result = call('process_pair_response_message', encodeContact(contact_message), (0, messages_1.encodeMessage)(messages_1.MessageKind.PairResponse, response), secret_key);
144
+ return { shared_key: bytes(result.shared_key), channel_id: result.channel_id };
145
+ },
146
+ produce_pre_pair(channel_id, request, secret_key) {
147
+ const envelope = call('produce_pre_pair_response_message', channel_id, (0, messages_1.encodeMessage)(messages_1.MessageKind.PrePairRequest, request), secret_key);
148
+ return { envelope: bytes(envelope) };
149
+ },
150
+ extract_pre_pair(envelope_bytes) {
151
+ const result = call('extract_pre_pair_response', envelope_bytes);
152
+ return {
153
+ response: (0, messages_1.decodeMessage)(messages_1.MessageKind.PrePairResponse, result.response_proto_bytes),
154
+ };
155
+ },
156
+ process_pre_pair(contact_message, response) {
157
+ const result = call('process_pre_pair_response_message', encodeContact(contact_message), (0, messages_1.encodeMessage)(messages_1.MessageKind.PrePairResponse, response));
158
+ return {
159
+ mlkem_encapsulation_key: bytes(result.mlkem_encapsulation_key),
160
+ ecies_public_key: bytes(result.ecies_public_key),
161
+ nonce: result.nonce,
162
+ };
163
+ },
164
+ },
165
+ };
166
+ const recovery = {
167
+ request: {
168
+ produce(channel_id, secret_id, version, shared_key, reply_to) {
169
+ const envelope = call('produce_get_share_request_message', channel_id, secret_id, version, shared_key, replyTo(reply_to));
170
+ return { envelope: bytes(envelope) };
171
+ },
172
+ extract(envelope_bytes, shared_key) {
173
+ const result = call('extract_get_share_request', envelope_bytes, shared_key);
174
+ return {
175
+ request: (0, messages_1.decodeMessage)(messages_1.MessageKind.GetShareRequest, result.request_proto_bytes),
176
+ };
177
+ },
178
+ },
179
+ response: {
180
+ produce(channel_id, request, stored_share_request, shared_key) {
181
+ const envelope = call('produce_get_share_response_message', channel_id, (0, messages_1.encodeMessage)(messages_1.MessageKind.GetShareRequest, request), (0, messages_1.encodeMessage)(messages_1.MessageKind.StoreShareRequest, stored_share_request), shared_key);
182
+ return { envelope: bytes(envelope) };
183
+ },
184
+ extract(envelope_bytes, shared_key) {
185
+ const result = call('extract_get_share_response', envelope_bytes, shared_key);
186
+ return {
187
+ response: (0, messages_1.decodeMessage)(messages_1.MessageKind.GetShareResponse, result.response_proto_bytes),
188
+ };
189
+ },
190
+ recover(secret_id, version, responses) {
191
+ const packed = (0, binary_1.encodeShareResponses)(responses.map((response) => (0, messages_1.encodeMessage)(messages_1.MessageKind.GetShareResponse, response)));
192
+ const secret = call('recover_from_share_responses', packed, secret_id, version);
193
+ return { secret_data: bytes(secret) };
194
+ },
195
+ },
196
+ };
197
+ const sharing = {
198
+ request: {
199
+ split(channels, secret_id, version, secret_data, threshold) {
200
+ const packed = call('protect_secret', secret_id, secret_data, channels, threshold, version);
201
+ const shares = new Map();
202
+ for (const entry of (0, binary_1.decodeCommittedShareEntries)(packed)) {
203
+ shares.set(entry.channelId, (0, messages_1.decodeMessage)(messages_1.MessageKind.CommittedDeRecShare, entry.shareProto));
204
+ }
205
+ return { shares };
206
+ },
207
+ produce(channel_id, version, secret_id, committed_share, keep_list, description, shared_key, reply_to) {
208
+ const envelope = call('produce_store_share_request_message', channel_id, version, secret_id, (0, messages_1.encodeMessage)(messages_1.MessageKind.CommittedDeRecShare, committed_share), keep_list, (0, codec_1.utf8Encode)(description), shared_key, replyTo(reply_to));
209
+ return { envelope: bytes(envelope) };
210
+ },
211
+ extract(envelope_bytes, shared_key) {
212
+ const result = call('extract_store_share_request', envelope_bytes, shared_key);
213
+ return {
214
+ request: (0, messages_1.decodeMessage)(messages_1.MessageKind.StoreShareRequest, result.request_proto_bytes),
215
+ };
216
+ },
217
+ },
218
+ response: {
219
+ produce(channel_id, request, shared_key) {
220
+ const result = call('produce_store_share_response_message', channel_id, (0, messages_1.encodeMessage)(messages_1.MessageKind.StoreShareRequest, request), shared_key);
221
+ return {
222
+ envelope: bytes(result.wire_bytes),
223
+ committed_share: (0, messages_1.decodeMessage)(messages_1.MessageKind.CommittedDeRecShare, result.committed_share_bytes),
224
+ secret_id: result.secret_id,
225
+ version: result.version,
226
+ };
227
+ },
228
+ extract(envelope_bytes, shared_key) {
229
+ const result = call('extract_store_share_response', envelope_bytes, shared_key);
230
+ return {
231
+ response: (0, messages_1.decodeMessage)(messages_1.MessageKind.StoreShareResponse, result.response_proto_bytes),
232
+ };
233
+ },
234
+ process(version, response) {
235
+ call('process_store_share_response_message', version, (0, messages_1.encodeMessage)(messages_1.MessageKind.StoreShareResponse, response));
236
+ },
237
+ },
238
+ };
239
+ const unpairing = {
240
+ request: {
241
+ produce(channel_id, memo, shared_key, reply_to) {
242
+ const envelope = call('produce_unpair_request_message', channel_id, (0, codec_1.utf8Encode)(memo), shared_key, replyTo(reply_to));
243
+ return { envelope: bytes(envelope) };
244
+ },
245
+ extract(envelope_bytes, shared_key) {
246
+ const result = call('extract_unpair_request', envelope_bytes, shared_key);
247
+ return {
248
+ request: (0, messages_1.decodeMessage)(messages_1.MessageKind.UnpairRequest, result.request_proto_bytes),
249
+ };
250
+ },
251
+ },
252
+ response: {
253
+ produce(channel_id, shared_key) {
254
+ const envelope = call('produce_unpair_response_message', channel_id, shared_key);
255
+ return { envelope: bytes(envelope) };
256
+ },
257
+ extract(envelope_bytes, shared_key) {
258
+ const result = call('extract_unpair_response', envelope_bytes, shared_key);
259
+ return {
260
+ response: (0, messages_1.decodeMessage)(messages_1.MessageKind.UnpairResponse, result.response_proto_bytes),
261
+ };
262
+ },
263
+ /**
264
+ * `acknowledged` is `true` for every value this can return. The library's
265
+ * `unpairing::response::process` yields `ProcessResult { acknowledged:
266
+ * true }` on success and an error on a non-Ok peer status, and the C ABI
267
+ * carries only the error — so a refusal arrives as a thrown `DeRecError`,
268
+ * never as `acknowledged: false`. The field exists because
269
+ * `@derec-alliance/nodejs` surfaces it, where serde serializes the same
270
+ * constant.
271
+ */
272
+ process(response) {
273
+ call('process_unpair_response_message', (0, messages_1.encodeMessage)(messages_1.MessageKind.UnpairResponse, response));
274
+ return { acknowledged: true };
275
+ },
276
+ },
277
+ };
278
+ const verification = {
279
+ request: {
280
+ produce(channel_id, secret_id, version, shared_key, reply_to) {
281
+ const envelope = call('produce_verify_share_request_message', channel_id, secret_id, version, shared_key, replyTo(reply_to));
282
+ return { envelope: bytes(envelope) };
283
+ },
284
+ extract(envelope_bytes, shared_key) {
285
+ const result = call('extract_verify_share_request', envelope_bytes, shared_key);
286
+ return {
287
+ request: (0, messages_1.decodeMessage)(messages_1.MessageKind.VerifyShareRequest, result.request_proto_bytes),
288
+ };
289
+ },
290
+ },
291
+ response: {
292
+ produce(channel_id, request, shared_key, share_content) {
293
+ const envelope = call('produce_verify_share_response_message', channel_id, (0, messages_1.encodeMessage)(messages_1.MessageKind.VerifyShareRequest, request), shared_key, share_content);
294
+ return { envelope: bytes(envelope) };
295
+ },
296
+ extract(envelope_bytes, shared_key) {
297
+ const result = call('extract_verify_share_response', envelope_bytes, shared_key);
298
+ return {
299
+ response: (0, messages_1.decodeMessage)(messages_1.MessageKind.VerifyShareResponse, result.response_proto_bytes),
300
+ };
301
+ },
302
+ /** `request` must be the request the owner previously produced for this
303
+ * challenge. Responses whose `(nonce, secret_id, version)` triple does
304
+ * not match are rejected — that is the anti-replay gate. */
305
+ process(request, response, share_content) {
306
+ return call('process_verify_share_response_message', (0, messages_1.encodeMessage)(messages_1.MessageKind.VerifyShareRequest, request), (0, messages_1.encodeMessage)(messages_1.MessageKind.VerifyShareResponse, response), share_content);
307
+ },
308
+ },
309
+ };
310
+ exports.primitives = {
311
+ discovery,
312
+ pairing,
313
+ recovery,
314
+ sharing,
315
+ unpairing,
316
+ verification,
317
+ };
318
+ /**
319
+ * Envelope-level helpers that operate on raw `DeRecMessage` bytes without
320
+ * touching the encrypted inner payload.
321
+ */
322
+ exports.envelope = {
323
+ apply_trace_id(envelope_bytes, trace_id) {
324
+ return bytes(call('apply_trace_id_to_envelope', envelope_bytes, trace_id));
325
+ },
326
+ read_trace_id(envelope_bytes) {
327
+ return call('read_trace_id_from_envelope', envelope_bytes);
328
+ },
329
+ };
@@ -0,0 +1,188 @@
1
+ import { FlowKind } from './types';
2
+ import type { AutoAcceptPolicy, ChannelStore, ContactMessage, ContactMode, DeRecEvent, DiscoveryParams, PairingParams, ProtectSecretParams, RecoverSecretParams, RemoveReplicaParams, SecretStore, ShareStore, StateStore, SyncCheckParams, Timeouts, Transport, UnpairAck, UnpairParams, UpdateChannelInfoParams, UserSecretStore, VerifySharesParams } from './types';
3
+ /** Shape of the `__DeRec` host object as seen from this file: every member is
4
+ * a plain callable, since the JSI layer exposes host functions this way and
5
+ * TypeScript has no static knowledge of them (see `primitives.ts`'s `call`
6
+ * helper, which uses the same escape hatch). */
7
+ type NativeHost = Record<string, (...args: any[]) => any>;
8
+ /**
9
+ * Maps a transport protocol name to the `derec_proto::Protocol` discriminant.
10
+ * `bindings/test_fixture/enums.json` — the shared enum fixture every other
11
+ * numeric mapping in this SDK is read from — 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 only `HTTPS = 0` is currently defined.
15
+ */
16
+ export declare function protocolDiscriminant(protocol: string): number;
17
+ /**
18
+ * `ProtectSecretParamsJson` (`library/src/interop/ffi/protocol/flow.rs`): every
19
+ * `UserSecret.id`/`.data` byte array travels as a bare JSON array of decimal
20
+ * byte values, matching `UserSecretJson`'s plain `Vec<u8>` fields — no
21
+ * base64, no wrapping.
22
+ *
23
+ * Exported so it can be golden-tested against
24
+ * `bindings/test_fixture/wire_golden.json` without a native module.
25
+ */
26
+ export declare function buildProtectSecretParams(params: ProtectSecretParams): Record<string, unknown>;
27
+ /**
28
+ * `RestoreParamsJson` (`library/src/interop/ffi/protocol/handle/flow.rs`). Mirrors
29
+ * `SecretWire`'s own shape: `channel_id`/`replica_id` are the decimal `u64`
30
+ * strings the `SecretRecovered` event already carries, forwarded verbatim;
31
+ * `communication_info` is omitted per-entry (not sent as `{}`) whenever a
32
+ * helper or replica member has none, matching the Go SDK's `omitempty` and
33
+ * the shared golden fixture byte-for-byte; `replicas` is omitted entirely
34
+ * when the recovered secret has no replica group.
35
+ *
36
+ * Exported so it can be golden-tested against
37
+ * `bindings/test_fixture/wire_golden.json` without a native module.
38
+ */
39
+ export declare function buildRestoreParams(recoveredSecret: Extract<DeRecEvent, {
40
+ type: 'SecretRecovered';
41
+ }>['secret'], version: number): Record<string, unknown>;
42
+ /**
43
+ * Builder for {@link DeRecProtocol}, mirroring `@derec-alliance/nodejs`'s
44
+ * `DeRecProtocolBuilder` method-for-method. The config JSON shape is dictated
45
+ * by the Rust `ProtocolConfig` struct (`library/src/interop/ffi/protocol/handle/mod.rs`);
46
+ * every field here writes exactly the `snake_case` key that struct expects.
47
+ *
48
+ * Every value the caller supplies is forwarded verbatim — defaults, clamping
49
+ * and the meaning of a disabled cleanup policy are library decisions.
50
+ * `threshold`, `keep_versions_count`, `auto_respond_on_failure`,
51
+ * `unpair_ack`, `auto_reply_to` and `auto_accept` are omitted entirely from
52
+ * the emitted config unless their setter was called: `ProtocolConfig` has a
53
+ * `#[serde(default = "...")]` on each of them, reading the same constants
54
+ * `DeRecProtocolBuilder::new` uses, so an absent key resolves to the
55
+ * library's own default rather than one frozen into this shim.
56
+ */
57
+ export declare class DeRecProtocolBuilder {
58
+ private readonly secretIdValue;
59
+ private config;
60
+ private stores;
61
+ private communicationInfo;
62
+ constructor(secretId: bigint | number);
63
+ withChannelStore(store: ChannelStore): this;
64
+ withShareStore(store: ShareStore): this;
65
+ withSecretStore(store: SecretStore): this;
66
+ withUserSecretStore(store: UserSecretStore): this;
67
+ withStateStore(store: StateStore): this;
68
+ withTransport(transport: Transport): this;
69
+ withOwnTransport(endpoint: {
70
+ uri: string;
71
+ protocol: string;
72
+ }): this;
73
+ /** Default: 3. */
74
+ withThreshold(threshold: number): this;
75
+ /** Default: 3. */
76
+ withKeepVersionsCount(count: number): this;
77
+ /**
78
+ * Every field is optional; not calling this at all leaves all four at the
79
+ * library's defaults — `timeouts` is genuinely absent from the JSON in
80
+ * that case, not filled in with a synthesized object. Values are forwarded
81
+ * verbatim; `Timeouts`'s field names already match `TimeoutsConfig`'s
82
+ * `snake_case` keys one for one.
83
+ */
84
+ withTimeouts(timeouts: Timeouts): this;
85
+ /** Default: false. */
86
+ withUnsafeHttp(allow: boolean): this;
87
+ /**
88
+ * Default: empty. `derec_protocol_new`'s own `communication_info` argument
89
+ * is a pre-encoded `CommunicationInfo` protobuf message, and this SDK has
90
+ * no encoder for that message — the C ABI exposes one only for
91
+ * `ContactMessage`. Hand-rolling one here would be SDK-side protocol logic
92
+ * with no test coverage — exactly what this codebase's "Rust decides, the
93
+ * SDK only marshals" rule forbids. Instead,
94
+ * `build()` constructs the protocol with an empty `communication_info`
95
+ * (a legitimate, always-accepted value — see `decode_communication_info`
96
+ * in `library/src/interop/ffi/protocol/handle/mod.rs`, which treats a zero-length
97
+ * buffer as "no entries") and then calls the already-bound
98
+ * {@link DeRecProtocol.setCommunicationInfo}, which takes the same map as
99
+ * plain JSON (`derec_protocol_set_communication_info` in
100
+ * `library/src/interop/ffi/protocol/handle/config.rs`). That setter is queued on
101
+ * the protocol's serial worker before `build()` returns, so it is ordered
102
+ * ahead of every call the caller can subsequently make.
103
+ */
104
+ withCommunicationInfo(info: Record<string, string>): this;
105
+ /** Default: false. */
106
+ withAutoRespondOnFailure(enabled: boolean): this;
107
+ /** Default: "required". */
108
+ withUnpairAck(ack: UnpairAck): this;
109
+ /** Default: false. */
110
+ withAutoReplyTo(enabled: boolean): this;
111
+ /** Default: empty policy (every flow off). */
112
+ withAutoAccept(policy: AutoAcceptPolicy): this;
113
+ /** Default: unset. */
114
+ withReplicaId(replicaId: bigint | number): this;
115
+ build(): DeRecProtocol;
116
+ }
117
+ /**
118
+ * Thin wrapper around the `ProtocolHost` JSI host object, mirroring
119
+ * `@derec-alliance/nodejs`'s `DeRecProtocol` — same methods, and the same
120
+ * sync/async split except for `setCommunicationInfo` and `setOwnTransport`,
121
+ * which return a `Promise` here (see their own doc comments for why);
122
+ * `secretId` is synchronous and everything else returns a `Promise`. Every method encodes its
123
+ * arguments into the wire shape the host function expects and decodes its
124
+ * result back into the typed value declared here; no protocol decision is
125
+ * made in this class.
126
+ */
127
+ export declare class DeRecProtocol {
128
+ private readonly host;
129
+ /** Use {@link DeRecProtocolBuilder} to construct instances. */
130
+ private constructor();
131
+ /**
132
+ * @internal Constructs an instance from a native `ProtocolHost`. Not part
133
+ * of the public surface — {@link DeRecProtocolBuilder.build} is the only
134
+ * caller. Exists because the constructor is `private` (matching
135
+ * `@derec-alliance/nodejs`'s `index.d.ts`), and a private constructor is
136
+ * only callable from within this class's own body, not from
137
+ * `DeRecProtocolBuilder`.
138
+ */
139
+ static fromHost(host: NativeHost): DeRecProtocol;
140
+ secretId(): bigint;
141
+ /**
142
+ * Returns a `Promise`, where `@derec-alliance/nodejs` declares this
143
+ * `void`. The native setter takes the same handle mutex a running flow
144
+ * holds across its store callbacks, so calling it on the JavaScript thread
145
+ * would block that thread until the flow released the mutex — which it
146
+ * cannot do while it is waiting on the JavaScript thread. The binding
147
+ * therefore queues the setter onto the same serial worker every flow runs
148
+ * on, which orders it after any call already in flight. The nodejs SDK is
149
+ * WASM and single-threaded, so it has no such hazard.
150
+ *
151
+ * Callers that ignore the result behave exactly as before, so this stays
152
+ * source-compatible with nodejs-shaped code; awaiting it additionally
153
+ * surfaces a failure that would otherwise be swallowed.
154
+ */
155
+ setCommunicationInfo(info: Record<string, string>): Promise<void>;
156
+ /** Returns a `Promise` for the same reason {@link setCommunicationInfo} does. */
157
+ setOwnTransport(uri: string, protocol: string): Promise<void>;
158
+ /**
159
+ * Decodes the `contact_wire_bytes` `derec_protocol_create_contact`
160
+ * produces into a typed `ContactMessage`, so an application can read the
161
+ * contact's `nonce`, `transport_protocol` and mode without a protobuf
162
+ * codec of its own. Feed the returned object straight back into
163
+ * `start(FlowKind.Pairing, { contact })`, which re-encodes it.
164
+ */
165
+ createContact(channelId: bigint | number | null | undefined, contactMode: ContactMode, nonce?: bigint | number | null): Promise<ContactMessage>;
166
+ start(flowKind: FlowKind.Pairing, params: PairingParams): Promise<DeRecEvent[]>;
167
+ start(flowKind: FlowKind.Discovery, params?: DiscoveryParams): Promise<DeRecEvent[]>;
168
+ start(flowKind: FlowKind.ProtectSecret, params: ProtectSecretParams): Promise<DeRecEvent[]>;
169
+ start(flowKind: FlowKind.VerifyShares, params: VerifySharesParams): Promise<DeRecEvent[]>;
170
+ start(flowKind: FlowKind.RecoverSecret, params: RecoverSecretParams): Promise<DeRecEvent[]>;
171
+ start(flowKind: FlowKind.Unpair, params: UnpairParams): Promise<DeRecEvent[]>;
172
+ start(flowKind: FlowKind.UpdateChannelInfo, params: UpdateChannelInfoParams): Promise<DeRecEvent[]>;
173
+ start(flowKind: FlowKind.SyncCheck, params?: SyncCheckParams): Promise<DeRecEvent[]>;
174
+ start(flowKind: FlowKind.RemoveReplica, params: RemoveReplicaParams): Promise<DeRecEvent[]>;
175
+ process(message: Uint8Array): Promise<DeRecEvent[]>;
176
+ tick(): Promise<DeRecEvent[]>;
177
+ accept(actionBytes: Uint8Array): Promise<DeRecEvent[]>;
178
+ reject(actionBytes: Uint8Array, status: number, memo: string): Promise<void>;
179
+ getFingerprint(channelId: bigint | number): Promise<string>;
180
+ verifyFingerprint(channelId: bigint | number, fingerprint: string): Promise<boolean>;
181
+ removeExpiredChannels(olderThanSecs: number): Promise<string[]>;
182
+ restore(recoveredSecret: Extract<DeRecEvent, {
183
+ type: 'SecretRecovered';
184
+ }>['secret'], version: number): Promise<DeRecEvent[]>;
185
+ /** Release the native handle. Safe to call more than once. */
186
+ free(): void;
187
+ }
188
+ export {};