From b7733e812fadd6007976d262bd1d793572a36ba7 Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Sat, 29 Aug 2026 11:15:54 +0200 Subject: feat: node workflow redesign — wizard auto-config, reset, MusicBrainz contact MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wizard (Electron): - Auto-provisions node config (hub URL + username) from logged-in user - node:start handles both cold start and restart of misconfigured daemon - Waits for daemon to reach 'running', auto-links node key on hub - probeNode accepts intermediate states for wizard progress feedback Reset (meshbay-node reset): - Unlinks node key from hub (DELETE /me/node_key, best-effort) - Stops and disables daemon (systemctl --user disable --now) - Erases ~/.config/meshbay, ~/.local/share/meshbay, ~/.local/state/meshbay MusicBrainz contact: - Resolved from owner's hub email instead of per-node roster config - Removed musicbrainz_contact UI and WebRTC handshake field - Removed set_musicbrainz_contact/musicbrainz_contact from roster Node pairing: - Added operator pairing banner on NodePage - Added operator_paired flag to list_groups Co-Authored-By: Claude Opus 4.6 --- packages/meshbay-node/src/meshbay_node/ops.py | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) (limited to 'packages/meshbay-node/src/meshbay_node/ops.py') diff --git a/packages/meshbay-node/src/meshbay_node/ops.py b/packages/meshbay-node/src/meshbay_node/ops.py index c880c75..cb8e01e 100644 --- a/packages/meshbay-node/src/meshbay_node/ops.py +++ b/packages/meshbay-node/src/meshbay_node/ops.py @@ -326,7 +326,13 @@ async def list_groups(state: dict) -> dict: "roots": roots.describe() if roots else [], "peers": sum(1 for p in peers.values() if p.get("group_id") == gid), }) - return {"groups": out} + roster = state.get("roster") + has_operator = False + if roster: + members = await roster.list_members() + has_operator = any(m["role"] == "operator" and m["status"] == "active" + for m in members) + return {"groups": out, "operator_paired": has_operator} async def attach_group(state: dict, name: str, shared_dir: str, @@ -783,22 +789,8 @@ async def set_tmdb_enabled(state: dict, group_id: str, enabled: bool) -> dict: # ── MusicBrainz config (Music app) ─────────────────────────────────────────── -async def set_musicbrainz_config(state: dict, contact: str | None = None) -> dict: - """ - The node-wide User-Agent contact string MusicBrainz's usage policy asks - for (docs/musicbay.md §3.2). Unlike set_tmdb_config there is no token to - manage — MusicBrainz's read endpoints need no credential — so this is a - single field. `contact=""` explicitly clears a previously-set contact - (reverting to "no calls at all", never a generic/unidentified - User-Agent); `contact=None` leaves whatever was there unchanged. - """ - roster = _roster(state) - await roster.set_musicbrainz_contact(contact, set_by=state.get("node_user_id", "")) - if contact is not None: - state["musicbrainz_contact_configured"] = bool(contact) - log.info("MusicBrainz config: contact_configured=%s", bool(contact)) - return {"contact_configured": state.get("musicbrainz_contact_configured", False)} - +# set_musicbrainz_config removed — MusicBrainz contact is now the owner's +# hub email, resolved at login (daemon.py / musicbrainz.py). async def set_musicbrainz_enabled(state: dict, group_id: str, enabled: bool) -> dict: """ -- cgit v1.2.3