diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index 0b225786..2ee713b4 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -5477,6 +5477,101 @@ } } }, + "globalSecurityMeshMatrix": { + "eyebrow": "全域資安納管矩陣", + "title": "所有產品、主機、工具放在同一張表", + "subtitle": "把 AwoooI、AwoooP、IwoooS、公開網站群、VibeWork、Kali 112、開發主機與 GitHub / Gitea 版本來源放到同一個只讀矩陣,讓使用者先看清楚納管範圍,再決定哪一段要收證或開人工閘門。", + "coverageLabel": "覆蓋", + "evidenceLabel": "證據", + "runtimeLabel": "執行", + "nextLabel": "下一步", + "boundaryTitle": "全域納管邊界", + "boundaryIntro": "以下鍵值固定:這張矩陣只呈現可視化、證據狀態與人工閘門,不提供掃描、修復、主機變更、部署或版本來源變更。", + "summary": { + "assets": { + "label": "資產列", + "detail": "八類產品、主機與工具同表。" + }, + "readOnly": { + "label": "只讀納管", + "detail": "八類都只先納入觀測與證據欄位。" + }, + "runtime": { + "label": "執行期", + "detail": "目前仍是 0,不開主動動作。" + }, + "nextGate": { + "label": "下一閘門", + "detail": "先等 S4.9 負責人證據。" + } + }, + "items": { + "awoooi": { + "title": "AwoooI 核心產品", + "layer": "前台、API、工單、告警與授權頁面。", + "coverage": "已可視化", + "evidence": "真相鏈已接上", + "runtime": "仍鎖住", + "next": "延續 Incident 真相鏈,不新增執行按鈕。" + }, + "awooop": { + "title": "AwoooP 工作流", + "layer": "Runs、Work Items、Approvals 與跨 Session 交接。", + "coverage": "已可視化", + "evidence": "正式頁已落地", + "runtime": "仍鎖住", + "next": "只同步狀態與證據,避免和另一個 Session 互踩。" + }, + "iwooos": { + "title": "IwoooS 資安入口", + "layer": "資訊安全總覽、矩陣、雷達、攻擊路徑與收件卡。", + "coverage": "主入口", + "evidence": "guard 已保護", + "runtime": "仍鎖住", + "next": "把抽象進度轉成可見工作項與證據欄位。" + }, + "publicSites": { + "title": "公開網站群", + "layer": "前台網站、品牌頁、服務頁與既有安全合規入口。", + "coverage": "已納入", + "evidence": "待補來源", + "runtime": "仍鎖住", + "next": "只收公開頁面與合規文案 evidence,不做阻擋控制。" + }, + "vibeWork": { + "title": "VibeWork 新專案", + "layer": "新專案收件、責任邊界、資料分級與部署邊界。", + "coverage": "已納入", + "evidence": "待補 6 項", + "runtime": "仍鎖住", + "next": "先完成 VibeWork 六項只讀收件。" + }, + "kali112": { + "title": "Kali 192.168.0.112", + "layer": "安全主機、掃描能力、維護窗口與主機狀態。", + "coverage": "只讀快照", + "evidence": "待維護窗口", + "runtime": "仍鎖住", + "next": "維持觀測,不執行更新、掃描或 /execute。" + }, + "devHosts": { + "title": "開發主機 111 / 168", + "layer": "兩台開發主機的資安範圍、證據收件與人工判定。", + "coverage": "已納入", + "evidence": "待補主機證據", + "runtime": "仍鎖住", + "next": "只收主機中繼資料與 owner decision。" + }, + "sourceControl": { + "title": "GitHub / Gitea 版本來源", + "layer": "主倉判定、refs 真相、workflow 名稱與 secret 名稱。", + "coverage": "待負責人回覆", + "evidence": "待 S4.9", + "runtime": "仍鎖住", + "next": "不建立 repo、不同步 refs、不改 workflow 或 secret。" + } + } + }, "vibeWorkSecurityOnboarding": { "eyebrow": "VibeWork 新專案收件卡", "title": "先把缺口收齊,不急著加管制", diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index 0b225786..2ee713b4 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -5477,6 +5477,101 @@ } } }, + "globalSecurityMeshMatrix": { + "eyebrow": "全域資安納管矩陣", + "title": "所有產品、主機、工具放在同一張表", + "subtitle": "把 AwoooI、AwoooP、IwoooS、公開網站群、VibeWork、Kali 112、開發主機與 GitHub / Gitea 版本來源放到同一個只讀矩陣,讓使用者先看清楚納管範圍,再決定哪一段要收證或開人工閘門。", + "coverageLabel": "覆蓋", + "evidenceLabel": "證據", + "runtimeLabel": "執行", + "nextLabel": "下一步", + "boundaryTitle": "全域納管邊界", + "boundaryIntro": "以下鍵值固定:這張矩陣只呈現可視化、證據狀態與人工閘門,不提供掃描、修復、主機變更、部署或版本來源變更。", + "summary": { + "assets": { + "label": "資產列", + "detail": "八類產品、主機與工具同表。" + }, + "readOnly": { + "label": "只讀納管", + "detail": "八類都只先納入觀測與證據欄位。" + }, + "runtime": { + "label": "執行期", + "detail": "目前仍是 0,不開主動動作。" + }, + "nextGate": { + "label": "下一閘門", + "detail": "先等 S4.9 負責人證據。" + } + }, + "items": { + "awoooi": { + "title": "AwoooI 核心產品", + "layer": "前台、API、工單、告警與授權頁面。", + "coverage": "已可視化", + "evidence": "真相鏈已接上", + "runtime": "仍鎖住", + "next": "延續 Incident 真相鏈,不新增執行按鈕。" + }, + "awooop": { + "title": "AwoooP 工作流", + "layer": "Runs、Work Items、Approvals 與跨 Session 交接。", + "coverage": "已可視化", + "evidence": "正式頁已落地", + "runtime": "仍鎖住", + "next": "只同步狀態與證據,避免和另一個 Session 互踩。" + }, + "iwooos": { + "title": "IwoooS 資安入口", + "layer": "資訊安全總覽、矩陣、雷達、攻擊路徑與收件卡。", + "coverage": "主入口", + "evidence": "guard 已保護", + "runtime": "仍鎖住", + "next": "把抽象進度轉成可見工作項與證據欄位。" + }, + "publicSites": { + "title": "公開網站群", + "layer": "前台網站、品牌頁、服務頁與既有安全合規入口。", + "coverage": "已納入", + "evidence": "待補來源", + "runtime": "仍鎖住", + "next": "只收公開頁面與合規文案 evidence,不做阻擋控制。" + }, + "vibeWork": { + "title": "VibeWork 新專案", + "layer": "新專案收件、責任邊界、資料分級與部署邊界。", + "coverage": "已納入", + "evidence": "待補 6 項", + "runtime": "仍鎖住", + "next": "先完成 VibeWork 六項只讀收件。" + }, + "kali112": { + "title": "Kali 192.168.0.112", + "layer": "安全主機、掃描能力、維護窗口與主機狀態。", + "coverage": "只讀快照", + "evidence": "待維護窗口", + "runtime": "仍鎖住", + "next": "維持觀測,不執行更新、掃描或 /execute。" + }, + "devHosts": { + "title": "開發主機 111 / 168", + "layer": "兩台開發主機的資安範圍、證據收件與人工判定。", + "coverage": "已納入", + "evidence": "待補主機證據", + "runtime": "仍鎖住", + "next": "只收主機中繼資料與 owner decision。" + }, + "sourceControl": { + "title": "GitHub / Gitea 版本來源", + "layer": "主倉判定、refs 真相、workflow 名稱與 secret 名稱。", + "coverage": "待負責人回覆", + "evidence": "待 S4.9", + "runtime": "仍鎖住", + "next": "不建立 repo、不同步 refs、不改 workflow 或 secret。" + } + } + }, "vibeWorkSecurityOnboarding": { "eyebrow": "VibeWork 新專案收件卡", "title": "先把缺口收齊,不急著加管制", diff --git a/apps/web/src/app/[locale]/iwooos/page.tsx b/apps/web/src/app/[locale]/iwooos/page.tsx index c972ffdd..ce90366d 100644 --- a/apps/web/src/app/[locale]/iwooos/page.tsx +++ b/apps/web/src/app/[locale]/iwooos/page.tsx @@ -134,6 +134,15 @@ type AllProductCoverageSnapshotItem = { tone: 'steady' | 'warn' | 'locked' } +type GlobalSecurityMeshMatrixItem = { + key: string + code: string + icon: typeof ShieldCheck + coverageTone: 'steady' | 'warn' | 'locked' + evidenceTone: 'steady' | 'warn' | 'locked' + runtimeTone: 'steady' | 'warn' | 'locked' +} + type VibeWorkSecurityOnboardingItem = { key: string check: string @@ -1356,6 +1365,40 @@ const iwooosConcreteSecurityBlockerResolutionBoundaries = [ 'gitea_disablement_authorized=false', ] as const +const globalSecurityMeshMatrixSummary = [ + { key: 'assets', value: '8', icon: Radar, tone: 'steady' }, + { key: 'readOnly', value: '8', icon: ShieldCheck, tone: 'steady' }, + { key: 'runtime', value: '0', icon: Lock, tone: 'locked' }, + { key: 'nextGate', value: 'S4.9', icon: ClipboardCheck, tone: 'warn' }, +] as const + +const globalSecurityMeshMatrixItems: GlobalSecurityMeshMatrixItem[] = [ + { key: 'awoooi', code: 'G1', icon: ShieldCheck, coverageTone: 'steady', evidenceTone: 'steady', runtimeTone: 'locked' }, + { key: 'awooop', code: 'G2', icon: Radar, coverageTone: 'steady', evidenceTone: 'steady', runtimeTone: 'locked' }, + { key: 'iwooos', code: 'G3', icon: Activity, coverageTone: 'steady', evidenceTone: 'steady', runtimeTone: 'locked' }, + { key: 'publicSites', code: 'G4', icon: FileText, coverageTone: 'steady', evidenceTone: 'warn', runtimeTone: 'locked' }, + { key: 'vibeWork', code: 'G5', icon: ListChecks, coverageTone: 'steady', evidenceTone: 'warn', runtimeTone: 'locked' }, + { key: 'kali112', code: 'G6', icon: SearchCheck, coverageTone: 'steady', evidenceTone: 'warn', runtimeTone: 'locked' }, + { key: 'devHosts', code: 'G7', icon: Activity, coverageTone: 'steady', evidenceTone: 'warn', runtimeTone: 'locked' }, + { key: 'sourceControl', code: 'G8', icon: GitBranch, coverageTone: 'warn', evidenceTone: 'warn', runtimeTone: 'locked' }, +] + +const globalSecurityMeshMatrixBoundaries = [ + 'iwooos_global_security_mesh_first_layer=true', + 'iwooos_global_security_mesh_asset_count=8', + 'iwooos_global_security_mesh_read_only_count=8', + 'iwooos_global_security_mesh_runtime_gate_count=0', + 'iwooos_global_security_mesh_source_control_mutation_authorized=false', + 'iwooos_global_security_mesh_kali_execution_authorized=false', + 'iwooos_global_security_mesh_host_change_authorized=false', + 'iwooos_global_security_mesh_scan_authorized=false', + 'iwooos_global_security_mesh_production_deploy_authorized=false', + 'runtime_execution_authorized=false', + 'active_runtime_gate_count=0', + 'action_buttons_allowed=false', + 'not_authorization=true', +] as const + const vibeWorkSecurityOnboardingSummary = [ { key: 'readOnly', value: '已納管', icon: ShieldCheck, tone: 'steady' }, { key: 'missingEvidence', value: '6', icon: ListChecks, tone: 'warn' }, @@ -4567,6 +4610,178 @@ function IwoooSAllProductCoverageSnapshotBoard() { ) } +function IwoooSGlobalSecurityMeshMatrixBoard() { + const t = useTranslations('iwooos.globalSecurityMeshMatrix') + const textWrap = { overflowWrap: 'anywhere' as const, wordBreak: 'break-word' as const } + + return ( +
+
+
+
+
+ + {t('eyebrow')} +
+

{t('title')}

+

+ {t('subtitle')} +

+
+ +
+ {globalSecurityMeshMatrixSummary.map(item => { + const Icon = item.icon + return ( +
+
+ {t(`summary.${item.key}.label` as never)} + +
+
+ {item.value} +
+

+ {t(`summary.${item.key}.detail` as never)} +

+
+ ) + })} +
+
+ +
+ {globalSecurityMeshMatrixItems.map(item => { + const Icon = item.icon + return ( +
+
+
+
{item.code}
+

+ {t(`items.${item.key}.title` as never)} +

+

+ {t(`items.${item.key}.layer` as never)} +

+
+ +
+ +
+ {[ + { label: t('coverageLabel'), value: t(`items.${item.key}.coverage` as never), tone: item.coverageTone }, + { label: t('evidenceLabel'), value: t(`items.${item.key}.evidence` as never), tone: item.evidenceTone }, + { label: t('runtimeLabel'), value: t(`items.${item.key}.runtime` as never), tone: item.runtimeTone }, + ].map(row => ( +
+ {row.label} + + {row.value} + +
+ ))} +
+ +

+ {t('nextLabel')}:{t(`items.${item.key}.next` as never)} +

+
+ ) + })} +
+ +
+ + {t('boundaryTitle')} + +

+ {t('boundaryIntro')} +

+
+ {globalSecurityMeshMatrixBoundaries.map(item => ( + + {item} + + ))} +
+
+
+
+ ) +} + function IwoooSVibeWorkSecurityOnboardingBoard() { const t = useTranslations('iwooos.vibeWorkSecurityOnboarding') const textWrap = { overflowWrap: 'anywhere' as const, wordBreak: 'break-word' as const } @@ -13219,6 +13434,7 @@ export default function IwoooSPage({ params }: { params: { locale: string } }) { + None: "iwooos_projection.summary.all_product_coverage_snapshot_detail_ledger_collapsed", iwooos_projection["summary"]["all_product_coverage_snapshot_detail_ledger_collapsed"], ) + assert_true( + "iwooos_projection.summary.global_security_mesh_matrix_first_layer", + iwooos_projection["summary"]["global_security_mesh_matrix_first_layer"], + ) + assert_equal( + "iwooos_projection.summary.global_security_mesh_matrix_asset_count", + iwooos_projection["summary"]["global_security_mesh_matrix_asset_count"], + 8, + ) + assert_equal( + "iwooos_projection.summary.global_security_mesh_matrix_read_only_count", + iwooos_projection["summary"]["global_security_mesh_matrix_read_only_count"], + 8, + ) + assert_equal( + "iwooos_projection.summary.global_security_mesh_matrix_runtime_gate_count", + iwooos_projection["summary"]["global_security_mesh_matrix_runtime_gate_count"], + 0, + ) assert_true( "iwooos_projection.summary.vibework_security_onboarding_first_layer", iwooos_projection["summary"]["vibework_security_onboarding_first_layer"], @@ -5899,6 +5918,7 @@ def validate(root: Path) -> None: "display_visual_command_dashboard", "display_professional_security_experience", "display_concrete_work_snapshot", + "display_global_security_mesh_matrix", "display_awooop_read_only_landing_readiness", "display_awooop_cross_session_handoff_packets", "display_progress_hold_movement_gates", @@ -9644,6 +9664,96 @@ def validate(root: Path) -> None: list(web_messages_en["iwooos"]["allProductCoverageSnapshot"]["items"].keys()), key, ) + assert_text_contains( + "iwooos_page.global_security_mesh_matrix_testid", + iwooos_projection_page, + 'data-testid="iwooos-global-security-mesh-matrix-board"', + ) + assert_text_contains( + "iwooos_page.global_security_mesh_matrix_boundary_testid", + iwooos_projection_page, + 'data-testid="iwooos-global-security-mesh-matrix-boundaries"', + ) + assert_text_contains( + "iwooos_page.global_security_mesh_matrix_component", + iwooos_projection_page, + "IwoooSGlobalSecurityMeshMatrixBoard", + ) + for text in [ + "iwooos_global_security_mesh_first_layer=true", + "iwooos_global_security_mesh_asset_count=8", + "iwooos_global_security_mesh_read_only_count=8", + "iwooos_global_security_mesh_runtime_gate_count=0", + "iwooos_global_security_mesh_source_control_mutation_authorized=false", + "iwooos_global_security_mesh_kali_execution_authorized=false", + "iwooos_global_security_mesh_host_change_authorized=false", + "iwooos_global_security_mesh_scan_authorized=false", + "iwooos_global_security_mesh_production_deploy_authorized=false", + "runtime_execution_authorized=false", + "active_runtime_gate_count=0", + "action_buttons_allowed=false", + "not_authorization=true", + ]: + assert_text_contains( + "iwooos_page.global_security_mesh_matrix_boundary", + iwooos_projection_page, + text, + ) + assert_contains( + "web_messages.zh-TW.iwooos.globalSecurityMeshMatrix", + list(web_messages_zh["iwooos"].keys()), + "globalSecurityMeshMatrix", + ) + assert_contains( + "web_messages.en.iwooos.globalSecurityMeshMatrix", + list(web_messages_en["iwooos"].keys()), + "globalSecurityMeshMatrix", + ) + for key in [ + "eyebrow", + "title", + "subtitle", + "coverageLabel", + "evidenceLabel", + "runtimeLabel", + "nextLabel", + "boundaryTitle", + "boundaryIntro", + "summary", + "items", + ]: + assert_contains( + "web_messages.zh-TW.iwooos.globalSecurityMeshMatrix.keys", + list(web_messages_zh["iwooos"]["globalSecurityMeshMatrix"].keys()), + key, + ) + assert_contains( + "web_messages.en.iwooos.globalSecurityMeshMatrix.keys", + list(web_messages_en["iwooos"]["globalSecurityMeshMatrix"].keys()), + key, + ) + for key in ["assets", "readOnly", "runtime", "nextGate"]: + assert_contains( + "web_messages.zh-TW.iwooos.globalSecurityMeshMatrix.summary", + list(web_messages_zh["iwooos"]["globalSecurityMeshMatrix"]["summary"].keys()), + key, + ) + assert_contains( + "web_messages.en.iwooos.globalSecurityMeshMatrix.summary", + list(web_messages_en["iwooos"]["globalSecurityMeshMatrix"]["summary"].keys()), + key, + ) + for key in ["awoooi", "awooop", "iwooos", "publicSites", "vibeWork", "kali112", "devHosts", "sourceControl"]: + assert_contains( + "web_messages.zh-TW.iwooos.globalSecurityMeshMatrix.items", + list(web_messages_zh["iwooos"]["globalSecurityMeshMatrix"]["items"].keys()), + key, + ) + assert_contains( + "web_messages.en.iwooos.globalSecurityMeshMatrix.items", + list(web_messages_en["iwooos"]["globalSecurityMeshMatrix"]["items"].keys()), + key, + ) assert_text_contains( "iwooos_page.vibework_security_onboarding_testid", iwooos_projection_page,