fix(notifications): ship recovery helper and reject superseded proofs

This commit is contained in:
martino
2026-10-01 09:03:27 +02:00
parent 54eef11334
commit aac75a0753
6 changed files with 311 additions and 3 deletions
+1
View File
@@ -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"
+6 -2
View File
@@ -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]:
+1 -1
View File
@@ -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