add false-positive filter and bulk-clear for findings
Active Feedback Rules gets a status filter, and Field Baseline Deviations gets multi-select with a bulk apply bar. Bulk scope is restricted to exact-value/field only, so a batch action can never create a broad rule that would suppress a genuinely new deviation.
This commit is contained in:
@@ -72,6 +72,37 @@ class FeedbackTests(unittest.TestCase):
|
||||
missing = store.revoke("does-not-exist")
|
||||
self.assertEqual(missing, {"removed": 0, "remaining": 1, "id": "does-not-exist"})
|
||||
|
||||
def test_add_many_writes_once_and_dedupes_by_id(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
store = FeedbackStore(str(Path(directory) / "feedback.json"))
|
||||
result = store.add_many([
|
||||
{"status": "false_positive", "entity": "alice", "stream_id": "windows", "field": "username", "value": "bob"},
|
||||
{"status": "confirmed", "entity": "carol", "stream_id": "vpn", "field": "username", "value": "dave"},
|
||||
# Same (stream_id, entity, field, value) as the first item -> same id -> collapses to one.
|
||||
{"status": "expected", "entity": "alice", "stream_id": "windows", "field": "username", "value": "bob"},
|
||||
])
|
||||
|
||||
self.assertEqual(len(result["added"]), 2)
|
||||
self.assertEqual(result["errors"], [])
|
||||
self.assertEqual(result["remaining"], 2)
|
||||
entries = store.entries()
|
||||
self.assertEqual(len(entries), 2)
|
||||
collapsed = next(item for item in entries if item["entity"] == "alice")
|
||||
self.assertEqual(collapsed["status"], "expected")
|
||||
|
||||
def test_add_many_reports_errors_without_aborting_the_batch(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
store = FeedbackStore(str(Path(directory) / "feedback.json"))
|
||||
result = store.add_many([
|
||||
{"status": "false_positive", "entity": "alice", "stream_id": "windows", "field": "username", "value": "bob"},
|
||||
{"status": "expected", "scope": "entity", "entity": "carol"}, # broad scope, no expiry -> invalid
|
||||
])
|
||||
|
||||
self.assertEqual(len(result["added"]), 1)
|
||||
self.assertEqual(len(result["errors"]), 1)
|
||||
self.assertEqual(result["errors"][0]["index"], 1)
|
||||
self.assertEqual(len(store.entries()), 1)
|
||||
|
||||
def test_feedback_matches_respects_scope_and_precedence(self):
|
||||
value_rule = {"scope": "value", "entity": "alice", "stream_id": "windows", "field": "username", "value": "10.0.0.1", "status": "confirmed"}
|
||||
field_rule = {"scope": "field", "entity": "alice", "stream_id": "windows", "field": "username", "status": "expected"}
|
||||
|
||||
Reference in New Issue
Block a user