Describe the bug
Since severity comparisons became numeric (#5101), preprocess_cel_expression (keep/api/utils/cel_utils.py:6-43) rewrites severity == 'critical' to severity == 5, and the workflow manager and rules engine turn the alert's severity into its order. However:
-
severity in ['critical', 'high'] is not rewritten. The regex only matches [=><!]=? operators. The payload holds 5 and the list holds strings, so the expression is always false:
- workflow triggers never fire;
RulesEngine.filter_alerts (preset counts, preset push updates, internal search) never matches.
The alert-rules query builder (react-querybuilder) emits exactly this form for its "in" operator.
-
Maintenance windows go the other way. MaintenanceWindowsBl.evaluate_cel (keep/api/bl/maintenance_windows_bl.py:121-133) preprocesses the CEL but leaves the payload severity as the string "critical". So severity == "critical", severity >= 'high', != 'low' and so on hit celpy's "no such overload", which is logged and treated as false. A maintenance window scoped by severity never suppresses anything. Only in happens to work there.
The two symptoms share one root cause (numeric CEL against a string payload, and vice versa). Fixing one alone breaks the other.
To Reproduce
- Create a workflow with the trigger
cel: severity in ['critical', 'high'] and send a critical alert. The workflow doesn't run.
- Create a maintenance window with the CEL
severity == "critical" and send a critical alert. It isn't suppressed.
Failing tests (red on main: 5 failed; green with the fix: 29 passed):
tests/test_workflow_severity_comparisons.py::test_severity_in_list, a workflow in sqlite through WorkflowManager.insert_events, the real trigger path.
tests/test_workflow_severity_comparisons.py::test_preprocess_severity_in_list.
tests/test_maintenance_windows_bl.py::test_alert_in_maintenance_window_by_severity[...] (5 cases).
tests/test_maintenance_windows_bl.py::test_evaluate_cel_by_severity_keeps_stored_event.
Expected behavior
severity in [...] in workflows and presets, and severity comparisons in maintenance windows, behave like severity == "critical" does in workflows today.
Additional context
A fix with regression tests is ready on breken-ai/keep fix/cel-severity-in-list:
- Quoted severity names inside
severity in [...] are rewritten to their orders.
evaluate_cel copies the stored event (so the DB row isn't mutated) and converts its severity to the order, as the workflow manager already does.
- ruff is clean. Related suites have the same pre-existing failures on baseline and fix (1 enrichment-in-search failure, and errors that need Elasticsearch).
This touches the same preprocessing as #6620. The PR will follow once the CLA is signed (same account as #6805).
Prepared with AI assistance (Claude) from the breken-ai account.
Describe the bug
Since severity comparisons became numeric (#5101),
preprocess_cel_expression(keep/api/utils/cel_utils.py:6-43) rewritesseverity == 'critical'toseverity == 5, and the workflow manager and rules engine turn the alert's severity into its order. However:severity in ['critical', 'high']is not rewritten. The regex only matches[=><!]=?operators. The payload holds5and the list holds strings, so the expression is always false:RulesEngine.filter_alerts(preset counts, preset push updates, internal search) never matches.The alert-rules query builder (react-querybuilder) emits exactly this form for its "in" operator.
Maintenance windows go the other way.
MaintenanceWindowsBl.evaluate_cel(keep/api/bl/maintenance_windows_bl.py:121-133) preprocesses the CEL but leaves the payload severity as the string"critical". Soseverity == "critical",severity >= 'high',!= 'low'and so on hit celpy's "no such overload", which is logged and treated as false. A maintenance window scoped by severity never suppresses anything. Onlyinhappens to work there.The two symptoms share one root cause (numeric CEL against a string payload, and vice versa). Fixing one alone breaks the other.
To Reproduce
cel: severity in ['critical', 'high']and send a critical alert. The workflow doesn't run.severity == "critical"and send a critical alert. It isn't suppressed.Failing tests (red on main: 5 failed; green with the fix: 29 passed):
tests/test_workflow_severity_comparisons.py::test_severity_in_list, a workflow in sqlite throughWorkflowManager.insert_events, the real trigger path.tests/test_workflow_severity_comparisons.py::test_preprocess_severity_in_list.tests/test_maintenance_windows_bl.py::test_alert_in_maintenance_window_by_severity[...](5 cases).tests/test_maintenance_windows_bl.py::test_evaluate_cel_by_severity_keeps_stored_event.Expected behavior
severity in [...]in workflows and presets, and severity comparisons in maintenance windows, behave likeseverity == "critical"does in workflows today.Additional context
A fix with regression tests is ready on breken-ai/keep
fix/cel-severity-in-list:severity in [...]are rewritten to their orders.evaluate_celcopies the stored event (so the DB row isn't mutated) and converts its severity to the order, as the workflow manager already does.This touches the same preprocessing as #6620. The PR will follow once the CLA is signed (same account as #6805).
Prepared with AI assistance (Claude) from the breken-ai account.