@decentnetwork/lan 0.1.42 → 0.1.43

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.
@@ -4,7 +4,7 @@
4
4
  import { resolve, dirname } from "path";
5
5
  import { existsSync, mkdirSync, readFileSync } from "fs";
6
6
  import { createConnection } from "net";
7
- import { ConfigLoader, DEFAULT_DORA_USERID, DEFAULT_DORA_ADDRESS } from "../config/loader.js";
7
+ import { ConfigLoader, DEFAULT_DORAS } from "../config/loader.js";
8
8
  import { ipcSocketPath } from "../daemon/ipc.js";
9
9
  import { DaemonServer } from "../daemon/server.js";
10
10
  import { Ipam } from "../ipam/ipam.js";
@@ -129,18 +129,21 @@ export async function cmdInit(args) {
129
129
  console.log(` Config dir: ${dir}`);
130
130
  console.log(` Subnet: ${config.network.subnet}`);
131
131
  console.log(` Interface: ${config.network.interface}`);
132
- // Send the one-time friend-request to the default dora so the daemon
132
+ // Send the one-time friend-request to each default dora so the daemon
133
133
  // can register on first start. Best-effort: a friend-request requires
134
134
  // joinNetwork + an announce round, ~10-30s; we cap the wait and
135
- // surface a hint if it doesn't go through. Skipped when the user
136
- // overrode dora.userids away from the default (i.e. they're pointing
137
- // at a private dora — they'll run `agentnet dora enable` themselves).
138
- const defaultDoraConfigured = (config.dora?.userids ?? []).includes(DEFAULT_DORA_USERID);
139
- if (defaultDoraConfigured) {
140
- console.log(`\nFriending the public dora (${DEFAULT_DORA_USERID.slice(0, 16)}...) so the daemon can join the shared network on first start.`);
135
+ // surface a hint if it doesn't go through. Skipped for any dora the
136
+ // user removed from dora.userids (i.e. they're pointing at a private
137
+ // set — they'll run `agentnet dora enable` themselves). The defaults
138
+ // are federated with non-overlapping IP segments, so friending all of
139
+ // them gives redundancy: any one staying up is enough to get an IP.
140
+ const configuredUserids = new Set(config.dora?.userids ?? []);
141
+ const dorasToFriend = DEFAULT_DORAS.filter((d) => configuredUserids.has(d.userid));
142
+ for (const dora of dorasToFriend) {
143
+ console.log(`\nFriending ${dora.name} (${dora.userid.slice(0, 16)}...) so the daemon can join the shared network on first start.`);
141
144
  try {
142
145
  await cmdFriendRequest({
143
- address: DEFAULT_DORA_ADDRESS,
146
+ address: dora.address,
144
147
  hello: `decentlan init (${nodeName})`,
145
148
  waitMs: 8000,
146
149
  configDir: dir,
@@ -149,8 +152,8 @@ export async function cmdInit(args) {
149
152
  }
150
153
  catch (err) {
151
154
  const msg = err instanceof Error ? err.message : String(err);
152
- console.warn(` Friend-request to the default dora failed: ${msg}`);
153
- console.warn(` Re-run later: agentnet dora enable --address ${DEFAULT_DORA_ADDRESS}`);
155
+ console.warn(` Friend-request to ${dora.name} failed: ${msg}`);
156
+ console.warn(` Re-run later: agentnet dora enable --address ${dora.address}`);
154
157
  }
155
158
  }
156
159
  console.log(`\nNext: sudo agentnet service install # or 'agentnet up --real-tun' to run in foreground`);
@@ -1,17 +1,26 @@
1
1
  import type { DecentAgentNetConfig } from "../types.js";
2
2
  /**
3
- * Public dora server baked into `agentnet init` so an operator can join
3
+ * Public dora servers baked into `agentnet init` so an operator can join
4
4
  * the canonical Decent AgentNet without first hunting down a registry
5
5
  * address. Override by editing `dora.userids` (and re-running
6
6
  * `agentnet dora enable --address <yours>`) — or by running a private
7
7
  * dora and pointing your own peers at it.
8
8
  *
9
- * Both fields are required: the daemon needs `userid` to talk to the
10
- * server over Carrier, and `address` so `agentnet init` can send the
11
- * one-time friend-request that establishes the Carrier session.
9
+ * These are FEDERATED with NON-OVERLAPPING IP segments, so the client
10
+ * merges all their rosters and any one staying up is enough to get an
11
+ * IP allocation redundancy against any single registry being down.
12
+ *
13
+ * Both fields are required per entry: the daemon needs `userid` to talk
14
+ * to the server over Carrier, and `address` so `agentnet init` can send
15
+ * the one-time friend-request that establishes the Carrier session.
12
16
  */
13
- export declare const DEFAULT_DORA_USERID = "98rsHv17h8G6AP9RagyrBiT1kmw4cn8MFPEembS6ZVjv";
14
- export declare const DEFAULT_DORA_ADDRESS = "Jt7w1pKkyLT5GVue9h6ZPkjg1EeuuTbD6JVSLycXLsdm6nvBGSUd";
17
+ export declare const DEFAULT_DORAS: {
18
+ name: string;
19
+ userid: string;
20
+ address: string;
21
+ }[];
22
+ export declare const DEFAULT_DORA_USERID: string;
23
+ export declare const DEFAULT_DORA_ADDRESS: string;
15
24
  export declare class ConfigLoader {
16
25
  static defaultConfigPath(): string;
17
26
  static defaultConfigDir(): string;
@@ -40,18 +40,29 @@ const DEFAULT_EXPRESS_NODES = [
40
40
  { host: "lens.beagle.chat", port: 443, pk: "ECbs4GxwGzxGerNkmqDJFibEmevu8jAXqAZtikccvD95" },
41
41
  ];
42
42
  /**
43
- * Public dora server baked into `agentnet init` so an operator can join
43
+ * Public dora servers baked into `agentnet init` so an operator can join
44
44
  * the canonical Decent AgentNet without first hunting down a registry
45
45
  * address. Override by editing `dora.userids` (and re-running
46
46
  * `agentnet dora enable --address <yours>`) — or by running a private
47
47
  * dora and pointing your own peers at it.
48
48
  *
49
- * Both fields are required: the daemon needs `userid` to talk to the
50
- * server over Carrier, and `address` so `agentnet init` can send the
51
- * one-time friend-request that establishes the Carrier session.
49
+ * These are FEDERATED with NON-OVERLAPPING IP segments, so the client
50
+ * merges all their rosters and any one staying up is enough to get an
51
+ * IP allocation redundancy against any single registry being down.
52
+ *
53
+ * Both fields are required per entry: the daemon needs `userid` to talk
54
+ * to the server over Carrier, and `address` so `agentnet init` can send
55
+ * the one-time friend-request that establishes the Carrier session.
52
56
  */
53
- export const DEFAULT_DORA_USERID = "98rsHv17h8G6AP9RagyrBiT1kmw4cn8MFPEembS6ZVjv";
54
- export const DEFAULT_DORA_ADDRESS = "Jt7w1pKkyLT5GVue9h6ZPkjg1EeuuTbD6JVSLycXLsdm6nvBGSUd";
57
+ export const DEFAULT_DORAS = [
58
+ { name: "dora-mac", userid: "98rsHv17h8G6AP9RagyrBiT1kmw4cn8MFPEembS6ZVjv", address: "Jt7w1pKkyLT5GVue9h6ZPkjg1EeuuTbD6JVSLycXLsdm6nvBGSUd" }, // 10.86.1.10–63.254
59
+ { name: "dora-beagle", userid: "AxKFEZFLDi23EmnJFNP6gjUM4CaNMPfWUvbFR9ixtMBN", address: "NsuN81dZdEoyvwEFgWaHkT8SPJB6UWeRmdYcCGFV5CdbbPXoK2RM" }, // 10.86.64.10–127.254
60
+ { name: "dora-sh", userid: "GMEMLmCWLMBK6BJiMkbLPNkEjF4S2xRf1SqR9hM8fWV3", address: "ajg1ZMBw86UyujmEJzqKSCbi3wwEtg6tdGFTdESakyqujyxmqJZK" }, // 10.86.128.10–191.254
61
+ { name: "dora-tokyo", userid: "AB6BZfbrTFWw9eUoVpHdJqhhRnY8bTttp4CHTZ2Xfzxi", address: "MAW2eBqBuQ6SmaXTrnZRRayQjAj3aLatwPy4xmBp7spnJeV569op" }, // 10.86.192.10–254.254
62
+ ];
63
+ // Back-compat single-value exports (first/primary dora).
64
+ export const DEFAULT_DORA_USERID = DEFAULT_DORAS[0].userid;
65
+ export const DEFAULT_DORA_ADDRESS = DEFAULT_DORAS[0].address;
55
66
  export class ConfigLoader {
56
67
  static defaultConfigPath() {
57
68
  return DEFAULT_CONFIG_FILE;
@@ -139,7 +150,7 @@ export class ConfigLoader {
139
150
  // replaces the default).
140
151
  dora: {
141
152
  enabled: true,
142
- userids: [DEFAULT_DORA_USERID],
153
+ userids: DEFAULT_DORAS.map((d) => d.userid),
143
154
  refreshIntervalMs: 60_000,
144
155
  // Default: auto-friend every peer in the dora roster. Dora
145
156
  // membership IS the trust statement — joining a dora means
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decentnetwork/lan",
3
- "version": "0.1.42",
3
+ "version": "0.1.43",
4
4
  "description": "Private virtual LAN for self-hosted services and AI agents, built on Elastos Carrier. NAT-traversal, name service, ACL, all over a peer-to-peer mesh — no public IP required.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",