@reticulum/dacar 1.3.0 → 1.4.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/README.md +7 -6
- package/package.json +5 -3
- package/src/cli/dacar.js +1 -1
- package/src/index.js +1 -1
- package/src/transport/index.js +5 -4
- package/src/transport/lxmfSync.js +10 -10
- package/src/transport/rfedSync.js +7 -7
- package/src/transport/rnsIdentity.js +2 -3
package/README.md
CHANGED
|
@@ -19,9 +19,9 @@ This is a modern ES-module package with JSDoc type annotations that runs on
|
|
|
19
19
|
| HMAC-SHA256 / SHA-256 (§3.3, §6.1) | Web Crypto `crypto.subtle` | Standard, runtime-portable |
|
|
20
20
|
| MessagePack (§5.3) | `@reticulum/core` `MsgPack` | Reuses the canonical stack's encoder |
|
|
21
21
|
|
|
22
|
-
`@reticulum/core` is the
|
|
23
|
-
transport adapters
|
|
24
|
-
`
|
|
22
|
+
`@reticulum/core` is the base dependency of the pure core; the optional
|
|
23
|
+
transport adapters additionally use `@reticulum/lxmf` (the `LXMRouter`),
|
|
24
|
+
`@reticulum/rfed` (the `RFedClient`), and core's `Destination`/`Link`.
|
|
25
25
|
|
|
26
26
|
> **Note on MessagePack + 64-bit HLCs:** a packed HLC (`physical_ms << 16`)
|
|
27
27
|
> exceeds `Number.MAX_SAFE_INTEGER`, so it is represented as a `bigint`. The HLC
|
|
@@ -112,8 +112,9 @@ console.log(await engine.evaluate("sensor:wind", "read", ROOT)); // true
|
|
|
112
112
|
|
|
113
113
|
The pure core has no transport: it is wired to the Reticulum transports by the
|
|
114
114
|
optional `@reticulum/dacar/transport` subpath. Importing the core
|
|
115
|
-
(`@reticulum/dacar`) never pulls it in
|
|
116
|
-
`@reticulum/core
|
|
115
|
+
(`@reticulum/dacar`) never pulls it in. The transport adapters build on
|
|
116
|
+
`@reticulum/core`, `@reticulum/lxmf`, and `@reticulum/rfed` (since reticulum-js
|
|
117
|
+
0.8.2, LXMF and rfed are packages of their own rather than core subpaths).
|
|
117
118
|
|
|
118
119
|
Every transport funnels received bytes through the same verify-on-ingest seam
|
|
119
120
|
(`DeltaReceiver.applyPayload()`, §11.2.4): a Delta is decoded, authenticated by
|
|
@@ -159,7 +160,7 @@ import {
|
|
|
159
160
|
### RFed convergence
|
|
160
161
|
|
|
161
162
|
```js
|
|
162
|
-
import { RFedClient } from "@reticulum/
|
|
163
|
+
import { RFedClient } from "@reticulum/rfed";
|
|
163
164
|
import { DeltaReceiver, StateVector } from "@reticulum/dacar";
|
|
164
165
|
import { RfedDeltaSync } from "@reticulum/dacar/transport";
|
|
165
166
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reticulum/dacar",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.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,10 @@
|
|
|
44
44
|
"node": ">=20"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@reticulum/core": "^0.
|
|
48
|
-
"@reticulum/
|
|
47
|
+
"@reticulum/core": "^0.8.2",
|
|
48
|
+
"@reticulum/lxmf": "^0.8.2",
|
|
49
|
+
"@reticulum/node": "^0.8.2",
|
|
50
|
+
"@reticulum/rfed": "^0.8.2",
|
|
49
51
|
"@types/node": "^26.2.0"
|
|
50
52
|
},
|
|
51
53
|
"publishConfig": {
|
package/src/cli/dacar.js
CHANGED
|
@@ -35,7 +35,7 @@ import process from "node:process";
|
|
|
35
35
|
import { Identity, toHex } from "@reticulum/core";
|
|
36
36
|
import { MemoryStorageAdapter } from "@reticulum/core";
|
|
37
37
|
import { DacarFileAdapter } from "./fileStore.js";
|
|
38
|
-
import { RFedClient } from "@reticulum/
|
|
38
|
+
import { RFedClient } from "@reticulum/rfed";
|
|
39
39
|
import { bootRns } from "./rns_boot.js";
|
|
40
40
|
|
|
41
41
|
import { Action, Operation, Tuple, Engine } from "../index.js";
|
package/src/index.js
CHANGED
package/src/transport/index.js
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* These wire the pure, transport-agnostic core — the §8 `Challenge`/
|
|
5
5
|
* `AuthoritativeServer`/`ChallengeClient` and the §11 `DeltaReceiver` — to the
|
|
6
|
-
* concrete Reticulum transports from `@reticulum/core
|
|
6
|
+
* concrete Reticulum transports from `@reticulum/core`, `@reticulum/lxmf`, and
|
|
7
|
+
* `@reticulum/rfed` (since reticulum-js 0.8.2, LXMF and rfed are packages of
|
|
8
|
+
* their own rather than core subpaths):
|
|
7
9
|
*
|
|
8
10
|
* - {@link RnsIdentityResolver} §3.1, §11.2.4 recall → verify key
|
|
9
11
|
* - {@link RnsChallengeServer} &c. §8 Challenge over an RNS Link
|
|
@@ -11,9 +13,8 @@
|
|
|
11
13
|
* - {@link RfedDeltaSync} §11.1 RFed many-to-many convergence
|
|
12
14
|
*
|
|
13
15
|
* Importing the pure core (`@reticulum/dacar`) does **not** import this
|
|
14
|
-
* subpath: it is opt-in via `@reticulum/dacar/transport`.
|
|
15
|
-
*
|
|
16
|
-
* transport layer adds no new dependency.
|
|
16
|
+
* subpath: it is opt-in via `@reticulum/dacar/transport`. The adapters build
|
|
17
|
+
* on the `@reticulum/*` reticulum-js packages (core, lxmf, rfed).
|
|
17
18
|
*/
|
|
18
19
|
|
|
19
20
|
export { RnsIdentityResolver } from "./rnsIdentity.js";
|
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
* through the router.
|
|
16
16
|
*
|
|
17
17
|
* This module is part of the optional transport layer: importing the pure core
|
|
18
|
-
* never pulls it in. It depends
|
|
19
|
-
*
|
|
18
|
+
* never pulls it in. It depends on `@reticulum/lxmf` (which itself builds on
|
|
19
|
+
* `@reticulum/core`).
|
|
20
20
|
*
|
|
21
|
-
* Typical use (receiver, wired to a {@link import("@reticulum/
|
|
21
|
+
* Typical use (receiver, wired to a {@link import("@reticulum/lxmf").LXMRouter
|
|
22
22
|
* LXMRouter}):
|
|
23
23
|
*
|
|
24
24
|
* ```js
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
* await delivery.handleMessage(event.detail.message);
|
|
39
39
|
*/
|
|
40
40
|
|
|
41
|
-
import { LXMessage as LXMFMessage } from "@reticulum/
|
|
41
|
+
import { LXMessage as LXMFMessage } from "@reticulum/lxmf";
|
|
42
42
|
import { LXMF_DELIVERY_TITLE } from "../naming.js";
|
|
43
43
|
|
|
44
44
|
/**
|
|
@@ -60,7 +60,7 @@ export function messageTitle(message) {
|
|
|
60
60
|
/**
|
|
61
61
|
* Best-effort content of an LXMF message as raw bytes (the §5.3 Delta payload).
|
|
62
62
|
*
|
|
63
|
-
* `@reticulum/
|
|
63
|
+
* `@reticulum/lxmf`'s `Message.deserialize()` UTF-8-decodes the content element
|
|
64
64
|
* into `message.content`, which corrupts arbitrary binary Deltas. The raw bytes
|
|
65
65
|
* are preserved on `_decodedPayload[2]` (the same field the library uses
|
|
66
66
|
* internally for §5.6 signature re-verification), so this helper recovers the
|
|
@@ -99,13 +99,13 @@ export class LxmfDeltaDelivery {
|
|
|
99
99
|
* @param {import("../delta.js").DeltaReceiver | null} [opts.receiver]
|
|
100
100
|
* The shared DeltaReceiver (state + key resolver). May be omitted on a
|
|
101
101
|
* send-only node (then `handleMessage` throws if called).
|
|
102
|
-
* @param {import("@reticulum/
|
|
102
|
+
* @param {import("@reticulum/lxmf").LXMRouter | null} [opts.router]
|
|
103
103
|
* Optional bound `LXMRouter` for `deliver` / `ingestPaperUri`.
|
|
104
104
|
*/
|
|
105
105
|
constructor({ receiver = null, router = null } = {}) {
|
|
106
106
|
/** @type {import("../delta.js").DeltaReceiver | null} */
|
|
107
107
|
this._receiver = receiver;
|
|
108
|
-
/** @type {import("@reticulum/
|
|
108
|
+
/** @type {import("@reticulum/lxmf").LXMRouter | null} */
|
|
109
109
|
this._router = router;
|
|
110
110
|
}
|
|
111
111
|
|
|
@@ -121,7 +121,7 @@ export class LxmfDeltaDelivery {
|
|
|
121
121
|
* @param {Uint8Array} deltaPayload
|
|
122
122
|
* @param {Uint8Array} destinationHash The recipient `lxmf.delivery` hash.
|
|
123
123
|
* @param {Uint8Array} sourceHash The sender's `lxmf.delivery` hash.
|
|
124
|
-
* @returns {import("@reticulum/
|
|
124
|
+
* @returns {import("@reticulum/lxmf").LXMessage}
|
|
125
125
|
*/
|
|
126
126
|
makeMessage(deltaPayload, destinationHash, sourceHash) {
|
|
127
127
|
if (!(deltaPayload instanceof Uint8Array)) {
|
|
@@ -145,7 +145,7 @@ export class LxmfDeltaDelivery {
|
|
|
145
145
|
* @param {Uint8Array} destinationHash The recipient `lxmf.delivery` hash.
|
|
146
146
|
* @param {Object} [opts]
|
|
147
147
|
* @param {Uint8Array | null} [opts.linkId] Reuse an existing DIRECT link id.
|
|
148
|
-
* @returns {Promise<import("@reticulum/
|
|
148
|
+
* @returns {Promise<import("@reticulum/lxmf").LXMessage>}
|
|
149
149
|
*/
|
|
150
150
|
async deliver(deltaPayload, destinationHash, { linkId = null } = {}) {
|
|
151
151
|
if (!this._router) {
|
|
@@ -210,7 +210,7 @@ export class LxmfDeltaDelivery {
|
|
|
210
210
|
* ingest result (the reconstructed message, or `null` if it was not for this
|
|
211
211
|
* node / already ingested).
|
|
212
212
|
* @param {string} uri
|
|
213
|
-
* @returns {Promise<import("@reticulum/
|
|
213
|
+
* @returns {Promise<import("@reticulum/lxmf").LXMessage | null>}
|
|
214
214
|
*/
|
|
215
215
|
async ingestPaperUri(uri) {
|
|
216
216
|
if (!this._router) {
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* delivery — **never** through the unauthenticated `StateVector.merge()` path.
|
|
11
11
|
* A forged or stale Delta is simply dropped before it can mutate state.
|
|
12
12
|
*
|
|
13
|
-
* `RfedDeltaSync` wraps a `@reticulum/
|
|
13
|
+
* `RfedDeltaSync` wraps a `@reticulum/rfed` `RFedClient`. A Delta travels in
|
|
14
14
|
* Dacar's **compact inner format** (§11.1.1): the raw §5.3 payload is placed
|
|
15
15
|
* straight after the RTID source-identity prelude and EC-encrypted to the
|
|
16
16
|
* derived channel identity — no LXMF envelope, which would only duplicate the
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* discriminator (every message on it is a Dacar Delta), and the recovered Delta
|
|
20
20
|
* bytes are fed to `DeltaReceiver`.
|
|
21
21
|
*
|
|
22
|
-
* The compact format is built on `@reticulum/
|
|
22
|
+
* The compact format is built on `@reticulum/rfed`'s raw RFed primitives —
|
|
23
23
|
* `subscribeRaw` / `publishRaw` / `unwrapRawChannelMessage` — which carry an
|
|
24
24
|
* arbitrary self-authenticating payload in place of the LXMF tail. The Delta's
|
|
25
25
|
* own Ed25519 signature (§5.3 field [7]) is the authenticity check at
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
* channel uses the compact format.
|
|
32
32
|
*
|
|
33
33
|
* This module is part of the optional transport layer: importing the pure core
|
|
34
|
-
* never pulls it in. It depends
|
|
35
|
-
*
|
|
34
|
+
* never pulls it in. It depends on `@reticulum/rfed` (which itself builds on
|
|
35
|
+
* `@reticulum/core`). It mirrors
|
|
36
36
|
* `python/dacar/transport/rfed_sync.py` (the canonical implementation).
|
|
37
37
|
*
|
|
38
38
|
* Typical use:
|
|
@@ -50,12 +50,12 @@ import { Destination, MsgPack } from "@reticulum/core";
|
|
|
50
50
|
import {
|
|
51
51
|
deriveChannel,
|
|
52
52
|
unwrapRawChannelMessage,
|
|
53
|
-
} from "@reticulum/
|
|
53
|
+
} from "@reticulum/rfed";
|
|
54
54
|
import { RFED_TOPIC } from "../naming.js";
|
|
55
55
|
|
|
56
56
|
/**
|
|
57
57
|
* The minimal `RFedClient` surface this adapter relies on. The real client from
|
|
58
|
-
* `@reticulum/
|
|
58
|
+
* `@reticulum/rfed` satisfies it; tests inject a fake. The raw-publish API
|
|
59
59
|
* (`subscribeRaw` / `publishRaw`) carries a self-authenticating payload in the
|
|
60
60
|
* RTID prelude instead of an LXMF envelope (§11.1.1).
|
|
61
61
|
*
|
|
@@ -99,7 +99,7 @@ export class RfedDeltaSync {
|
|
|
99
99
|
* @param {import("../delta.js").DeltaReceiver | null} [opts.receiver]
|
|
100
100
|
* The shared DeltaReceiver (state + key resolver). May be omitted on a
|
|
101
101
|
* publish-only node (then `listen`/`pull` throw if called).
|
|
102
|
-
* @param {RFedClientLike} opts.client A `@reticulum/
|
|
102
|
+
* @param {RFedClientLike} opts.client A `@reticulum/rfed` `RFedClient`.
|
|
103
103
|
* @param {string} [opts.topic] RFed channel name (default `dacar.policy.v1`).
|
|
104
104
|
*/
|
|
105
105
|
constructor({ receiver = null, client, topic = RFED_TOPIC }) {
|
|
@@ -21,9 +21,8 @@
|
|
|
21
21
|
* identities always win.
|
|
22
22
|
*
|
|
23
23
|
* This module is part of the optional transport layer: importing the pure
|
|
24
|
-
* core (`@reticulum/dacar`) never pulls it in. It
|
|
25
|
-
*
|
|
26
|
-
* for `Identity` / `MsgPack`, so it adds no new dependency.
|
|
24
|
+
* core (`@reticulum/dacar`) never pulls it in. It uses only `@reticulum/core`'s
|
|
25
|
+
* `Destination.recall`.
|
|
27
26
|
*/
|
|
28
27
|
|
|
29
28
|
import { Destination } from "@reticulum/core";
|