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
+1 -6
View File
@@ -22,6 +22,7 @@ import json
import requests
from base_service_manager import BaseServiceManager
from constants import RESERVED_SUBDOMAINS
from manifest_validator import validate_manifest, validate_provision_hook
logger = logging.getLogger(__name__)
@@ -57,12 +58,6 @@ TRUSTED_IMAGES_NO_DIGEST = frozenset({
FORBIDDEN_MOUNTS = frozenset([
'/', '/etc', '/var', '/proc', '/sys', '/dev', '/app', '/run', '/boot',
])
RESERVED_SUBDOMAINS = frozenset([
'api', 'webui', 'admin', 'www', 'ns1', 'ns2',
'git', 'registry', 'install',
# mail, calendar, files, webmail are intentionally absent:
# they are claimed by official PIC store services.
])
ENV_VALUE_RE = re.compile(r'^[A-Za-z0-9._@:/+\-= ]*$')
SUBDOMAIN_RE = re.compile(r'^[a-z][a-z0-9-]{0,30}$')
BACKEND_RE = re.compile(r'^[A-Za-z0-9._-]+:\d{1,5}$')