feat: connectivity — registry-driven peer table, sshuttle/proxy egress, egress UI

The peer table was empty because it was not consulting the peer registry;
now peers are driven by PeerRegistry so the Connectivity page reflects actual
connected cells.

Exit-key handling is unified: all code paths now use the same key derivation
so a store-service exit bridge and a manual WireGuard peer both produce
consistent routing state.

Two new egress exit types are added (sshuttle via SSH tunnel and proxy via
redsocks SOCKS5), wiring through connectivity_manager, egress_manager, and
app.py routes. This lets a cell route its traffic through an SSH host or a
SOCKS5 proxy as an alternative to WireGuard exit nodes.

ServiceStoreManager and ServiceBus updated so the egress lifecycle (install /
uninstall) is cleanly signalled between components.

Connectivity.jsx gains the Service Egress section, letting operators assign
and reassign egress methods from the UI without touching config files.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-10 08:36:15 -04:00
parent cc7a223fdf
commit 6232ef23a9
8 changed files with 1096 additions and 61 deletions
+2 -1
View File
@@ -351,7 +351,8 @@ class PeerRegistry(BaseServiceManager):
raise ValueError(f"Peer '{peer_name}' not found")
# Phase 5: extended connectivity per-peer egress exit
VALID_EXIT_VIA = ('default', 'wireguard_ext', 'openvpn', 'tor')
VALID_EXIT_VIA = ('default', 'wireguard_ext', 'openvpn', 'tor',
'sshuttle', 'proxy')
def set_peer_exit_via(self, peer_name: str, exit_type: str) -> bool:
"""Set the per-peer egress exit type. Returns True if updated, False