feat: connectivity redesign phase 7 — cell-relay as a connection type
Unit Tests / test (push) Successful in 13m22s
Unit Tests / test (push) Successful in 13m22s
cell exits surface as cell_relay connections via reconcile, bridged onto the existing cell route_via mechanism, health from handshake, loop detection, assignable in the unified UI - CELL_RELAY_TYPE constant; not manually creatable - reconcile_cell_relays() derives connections from cell links offering an exit (name "Cell: <cellname>", mark+table only, no iface/port/container) - apply_routes bridges cell_relay to existing route_via path via apply_peer_route_via + cell firewall rules + set_exit_relay_active; keeps peer.route_via in sync - _probe_cell_relay health from cell handshake + offer state - _cell_relay_loops loop detection at assign and apply time - FAILOPEN_DEFAULTS cell_relay=False - set_peer_exit clears stale route_via on reassignment - reconcile hooked into PUT /exit-offer and peer-sync/permissions handlers - cell_link_manager + wireguard_manager wired into connectivity_manager - UI: cell_relay in TYPE_META/GROUP_TYPES/GROUP_LABELS (Cells optgroup), removed "coming soon" placeholder - 18 new tests in tests/test_connectivity_cell_relay.py Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -70,7 +70,7 @@ function FailopenControl({ value, onChange, saving }) {
|
||||
export default function AssignmentsPage() {
|
||||
const toasts = useToasts();
|
||||
const {
|
||||
connections, peerExits, peerFailopen, serviceEgress, installed, peers, cells,
|
||||
connections, peerExits, peerFailopen, serviceEgress, installed, peers,
|
||||
loading, error, reload, setPeerExits, setPeerFailopen, setServiceEgress,
|
||||
} = useConnectivityData();
|
||||
|
||||
@@ -78,7 +78,9 @@ export default function AssignmentsPage() {
|
||||
const [savingFailopen, setSavingFailopen] = useState({});
|
||||
const [savingService, setSavingService] = useState({});
|
||||
|
||||
// Build grouped options from connection instances + cell-relay placeholders.
|
||||
// Build grouped options from connection instances. cell_relay connections
|
||||
// (derived from cell links that offer an exit) flow through the same
|
||||
// `connections` list and land in the "Cells" group automatically.
|
||||
const options = (() => {
|
||||
const groups = [];
|
||||
Object.keys(GROUP_TYPES).forEach((group) => {
|
||||
@@ -87,17 +89,6 @@ export default function AssignmentsPage() {
|
||||
.map((c) => ({ id: c.id, label: `${c.name} (${typeMeta(c.type).short})` }));
|
||||
if (items.length) groups.push({ label: GROUP_LABELS[group], items });
|
||||
});
|
||||
// Cell-relay: remote cells that offer their internet. Backend wiring for
|
||||
// cell-relay exits lands in P7; surface them disabled so the option is
|
||||
// discoverable without breaking assignment.
|
||||
const relayItems = (cells || [])
|
||||
.filter((c) => c.remote_exit_offered || c.exit_offered)
|
||||
.map((c) => ({
|
||||
id: `cell:${c.cell_name}`,
|
||||
label: `${c.cell_name} (cell relay — coming soon)`,
|
||||
disabled: true,
|
||||
}));
|
||||
if (relayItems.length) groups.push({ label: 'Cell relay', items: relayItems });
|
||||
return { groups };
|
||||
})();
|
||||
|
||||
|
||||
@@ -50,6 +50,14 @@ export const TYPE_META = {
|
||||
group: 'tor',
|
||||
service: 'tor',
|
||||
},
|
||||
cell_relay: {
|
||||
label: 'Cell relay',
|
||||
short: 'Cell',
|
||||
Icon: Network,
|
||||
color: 'gray',
|
||||
group: 'cells',
|
||||
service: null,
|
||||
},
|
||||
};
|
||||
|
||||
// Subpage groups → which connection types they contain.
|
||||
@@ -58,6 +66,7 @@ export const GROUP_TYPES = {
|
||||
proxies: ['proxy'],
|
||||
ssh: ['sshuttle'],
|
||||
tor: ['tor'],
|
||||
cells: ['cell_relay'],
|
||||
};
|
||||
|
||||
export const GROUP_LABELS = {
|
||||
@@ -65,6 +74,7 @@ export const GROUP_LABELS = {
|
||||
proxies: 'Proxies',
|
||||
ssh: 'SSH',
|
||||
tor: 'Tor',
|
||||
cells: 'Cells',
|
||||
};
|
||||
|
||||
export function typeMeta(type) {
|
||||
|
||||
Reference in New Issue
Block a user