You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The generation engine uses a **canonical event model** -- an intermediate representation layer between activity generation and log rendering. Instead of ActivityGenerator calling each emitter separately with manually-coordinated fields, it builds a single `SecurityEvent` object that carries all shared metadata. An `EventDispatcher` routes the event to StateManager and to matching emitters.
571
+
572
+
**Core principle: consistency by construction, not by coordination.** Two emitters cannot disagree about a port number because there is only one port number -- on the event object.
573
+
574
+
**Two-phase build + dispatch pattern:**
575
+
576
+
```python
577
+
def generate_logon(self, user, system, time, logon_type=2, source_ip=None):
- `EventDispatcher`-- Routes events to `StateManager.apply()` + matching emitters, with network visibility filtering via `NetworkVisibilityEngine.get_log_formats_for_connection()`
599
+
600
+
**Event model rules:**
601
+
- ActivityGenerator builds `SecurityEvent` objects; it never calls emitter methods directly
602
+
- IDs (logon_id, pid, zeek_uid) are allocated by StateManager *before* building the SecurityEvent (two-phase build)
603
+
- `StateManager.apply()`records state from a fully-constructed event; it does not allocate IDs
604
+
- Each emitter declares `_supported_types` and implements `can_handle(event)` for self-selection
605
+
- `RawLogEntry`is the escape hatch for simple, single-format log entries -- use sparingly
606
+
- Events are transient -- they are GC'd after dispatch; StateManager owns durable state
607
+
- Full design details in `docs/event-model-prd.md`
608
+
562
609
### LLM Client Abstraction (Future)
563
610
564
611
The LLM client abstraction is planned for future built-in LLM integration. Currently, scenario creation is handled by Claude Code Skills (external to the codebase). The patterns below are kept as reference for when the `llm/` module is implemented.
@@ -792,7 +839,8 @@ class StateManager:
792
839
**State rules:**
793
840
- StateManager is the ONLY place to track sessions, processes, connections
794
841
- Emitters READ state (to get LogonIDs, PIDs for events)
795
-
- Orchestrator WRITES state (creates sessions/processes as scenario executes)
842
+
- ActivityGenerator WRITES state (allocates IDs via `create_session()`, `create_process()`, `open_connection()` before building SecurityEvents)
843
+
- `apply(event)`records state from a fully-constructed `SecurityEvent` — handles teardown (logoff, process termination) and updates (connection bytes). Does NOT allocate IDs.
796
844
- No automatic cleanup (realistic incompleteness is acceptable per PRD)
797
845
- Thread-safe for reads, single-threaded for writes
798
846
@@ -802,87 +850,51 @@ All log format emitters inherit from `LogEmitter` ABC:
0 commit comments