aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/api/revocation.py
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/api/revocation.py')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/api/revocation.py11
1 files changed, 10 insertions, 1 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/api/revocation.py b/packages/meshbay-hub/src/meshbay_hub/api/revocation.py
index 8f30745..8f65f89 100644
--- a/packages/meshbay-hub/src/meshbay_hub/api/revocation.py
+++ b/packages/meshbay-hub/src/meshbay_hub/api/revocation.py
@@ -51,6 +51,7 @@ router = APIRouter(tags=["revocation"])
# ── Connected node registry ───────────────────────────────────────────────────
_connected_nodes: dict[str, WebSocket] = {} # node_id → websocket
+_node_groups: dict[str, list[str]] = {} # node_id → [group_id, ...]
_punch_events: dict[str, asyncio.Event] = {} # node_id → signaling event
@@ -58,6 +59,10 @@ def get_connected_node_count() -> int:
return len(_connected_nodes)
+def get_online_nodes_for_group(group_id: str) -> list[str]:
+ return [nid for nid, gids in _node_groups.items() if group_id in gids]
+
+
async def broadcast_revocation(token: str) -> int:
"""Push a signed revocation token to all connected nodes. Returns count sent."""
payload = json.dumps({"type": "revocation", "token": token})
@@ -121,7 +126,10 @@ async def node_websocket(ws: WebSocket):
node_id = msg.get("node_id") or decoded.get("sub", "unknown")
_connected_nodes[node_id] = ws
- log.info("Node WS connected: %s", node_id[:8])
+ group_ids = msg.get("group_ids", [])
+ if group_ids:
+ _node_groups[node_id] = group_ids
+ log.info("Node WS connected: %s (groups=%d)", node_id[:8], len(group_ids))
await ws.send_text(json.dumps({"type": "auth_ok", "node_id": node_id}))
# Message loop — handle ping, punch_ready, etc.
@@ -145,6 +153,7 @@ async def node_websocket(ws: WebSocket):
finally:
if node_id:
_connected_nodes.pop(node_id, None)
+ _node_groups.pop(node_id, None)
# ── Admin revocation endpoint ─────────────────────────────────────────────────