@reticulum/dacar 1.2.1 → 1.3.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reticulum/dacar",
3
- "version": "1.2.1",
3
+ "version": "1.3.0",
4
4
  "description": "JavaScript implementation of Dacar, a Decentralized Access Control system for Reticulum",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -44,8 +44,8 @@
44
44
  "node": ">=20"
45
45
  },
46
46
  "dependencies": {
47
- "@reticulum/core": "^0.6.5",
48
- "@reticulum/node": "^0.6.5",
47
+ "@reticulum/core": "^0.7.0",
48
+ "@reticulum/node": "^0.7.0",
49
49
  "@types/node": "^26.2.0"
50
50
  },
51
51
  "publishConfig": {
@@ -46,6 +46,7 @@
46
46
  * ```
47
47
  */
48
48
 
49
+ import { Destination, MsgPack } from "@reticulum/core";
49
50
  import {
50
51
  deriveChannel,
51
52
  unwrapRawChannelMessage,
@@ -80,7 +81,7 @@ import { RFED_TOPIC } from "../naming.js";
80
81
  * @typedef {Object} RfedDecodedRaw
81
82
  * @property {"raw"|"lxmf"} kind
82
83
  * @property {Uint8Array} [payload] Raw application payload (`kind === "raw"`).
83
- * @property {import("@reticulum/core/src/core/identity.js").Identity} [senderIdentity]
84
+ * @property {import("@reticulum/core").Identity} [senderIdentity]
84
85
  * @property {Uint8Array} [senderPub]
85
86
  * @property {Uint8Array} [channelHash]
86
87
  * @property {string} [channelName]
@@ -182,8 +183,29 @@ export class RfedDeltaSync {
182
183
  throw new Error("RfedDeltaSync.listen requires a receiver");
183
184
  }
184
185
  const receiver = this._receiver;
185
- return this._client.listen((decoded) => {
186
+ return this._client.listen(async (decoded) => {
186
187
  if (decoded?.kind !== "raw") return; // not a raw channel payload
188
+
189
+ // Remember the sender identity so future RNS recalls succeed without
190
+ // needing an announce. Best-effort: decode must still succeed without it.
191
+ try {
192
+ // Extract issuer_hash (field [0]) from the delta to map identity.
193
+ const decodedDelta = MsgPack.decode(decoded.payload);
194
+ if (Array.isArray(decodedDelta) && decodedDelta.length > 0) {
195
+ const issuerHash = decodedDelta[0];
196
+ if (issuerHash instanceof Uint8Array && issuerHash.length === 16) {
197
+ await Destination.remember(
198
+ decoded.senderIdentity.identityHash,
199
+ decoded.senderIdentity.identityHash,
200
+ decoded.senderPub,
201
+ null,
202
+ );
203
+ }
204
+ }
205
+ } catch {
206
+ // Remembering is best-effort; failure doesn't affect correctness.
207
+ }
208
+
187
209
  // RFedClient.invoke does not await the callback; run applyPayload without
188
210
  // leaving an unhandled rejection (it swallows malformed payloads itself).
189
211
  Promise.resolve(receiver.applyPayload(decoded.payload)).catch(() => {});
@@ -224,6 +246,27 @@ export class RfedDeltaSync {
224
246
  innerBlob: item.blob,
225
247
  channelIdentity,
226
248
  });
249
+
250
+ // Remember the sender identity so future RNS recalls succeed without
251
+ // needing an announce. Best-effort: decode must still succeed without it.
252
+ try {
253
+ // Extract issuer_hash (field [0]) from the delta to map identity.
254
+ const decodedDelta = MsgPack.decode(decoded.payload);
255
+ if (Array.isArray(decodedDelta) && decodedDelta.length > 0) {
256
+ const issuerHash = decodedDelta[0];
257
+ if (issuerHash instanceof Uint8Array && issuerHash.length === 16) {
258
+ await Destination.remember(
259
+ decoded.senderIdentity.identityHash,
260
+ decoded.senderIdentity.identityHash,
261
+ decoded.senderPub,
262
+ null,
263
+ );
264
+ }
265
+ }
266
+ } catch {
267
+ // Remembering is best-effort; failure doesn't affect correctness.
268
+ }
269
+
227
270
  if (await receiver.applyPayload(decoded.payload)) {
228
271
  applied++;
229
272
  }