mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-10-09 06:56:37 +00:00
fix(notifications): ship recovery helper and reject superseded proofs
This commit is contained in:
@@ -131,6 +131,7 @@ cp "$SCRIPT_DIR/auth_manager.py" "$APP_DIR/usr/bin/" 2>/dev/null || echo "⚠️
|
||||
cp "$SCRIPT_DIR/jwt_middleware.py" "$APP_DIR/usr/bin/" 2>/dev/null || echo "⚠️ jwt_middleware.py not found"
|
||||
cp "$SCRIPT_DIR/health_monitor.py" "$APP_DIR/usr/bin/" 2>/dev/null || echo "⚠️ health_monitor.py not found"
|
||||
cp "$SCRIPT_DIR/health_persistence.py" "$APP_DIR/usr/bin/" 2>/dev/null || echo "⚠️ health_persistence.py not found"
|
||||
cp "$SCRIPT_DIR/health_recovery.py" "$APP_DIR/usr/bin/"
|
||||
cp "$SCRIPT_DIR/flask_health_routes.py" "$APP_DIR/usr/bin/" 2>/dev/null || echo "⚠️ flask_health_routes.py not found"
|
||||
cp "$SCRIPT_DIR/flask_proxmenux_routes.py" "$APP_DIR/usr/bin/" 2>/dev/null || echo "⚠️ flask_proxmenux_routes.py not found"
|
||||
cp "$SCRIPT_DIR/post_install_versions.py" "$APP_DIR/usr/bin/" 2>/dev/null || echo "⚠️ post_install_versions.py not found"
|
||||
|
||||
@@ -828,14 +828,18 @@ class HealthPersistence:
|
||||
return None
|
||||
try:
|
||||
# One SQLite statement is one consistent row/ack/closure snapshot.
|
||||
# Latest closure by event id, never search past a generic clear.
|
||||
# Latest native observation/closure by durable event id: a later
|
||||
# abnormal record supersedes proof even when a resolved row is
|
||||
# reused and wall-clock time moves backward. No-op clears create
|
||||
# no event, so they do not invalidate a genuine closure.
|
||||
with self._db_lock, self._db_connection() as conn:
|
||||
row = conn.execute('''
|
||||
SELECT e.first_seen, e.last_seen, e.resolved_at, e.acknowledged,
|
||||
e.id, v.timestamp, v.data
|
||||
FROM errors e JOIN events v ON v.id = (
|
||||
SELECT id FROM events WHERE error_key = e.error_key
|
||||
AND event_type IN ('resolved', 'cleared') ORDER BY id DESC LIMIT 1
|
||||
AND event_type IN ('resolved', 'cleared', 'new', 'updated', 'escalated')
|
||||
ORDER BY id DESC LIMIT 1
|
||||
) WHERE e.error_key = ?
|
||||
''', (error_key,)).fetchone()
|
||||
if not row or row[0] != first_seen or not row[2] or row[3]:
|
||||
|
||||
@@ -2189,7 +2189,7 @@ def render_template(event_type: str, data: Dict[str, Any],
|
||||
source_subject = cause.group(1).strip() if cause else ''
|
||||
if source_subject.lower() == 'multiple problems':
|
||||
source_subject = ''
|
||||
if source_subject and source_subject not in body_text:
|
||||
if source_subject and source_subject not in {line.strip() for line in body_text.splitlines()}:
|
||||
# Reserve the subject-equivalent diagnostic BEFORE the cap. Finding
|
||||
# it in uncapped logs is not enough: that late line could be omitted.
|
||||
principal_cause = next((line for line in backup_diagnostics
|
||||
|
||||
Reference in New Issue
Block a user