"""Curated Windows event catalog: id -> human title and severity. Single server-side source of truth shared by the recent-events asset panel and the stability dashboard card, so a 4625 reads as "Failed logon (warning)" in both places without either restating the mapping. The set of IDs here MUST stay in step with CURATED_EVENT_IDS in plugin.py; a test asserts they match. Severity vocabulary matches the dashboard card renderer: 'critical', 'warning', 'info'. The IDs marked critical are the ones an operator/tech should act on without being asked - unexpected shutdown, crash, filesystem corruption, SCM timeout. Logon activity is informational history unless it is a failure. """ # id -> (title, severity, channel) EVENT_CATALOG = { 4624: ('Successful logon', 'info', 'Security'), 4625: ('Failed logon', 'warning', 'Security'), 4634: ('Logoff', 'info', 'Security'), 4672: ('Special privileges assigned', 'info', 'Security'), 4697: ('Service installed', 'warning', 'Security'), 4698: ('Scheduled task created', 'warning', 'Security'), 41: ('Unexpected shutdown', 'critical', 'System'), 4618: ('Monitored security event', 'warning', 'Security'), 55: ('File system corruption', 'critical', 'System'), 7011: ('Service timeout', 'critical', 'System'), 10016: ('DCOM permission error', 'warning', 'System'), # Windows Error Reporting trio on the Application channel. 1000 is the # faulting-application record (app name, version, faulting module, exception # code) and is the one that says what actually broke; 1001 is the WER bucket # record Windows writes alongside it; 1002 is a hang rather than a crash, so # it is a warning - the app is unresponsive, not gone. 1000: ('Application error', 'critical', 'Application'), 1001: ('Application crash', 'critical', 'Application'), 1002: ('Application hang', 'warning', 'Application'), } # The IDs a tech should see surfaced fleet-wide on the dashboard stability card. CRITICAL_EVENT_IDS = tuple( eventid for eventid, (_t, severity, _c) in EVENT_CATALOG.items() if severity == 'critical' ) def event_title(eventid): """Human title for a curated event id, or a generic fallback.""" entry = EVENT_CATALOG.get(eventid) return entry[0] if entry else 'Event {}'.format(eventid) def event_severity(eventid): """Severity ('critical'|'warning'|'info') for a curated event id.""" entry = EVENT_CATALOG.get(eventid) return entry[1] if entry else 'info'