codeflash-agent/reports/unstructured/security_report.py
Kevin Turcios 3ee9c22c8e
fix: resolve all ruff lint errors across repo (#38)
* fix: resolve all ruff lint errors across repo

Auto-fixed 31 errors (unused imports, formatting, simplifications).
Manually fixed 14 remaining:
- EXE001: removed shebangs from non-executable bench scripts
- C417: replaced map(lambda) with generator expression
- C901/PLR0915: extracted _write_and_instrument_tests from generate_ai_tests
- C901/PLR0912: extracted _parse_toml_addopts and _ini_section_name from modify_addopts
- RUF001/RUF002: replaced ambiguous Unicode chars (en dash, multiplication sign)
- FBT002: made boolean params keyword-only in report functions
- E402: moved `import re` to top of file in security reports

* fix: resolve pre-existing mypy errors across packages

- _testgen.py: annotate `generated` as `str` to avoid no-any-return
- _test_runner.py: use str() for TimeoutExpired stdout/stderr (bytes|str),
  remove unused type: ignore on proc.kill()
- _candidate_eval.py: annotate `speedup` as `float` to avoid no-any-return
  from lazy-loaded performance_gain
2026-04-23 10:22:42 -05:00

1183 lines
41 KiB
Python

"""Unstructured x Codeflash — Security Audit Report
Four-tab standalone report covering supply chain and build pipeline security
findings identified during the performance engagement:
1. Summary — hero metrics, executive summary, audit scope, CTA
2. Critical & High — the 21 most urgent findings
3. Medium & Low — 18 remaining findings
4. By Category — category breakdown with horizontal bars
"""
import json
import re
from pathlib import Path
from dash import Dash, Input, Output, clientside_callback, html
from theme import (
ACCENT,
AMBER,
BG,
BLUE,
CARD,
CARD_BG,
CARD_BORDER,
FONT,
GRAY,
GREEN,
LIGHT_GRAY,
LIGHT_RED,
MONO,
RED,
SLATE,
WHITE,
)
# ── Data ────────────────────────────────────────────────────────────────────
_DATA = json.loads((Path(__file__).parent / "security_data.json").read_text())
FINDINGS = _DATA["findings"]
SUMMARY = _DATA["summary"]
AUDIT_META = _DATA.get("audit_metadata", {})
CORE_PRODUCT_BASE = _DATA["core_product_base"]
GITHUB_WORKFLOWS_BASE = _DATA["github_workflows_base"]
SEVERITY_COLORS = {
"critical": RED,
"high": "#f97316", # orange
"medium": AMBER,
"low": BLUE,
"info": GRAY,
}
SEVERITY_BG = {
"critical": LIGHT_RED,
"high": "rgba(249,115,22,0.12)",
"medium": "rgba(251,191,36,0.12)",
"low": "rgba(96,165,250,0.12)",
"info": "rgba(161,161,170,0.12)",
}
STATUS_COLORS = {
"fixed": "#34d399", # emerald-400 (distinct from severity green)
"partially-fixed": "#c084fc", # purple-400 (avoids orange/amber overlap)
"open": "#f87171", # red-400 (open = still a problem)
"active": "#22d3ee", # cyan-400 (distinct from severity blue)
}
_TAB_BTN_STYLE = {
"padding": "10px 24px",
"border": "none",
"borderRadius": "8px",
"cursor": "pointer",
"fontSize": "14px",
"fontWeight": "600",
"fontFamily": f"'{FONT}', system-ui, -apple-system, sans-serif",
"background": "transparent",
"color": GRAY,
"transition": "all 0.2s",
}
_TAB_BTN_ACTIVE = {**_TAB_BTN_STYLE, "background": RED, "color": WHITE}
# ── Helpers ──────────────────────────────────────────────────────────────────
def section(title, subtitle=None):
children = [
html.H2(
title,
style={
"fontSize": "22px",
"fontWeight": "700",
"color": SLATE,
"margin": "0",
"fontFamily": FONT,
"letterSpacing": "-0.01em",
},
)
]
if subtitle:
children.append(
html.P(
subtitle,
style={
"fontSize": "14px",
"color": GRAY,
"margin": "6px 0 0",
"lineHeight": "1.5",
},
)
)
return html.Div(children, style={"margin": "56px 0 24px"})
def card(children, **kw):
style = {**CARD}
for k, v in kw.items():
style[k] = v
return html.Div(children, style=style)
SEVERITY_ICONS = {
"critical": "\u25cf", # filled circle
"high": "\u25b2", # filled triangle
"medium": "\u25c6", # filled diamond
"low": "\u25cb", # open circle
"info": "\u2139", # info symbol
}
def severity_badge(severity):
icon = SEVERITY_ICONS.get(severity, "")
return html.Span(
[
html.Span(
icon,
style={"marginRight": "5px", "fontSize": "9px"},
),
severity.upper(),
],
style={
"fontSize": "11px",
"fontWeight": "700",
"color": SEVERITY_COLORS.get(severity, GRAY),
"background": SEVERITY_BG.get(severity, "transparent"),
"padding": "3px 10px",
"borderRadius": "999px",
"letterSpacing": "0.05em",
"display": "inline-flex",
"alignItems": "center",
},
)
def status_badge(status):
return html.Span(
status.upper(),
style={
"fontSize": "11px",
"fontWeight": "700",
"color": STATUS_COLORS.get(status, GRAY),
"background": "transparent",
"border": f"1px solid {STATUS_COLORS.get(status, GRAY)}",
"padding": "2px 10px",
"borderRadius": "999px",
"letterSpacing": "0.05em",
},
)
_REPO_URLS = {
"core-product": "https://github.com/Unstructured-IO/core-product/pull",
"github-workflows": "https://github.com/Unstructured-IO/github-workflows/pull",
"platform-libs": "https://github.com/Unstructured-IO/platform-libs/pull",
"unstructured": "https://github.com/Unstructured-IO/unstructured/pull",
"unstructured-inference": "https://github.com/Unstructured-IO/unstructured-inference/pull",
}
def _linkify_fixed_by(text, repo):
"""Turn 'Unstructured (PR #1465)' into text with clickable PR links."""
# Find all #NNNN references
parts = re.split(r"(#\d+)", text)
result = []
for part in parts:
m = re.match(r"#(\d+)", part)
if m:
pr_num = m.group(1)
# Determine base URL from repo field
base = None
for key, url in _REPO_URLS.items():
if key in repo:
base = url
break
if base:
result.append(
html.A(
part,
href=f"{base}/{pr_num}",
target="_blank",
rel="noopener noreferrer",
style={
"color": GREEN,
"fontWeight": "600",
"textDecoration": "underline",
"cursor": "pointer",
},
)
)
else:
result.append(
html.Span(
part, style={"color": GREEN, "fontWeight": "600"}
)
)
else:
result.append(
html.Span(part, style={"color": GREEN, "fontWeight": "600"})
)
return result
def _hero_metric(value, label, color):
return html.Div(
[
html.Div(
value,
style={
"fontSize": "42px",
"fontWeight": "800",
"color": color,
"lineHeight": "1",
},
),
html.Div(
label,
style={
"fontSize": "14px",
"fontWeight": "600",
"color": SLATE,
"marginTop": "8px",
},
),
],
style={
"background": CARD_BG,
"borderRadius": "16px",
"padding": "32px 20px",
"textAlign": "center",
"flex": "1",
"minWidth": "140px",
"border": f"1px solid {CARD_BORDER}",
},
)
def _scope_card(value, label, detail):
return html.Div(
[
html.Div(
value,
style={
"fontSize": "28px",
"fontWeight": "800",
"color": ACCENT,
"lineHeight": "1",
},
),
html.Div(
label,
style={
"fontSize": "14px",
"fontWeight": "700",
"color": SLATE,
"marginTop": "8px",
},
),
html.Div(
detail,
style={
"fontSize": "12px",
"color": GRAY,
"marginTop": "4px",
},
),
],
style={
"background": CARD_BG,
"borderRadius": "12px",
"padding": "24px 20px",
"textAlign": "center",
"flex": "1",
"minWidth": "180px",
"border": f"1px solid {CARD_BORDER}",
},
)
def _category_row(category, count, total):
pct = count / total * 100 if total else 0
return html.Div(
[
html.Div(
category,
style={
"fontSize": "14px",
"color": SLATE,
"fontWeight": "600",
"minWidth": "180px",
},
),
html.Div(
style={
"flex": "1",
"height": "8px",
"background": "rgba(255,255,255,0.05)",
"borderRadius": "4px",
"overflow": "hidden",
},
children=[
html.Div(
style={
"width": f"{pct}%",
"height": "100%",
"background": ACCENT,
"borderRadius": "4px",
},
),
],
),
html.Div(
str(count),
style={
"fontSize": "14px",
"fontWeight": "700",
"color": SLATE,
"minWidth": "30px",
"textAlign": "right",
},
),
],
style={
"display": "flex",
"alignItems": "center",
"gap": "16px",
"marginBottom": "12px",
},
)
def finding_card(f):
"""Render a single finding as a card."""
sev = f["severity"]
border_color = SEVERITY_COLORS.get(sev, GRAY)
# Header: title first (F-pattern), ID secondary, badges right
header = html.Div(
[
html.Div(
[
html.Div(
f["title"],
style={
"fontWeight": "700",
"color": SLATE,
"fontSize": "17px",
"lineHeight": "1.3",
},
),
html.Span(
f["id"],
style={
"fontFamily": MONO,
"fontSize": "12px",
"color": LIGHT_GRAY,
"marginTop": "4px",
"display": "block",
},
),
],
style={"flex": "1"},
),
html.Div(
[
severity_badge(sev),
status_badge(f["status"]),
],
style={
"display": "flex",
"gap": "8px",
"alignItems": "center",
},
),
],
style={
"display": "flex",
"alignItems": "flex-start",
"gap": "16px",
"marginBottom": "16px",
"flexWrap": "wrap",
},
)
# Metadata row
meta_items = []
if f.get("repo"):
meta_items.append(
html.Span(
[
html.Span("Repo: ", style={"color": LIGHT_GRAY}),
html.Span(
f["repo"],
style={"color": SLATE, "fontWeight": "600"},
),
],
)
)
if f.get("category"):
meta_items.append(
html.Span(
[
html.Span("Category: ", style={"color": LIGHT_GRAY}),
html.Span(
f["category"],
style={"color": SLATE, "fontWeight": "600"},
),
],
)
)
if f.get("duration_exposed"):
meta_items.append(
html.Span(
[
html.Span("Exposed: ", style={"color": LIGHT_GRAY}),
html.Span(
f["duration_exposed"],
style={"color": RED, "fontWeight": "600"},
),
],
)
)
if f.get("fixed_by"):
meta_items.append(
html.Div(
[
html.Span("Fixed by: ", style={"color": LIGHT_GRAY}),
*_linkify_fixed_by(f["fixed_by"], f.get("repo", "")),
],
style={"display": "inline"},
)
)
meta = html.Div(
meta_items,
style={
"display": "flex",
"gap": "24px",
"flexWrap": "wrap",
"fontSize": "13px",
"marginBottom": "16px",
"paddingBottom": "16px",
"borderBottom": f"1px solid {CARD_BORDER}",
},
)
# Description
desc = html.P(
f["description"],
style={
"color": GRAY,
"fontSize": "14px",
"lineHeight": "1.7",
"margin": "0 0 16px",
},
)
# Impact list
impact = html.Div(
[
html.Div(
"Impact",
style={
"fontSize": "12px",
"fontWeight": "700",
"color": ACCENT,
"textTransform": "uppercase",
"letterSpacing": "0.05em",
"marginBottom": "8px",
},
),
html.Ul(
[
html.Li(
i,
style={
"fontSize": "13px",
"color": GRAY,
"lineHeight": "1.6",
"marginBottom": "4px",
},
)
for i in f["impact"]
],
style={
"paddingLeft": "20px",
"margin": "0",
},
),
],
style={"marginBottom": "16px"},
)
children = [header, meta, desc, impact]
# Files affected
if f.get("files"):
files_section = html.Div(
[
html.Div(
"Affected Files",
style={
"fontSize": "12px",
"fontWeight": "700",
"color": ACCENT,
"textTransform": "uppercase",
"letterSpacing": "0.05em",
"marginBottom": "8px",
},
),
html.Div(
[
html.Div(
path,
style={
"fontFamily": MONO,
"fontSize": "12px",
"color": LIGHT_GRAY,
"padding": "4px 0",
},
)
for path in (
f["files"]
if isinstance(f["files"], list)
else [f["files"]]
)
],
),
],
style={"marginBottom": "16px"},
)
children.append(files_section)
# Context
if f.get("context"):
children.append(
html.P(
f["context"],
style={
"color": LIGHT_GRAY,
"fontSize": "13px",
"lineHeight": "1.6",
"margin": "0",
"fontStyle": "italic",
},
)
)
return html.Div(
children,
style={
**CARD,
"marginBottom": "20px",
"borderLeft": f"4px solid {border_color}",
},
)
# ── Findings split by severity ──────────────────────────────────────────────
# Order categories by what matters most to the audience: supply chain and
# container security work they're already doing, then CI/CD, secrets, code.
_CATEGORY_PRIORITY = {
"Supply Chain": 0,
"Docker/Container Security": 1,
"CI/CD Security": 2,
"Secrets Management": 3,
"Code-Level Vulnerability": 4,
"PKI/Cryptography": 5,
"Vulnerability Management": 6,
"Build Reproducibility": 7,
"Build Pipeline": 8,
"Positive Control": 9,
}
_SEV_PRIORITY = {"critical": 0, "high": 1, "medium": 2, "low": 3, "info": 4}
def _finding_sort_key(f):
return (
_SEV_PRIORITY.get(f["severity"], 9),
_CATEGORY_PRIORITY.get(f["category"], 9),
)
_CRITICAL_HIGH = sorted(
[f for f in FINDINGS if f["severity"] in ("critical", "high")],
key=_finding_sort_key,
)
_MEDIUM_LOW = sorted(
[f for f in FINDINGS if f["severity"] not in ("critical", "high")],
key=_finding_sort_key,
)
# ── Tab content builders ────────────────────────────────────────────────────
def _build_summary_tab():
"""Tab 1: hero metrics, executive summary, scope cards, CTA."""
return html.Div(
id="summary-view",
children=[
# ── Executive Summary ──
section("Executive Summary"),
card(
[
html.P(
[
"We audited all ",
html.Span(
"8 Unstructured repositories",
style={"fontWeight": "700", "color": SLATE},
),
f" end-to-end: {AUDIT_META.get('workflow_files_audited', 69)} CI/CD workflows, "
f"{AUDIT_META.get('dockerfiles_audited', 6)} Dockerfiles, "
f"and {AUDIT_META.get('action_references_audited', 446)} GitHub Action references. "
"The scope covers the same layers you're already hardening \u2014 "
"supply chain integrity, container security, CI/CD pipeline permissions, "
"and dependency management \u2014 plus code-level vulnerabilities, "
"secrets handling, and PKI.",
],
style={
"color": GRAY,
"fontSize": "15px",
"lineHeight": "1.7",
"margin": "0 0 16px",
},
),
html.P(
[
"We found ",
html.Span(
f"{SUMMARY['total_findings']} findings",
style={"fontWeight": "700", "color": SLATE},
),
" including ",
html.Span(
f"{SUMMARY['critical']} critical",
style={"fontWeight": "700", "color": RED},
),
" and ",
html.Span(
f"{SUMMARY['high']} high",
style={
"fontWeight": "700",
"color": "#f97316",
},
),
" severity issues. The lockfile-bypass pattern you fixed in core-product "
"(PR #1465) still persists in CI steps and Makefiles across the org. "
"Supply chain, container, and CI/CD injection issues account for the "
"majority \u2014 the same categories where Renovate and Anchore give you "
"visibility but not full coverage.",
],
style={
"color": GRAY,
"fontSize": "15px",
"lineHeight": "1.7",
"margin": "0 0 16px",
},
),
html.P(
[
"For a platform processing sensitive documents across regulated industries "
"(HIPAA, SOC 2, PCI-DSS), these gaps are material \u2014 especially ahead "
"of the next NCC Group assessment cycle.",
],
style={
"color": GRAY,
"fontSize": "15px",
"lineHeight": "1.7",
"margin": "0",
},
),
]
),
# ── Audit scope ──
section("Audit Scope"),
html.Div(
style={
"display": "flex",
"gap": "16px",
"flexWrap": "wrap",
"marginBottom": "24px",
},
children=[
_scope_card(
"69",
"CI/CD Workflows",
"Injection, permissions, secrets, runners",
),
_scope_card(
"6",
"Dockerfiles",
"Root containers, base images, layer leaks",
),
_scope_card(
"446",
"Action References",
"SHA pinning, supply chain, third-party risk",
),
_scope_card(
"8",
"Repositories",
"Code, config, infrastructure, PKI",
),
],
),
# ── CTA ──
html.Div(
style={
"marginTop": "56px",
"textAlign": "center",
"padding": "56px 32px",
"background": f"linear-gradient(135deg, rgba(239,68,68,0.06) 0%, {CARD_BG} 40%, {CARD_BG} 60%, rgba(239,68,68,0.06) 100%)",
"borderRadius": "16px",
"border": f"1px solid {CARD_BORDER}",
},
children=[
# Loss-framed percentage anchor (Change #4)
html.Div(
f"{round(SUMMARY['open'] / SUMMARY['total_findings'] * 100)}%",
style={
"fontSize": "72px",
"fontWeight": "800",
"color": RED,
"lineHeight": "1",
},
),
html.Div(
"of findings remain unresolved",
style={
"fontSize": "20px",
"fontWeight": "600",
"color": SLATE,
"marginTop": "8px",
},
),
html.Div(
f"{SUMMARY['open']} of {SUMMARY['total_findings']} security issues across {len(SUMMARY.get('by_repo', {}))} repositories",
style={
"fontSize": "14px",
"fontFamily": MONO,
"color": LIGHT_GRAY,
"marginTop": "8px",
},
),
# Urgency line (loss framing)
html.P(
"These span supply chain, CI/CD injection, container, and secrets management "
"\u2014 the same categories where one engineer can't cover everything alone.",
style={
"color": GRAY,
"fontSize": "15px",
"lineHeight": "1.7",
"margin": "24px auto 0",
"maxWidth": "560px",
},
),
],
),
],
)
def _build_critical_high_tab():
"""Tab 2: critical and high severity findings."""
n = len(_CRITICAL_HIGH)
return html.Div(
id="critical-high-view",
style={"display": "none"},
children=[
section(
"Critical & High Findings",
f"{n} findings \u2014 supply chain, container, CI/CD, and secrets",
),
*[finding_card(f) for f in _CRITICAL_HIGH],
],
)
def _build_medium_low_tab():
"""Tab 3: medium, low, and info severity findings."""
n = len(_MEDIUM_LOW)
return html.Div(
id="medium-low-view",
style={"display": "none"},
children=[
section(
"Medium & Low Findings",
f"{n} findings for planned remediation",
),
*[finding_card(f) for f in _MEDIUM_LOW],
],
)
def _build_category_tab():
"""Tab 4: findings breakdown by category with horizontal bars."""
return html.Div(
id="category-view",
style={"display": "none"},
children=[
section("Findings by Category"),
card(
[
_category_row(cat, cnt, SUMMARY["total_findings"])
for cat, cnt in sorted(
SUMMARY.get("by_category", {}).items(),
key=lambda x: x[1],
reverse=True,
)
],
padding="28px",
),
# ── By repo breakdown ──
section("Findings by Repository"),
card(
[
_category_row(repo, cnt, SUMMARY["total_findings"])
for repo, cnt in sorted(
SUMMARY.get("by_repo", {}).items(),
key=lambda x: x[1],
reverse=True,
)
],
padding="28px",
),
],
)
# ── App ──────────────────────────────────────────────────────────────────────
app = Dash(
__name__,
meta_tags=[
{"name": "viewport", "content": "width=device-width, initial-scale=1"},
{
"property": "og:title",
"content": "Unstructured x Codeflash \u2014 Security Audit",
},
],
suppress_callback_exceptions=True,
)
app.title = "Unstructured x Codeflash \u2014 Security Audit"
app.index_string = """<!DOCTYPE html>
<html>
<head>
{%metas%}
<title>{%title%}</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700;800&family=JetBrains+Mono:wght@400;600;700&display=swap" rel="stylesheet">
{%favicon%}
{%css%}
</head>
<body>
{%app_entry%}
<footer>
{%config%}
{%scripts%}
{%renderer%}
</footer>
</body>
</html>"""
app.layout = html.Div(
style={
"background": BG,
"minHeight": "100vh",
"fontFamily": FONT,
"position": "relative",
},
children=[
# ── Hero ──
html.Div(
style={
"background": f"linear-gradient(135deg, {BG} 0%, #131a24 50%, {BG} 100%)",
"padding": "60px 24px 52px",
"textAlign": "center",
"borderBottom": f"1px solid {CARD_BORDER}",
"position": "relative",
"zIndex": "1",
},
children=[
html.Div(
style={
"display": "flex",
"alignItems": "center",
"justifyContent": "center",
"gap": "20px",
"marginBottom": "24px",
},
children=[
html.Img(
src="/assets/codeflash.svg",
style={"height": "32px"},
),
html.Span(
"\u00d7",
style={
"fontSize": "24px",
"fontWeight": "300",
"color": LIGHT_GRAY,
},
),
html.Img(
src="/assets/unstructured_logo.jpg",
style={
"height": "36px",
"borderRadius": "6px",
},
),
],
),
html.H1(
"Security Audit",
style={
"color": WHITE,
"fontSize": "36px",
"fontWeight": "800",
"margin": "0",
"letterSpacing": "-0.02em",
"fontFamily": FONT,
},
),
html.P(
"Comprehensive security audit across 8 repositories \u2014 supply chain, CI/CD, "
"container security, code-level vulnerabilities, secrets management, and PKI",
style={
"color": GRAY,
"fontSize": "17px",
"margin": "12px auto 0",
"maxWidth": "700px",
},
),
html.Div(
style={
"marginTop": "24px",
"display": "flex",
"justifyContent": "center",
"gap": "24px",
"flexWrap": "wrap",
},
children=[
html.Span(
"April 2026",
style={"color": LIGHT_GRAY, "fontSize": "13px"},
),
html.Span("|", style={"color": LIGHT_GRAY}),
html.Span(
f"{AUDIT_META.get('repos_audited', 8)} repos audited",
style={"color": LIGHT_GRAY, "fontSize": "13px"},
),
html.Span("|", style={"color": LIGHT_GRAY}),
html.Span(
f"{SUMMARY['total_findings']} findings",
style={"color": LIGHT_GRAY, "fontSize": "13px"},
),
html.Span("|", style={"color": LIGHT_GRAY}),
html.Span(
f"{SUMMARY['open']} open",
style={"color": LIGHT_GRAY, "fontSize": "13px"},
),
],
),
],
),
# ── Content ──
html.Div(
style={
"maxWidth": "960px",
"margin": "0 auto",
"padding": "0 24px 80px",
"position": "relative",
"zIndex": "1",
},
children=[
# ── Summary metrics ──
html.Div(
style={
"display": "flex",
"gap": "16px",
"flexWrap": "wrap",
"marginTop": "-40px",
"position": "relative",
"zIndex": "1",
},
children=[
_hero_metric(
str(SUMMARY["critical"]), "Critical", RED
),
_hero_metric(str(SUMMARY["high"]), "High", "#f97316"),
_hero_metric(str(SUMMARY["medium"]), "Medium", AMBER),
_hero_metric(str(SUMMARY["low"]), "Low", BLUE),
_hero_metric(
str(SUMMARY["open"]),
"Open",
AMBER,
),
],
),
# ── Tab bar ──
html.Div(
style={
"display": "flex",
"justifyContent": "center",
"margin": "40px 0 8px",
},
children=[
html.Div(
style={
"display": "inline-flex",
"background": CARD_BG,
"borderRadius": "12px",
"padding": "4px",
"border": f"1px solid {CARD_BORDER}",
},
children=[
html.Button(
"Summary",
id="btn-summary",
n_clicks=1,
style=_TAB_BTN_ACTIVE,
),
html.Button(
f"Critical & High ({len(_CRITICAL_HIGH)})",
id="btn-crit-high",
n_clicks=0,
style=_TAB_BTN_STYLE,
),
html.Button(
f"Medium & Low ({len(_MEDIUM_LOW)})",
id="btn-med-low",
n_clicks=0,
style=_TAB_BTN_STYLE,
),
html.Button(
"By Category",
id="btn-category",
n_clicks=0,
style=_TAB_BTN_STYLE,
),
],
),
],
),
# ═══════════════════════════════════════════════════════════════
# TAB 1: SUMMARY
# ═══════════════════════════════════════════════════════════════
_build_summary_tab(),
# ═══════════════════════════════════════════════════════════════
# TAB 2: CRITICAL & HIGH
# ═══════════════════════════════════════════════════════════════
_build_critical_high_tab(),
# ═══════════════════════════════════════════════════════════════
# TAB 3: MEDIUM & LOW
# ═══════════════════════════════════════════════════════════════
_build_medium_low_tab(),
# ═══════════════════════════════════════════════════════════════
# TAB 4: BY CATEGORY
# ═══════════════════════════════════════════════════════════════
_build_category_tab(),
# ── Footer (always visible) ──
html.Div(
style={
"textAlign": "center",
"marginTop": "64px",
"paddingTop": "24px",
"borderTop": f"1px solid {CARD_BORDER}",
},
children=[
html.Div(
style={
"display": "flex",
"alignItems": "center",
"justifyContent": "center",
"gap": "10px",
"marginBottom": "4px",
},
children=[
html.Img(
src="/assets/codeflash.svg",
style={"height": "16px"},
),
html.Span(
"\u00d7",
style={
"fontSize": "13px",
"color": LIGHT_GRAY,
},
),
html.Img(
src="/assets/unstructured_logo.jpg",
style={
"height": "20px",
"borderRadius": "3px",
},
),
],
),
html.P(
"Security Audit \u2014 April 2026",
style={
"color": LIGHT_GRAY,
"fontSize": "13px",
"margin": "0",
},
),
],
),
],
),
],
)
# ── Tab toggle callback ─────────────────────────────────────────────────────
clientside_callback(
"""
function(sum_c, ch_c, ml_c, cat_c) {
sum_c = sum_c || 0;
ch_c = ch_c || 0;
ml_c = ml_c || 0;
cat_c = cat_c || 0;
var base = {
"padding": "10px 24px", "border": "none", "borderRadius": "8px",
"cursor": "pointer", "fontSize": "14px", "fontWeight": "600",
"fontFamily": "'Inter', system-ui, -apple-system, sans-serif",
"transition": "all 0.2s"
};
var active = Object.assign({}, base, {"background": "#ef4444", "color": "#ffffff"});
var inactive = Object.assign({}, base, {"background": "transparent", "color": "#a1a1aa"});
var show = {"display": "block"};
var hide = {"display": "none"};
var mx = Math.max(sum_c, ch_c, ml_c, cat_c);
if (cat_c === mx && cat_c > 0)
return [hide, hide, hide, show, inactive, inactive, inactive, active];
if (ml_c === mx && ml_c > 0)
return [hide, hide, show, hide, inactive, inactive, active, inactive];
if (ch_c === mx && ch_c > 0)
return [hide, show, hide, hide, inactive, active, inactive, inactive];
return [show, hide, hide, hide, active, inactive, inactive, inactive];
}
""",
Output("summary-view", "style"),
Output("critical-high-view", "style"),
Output("medium-low-view", "style"),
Output("category-view", "style"),
Output("btn-summary", "style"),
Output("btn-crit-high", "style"),
Output("btn-med-low", "style"),
Output("btn-category", "style"),
Input("btn-summary", "n_clicks"),
Input("btn-crit-high", "n_clicks"),
Input("btn-med-low", "n_clicks"),
Input("btn-category", "n_clicks"),
)
server = app.server
if __name__ == "__main__":
app.run(debug=True, port=8052)