feat(reports): add quarterly and technique HTML templates [FASE-2.2]

Introduce quarterly_summary and technique_detail Jinja layouts; use SVG logo asset across report covers.
This commit is contained in:
2026-05-18 14:00:40 +02:00
parent c28a47c43b
commit 96fdd9fa85
5 changed files with 137 additions and 3 deletions

View File

@@ -7,7 +7,7 @@
</head>
<body>
<section class="cover-page">
<img src="assets/logo.png" class="logo" alt="Logo">
<img src="assets/logo.svg" class="logo" alt="Logo">
<h1>MITRE ATT&amp;CK Coverage Report</h1>
<h2>{{ company_name }}</h2>
<p class="date">{{ generated_at }}</p>

View File

@@ -7,7 +7,7 @@
</head>
<body>
<section class="cover-page">
<img src="assets/logo.png" class="logo" alt="Logo">
<img src="assets/logo.svg" class="logo" alt="Logo">
<h1>Executive Security Summary</h1>
<h2>{{ company_name }}</h2>
<p class="date">{{ generated_at }}</p>

View File

@@ -7,7 +7,7 @@
</head>
<body>
<section class="cover-page">
<img src="assets/logo.png" class="logo" alt="Logo">
<img src="assets/logo.svg" class="logo" alt="Logo">
<h1>Purple Team Assessment Report</h1>
<h2>{{ campaign.name }}</h2>
<p class="date">{{ generated_at }}</p>

View File

@@ -0,0 +1,72 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="styles/report.css">
<title>Quarterly Summary — {{ company_name }}</title>
</head>
<body>
<section class="cover-page">
<img src="assets/logo.svg" class="logo" alt="Logo">
<h1>Quarterly Security Summary</h1>
<h2>{{ quarter_label }}</h2>
<p class="date">{{ generated_at }}</p>
<p class="classification">{{ classification | default('INTERNAL') }}</p>
</section>
<section>
<h2>1. Quarter Overview</h2>
<div class="stats-grid">
<div class="stat">
<span class="number">{{ tests_this_quarter }}</span>
<span class="label">Tests Executed</span>
</div>
<div class="stat">
<span class="number">{{ org_score.overall | default(0) }}%</span>
<span class="label">Org Score</span>
</div>
<div class="stat">
<span class="number">{{ detection_rate }}%</span>
<span class="label">Detection Rate</span>
</div>
</div>
</section>
<section>
<h2>2. Coverage Trend</h2>
<table class="data-table">
<thead>
<tr>
<th>Date</th>
<th>Validated</th>
<th>Total Techniques</th>
<th>Org Score</th>
</tr>
</thead>
<tbody>
{% for row in trend_rows %}
<tr>
<td>{{ row.date }}</td>
<td>{{ row.validated_count }}</td>
<td>{{ row.total_techniques }}</td>
<td>{{ row.organization_score }}%</td>
</tr>
{% endfor %}
</tbody>
</table>
</section>
<section>
<h2>3. Top Gaps</h2>
<ul>
{% for gap in top_gaps %}
<li><strong>{{ gap.tactic }}</strong>: {{ gap.coverage_pct }}% coverage</li>
{% endfor %}
</ul>
</section>
<footer>
<p>{{ company_name }} — Confidential</p>
</footer>
</body>
</html>

View File

@@ -0,0 +1,62 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="styles/report.css">
<title>Technique Detail — {{ technique.mitre_id }}</title>
</head>
<body>
<section class="cover-page">
<img src="assets/logo.svg" class="logo" alt="Logo">
<h1>Technique Assessment</h1>
<h2>{{ technique.mitre_id }} — {{ technique.name }}</h2>
<p class="date">{{ generated_at }}</p>
</section>
<section>
<h2>1. Technique Profile</h2>
<table class="data-table">
<tbody>
<tr><th>MITRE ID</th><td>{{ technique.mitre_id }}</td></tr>
<tr><th>Name</th><td>{{ technique.name }}</td></tr>
<tr><th>Tactic</th><td>{{ technique.tactic or 'N/A' }}</td></tr>
<tr><th>Status</th><td>{{ technique_status }}</td></tr>
<tr><th>Review required</th><td>{{ 'Yes' if technique.review_required else 'No' }}</td></tr>
</tbody>
</table>
{% if technique.description %}
<p>{{ technique.description }}</p>
{% endif %}
</section>
<section>
<h2>2. Test History</h2>
<table class="data-table">
<thead>
<tr>
<th>Test</th>
<th>State</th>
<th>Detection</th>
<th>Created</th>
</tr>
</thead>
<tbody>
{% for test in tests %}
<tr class="result-{{ test.detection_result }}">
<td>{{ test.name }}</td>
<td>{{ test.state }}</td>
<td>{{ test.detection_result }}</td>
<td>{{ test.created_at }}</td>
</tr>
{% else %}
<tr><td colspan="4">No tests recorded for this technique.</td></tr>
{% endfor %}
</tbody>
</table>
</section>
<footer>
<p>{{ company_name }} — Confidential</p>
</footer>
</body>
</html>