aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/src
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-08-09 05:28:15 +0200
committerChristophe Besson <cbesson@gmail.com>2026-08-09 05:28:15 +0200
commit6d64da7816aec2cc58bb1a6f0aceb9c9a921129f (patch)
treea7ee2b14b3c03c22b3c8a670aa7eb56753aeb574 /packages/meshbay-node/src
parentcb6e33a2c82a2f61712c3418c156b1ef3e12aaf4 (diff)
downloadmeshbay-6d64da7816aec2cc58bb1a6f0aceb9c9a921129f.tar.gz
feat(node): multi-group config support — 6.2
Config now supports [[groups]] array (N groups) alongside back-compat [group] single section. Each group has independent port/quic_port/http_port and visibility. GroupConfig gains quic_port, http_port, visibility fields. NodeConfig gains quic_port and http_port defaults. 70/70 tests. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-node/src')
-rw-r--r--packages/meshbay-node/src/meshbay_node/config.py89
1 files changed, 65 insertions, 24 deletions
diff --git a/packages/meshbay-node/src/meshbay_node/config.py b/packages/meshbay-node/src/meshbay_node/config.py
index 27301af..b420013 100644
--- a/packages/meshbay-node/src/meshbay_node/config.py
+++ b/packages/meshbay-node/src/meshbay_node/config.py
@@ -18,22 +18,36 @@ except ImportError:
DEFAULT_CONFIG_PATH = Path.home() / ".config" / "meshbay" / "node.toml"
EXAMPLE_CONFIG = """\
-# MeshBay Node configuration
+# MeshBay Node configuration — multi-group example
# See: https://meshbay.org/docs/node-config
[hub]
-url = "http://meshbay.org"
+url = "https://meshbay.org"
username = "myusername"
-# password stored separately via keystore
[node]
+port = 19000 # TCP+TLS (MNP v1)
+quic_port = 19010 # QUIC (MNP v2)
+http_port = 19001 # HTTP file API (public content)
+ui_port = 18000 # local web UI
+
+# Multiple groups — each with its own directory and ports
+[[groups]]
+id = "" # set after joining
+name = "My Media"
+shared_dir = "/home/user/Media"
port = 19000
-ui_port = 18000
-shared_dirs = ["/home/user/MeshBay"]
+quic_port = 19010
+http_port = 19001
-[group]
-id = "" # set after joining a group
-name = ""
+[[groups]]
+id = ""
+name = "Public Archive"
+shared_dir = "/home/user/Archive"
+port = 19002
+quic_port = 19012
+http_port = 19003
+visibility = "public"
[keystore]
# unlock_file = "~/.config/meshbay/unlock.key"
@@ -43,21 +57,26 @@ name = ""
@dataclass
class HubConfig:
- url: str = "http://meshbay.org"
+ url: str = "https://meshbay.org"
username: str = ""
password: str = "" # loaded from keystore or env; never written to TOML
@dataclass
class NodeConfig:
- port: int = 19000
- ui_port: int = 18000
- shared_dirs: list[str] = field(default_factory=list)
+ port: int = 19000
+ quic_port: int = 19010
+ http_port: int = 19001
+ ui_port: int = 18000
@dataclass
class GroupConfig:
- id: str = ""
+ id: str = ""
+ visibility: str = "private" # public|private
+ port: int = 19000 # TCP+TLS MNP port for this group
+ quic_port: int = 19010 # QUIC MNP port
+ http_port: int = 19001 # HTTP file API port
name: str = ""
@@ -71,31 +90,53 @@ class KeystoreConfig:
class Config:
hub: HubConfig = field(default_factory=HubConfig)
node: NodeConfig = field(default_factory=NodeConfig)
- group: GroupConfig = field(default_factory=GroupConfig)
+ groups: list[GroupConfig] = field(default_factory=list)
keystore: KeystoreConfig = field(default_factory=KeystoreConfig)
+ # Back-compat: single-group access
+ @property
+ def group(self) -> GroupConfig:
+ return self.groups[0] if self.groups else GroupConfig()
+
def load_config(path: Path = DEFAULT_CONFIG_PATH) -> Config:
"""
- Load config from TOML file. Missing file returns defaults.
- Env vars override file values.
+ Load config from TOML file. Supports both single [group] and
+ multiple [[groups]] sections. Env vars override file values.
"""
cfg = Config()
if path.exists():
raw = tomllib.loads(path.read_text())
+
hub = raw.get("hub", {})
cfg.hub.url = hub.get("url", cfg.hub.url)
cfg.hub.username = hub.get("username", cfg.hub.username)
nd = raw.get("node", {})
- cfg.node.port = nd.get("port", cfg.node.port)
- cfg.node.ui_port = nd.get("ui_port", cfg.node.ui_port)
- cfg.node.shared_dirs = nd.get("shared_dirs", cfg.node.shared_dirs)
+ cfg.node.port = nd.get("port", cfg.node.port)
+ cfg.node.quic_port = nd.get("quic_port", cfg.node.quic_port)
+ cfg.node.http_port = nd.get("http_port", cfg.node.http_port)
+ cfg.node.ui_port = nd.get("ui_port", cfg.node.ui_port)
- grp = raw.get("group", {})
- cfg.group.id = grp.get("id", cfg.group.id)
- cfg.group.name = grp.get("name", cfg.group.name)
+ # Multi-group: [[groups]] array
+ if "groups" in raw:
+ for g in raw["groups"]:
+ cfg.groups.append(GroupConfig(
+ id=g.get("id", ""),
+ name=g.get("name", ""),
+ visibility=g.get("visibility", "private"),
+ port=g.get("port", cfg.node.port),
+ quic_port=g.get("quic_port", cfg.node.quic_port),
+ http_port=g.get("http_port", cfg.node.http_port),
+ ))
+ # Back-compat: single [group] section
+ elif "group" in raw:
+ grp = raw["group"]
+ cfg.groups.append(GroupConfig(
+ id=grp.get("id", ""),
+ name=grp.get("name", ""),
+ ))
ks = raw.get("keystore", {})
if "path" in ks:
@@ -104,11 +145,11 @@ def load_config(path: Path = DEFAULT_CONFIG_PATH) -> Config:
cfg.keystore.unlock_file = Path(ks["unlock_file"]).expanduser()
# Env var overrides
- if url := os.environ.get("MESHBAY_HUB_URL"):
+ if url := os.environ.get("MESHBAY_HUB_URL"):
cfg.hub.url = url
if user := os.environ.get("MESHBAY_USERNAME"):
cfg.hub.username = user
- if pwd := os.environ.get("MESHBAY_PASSWORD"):
+ if pwd := os.environ.get("MESHBAY_PASSWORD"):
cfg.hub.password = pwd
if port := os.environ.get("MESHBAY_PORT"):
cfg.node.port = int(port)