@@ -136,128 +136,78 @@ def _render_html(**ctx: Any) -> str:
136136
137137
138138def _render_timeline_table (events : list [dict [str , Any ]], fmt : str ) -> str :
139+ """Render a timeline table in markdown format (HTML uses Jinja2)."""
139140 if not events :
140- return "No events recorded.\n " if fmt == "markdown" else "<p>No events recorded.</p>"
141-
142- lines : list [str ] = []
143- if fmt == "markdown" :
144- lines .append ("| # | Source | Severity | Event | Timestamp | Risk |" )
145- lines .append ("|---|---|---|---|---|---|" )
146- for i , ev in enumerate (events [:50 ], 1 ):
147- sev = ev .get ("severity" , "?" )
148- title = (ev .get ("title" ) or ev .get ("event_type" ) or "?" )[:60 ]
149- ts = ev .get ("timestamp" , "?" )[:19 ]
150- risk = f"{ float (ev .get ('risk_score' , 0 )):.1f} "
151- src = ev .get ("source" , "?" )
152- lines .append (f"| { i } | { src } | { sev } | { title } | { ts } | { risk } |" )
153- if len (events ) > 50 :
154- lines .append (f"| ... | *{ len (events ) - 50 } more events* | | | | |" )
155- else :
156- lines .append (
157- "<table><tr><th>#</th><th>Source</th><th>Severity</th><th>Event</th><th>Timestamp</th><th>Risk</th></tr>"
158- )
159- for i , ev in enumerate (events [:50 ], 1 ):
160- sev = ev .get ("severity" , "?" )
161- css = f" severity-{ sev } " if sev in ("critical" , "high" , "medium" , "low" ) else ""
162- title = (ev .get ("title" ) or ev .get ("event_type" ) or "?" )[:60 ]
163- ts = ev .get ("timestamp" , "?" )[:19 ]
164- risk = f"{ float (ev .get ('risk_score' , 0 )):.1f} "
165- src = ev .get ("source" , "?" )
166- lines .append (
167- f'<tr><td>{ i } </td><td>{ src } </td><td class="{ css .strip ()} ">{ sev } </td><td>{ title } </td><td>{ ts } </td><td>{ risk } </td></tr>'
168- )
169- if len (events ) > 50 :
170- lines .append (f"<tr><td colspan='6'><em>… { len (events ) - 50 } more events</em></td></tr>" )
171- lines .append ("</table>" )
141+ return "No events recorded.\n "
142+
143+ lines : list [str ] = [
144+ "| # | Source | Severity | Event | Timestamp | Risk |" ,
145+ "|---|---|---|---|---|---|" ,
146+ ]
147+ for i , ev in enumerate (events [:50 ], 1 ):
148+ title = (ev .get ("title" ) or ev .get ("event_type" ) or "?" )[:60 ]
149+ ts = ev .get ("timestamp" , "?" )[:19 ]
150+ risk = f"{ float (ev .get ('risk_score' , 0 )):.1f} "
151+ lines .append (f"| { i } | { ev .get ('source' , '?' )} | { ev .get ('severity' , '?' )} | { title } | { ts } | { risk } |" )
152+ if len (events ) > 50 :
153+ lines .append (f"| ... | *{ len (events ) - 50 } more events* | | | | |" )
172154 return "\n " .join (lines )
173155
174156
175157def _render_correlation_summary (groups : list [dict [str , Any ]], fmt : str ) -> str :
158+ """Render correlation summary in markdown format (HTML uses Jinja2)."""
176159 if not groups :
177- return "No correlated event groups.\n " if fmt == "markdown" else "<p>No correlated event groups.</p>"
178-
179- lines : list [str ] = []
180- if fmt == "markdown" :
181- lines .append (f"**{ len (groups )} correlated group(s) found**\n " )
182- for g in groups [:10 ]:
183- lines .append (
184- f"- Window: { g ['window_start' ][:19 ]} → { g ['window_end' ][:19 ]} | "
185- f"{ g ['event_count' ]} events | Risk: { g ['max_risk' ]:.1f} | "
186- f"Sources: { ', ' .join (g ['sources' ])} "
187- )
188- if len (groups ) > 10 :
189- lines .append (f"- … { len (groups ) - 10 } more groups" )
190- else :
191- lines .append (f"<p><strong>{ len (groups )} correlated group(s) found</strong></p><ul>" )
192- for g in groups [:10 ]:
193- lines .append (
194- f"<li>{ g ['window_start' ][:19 ]} → { g ['window_end' ][:19 ]} — "
195- f"{ g ['event_count' ]} events, risk { g ['max_risk' ]:.1f} "
196- f"({ ', ' .join (g ['sources' ])} )</li>"
197- )
198- if len (groups ) > 10 :
199- lines .append (f"<li>… { len (groups ) - 10 } more groups</li>" )
200- lines .append ("</ul>" )
160+ return "No correlated event groups.\n "
161+
162+ lines : list [str ] = [f"**{ len (groups )} correlated group(s) found**\n " ]
163+ for g in groups [:10 ]:
164+ lines .append (
165+ f"- Window: { g ['window_start' ][:19 ]} → { g ['window_end' ][:19 ]} | "
166+ f"{ g ['event_count' ]} events | Risk: { g ['max_risk' ]:.1f} | "
167+ f"Sources: { ', ' .join (g ['sources' ])} "
168+ )
169+ if len (groups ) > 10 :
170+ lines .append (f"- … { len (groups ) - 10 } more groups" )
201171 return "\n " .join (lines )
202172
203173
204174def _render_deviations (deviations : list [dict [str , Any ]], fmt : str ) -> str :
175+ """Render deviations in markdown format (HTML uses Jinja2)."""
205176 if not deviations :
206- return "No policy deviations detected.\n " if fmt == "markdown" else "<p>No policy deviations detected.</p>"
207-
208- lines : list [str ] = []
209- if fmt == "markdown" :
210- lines .append (f"**{ len (deviations )} deviation(s) found**\n " )
211- for d in deviations :
212- lines .append (f"- **[{ d ['type' ]} ]** { d ['description' ]} " )
213- else :
214- lines .append (f"<p><strong>{ len (deviations )} deviation(s) found</strong></p>" )
215- for d in deviations :
216- lines .append (f'<div class="deviation"><strong>[{ d ["type" ]} ]</strong> { d ["description" ]} </div>' )
177+ return "No policy deviations detected.\n "
178+
179+ lines : list [str ] = [f"**{ len (deviations )} deviation(s) found**\n " ]
180+ for d in deviations :
181+ lines .append (f"- **[{ d ['type' ]} ]** { d ['description' ]} " )
217182 return "\n " .join (lines )
218183
219184
220185def _render_anomalies (anomalies : list [dict [str , Any ]], fmt : str ) -> str :
186+ """Render anomalies in markdown format (HTML uses Jinja2)."""
221187 if not anomalies :
222- return "No anomalies detected.\n " if fmt == "markdown" else "<p>No anomalies detected.</p>"
223-
224- lines : list [str ] = []
225- if fmt == "markdown" :
226- lines .append (f"**{ len (anomalies )} anomaly(ies) found**\n " )
227- for a in anomalies :
228- sev = a .get ("severity" , "?" )
229- score = f" (score: { a .get ('score' , 0 ):.1f} )"
230- lines .append (f"- **[severity: { sev } ]{ score } ** { a ['description' ]} " )
231- else :
232- lines .append (f"<p><strong>{ len (anomalies )} anomaly(ies) found</strong></p>" )
233- for a in anomalies :
234- sev = a .get ("severity" , "?" )
235- lines .append (f'<div class="anomaly"><strong>[{ sev } ]</strong> { a ["description" ]} </div>' )
188+ return "No anomalies detected.\n "
189+
190+ lines : list [str ] = [f"**{ len (anomalies )} anomaly(ies) found**\n " ]
191+ for a in anomalies :
192+ sev = a .get ("severity" , "?" )
193+ score = f" (score: { a .get ('score' , 0 ):.1f} )"
194+ lines .append (f"- **[severity: { sev } ]{ score } ** { a ['description' ]} " )
236195 return "\n " .join (lines )
237196
238197
239198def _render_evidence (evidence_chain : list [dict [str , Any ]], fmt : str ) -> str :
199+ """Render evidence in markdown format (HTML uses Jinja2)."""
240200 if not evidence_chain :
241- return "No evidence collected.\n " if fmt == "markdown" else "<p>No evidence collected.</p>"
242-
243- lines : list [str ] = []
244- if fmt == "markdown" :
245- lines .append (f"**{ len (evidence_chain )} evidence entries**\n " )
246- lines .append ("| ID | Hash | Collector | Timestamp |" )
247- lines .append ("|---|---|---|---|" )
248- for e in evidence_chain :
249- h = e .get ("hash" , "?" )[:16 ]
250- lines .append (
251- f"| { e .get ('evidence_id' , '?' )} | { h } … | { e .get ('collector' , '?' )} | { e .get ('timestamp' , '?' )[:19 ]} |"
252- )
253- else :
254- lines .append (f"<p><strong>{ len (evidence_chain )} evidence entries</strong></p><table>" )
255- lines .append ("<tr><th>ID</th><th>Hash</th><th>Collector</th><th>Timestamp</th></tr>" )
256- for e in evidence_chain :
257- h = e .get ("hash" , "?" )[:16 ]
258- lines .append (
259- f"<tr><td>{ e .get ('evidence_id' , '?' )} </td><td>{ h } …</td><td>{ e .get ('collector' , '?' )} </td>"
260- f"<td>{ e .get ('timestamp' , '?' )[:19 ]} </td></tr>"
261- )
262- lines .append ("</table>" )
201+ return "No evidence collected.\n "
202+
203+ lines : list [str ] = [
204+ f"**{ len (evidence_chain )} evidence entries**\n " ,
205+ "| ID | Hash | Collector | Timestamp |" ,
206+ "|---|---|---|---|" ,
207+ ]
208+ for e in evidence_chain :
209+ h = e .get ("hash" , "?" )[:16 ]
210+ lines .append (
211+ f"| { e .get ('evidence_id' , '?' )} | { h } … | { e .get ('collector' , '?' )} | { e .get ('timestamp' , '?' )[:19 ]} |"
212+ )
263213 return "\n " .join (lines )
0 commit comments