From d8a77c700b12c1dece44c6337783188c6c07540d Mon Sep 17 00:00:00 2001 From: Gmer4Lfe Date: Mon, 17 Aug 2026 11:39:19 -0400 Subject: [PATCH] Stop counting a gated-off critical rsync as an unreachable partner, and report the counter in the unit it is stored in MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The guard tested Tier 1 only, so onboard Step 1d's posture — Tier 1 open, every Tier 2 closed — made a healthy partner climb toward auto-offboard every 30 minutes. The counter holds intervals, not days, and was rendered raw. --- Orchestrators/critical_sync_maintenance.sh | 13 +++++++++++-- Plugin/unraid/include/partnership.php | 14 ++++++++++++-- Plugin/unraid/pages/partnership.php | 7 +++++-- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/Orchestrators/critical_sync_maintenance.sh b/Orchestrators/critical_sync_maintenance.sh index 99ca7b3..dd67ddc 100755 --- a/Orchestrators/critical_sync_maintenance.sh +++ b/Orchestrators/critical_sync_maintenance.sh @@ -250,11 +250,20 @@ if [[ "${PARTNERSHIP_ENABLED:-false}" == true ]]; then # only fault was that RSYNC_ENABLED=false. That is how a deliberately paused sync ends up # dismantling the partnership it was paused for. With no rsync attempt there is nothing to # report, so the check runs without touching the counter either way. + # Tier 2 counts as "switched off" here exactly as much as Tier 1 does. The guard below used + # to test RSYNC_ENABLED alone, but it is CRITICAL_RSYNC_ENABLED that governs whether this + # orchestrator attempts an rsync at all — so with Tier 1 open and Tier 2 closed, no transfer + # was attempted, RSYNC_OK stayed false, and the run fell through to --remote-unseen and + # incremented the counter every 30 minutes against a partner that was answering fine. + # + # Onboard Step 1d now leaves precisely that posture on purpose — Tier 1 open so provisioning + # can run, every Tier 2 gate closed so nothing is scheduled. A freshly onboarded, perfectly + # healthy partnership would have auto-offboarded itself 30 days later. if [[ "$RSYNC_OK" == true ]]; then bash "$SCRIPT_DIR/../Partnership/partnership_manager.sh" \ --check --remote-seen $PARTNER_DRY - elif [[ "${RSYNC_ENABLED:-false}" != true ]]; then - echo "Rsync disabled — partnership check runs, offline counter untouched" + elif [[ "${RSYNC_ENABLED:-false}" != true || "${CRITICAL_RSYNC_ENABLED:-false}" != true ]]; then + echo "Critical rsync gated off — partnership check runs, offline counter untouched" bash "$SCRIPT_DIR/../Partnership/partnership_manager.sh" \ --check $PARTNER_DRY else diff --git a/Plugin/unraid/include/partnership.php b/Plugin/unraid/include/partnership.php index f8c2a7f..8f2d9f2 100644 --- a/Plugin/unraid/include/partnership.php +++ b/Plugin/unraid/include/partnership.php @@ -59,11 +59,20 @@ require_once __DIR__ . '/common.php'; // vv_system_info(), vv_docker_containers( function vv_pt_config(): array { $v = vv_conf_vars(); - $offlineDays = null; + // The file is named ..._days.db and does not hold days. partnership_manager.sh --check runs + // from the 30-minute orchestrator and increments once per run, so the unit is INTERVALS, and + // the auto-offboard threshold it is compared against is computed as days × 48. Reading the + // raw number and printing it as days overstated the outage by 48× — a partner unreachable + // for half an hour rendered as "unreachable 1 day · auto-offboard in 29 days". + $offlineDays = null; + $offlineIntervals = null; $odFile = STATE_DIR . '/partnership_offline_days.db'; if (file_exists($odFile)) { $raw = trim(@file_get_contents($odFile) ?: ''); - if (is_numeric($raw)) $offlineDays = (int)$raw; + if (is_numeric($raw)) { + $offlineIntervals = (int)$raw; + $offlineDays = $offlineIntervals / 48; + } } return [ 'enabled' => ($v['PARTNERSHIP_ENABLED'] ?? 'false') === 'true', @@ -72,6 +81,7 @@ function vv_pt_config(): array { 'grace_hours' => (int)($v['PARTNERSHIP_GRACE_HOURS'] ?? 6), 'offline_threshold' => (int)($v['PARTNERSHIP_OFFLINE_THRESHOLD'] ?? 30), 'offline_days' => $offlineDays, + 'offline_intervals' => $offlineIntervals, 'remove_tailscale' => ($v['PARTNERSHIP_REMOVE_TAILSCALE'] ?? 'false') === 'true', 'folderview3' => ($v['PARTNERSHIP_FOLDERVIEW3'] ?? 'false') === 'true', 'tailscale_configured' => !empty($v['TAILSCALE_API_KEY']) && !empty($v['TAILSCALE_TAILNET']), diff --git a/Plugin/unraid/pages/partnership.php b/Plugin/unraid/pages/partnership.php index cd83be6..ec59684 100644 --- a/Plugin/unraid/pages/partnership.php +++ b/Plugin/unraid/pages/partnership.php @@ -687,9 +687,12 @@ function _renderOfflineWarn(cfg) { const days = cfg.offline_days; const thr = cfg.offline_threshold || 30; // Auto-offboard only runs for active partnerships — a stale counter while disabled is meaningless. + // The 1-day floor is what keeps a single missed 30-minute check from raising a banner: the + // counter ticks per interval, so one tick is half an hour, not a day. if (!cfg.enabled || !days || days < 1) { el.style.display = 'none'; el.innerHTML = ''; return; } + const daysTxt = days < 10 ? days.toFixed(1) : Math.round(days); - const left = Math.max(0, thr - days); + const left = Math.max(0, Math.round(thr - days)); const crit = left <= 5; const col = crit ? '#f44336' : '#ff9800'; const bg = crit ? '#2a1212' : '#1a1200'; @@ -697,7 +700,7 @@ function _renderOfflineWarn(cfg) { el.style.display = ''; el.innerHTML = `
- ⚠ Partner unreachable ${days} day${days===1?'':'s'} + ⚠ Partner unreachable ${daysTxt} day${daysTxt==="1.0"||daysTxt===1?"":"s"} Auto-offboard in ${left} day${left===1?'':'s'} (threshold ${thr}d)