Pool baseline state across streams sharing an entity concept
Completes the last deferred item from ROADMAP §0: entities recognized as the same real-world concept across enabled streams (e.g. srcip in both a firewall and an IIS stream) now share baseline knowledge of entity presence/age and known relationship-target values, instead of each stream learning it cold. Implemented additively (synthetic shared_entity:<group> namespace in the existing baseline.py tables, no schema migration), scoped to entity presence + relationship known-values only — per-stream distribution baselines stay untouched. Also fixes a latent alias-map collision bug found while building this (ALIAS_CANONICAL_BY_FIELD let "context" silently steal "hostname"/"dns_query" from their own canonical groups). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import unittest
|
||||
|
||||
from fgai.logs import parse_log_line
|
||||
from fgai.profile_suggestions import apply_profile_advice, detect_shape_mismatches, suggest_stream_profiles
|
||||
from fgai.profile_suggestions import ALIAS_CANONICAL_BY_FIELD, apply_profile_advice, detect_shape_mismatches, shared_entity_pools, suggest_stream_profiles
|
||||
from fgai.stream_profiles import RelationshipField, StreamProfile
|
||||
|
||||
|
||||
@@ -456,6 +456,37 @@ class ProfileSuggestionTests(unittest.TestCase):
|
||||
self.assertIn("srcip", suggestion["field_shapes"])
|
||||
self.assertEqual(suggestion["field_shapes"]["srcip"], "ip")
|
||||
|
||||
def test_alias_canonical_map_prefers_specific_group_over_context_fallback(self):
|
||||
self.assertEqual(ALIAS_CANONICAL_BY_FIELD["hostname"], "hostname")
|
||||
self.assertEqual(ALIAS_CANONICAL_BY_FIELD["dns_query"], "dns_query")
|
||||
self.assertEqual(ALIAS_CANONICAL_BY_FIELD["query_domain"], "dns_query")
|
||||
self.assertEqual(ALIAS_CANONICAL_BY_FIELD["qh"], "dns_query")
|
||||
|
||||
def test_shared_entity_pools_groups_streams_with_the_same_entity_concept(self):
|
||||
stream_profiles = {
|
||||
"firewall": StreamProfile(stream_id="firewall", name="Firewall", entity_field="srcip", timestamp_field="timestamp", entity_fields=("srcip",)),
|
||||
"iis": StreamProfile(stream_id="iis", name="IIS", entity_field="client_ip", timestamp_field="timestamp", entity_fields=("client_ip",)),
|
||||
"billing": StreamProfile(stream_id="billing", name="Billing", entity_field="actor_id", timestamp_field="timestamp", entity_fields=("actor_id",)),
|
||||
}
|
||||
|
||||
pools = shared_entity_pools(stream_profiles)
|
||||
|
||||
self.assertEqual(pools["firewall"]["srcip"], pools["iis"]["client_ip"])
|
||||
self.assertTrue(pools["firewall"]["srcip"].startswith("shared_entity:"))
|
||||
self.assertNotIn("billing", pools)
|
||||
|
||||
def test_shared_entity_pools_keeps_source_and_destination_ip_separate(self):
|
||||
stream_profiles = {
|
||||
"firewall": StreamProfile(stream_id="firewall", name="Firewall", entity_field="srcip", timestamp_field="timestamp", entity_fields=("srcip", "dstip")),
|
||||
"proxy": StreamProfile(stream_id="proxy", name="Proxy", entity_field="client_ip", timestamp_field="timestamp", entity_fields=("client_ip", "server_ip")),
|
||||
}
|
||||
|
||||
pools = shared_entity_pools(stream_profiles)
|
||||
|
||||
self.assertEqual(pools["firewall"]["srcip"], pools["proxy"]["client_ip"])
|
||||
self.assertEqual(pools["firewall"]["dstip"], pools["proxy"]["server_ip"])
|
||||
self.assertNotEqual(pools["firewall"]["srcip"], pools["firewall"]["dstip"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user