From 2cb1afad4f7a40ae802962114764a1e9e7245a34 Mon Sep 17 00:00:00 2001 From: igor04091968 Date: Thu, 4 Jun 2026 22:52:03 +0300 Subject: [PATCH] fix(portal): hide technical terms in executive demo view --- adk-rust/crates/detmir-portal/src/main.rs | 27 ++++++++++++++++++- .../crates/detmir-portal/src/static/app.js | 2 +- scripts/detmir-portal-tabs-smoke.mjs | 27 ++++++++++++++++++- 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/adk-rust/crates/detmir-portal/src/main.rs b/adk-rust/crates/detmir-portal/src/main.rs index 673b582..a764b84 100644 --- a/adk-rust/crates/detmir-portal/src/main.rs +++ b/adk-rust/crates/detmir-portal/src/main.rs @@ -2549,6 +2549,19 @@ fn security_events_summary_text(summary: &SecurityEventsSummary) -> String { ) } +fn security_events_executive_text(summary: &SecurityEventsSummary) -> String { + if summary.backend == "disabled" || summary.status == "disabled" { + return "Источник событий безопасности отключён.".to_string(); + } + if summary.fallback_used { + return "События безопасности временно недоступны.".to_string(); + } + format!( + "События безопасности доступны: событий за 24 часа {}.", + summary.events_24h + ) +} + fn security_events_block(summary: &SecurityEventsSummary) -> SummaryBlock { SummaryBlock { status: security_events_summary_status(summary), @@ -2844,7 +2857,7 @@ fn build_reports( )); executive_points.push(format!( "События безопасности за 24 часа: {}", - security_events_summary_text(&security_events_summary) + security_events_executive_text(&security_events_summary) )); executive_points.extend([ format!("Сбор данных: {}. {}", collection.status, collection.text), @@ -10174,6 +10187,15 @@ mod tests { error: None, }; assert!(security_events_summary_text(&available).contains("События безопасности доступны")); + assert_eq!( + security_events_executive_text(&disabled), + "Источник событий безопасности отключён." + ); + assert_eq!( + security_events_executive_text(&fallback), + "События безопасности временно недоступны." + ); + assert!(!security_events_executive_text(&disabled).contains("ClickHouse")); } #[test] @@ -10733,6 +10755,9 @@ mod tests { .unwrap() .contains("Статус связанной картины риска")) ); + let executive_points_text = report["executive_points"].to_string(); + assert!(!executive_points_text.contains("ClickHouse")); + assert!(!executive_points_text.contains("SECURITY_EVENTS_BACKEND")); assert!( report["markdown"] .as_str() diff --git a/adk-rust/crates/detmir-portal/src/static/app.js b/adk-rust/crates/detmir-portal/src/static/app.js index 9bbf296..02a6cac 100644 --- a/adk-rust/crates/detmir-portal/src/static/app.js +++ b/adk-rust/crates/detmir-portal/src/static/app.js @@ -2174,7 +2174,7 @@ function renderSecurityEventsSummary(summary, options = {}) { : fallback ? "События безопасности временно недоступны" : "События безопасности доступны"; - const localModeText = disabled ? "Используется локальный режим без ClickHouse" : ""; + const localModeText = disabled ? "Локальный режим" : ""; const title = options.compact ? "События безопасности" : "События безопасности за 24 часа"; diff --git a/scripts/detmir-portal-tabs-smoke.mjs b/scripts/detmir-portal-tabs-smoke.mjs index 08e0b0d..1afe3bb 100644 --- a/scripts/detmir-portal-tabs-smoke.mjs +++ b/scripts/detmir-portal-tabs-smoke.mjs @@ -61,6 +61,24 @@ function expectedSecurityEventsText(mode) { return ""; } +function forbiddenExecutiveTerms(text) { + const forbidden = [ + "Trust KPI", + "Business Risk", + "Risk Narrative", + "Security Events", + "Incident Candidate", + "Coverage SLA", + "ERROR", + "EMPTY", + "STALE", + "SECURITY_EVENTS_BACKEND", + "CLICKHOUSE_*", + "ClickHouse", + ]; + return forbidden.filter((term) => containsText(text, term)); +} + function assertStaticTabHandlers() { const index = fs.readFileSync(path.join(root, "adk-rust/crates/detmir-portal/src/static/index.html"), "utf8"); const app = fs.readFileSync(path.join(root, "adk-rust/crates/detmir-portal/src/static/app.js"), "utf8"); @@ -203,6 +221,12 @@ async function main() { ok: requiredExecutive.every((marker) => containsText(readyBodyText, marker)), required: requiredExecutive, }); + const forbiddenExecutive = forbiddenExecutiveTerms(readyBodyText); + checks.push({ + name: "executive_view_no_technical_terms", + ok: forbiddenExecutive.length === 0, + forbidden: forbiddenExecutive, + }); const cardHeadings = await page.$$eval("#content section.card h3, #content h3.section-title", (nodes) => nodes.map((node) => node.textContent.trim()), ); @@ -238,7 +262,8 @@ async function main() { !expectedSecurityText || (containsText(readyBodyText, expectedSecurityText) && !containsText(readyBodyText, "SECURITY_EVENTS_BACKEND") - && !containsText(readyBodyText, "CLICKHOUSE_*")), + && !containsText(readyBodyText, "CLICKHOUSE_*") + && !containsText(readyBodyText, "ClickHouse")), mode: securityMode, expected_text: expectedSecurityText, });