diff --git a/Plugin/unraid/include/partnership.php b/Plugin/unraid/include/partnership.php index 318e767..c5e9f80 100644 --- a/Plugin/unraid/include/partnership.php +++ b/Plugin/unraid/include/partnership.php @@ -548,6 +548,15 @@ function vv_pt_nodes(): array { 'api_key_preview' => $apiKeyPreview, 'metrics' => $metrics, 'media_seed' => $isMe ? [] : vv_pt_media_seed($setupDb, $nodeIdUpper), + // Every condition that has to hold for this partner to actually be usable, each + // reported separately. One rolled-up boolean would have said "not ok" for the last + // hour without saying that the only failing part was a name lookup. + 'mesh' => $isMe ? null : [ + 'tailscale' => $ts['online'] === true, + 'ssh' => !empty($system['unraid_version']) || !empty($system['uptime_sec']), + 'partnership' => ($ptDb['state'] ?? '') === 'ACTIVE', + 'onboarded' => $onboardPhase >= 2, + ], ]; } return $nodes; diff --git a/Plugin/unraid/pages/partnership.php b/Plugin/unraid/pages/partnership.php index 05a69a0..5d250b5 100644 --- a/Plugin/unraid/pages/partnership.php +++ b/Plugin/unraid/pages/partnership.php @@ -1311,6 +1311,30 @@ function _renderActions(nodes, cfg) { } } + // ── Mesh health banner ───────────────────────────────────────────────── + // Green only when every leg holds. When one does not, the banner names which — "mesh + // degraded" on its own sends someone hunting through four subsystems, and the answer is + // already known here. + const mesh = remote.mesh; + if (mesh) { + const legs = [ + ['Tailscale', mesh.tailscale], + ['SSH', mesh.ssh], + ['Partnership', mesh.partnership], + ['Onboarded', mesh.onboarded], + ]; + const bad = legs.filter(l => !l[1]).map(l => l[0]); + const ok = bad.length === 0; + html += `