1
0
Files
homelab-public-context/runtime/history/HOMELAB-SKLADCHIK-COOKIE-EXACT-LOGIC-419.json
T
2026-07-24 09:06:50 +00:00

31 lines
23 KiB
JSON

{
"schema_version": 1,
"channel": "homelab-runtime",
"command_id": "HOMELAB-SKLADCHIK-COOKIE-EXACT-LOGIC-419",
"status": "OK",
"rc": 0,
"host": "pve01",
"mode": "read-only",
"component": "cluster-audit",
"started_at_utc": "2026-07-24T09:06:49Z",
"finished_at_utc": "2026-07-24T09:06:49Z",
"reference_register_checked": true,
"reference_sha256": "5763f2f8edc75fcf6f3951f8c95896d1cc112ceccb6cf5b64a383f540a4deb8e",
"error_register_checked": true,
"error_register_sha256": "08b3a769b8e38eaa1acec915352fb328180d70caa7ff6cd9d1ec0da426262752",
"command_sha256": "77896618b46e2f97362240deb743fb8e625075381e57377ee0314130be2b2026",
"duplicate_failed_command_blocked": false,
"block_reason": null,
"execution_started": true,
"changes_made": false,
"sanitized": true,
"secrets_included": false,
"private_addresses_included": false,
"raw_evidence_retained_locally": true,
"raw_evidence_sha256": "63d14ea58a82bd34d78884b4db6d047e8fa64822200c7bc20a8587057f3f9e25",
"sanitized_output_sha256": "702451cb7bfbc7d831b17b7e062a00f5215e5dc3729bd8e3331dfe4c3dc28851",
"output_truncated_in_json": false,
"full_sanitized_output_url": "https://git.gram1.ru/.well-known/homelab-runtime/latest.txt",
"output": "DETAIL=SCRIPT_SHA256=35c68ae0929ff3795be2bde40de334fc8e26413a3d8a620a137be90d1f2c164e\nDETAIL=EXACT_COOKIE_LOGIC_BEGIN\nDETAIL=SOURCE_BLOCK=TOP_LEVEL_CONSTANT|LINES=12-12\nDETAIL=SOURCE_LINE=0012:EDGE = os.environ.get(\"SKLADCHIK_EDGE\", \"debian@[PRIVATE_IP]\")\nDETAIL=SOURCE_BLOCK=TOP_LEVEL_CONSTANT|LINES=22-22\nDETAIL=SOURCE_LINE=0022:COOKIE_EXPIRY_WARN_SECONDS = int(os.environ.get(\"SKLADCHIK_COOKIE_EXPIRY_WARN_SECONDS\", \"604800\"))\nDETAIL=SOURCE_BLOCK=FUNCTION:gather|LINES=105-271\nDETAIL=SOURCE_LINE=0105:def gather():\nDETAIL=SOURCE_LINE=0106: facts = {}\nDETAIL=SOURCE_LINE=0107: problems = []\nDETAIL=SOURCE_LINE=0108:\nDETAIL=SOURCE_LINE=0109: edge_cmd = r'''\nDETAIL=SOURCE_LINE=0110:set +e\nDETAIL=SOURCE_LINE=0111:echo __MONITOR_HEALTH_BEGIN__\nDETAIL=SOURCE_LINE=0112:cat /var/lib/skladchik-reports-monitor/health.txt 2>/dev/null || true\nDETAIL=SOURCE_LINE=0113:echo __MONITOR_HEALTH_END__\nDETAIL=SOURCE_LINE=0114:echo __ALERT_HEALTH_BEGIN__\nDETAIL=SOURCE_LINE=0115:cat /var/lib/skladchik-reports-monitor/alert-health.txt 2>/dev/null || true\nDETAIL=SOURCE_LINE=0116:echo __ALERT_HEALTH_END__\nDETAIL=SOURCE_LINE=0117:echo __TIMERS_BEGIN__\nDETAIL=SOURCE_LINE=0118:for u in skladchik-reports-monitor.timer skladchik-reports-monitor-watchdog.timer skladchik-reports-monitor-heartbeat.timer skladchik-reports-monitor-weekly-summary.timer skladchik-reports-monitor-age-alert.timer skladchik-reports-monitor-event-selftest.timer; do echo \"$u enabled=$(systemctl is-enabled \"$u\" 2>/dev/null) active=$(systemctl is-active \"$u\" 2>/dev/null)\"; done\nDETAIL=SOURCE_LINE=0119:echo __TIMERS_END__\nDETAIL=SOURCE_LINE=0120:echo __ROUTE_BEGIN__\nDETAIL=SOURCE_LINE=0121:ip route get 1.1.1.1 2>&1 | head -n 1\nDETAIL=SOURCE_LINE=0122:echo __ROUTE_END__\nDETAIL=SOURCE_LINE=0123:echo __FILES_BEGIN__\nDETAIL=SOURCE_LINE=0124:test -s /opt/skladchik-reports-monitor/monitor.py && echo monitor_py=yes || echo monitor_py=no\nDETAIL=SOURCE_LINE=0125:test -s /etc/skladchik-reports-monitor/config.ini && echo config_ini=yes || echo config_ini=no\nDETAIL=SOURCE_LINE=0126:test -s /etc/skladchik-reports-monitor/secrets.env && echo secrets_env=<REDACTED>\nDETAIL=SOURCE_LINE=0127:test -s /var/lib/skladchik-reports-monitor/cookies.jar && echo cookies_jar=yes || echo cookies_jar=no\nDETAIL=SOURCE_LINE=0128:[ -s /var/lib/skladchik-reports-monitor/cookies.jar ] && echo cookies_jar_bytes=$(stat -c %s /var/lib/skladchik-reports-monitor/cookies.jar 2>/dev/null) || echo cookies_jar_bytes=0\nDETAIL=SOURCE_LINE=0129:test -s /opt/skladchik-reports-monitor/operational_digest.py && echo operational_digest_py=yes || echo operational_digest_py=no\nDETAIL=SOURCE_LINE=0130:test -s /opt/skladchik-reports-monitor/event-selftest-runner.py && echo event_selftest_runner_py=yes || echo event_selftest_runner_py=no\nDETAIL=SOURCE_LINE=0131:test -s /opt/skladchik-reports-monitor/event-selftest-core && echo event_selftest_core=yes || echo event_selftest_core=no\nDETAIL=SOURCE_LINE=0132:test -s /var/lib/skladchik-reports-monitor/weekly-summary-health.txt && echo weekly_summary_health=yes || echo weekly_summary_health=no\nDETAIL=SOURCE_LINE=0133:test -s /var/lib/skladchik-reports-monitor/age-alert-health.txt && echo age_alert_health=yes || echo age_alert_health=no\nDETAIL=SOURCE_LINE=0134:test -s /var/lib/skladchik-reports-monitor/event-selftest-health.txt && echo event_selftest_health=yes || echo event_selftest_health=no\nDETAIL=SOURCE_LINE=0135:python3 -m py_compile /opt/skladchik-reports-monitor/monitor.py /opt/skladchik-reports-monitor/operational_digest.py /opt/skladchik-reports-monitor/event-selftest-runner.py /opt/skladchik-reports-monitor/event-selftest-core >/dev/null 2>&1 && echo py_compile=yes || echo py_compile=no\nDETAIL=SOURCE_LINE=0136:echo __FILES_END__\nDETAIL=SOURCE_LINE=0137:'''\nDETAIL=SOURCE_LINE=0138: rc, out = ssh_edge(edge_cmd, timeout=45)\nDETAIL=SOURCE_LINE=0139: facts[\"edge_ssh_rc\"] = str(rc)\nDETAIL=SOURCE_LINE=0140: if rc != 0:\nDETAIL=SOURCE_LINE=0141: problems.append(\"edge_ssh_failed\")\nDETAIL=SOURCE_LINE=0142:\nDETAIL=SOURCE_LINE=0143: def section(name):\nDETAIL=SOURCE_LINE=0144: m = re.search(rf\"__{name}_BEGIN__\\n(.*?)\\n__{name}_END__\", out, re.S)\nDETAIL=SOURCE_LINE=0145: return m.group(1).strip() if m else \"\"\nDETAIL=SOURCE_LINE=0146:\nDETAIL=SOURCE_LINE=0147: mon = parse_env_text(section(\"MONITOR_HEALTH\"))\nDETAIL=SOURCE_LINE=0148: facts[\"monitor_status\"] = mon.get(\"STATUS\", \"MISSING\")\nDETAIL=SOURCE_LINE=0149: facts[\"monitor_reports\"] = mon.get(\"reports\", \"\")\nDETAIL=SOURCE_LINE=0150: facts[\"monitor_open\"] = mon.get(\"open\", \"\")\nDETAIL=SOURCE_LINE=0151: facts[\"monitor_resolved\"] = mon.get(\"resolved\", \"\")\nDETAIL=SOURCE_LINE=0152: facts[\"monitor_smtp_configured\"] = mon.get(\"smtp_configured\", \"\")\nDETAIL=SOURCE_LINE=0153: facts[\"session_keepalive\"] = mon.get(\"session_keepalive\", \"\")\nDETAIL=SOURCE_LINE=0154: facts[\"cookie_jar\"] = mon.get(\"cookie_jar\", \"\")\nDETAIL=SOURCE_LINE=0155: facts[\"cookie_jar_bytes\"] = mon.get(\"cookie_jar_bytes\", \"\")\nDETAIL=SOURCE_LINE=0156: facts[\"cookie_expiry_status\"] = mon.get(\"cookie_expiry_status\", \"\")\nDETAIL=SOURCE_LINE=0157: facts[\"cookie_expiry_utc\"] = mon.get(\"cookie_expiry_utc\", \"\")\nDETAIL=SOURCE_LINE=0158: facts[\"cookie_expires_in_seconds\"] = mon.get(\"cookie_expires_in_seconds\", \"\")\nDETAIL=SOURCE_LINE=0159: facts[\"cookie_expires_in_days\"] = mon.get(\"cookie_expires_in_days\", \"\")\nDETAIL=SOURCE_LINE=0160: facts[\"cookie_persistent_count\"] = mon.get(\"cookie_persistent_count\", \"\")\nDETAIL=SOURCE_LINE=0161: facts[\"monitor_health_age_seconds\"] = str(age_seconds_from_ts(mon.get(\"TS\")))\nDETAIL=SOURCE_LINE=0162: if mon.get(\"STATUS\") != \"OK\":\nDETAIL=SOURCE_LINE=0163: problems.append(\"monitor_status_not_ok\")\nDETAIL=SOURCE_LINE=0164: if int(facts[\"monitor_health_age_seconds\"]) > MONITOR_HEALTH_AGE_MAX:\nDETAIL=SOURCE_LINE=0165: problems.append(\"monitor_health_stale\")\nDETAIL=SOURCE_LINE=0166: if mon.get(\"reports\") in (\"\", \"0\"):\nDETAIL=SOURCE_LINE=0167: problems.append(\"monitor_reports_zero_or_missing\")\nDETAIL=SOURCE_LINE=0168: if mon.get(\"session_keepalive\") != \"persistent_cookie_jar\":\nDETAIL=SOURCE_LINE=0169: problems.append(\"session_keepalive_not_persistent\")\nDETAIL=SOURCE_LINE=0170: if mon.get(\"cookie_jar\") not in (\"yes\", \"empty\"):\nDETAIL=SOURCE_LINE=0171: problems.append(\"monitor_cookie_jar_bad\")\nDETAIL=SOURCE_LINE=0172: expiry_status = mon.get(\"cookie_expiry_status\", \"\")\nDETAIL=SOURCE_LINE=0173: try:\nDETAIL=SOURCE_LINE=0174: expires_in = int(mon.get(\"cookie_expires_in_seconds\", \"\"))\nDETAIL=SOURCE_LINE=0175: except Exception:\nDETAIL=SOURCE_LINE=0176: expires_in = None\nDETAIL=SOURCE_LINE=0177: if expiry_status in (\"\", \"NO_COOKIE_JAR\", \"NO_PERSISTENT_COOKIE\", \"ERROR\"):\nDETAIL=SOURCE_LINE=0178: problems.append(\"cookie_expiry_missing\")\nDETAIL=SOURCE_LINE=0179: elif expiry_status == \"EXPIRED\" or (expires_in is not None and expires_in <= 0):\nDETAIL=SOURCE_LINE=0180: problems.append(\"cookie_expiry_expired\")\nDETAIL=SOURCE_LINE=0181: elif expiry_status == \"WARN\" or (expires_in is not None and expires_in < COOKIE_EXPIRY_WARN_SECONDS):\nDETAIL=SOURCE_LINE=0182: problems.append(\"cookie_expiry_warn\")\nDETAIL=SOURCE_LINE=0183:\nDETAIL=SOURCE_LINE=0184: timers_text = section(\"TIMERS\")\nDETAIL=SOURCE_LINE=0185: for unit in [\"skladchik-reports-monitor.timer\", \"skladchik-reports-monitor-watchdog.timer\", \"skladchik-reports-monitor-heartbeat.timer\", \"skladchik-reports-monitor-weekly-summary.timer\", \"skladchik-reports-monitor-age-alert.timer\", \"skladchik-reports-monitor-event-selftest.timer\"]:\nDETAIL=SOURCE_LINE=0186: safe = unit.replace(\".timer\", \"\").replace(\"_\", \"-\")\nDETAIL=SOURCE_LINE=0187: m = re.search(re.escape(unit) + r\"\\s+enabled=([^\\s]+)\\s+active=([^\\s]+)\", timers_text)\nDETAIL=SOURCE_LINE=0188: enabled = m.group(1) if m else \"missing\"\nDETAIL=SOURCE_LINE=0189: active = m.group(2) if m else \"missing\"\nDETAIL=SOURCE_LINE=0190: facts[f\"edge_{safe}_timer_enabled\"] = enabled\nDETAIL=SOURCE_LINE=0191: facts[f\"edge_{safe}_timer_active\"] = active\nDETAIL=SOURCE_LINE=0192: if enabled != \"enabled\" or active != \"active\":\nDETAIL=SOURCE_LINE=0193: problems.append(f\"edge_{safe}_timer_bad\")\nDETAIL=SOURCE_LINE=0194:\nDETAIL=SOURCE_LINE=0195: route_lines = section(\"ROUTE\").splitlines()\nDETAIL=SOURCE_LINE=0196: route = route_lines[0] if route_lines else \"\"\nDETAIL=SOURCE_LINE=0197: facts[\"netbird_route\"] = route\nDETAIL=SOURCE_LINE=0198: if \" wt0 \" not in (\" \" + route + \" \"):\nDETAIL=SOURCE_LINE=0199: problems.append(\"netbird_route_not_wt0\")\nDETAIL=SOURCE_LINE=0200:\nDETAIL=SOURCE_LINE=0201: files = parse_env_text(section(\"FILES\"))\nDETAIL=SOURCE_LINE=0202: for k in [\"monitor_py\", \"config_ini\", \"secrets_env\", \"cookies_jar\", \"operational_digest_py\", \"event_selftest_runner_py\", \"event_selftest_core\", \"weekly_summary_health\", \"age_alert_health\", \"event_selftest_health\", \"py_compile\"]:\nDETAIL=SOURCE_LINE=0203: facts[k] = files.get(k, \"no\")\nDETAIL=SOURCE_LINE=0204: if facts[k] != \"yes\":\nDETAIL=SOURCE_LINE=0205: problems.append(f\"edge_{k}_bad\")\nDETAIL=SOURCE_LINE=0206: facts[\"cookies_jar_bytes_file\"] = files.get(\"cookies_jar_bytes\", \"0\")\nDETAIL=SOURCE_LINE=0207:\nDETAIL=SOURCE_LINE=0208: backup = read_env_file(PVE_BACKUP_HEALTH)\nDETAIL=SOURCE_LINE=0209: facts[\"backup_status\"] = backup.get(\"STATUS\", \"MISSING\")\nDETAIL=SOURCE_LINE=0210: facts[\"backup_run_id\"] = backup.get(\"RUN_ID\", \"\")\nDETAIL=SOURCE_LINE=0211: facts[\"backup_size_bytes\"] = backup.get(\"SIZE_BYTES\", \"\")\nDETAIL=SOURCE_LINE=0212: facts[\"backup_version\"] = backup.get(\"BACKUP_VERSION\", \"\")\nDETAIL=SOURCE_LINE=0213: facts[\"backup_cookie_jar_backed_up\"] = backup.get(\"COOKIE_JAR_BACKED_UP\", \"\")\nDETAIL=SOURCE_LINE=0214: facts[\"backup_extension_health_files_backed_up\"] = backup.get(\"EXTENSION_HEALTH_FILES_BACKED_UP\", \"\")\nDETAIL=SOURCE_LINE=0215: facts[\"backup_title_in_email_subject\"] = backup.get(\"TITLE_IN_EMAIL_SUBJECT\", \"\")\nDETAIL=SOURCE_LINE=0216: facts[\"backup_health_age_seconds\"] = str(age_seconds_from_ts(backup.get(\"TS\")))\nDETAIL=SOURCE_LINE=0217: if backup.get(\"STATUS\") != \"OK\":\nDETAIL=SOURCE_LINE=0218: problems.append(\"backup_status_not_ok\")\nDETAIL=SOURCE_LINE=0219: if backup.get(\"COOKIE_JAR_BACKED_UP\") != \"yes\":\nDETAIL=SOURCE_LINE=0220: problems.append(\"backup_cookie_jar_not_marked\")\nDETAIL=SOURCE_LINE=0221: if backup.get(\"BACKUP_VERSION\") != \"4\":\nDETAIL=SOURCE_LINE=0222: problems.append(\"backup_version_not_4\")\nDETAIL=SOURCE_LINE=0223: if backup.get(\"EXTENSION_HEALTH_FILES_BACKED_UP\") != \"yes\":\nDETAIL=SOURCE_LINE=0224: problems.append(\"backup_extension_health_files_not_marked\")\nDETAIL=SOURCE_LINE=0225: if backup.get(\"TITLE_IN_EMAIL_SUBJECT\") != \"yes\":\nDETAIL=SOURCE_LINE=0226: problems.append(\"email_title_subject_not_marked\")\nDETAIL=SOURCE_LINE=0227: if int(facts[\"backup_health_age_seconds\"]) > BACKUP_HEALTH_AGE_MAX:\nDETAIL=SOURCE_LINE=0228: problems.append(\"backup_health_stale\")\nDETAIL=SOURCE_LINE=0229: try:\nDETAIL=SOURCE_LINE=0230: if int(backup.get(\"SIZE_BYTES\", \"0\")) <= 0:\nDETAIL=SOURCE_LINE=0231: problems.append(\"backup_size_bad\")\nDETAIL=SOURCE_LINE=0232: except Exception:\nDETAIL=SOURCE_LINE=0233: problems.append(\"backup_size_bad\")\nDETAIL=SOURCE_LINE=0234:\nDETAIL=SOURCE_LINE=0235: restore = read_env_file(PVE_RESTORE_HEALTH)\nDETAIL=SOURCE_LINE=0236: facts[\"restore_status\"] = restore.get(\"STATUS\", \"MISSING\")\nDETAIL=SOURCE_LINE=0237: facts[\"restore_run_id\"] = restore.get(\"RUN_ID\", \"\")\nDETAIL=SOURCE_LINE=0238: facts[\"restore_health_age_seconds\"] = str(age_seconds_from_ts(restore.get(\"TS\")))\nDETAIL=SOURCE_LINE=0239: for key in [\"CLOUD_1_STATUS\", \"CLOUD_2_STATUS\", \"SHA256_OK\", \"TAR_OK\", \"REQUIRED_FILES_OK\", \"COOKIE_JAR_OK\", \"EXTENSION_HEALTH_FILES_OK\", \"EXTENSION_SCRIPTS_OK\", \"EXTENSION_UNITS_OK\", \"SQLITE_OK\", \"PY_COMPILE_OK\"]:\nDETAIL=SOURCE_LINE=0240: facts[key.lower()] = restore.get(key, \"\")\nDETAIL=SOURCE_LINE=0241: if restore.get(\"STATUS\") != \"OK\":\nDETAIL=SOURCE_LINE=0242: problems.append(\"restore_status_not_ok\")\nDETAIL=SOURCE_LINE=0243: if int(facts[\"restore_health_age_seconds\"]) > RESTORE_HEALTH_AGE_MAX:\nDETAIL=SOURCE_LINE=0244: problems.append(\"restore_health_stale\")\nDETAIL=SOURCE_LINE=0245: for key in [\"CLOUD_1_STATUS\", \"CLOUD_2_STATUS\"]:\nDETAIL=SOURCE_LINE=0246: if restore.get(key) != \"OK\":\nDETAIL=SOURCE_LINE=0247: problems.append(key.lower() + \"_bad\")\nDETAIL=SOURCE_LINE=0248: for key in [\"SHA256_OK\", \"TAR_OK\", \"REQUIRED_FILES_OK\", \"COOKIE_JAR_OK\", \"EXTENSION_HEALTH_FILES_OK\", \"EXTENSION_SCRIPTS_OK\", \"EXTENSION_UNITS_OK\", \"SQLITE_OK\", \"PY_COMPILE_OK\"]:\nDETAIL=SOURCE_LINE=0249: if restore.get(key) != \"yes\":\nDETAIL=SOURCE_LINE=0250: problems.append(key.lower() + \"_bad\")\nDETAIL=SOURCE_LINE=0251:\nDETAIL=SOURCE_LINE=0252: local_units = [\nDETAIL=SOURCE_LINE=0253: \"skladchik-reports-monitor-backup.timer\",\nDETAIL=SOURCE_LINE=0254: \"skladchik-reports-monitor-backup-restore-check.timer\",\nDETAIL=SOURCE_LINE=0255: \"skladchik-reports-monitor-supervisor.timer\",\nDETAIL=SOURCE_LINE=0256: \"skladchik-reports-monitor-monthly-selftest-watch.timer\",\nDETAIL=SOURCE_LINE=0257: ]\nDETAIL=SOURCE_LINE=0258: props = systemctl_props(local_units)\nDETAIL=SOURCE_LINE=0259: for u, p in props.items():\nDETAIL=SOURCE_LINE=0260: base = u.replace(\".timer\", \"\").replace(\"-\", \"_\")\nDETAIL=SOURCE_LINE=0261: facts[base + \"_timer_enabled\"] = p[\"enabled\"]\nDETAIL=SOURCE_LINE=0262: facts[base + \"_timer_active\"] = p[\"active\"]\nDETAIL=SOURCE_LINE=0263: if u != \"skladchik-reports-monitor-supervisor.timer\":\nDETAIL=SOURCE_LINE=0264: if p[\"enabled\"] != \"enabled\" or p[\"active\"] != \"active\":\nDETAIL=SOURCE_LINE=0265: problems.append(base + \"_timer_bad\")\nDETAIL=SOURCE_LINE=0266: else:\nDETAIL=SOURCE_LINE=0267: # Before first enable it can be disabled/inactive during test. After enable next runs will see enabled/active.\nDETAIL=SOURCE_LINE=0268: if p[\"enabled\"] not in (\"enabled\", \"disabled\") or p[\"active\"] not in (\"active\", \"inactive\"):\nDETAIL=SOURCE_LINE=0269: problems.append(base + \"_timer_unknown\")\nDETAIL=SOURCE_LINE=0270:\nDETAIL=SOURCE_LINE=0271: return facts, problems\nDETAIL=SOURCE_BLOCK=FUNCTION:render_body|LINES=273-321\nDETAIL=SOURCE_LINE=0273:def render_body(status, facts, problems, mode):\nDETAIL=SOURCE_LINE=0274: ru_status = \"OK\" if status == \"OK\" else \"АВАРИЯ\"\nDETAIL=SOURCE_LINE=0275: lines = [\nDETAIL=SOURCE_LINE=0276: f\"Статус надзора: {ru_status}\",\nDETAIL=SOURCE_LINE=0277: f\"Время UTC: {iso()}\",\nDETAIL=SOURCE_LINE=0278: \"\",\nDETAIL=SOURCE_LINE=0279: \"Монитор жалоб:\",\nDETAIL=SOURCE_LINE=0280: f\"- статус: {facts.get('monitor_status')}\",\nDETAIL=SOURCE_LINE=0281: f\"- всего жалоб на странице: {facts.get('monitor_reports')}\",\nDETAIL=SOURCE_LINE=0282: f\"- открытые/назначенные: {facts.get('monitor_open')}\",\nDETAIL=SOURCE_LINE=0283: f\"- закрытые: {facts.get('monitor_resolved')}\",\nDETAIL=SOURCE_LINE=0284: f\"- возраст health, сек: {facts.get('monitor_health_age_seconds')}\",\nDETAIL=SOURCE_LINE=0285: f\"- автопродление авторизации: {facts.get('session_keepalive')}\",\nDETAIL=SOURCE_LINE=0286: f\"- cookie jar: {facts.get('cookie_jar')} / {facts.get('cookie_jar_bytes')} байт\",\nDETAIL=SOURCE_LINE=0287: f\"- постоянная cookie действует до UTC: {facts.get('cookie_expiry_utc') or 'не определено'}\",\nDETAIL=SOURCE_LINE=0288: f\"- осталось дней по cookie: {facts.get('cookie_expires_in_days') or 'не определено'}\",\nDETAIL=SOURCE_LINE=0289: f\"- статус срока cookie: {facts.get('cookie_expiry_status') or 'не определено'}\",\nDETAIL=SOURCE_LINE=0290: f\"- NetBird route: {facts.get('netbird_route')}\",\nDETAIL=SOURCE_LINE=0291: \"\",\nDETAIL=SOURCE_LINE=0292: \"Бэкап:\",\nDETAIL=SOURCE_LINE=0293: f\"- статус: {facts.get('backup_status')}\",\nDETAIL=SOURCE_LINE=0294: f\"- последний RUN_ID: {facts.get('backup_run_id')}\",\nDETAIL=SOURCE_LINE=0295: f\"- размер архива, байт: {facts.get('backup_size_bytes')}\",\nDETAIL=SOURCE_LINE=0296: f\"- cookie jar в бэкапе: {facts.get('backup_cookie_jar_backed_up')}\",\nDETAIL=SOURCE_LINE=0297: f\"- health-файлы расширений в бэкапе: {facts.get('backup_extension_health_files_backed_up')}\",\nDETAIL=SOURCE_LINE=0298: f\"- название жалобы в теме письма: {facts.get('backup_title_in_email_subject')}\",\nDETAIL=SOURCE_LINE=0299: f\"- возраст health, сек: {facts.get('backup_health_age_seconds')}\",\nDETAIL=SOURCE_LINE=0300: \"\",\nDETAIL=SOURCE_LINE=0301: \"Restore-check:\",\nDETAIL=SOURCE_LINE=0302: f\"- статус: {facts.get('restore_status')}\",\nDETAIL=SOURCE_LINE=0303: f\"- последний RUN_ID: {facts.get('restore_run_id')}\",\nDETAIL=SOURCE_LINE=0304: f\"- cloud1/cloud2: {facts.get('cloud_1_status')}/{facts.get('cloud_2_status')}\",\nDETAIL=SOURCE_LINE=0305: f\"- sha256/tar/cookie/sqlite/python: {facts.get('sha256_ok')}/{facts.get('tar_ok')}/{facts.get('cookie_jar_ok')}/{facts.get('sqlite_ok')}/{facts.get('py_compile_ok')}\",\nDETAIL=SOURCE_LINE=0306: f\"- health/scripts/units расширений: {facts.get('extension_health_files_ok')}/{facts.get('extension_scripts_ok')}/{facts.get('extension_units_ok')}\",\nDETAIL=SOURCE_LINE=0307: \"\",\nDETAIL=SOURCE_LINE=0308: \"Проблемы:\",\nDETAIL=SOURCE_LINE=0309: ]\nDETAIL=SOURCE_LINE=0310: if problems:\nDETAIL=SOURCE_LINE=0311: lines.extend([f\"- {p}\" for p in problems])\nDETAIL=SOURCE_LINE=0312: else:\nDETAIL=SOURCE_LINE=0313: lines.append(\"- нет\")\nDETAIL=SOURCE_LINE=0314: lines.extend([\nDETAIL=SOURCE_LINE=0315: \"\",\nDETAIL=SOURCE_LINE=0316: \"Авторизация:\",\nDETAIL=SOURCE_LINE=0317: \"- ручной ежемесячный перелогин обычно не нужен; монитор сам продлевает сессию постоянным cookie jar при каждом опросе;\",\nDETAIL=SOURCE_LINE=0318: \"- supervisor теперь отдельно следит за сроком постоянной cookie и заранее предупредит, если до истечения останется меньше 7 дней;\",\nDETAIL=SOURCE_LINE=0319: \"- если форум принудительно сбросит сессию, придёт отдельная тревога AUTH_REQUIRED; тогда нужно будет разово обновить вход, но это аварийный сценарий, а не ежемесячная рутина.\",\nDETAIL=SOURCE_LINE=0320: ])\nDETAIL=SOURCE_LINE=0321: return \"\\n\".join(lines)\nDETAIL=EXACT_COOKIE_LOGIC_END\nDETAIL=PVE01_TIMER_CORRELATION_BEGIN\nDETAIL=PVE01_TIMER=Fri 2026-07-24 12:08:38 MSK 1min 48s Fri 2026-07-24 11:58:38 MSK 8min ago skladchik-reports-monitor-supervisor.timer skladchik-reports-monitor-supervisor.service\nDETAIL=PVE01_TIMER=Sat 2026-07-25 04:39:05 MSK 16h Fri 2026-07-24 04:28:08 MSK 7h ago skladchik-reports-monitor-backup.timer skladchik-reports-monitor-backup.service\nDETAIL=PVE01_TIMER=Sat 2026-07-25 10:15:00 MSK 22h Fri 2026-07-24 10:15:04 MSK 1h 51min ago skladchik-reports-monitor-monthly-selftest-watch.timer skladchik-reports-monitor-monthly-selftest-watch.service\nDETAIL=PVE01_TIMER=Sun 2026-07-26 05:15:13 MSK 1 day 17h Sun 2026-07-19 05:11:25 MSK - skladchik-reports-monitor-backup-restore-check.timer skladchik-reports-monitor-backup-restore-check.service\nDETAIL=PVE01_TIMER_CORRELATION_END\nDETAIL=EDGE_TIMER_CORRELATION_BEGIN\nDETAIL=EDGE_TIMER=Fri 2026-07-24 12:06:51 MSK 1s Fri 2026-07-24 12:06:21 MSK 28s ago skladchik-reports-monitor.timer skladchik-reports-monitor.service\nDETAIL=EDGE_TIMER=Fri 2026-07-24 12:08:35 MSK 1min 45s Fri 2026-07-24 12:03:35 MSK 3min 14s ago skladchik-reports-monitor-watchdog.timer skladchik-reports-monitor-watchdog.service\nDETAIL=EDGE_TIMER=Sat 2026-07-25 09:16:28 MSK 21h Fri 2026-07-24 09:18:35 MSK 2h 48min ago skladchik-reports-monitor-heartbeat.timer skladchik-reports-monitor-heartbeat.service\nDETAIL=EDGE_TIMER=Sat 2026-07-25 09:45:00 MSK 21h Fri 2026-07-24 09:45:03 MSK 2h 21min ago skladchik-reports-monitor-age-alert.timer skladchik-reports-monitor-age-alert.service\nDETAIL=EDGE_TIMER=Mon 2026-07-27 09:35:00 MSK 2 days Mon 2026-07-20 09:35:06 MSK - skladchik-reports-monitor-weekly-summary.timer skladchik-reports-monitor-weekly-summary.service\nDETAIL=EDGE_TIMER=Sat 2026-08-01 09:25:00 MSK 1 week 0 days Fri 2026-07-10 10:28:28 MSK - skladchik-reports-monitor-event-selftest.timer skladchik-reports-monitor-event-selftest.service\nDETAIL=EDGE_TIMER_CORRELATION_END\nDETAIL=SECRET_VALUES_OUTPUT=NONE\nDETAIL=COOKIE_CONTENT_OUTPUT=NONE\nDETAIL=COOKIE_EXACT_LOGIC_AUDIT=PASS\nCHANGES_MADE=NO\n"
}