增强系统级实体覆盖摘要与工作台索引

这个提交包含在:
hao
2026-03-20 08:47:16 -07:00
父节点 5e1ea395ef
当前提交 c3a853d2cf
修改 160 个文件,包含 26943 行新增5119 行删除

查看文件

@@ -599,19 +599,55 @@ def build_entity_views(source_map: Dict[str, Any], advisories: List[AdvisoryReco
"system_id": entity["root_system_id"],
"display_name": systems.get(entity["root_system_id"], {}).get("display_name", entity["root_system_id"]),
"cataloged_entity_total": 0,
"child_entity_total": 0,
"candidate_entity_total": 0,
"workflow_complete_count": 0,
"version_mapped_count": 0,
"official_source_covered_count": 0,
"history_full_complete_count": 0,
"latest_green_count": 0,
"version_gap_entity_count": 0,
"workflow_gap_entity_count": 0,
"plugin_total": 0,
"entity_type_counts": {},
"top_entities": [],
"backlog_preview": [],
},
)
summary["cataloged_entity_total"] += 1
if entity["entity_type"] != "system":
summary["child_entity_total"] += 1
summary["entity_type_counts"][entity["entity_type"]] = summary["entity_type_counts"].get(entity["entity_type"], 0) + 1
summary["workflow_complete_count"] += 1 if entity["advisory_count"] and entity["workflow_complete_advisory_count"] >= entity["advisory_count"] else 0
summary["version_mapped_count"] += 1 if entity["advisory_count"] and entity["version_mapped_advisory_count"] >= entity["advisory_count"] else 0
summary["official_source_covered_count"] += 1 if entity["official_source_covered"] else 0
summary["history_full_complete_count"] += 1 if entity.get("history_backfill_status") == "complete" else 0
summary["latest_green_count"] += 1 if entity.get("latest_sync_status") == "green" else 0
summary["version_gap_entity_count"] += 1 if entity.get("advisory_count") and entity.get("version_mapped_advisory_count", 0) < entity.get("advisory_count", 0) else 0
summary["workflow_gap_entity_count"] += 1 if entity.get("advisory_count") and entity.get("workflow_complete_advisory_count", 0) < entity.get("advisory_count", 0) else 0
if entity["entity_type"] in PLUGINISH_ENTITY_TYPES:
summary["plugin_total"] += 1
for system_id, summary in system_summary.items():
ranked_entities = sorted(
[
entity
for entity in entities.values()
if entity["root_system_id"] == system_id and entity["entity_type"] != "system"
],
key=lambda item: (-(item.get("advisory_count") or 0), item["entity_type"], item["display_name"].lower()),
)
summary["top_entities"] = [
{
"entity_id": entity["entity_id"],
"entity_type": entity["entity_type"],
"display_name": entity["display_name"],
"advisory_count": entity.get("advisory_count", 0),
"history_backfill_status": entity.get("history_backfill_status"),
"latest_sync_status": entity.get("latest_sync_status"),
}
for entity in ranked_entities[:5]
]
for candidate in candidate_backlog:
system_summary.setdefault(
candidate["root_system_id"],
@@ -619,13 +655,31 @@ def build_entity_views(source_map: Dict[str, Any], advisories: List[AdvisoryReco
"system_id": candidate["root_system_id"],
"display_name": systems.get(candidate["root_system_id"], {}).get("display_name", candidate["root_system_id"]),
"cataloged_entity_total": 0,
"child_entity_total": 0,
"candidate_entity_total": 0,
"workflow_complete_count": 0,
"version_mapped_count": 0,
"official_source_covered_count": 0,
"history_full_complete_count": 0,
"latest_green_count": 0,
"version_gap_entity_count": 0,
"workflow_gap_entity_count": 0,
"plugin_total": 0,
"entity_type_counts": {},
"top_entities": [],
"backlog_preview": [],
},
)["candidate_entity_total"] += 1
preview = system_summary[candidate["root_system_id"]]["backlog_preview"]
if len(preview) < 5:
preview.append(
{
"candidate_id": candidate["candidate_id"],
"display_name": candidate["display_name"],
"entity_type": candidate["entity_type"],
"risk": candidate["risk"],
}
)
cataloged_entities = [entity for entity in entities.values() if entity.get("status") == "cataloged"]
history_full_complete_count = len(

查看文件

@@ -534,6 +534,7 @@ def render_registry(
) -> None:
run_map = latest_runs_by_advisory()
entity_views = build_entity_views(source_map, advisories)
entity_summary_map = {item["system_id"]: item for item in entity_views["completeness"]["systems"]}
grouped: Dict[str, List[AdvisoryRecord]] = defaultdict(list)
advisory_payloads: Dict[str, Dict[str, Any]] = {}
for advisory in advisories:
@@ -556,6 +557,7 @@ def render_registry(
items = grouped.get(system_id, [])
merged_items = [_merged_item(item, run_map) for item in items]
counts = _status_counts(merged_items)
entity_summary = entity_summary_map.get(system_id, {})
system_payloads[f"{system_id}.json"] = {
"system_id": system_id,
"display_name": system["display_name"],
@@ -571,6 +573,7 @@ def render_registry(
"verified_synthetic": counts["verified_synthetic"],
"blocked_count": counts["blocked"],
"manual_count": counts["manual"],
"entity_summary": entity_summary,
"items": [item.canonical_id for item in sorted(items, key=lambda item: item.published_at or "", reverse=True)],
}
if selected_system_ids:

查看文件

@@ -162,6 +162,7 @@ def validate(source_map: Dict[str, Any]) -> List[str]:
GENERATED_DIR / "dashboard" / "advisories.json",
GENERATED_DIR / "dashboard" / "profiles.json",
GENERATED_DIR / "dashboard" / "architecture.json",
GENERATED_DIR / "dashboard" / "entities.json",
GENERATED_DIR / "dashboard" / "assets" / "app.js",
GENERATED_DIR / "dashboard" / "assets" / "styles.css",
GENERATED_DIR / "dashboard" / "assets" / "icons.svg",

查看文件

@@ -65,6 +65,7 @@ const DATA_HUB_ITEMS = [
{ title: "entity-queues.json", href: "/data/entity-queues.json", description: "discovery/history/latest/workflow 四类队列摘要。", badge: "json" },
{ title: "runs.json", href: "/runs.json", description: "最近运行的结构化详情,可用于 UI 和调试。", badge: "json" },
{ title: "systems.json", href: "/systems.json", description: "系统级覆盖、分类、更新时间和浏览器证据统计。", badge: "json" },
{ title: "entities.json", href: "/entities.json", description: "分层实体索引、实体状态和系统归属。", badge: "json" },
{ title: "advisories.json", href: "/advisories.json", description: "漏洞条目元数据、来源和 secure-code 主题。", badge: "json" },
{ title: "profiles.json", href: "/profiles.json", description: "复现档案元数据、成功判据和 browser assertions。", badge: "json" },
{ title: "architecture.json", href: "/architecture.json", description: "当前架构库的结构化真值。", badge: "json" },
@@ -94,6 +95,7 @@ const state = {
summary: null,
runs: [],
systems: [],
entities: [],
advisories: {},
profiles: {},
architecture: null,
@@ -599,6 +601,9 @@ function renderSystemCards(items, compact = false) {
const total = Math.max(Number(system.total || 0), 1);
const verified = Number(system.verified_real || 0) + Number(system.verified_synthetic || 0);
const coverage = Math.round((verified / total) * 100);
const entitySummary = system.entity_summary || {};
const topEntities = system.top_entities || [];
const backlogPreview = system.backlog_preview || [];
return `
<article class="system-card ${compact ? "system-card-compact" : ""}">
<div class="timeline-head">
@@ -610,8 +615,28 @@ function renderSystemCards(items, compact = false) {
<span class="tag">真实 ${escapeHtml(system.verified_real || 0)}</span>
<span class="tag">合成 ${escapeHtml(system.verified_synthetic || 0)}</span>
<span class="tag">阻塞 ${escapeHtml(system.blocked || 0)}</span>
<span class="tag">实体 ${escapeHtml(entitySummary.cataloged_entity_total || 0)}</span>
<span class="tag">backlog ${escapeHtml(entitySummary.candidate_entity_total || 0)}</span>
</div>
<div class="meter"><span style="--fill:${coverage}%"></span></div>
${compact ? "" : `
<div class="plan-grid" style="margin-top:12px;">
<article class="plan-card">
<span class="plan-label">实体覆盖</span>
<div class="plan-copy">cataloged ${escapeHtml(entitySummary.cataloged_entity_total || 0)} · child ${escapeHtml(entitySummary.child_entity_total || 0)} · plugins ${escapeHtml(entitySummary.plugin_total || 0)}</div>
</article>
<article class="plan-card">
<span class="plan-label">队列与缺口</span>
<div class="plan-copy">history complete ${escapeHtml(entitySummary.history_full_complete_count || 0)} · latest green ${escapeHtml(entitySummary.latest_green_count || 0)} · version gap ${escapeHtml(entitySummary.version_gap_entity_count || 0)}</div>
</article>
</div>
${(topEntities.length || backlogPreview.length) ? `
<div class="tag-row" style="margin-top:10px;">
${topEntities.map((item) => `<span class="tag">${escapeHtml(item.entity_type)} · ${escapeHtml(item.display_name)} · ${escapeHtml(item.advisory_count || 0)}</span>`).join("")}
${backlogPreview.map((item) => `<span class="tag">${escapeHtml(item.entity_type)} backlog · ${escapeHtml(item.display_name)}</span>`).join("")}
</div>
` : ""}
`}
<div class="detail-actions" style="margin-top:12px;">
<button class="button button-secondary button-small" type="button" data-filter-key="system" data-filter-value="${escapeHtml(system.system_id)}">锁定系统</button>
<a class="button button-secondary button-small" href="${escapeHtml(buildUrl("runs", { system: system.system_id, run: null }))}">查看运行</a>
@@ -1609,10 +1634,11 @@ async function loadData(preserveSelection = true) {
renderSyncState("loading", "刷新中", `本地时间 ${new Date().toLocaleTimeString("zh-CN", { hour12: false })}`);
try {
const [summary, runs, systems, advisories, profiles, architecture, completeness, entityCompleteness, sourceHealth, alerts, monitorSummary] = await Promise.all([
const [summary, runs, systems, entities, advisories, profiles, architecture, completeness, entityCompleteness, sourceHealth, alerts, monitorSummary] = await Promise.all([
fetchJson("/summary.json"),
fetchJson("/runs.json"),
fetchJson("/systems.json"),
fetchJson("/entities.json"),
fetchJson("/advisories.json"),
fetchJson("/profiles.json"),
fetchJson("/architecture.json"),
@@ -1626,6 +1652,7 @@ async function loadData(preserveSelection = true) {
state.summary = summary;
state.runs = runs;
state.systems = systems;
state.entities = entities;
state.advisories = advisories;
state.profiles = profiles;
state.architecture = architecture;

查看文件

@@ -18,6 +18,7 @@ LEGACY_TEMPLATE_DIR = TEMPLATES_DIR / "legacy"
LOVART_VENDOR_MANIFEST = LOVART_TEMPLATE_DIR / "vendor" / "source-manifest.json"
ROOT_JSON_FILES = ["summary.json", "runs.json", "systems.json", "advisories.json", "profiles.json"]
ROOT_JSON_FILES.append("architecture.json")
ROOT_JSON_FILES.append("entities.json")
SECTION_ROUTE_DIRS = ["overview", "runs", "systems", "architecture", "data"]
CATEGORY_LABELS = {
@@ -570,6 +571,7 @@ def _build_architecture_data(summary: Dict[str, Any], source_map: Dict[str, Any]
_link("entity-queues.json", "/data/entity-queues.json", "discovery/history/latest/workflow 四类队列摘要。"),
_link("runs.json", "/runs.json", "最近 run 的结构化详情。"),
_link("systems.json", "/systems.json", "系统级覆盖与浏览器证据摘要。"),
_link("entities.json", "/entities.json", "分层实体索引、实体状态和系统归属。"),
_link("advisories.json", "/advisories.json", "漏洞条目元数据与来源。"),
_link("profiles.json", "/profiles.json", "复现档案元数据。"),
_link("architecture.json", "/architecture.json", "当前架构库结构化 JSON。"),
@@ -1363,12 +1365,17 @@ def render_dashboard(
entity_completeness = read_json(ROOT / "08-threat-intel" / "generated" / "entity-completeness.json", default={}) or {}
entity_backlog = read_json(ROOT / "08-threat-intel" / "generated" / "entity-discovery-backlog.json", default=[]) or []
entity_queues = read_json(ROOT / "08-threat-intel" / "generated" / "entity-queues.json", default={}) or {}
entity_records = load_json_dir(ROOT / "08-threat-intel" / "registry" / "entities")
source_map = source_map_data if source_map_data is not None else (read_yaml(SOURCE_MAP_PATH, default={}) or {})
repro_map = repro_map_data if repro_map_data is not None else (read_yaml(REPRO_MAP_PATH, default={}) or {})
source_system_map = {item["system_id"]: item for item in source_map.get("systems", []) if item.get("system_id")}
merged_advisories = _merge_latest_advisories(advisory_records, runs, source_system_map)
advisory_map = {item["canonical_id"]: item for item in merged_advisories if item.get("canonical_id")}
profile_map = load_profiles()
entity_summary_map = {item.get("system_id"): item for item in (entity_completeness.get("systems") or []) if item.get("system_id")}
entities_by_system: Dict[str, List[Dict[str, Any]]] = {}
for item in sorted(entity_records, key=lambda value: (value.get("root_system_id") or "", value.get("entity_type") or "", value.get("display_name") or "")):
entities_by_system.setdefault(item.get("root_system_id") or "", []).append(item)
_sync_run_bundles(runs)
@@ -1419,6 +1426,15 @@ def render_dashboard(
elif status not in {"verified-synthetic"}:
family_entry["manual"] += 1
for system_id, system in systems.items():
entity_summary = entity_summary_map.get(system_id, {})
system["entity_summary"] = entity_summary
system["top_entities"] = entity_summary.get("top_entities", [])
system["backlog_preview"] = entity_summary.get("backlog_preview", [])
system["entity_total"] = entity_summary.get("cataloged_entity_total", 0)
system["entity_backlog"] = entity_summary.get("candidate_entity_total", 0)
system["entity_type_counts"] = entity_summary.get("entity_type_counts", {})
recent_runs = sorted(runs, key=lambda item: item.get("finished_at") or "", reverse=True)[:100]
decorated_runs: List[Dict[str, Any]] = []
for item in recent_runs:
@@ -1532,6 +1548,7 @@ def render_dashboard(
write_json(DASHBOARD_DIR / "summary.json", summary)
write_json(DASHBOARD_DIR / "runs.json", decorated_runs)
write_json(DASHBOARD_DIR / "systems.json", summary["systems"])
write_json(DASHBOARD_DIR / "entities.json", entity_records)
write_json(DASHBOARD_DIR / "advisories.json", {key: _advisory_meta(value) for key, value in advisory_map.items()})
write_json(DASHBOARD_DIR / "profiles.json", {key: _profile_meta(value) for key, value in profile_map.items()})
write_json(DASHBOARD_DIR / "data" / "completeness.json", completeness)