diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index 3a97a2d36..93e971d3e 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -20380,7 +20380,7 @@ "runtimeSecurityReadback": { "eyebrow": "IwoooS Runtime 資安讀回", "title": "九條 P0 資安線先接到同一張讀回板", - "subtitle": "這張板讀取後端彙整的只讀快照,並附上 Wazuh 正式只讀路由的公開安全 aggregate 讀回;它不保存 raw Wazuh payload、不啟動掃描、不送訊息、不改主機。", + "subtitle": "這張板讀取後端彙整的只讀快照,並附上 Wazuh 正式只讀路由的公開安全彙總讀回;它不保存原始 Wazuh 載荷、不啟動掃描、不送訊息、不改主機。", "statusLabel": "讀回狀態", "statusDetail": "讀回成功只代表 IwoooS 能看見目前的證據邊界;runtime 寫入、主動回應、掃描、重啟、Nginx reload、workflow 修改與機密操作仍全部關閉。", "laneStatusLabel": "目前狀態", @@ -20391,7 +20391,19 @@ "status": { "loading": "正在讀取只讀資安總板", "failed": "只讀總板尚未部署或讀取失敗", - "readbackReady": "只讀總板已讀回,但 runtime 閘門仍關閉" + "readbackReady": "只讀總板已讀回,但執行期閘門仍關閉" + }, + "laneStatusValues": { + "wazuh_registry": "等待管理器清單交叉驗收", + "wazuh_live_route": "正式只讀路由已關閉,等待 IwoooS Wazuh 負責人閘門", + "wazuh_live_metadata_gate": "等待即時中繼資料負責人回覆", + "wazuh_owner_evidence_preflight": "負責人證據預檢已就緒,尚未授權執行期動作", + "wazuh_dashboard_api": "API 連線退化,禁止顯示綠燈", + "kali_intake": "部分執行期健康已整合,仍待完整驗收", + "alert_readability": "格式合約已就緒,尚未有實發收件證據", + "owner_dispatch": "負責人請求草案已就緒,尚未送出", + "intrusion_prevention": "僅為候選,尚未授權執行期圍堵", + "unknown": "待補狀態映射" }, "summary": { "controlPlane": { @@ -20407,7 +20419,7 @@ "detail": "管理器清單接受數仍為 0。" }, "wazuhLive": { - "label": "Wazuh live", + "label": "Wazuh 即時路由", "detail": "正式只讀路由若 disabled、空清單或低於預期,首屏直接顯示警示。" }, "metadataGate": { @@ -20423,13 +20435,13 @@ "detail": "active scan / execute 都維持 0。" }, "runtimeGate": { - "label": "Runtime Gate", + "label": "執行期閘門", "detail": "任何修復、封鎖、重啟或 reload 都還沒開門。" } }, "lanes": { "wazuh_registry": { - "title": "Wazuh manager registry", + "title": "Wazuh 管理器清單", "body": "必須拿到總數、在線、離線、從未連線與時間窗;transport 或儀表板可見不能代替驗收。" }, "wazuh_live_route": { diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index 3a97a2d36..93e971d3e 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -20380,7 +20380,7 @@ "runtimeSecurityReadback": { "eyebrow": "IwoooS Runtime 資安讀回", "title": "九條 P0 資安線先接到同一張讀回板", - "subtitle": "這張板讀取後端彙整的只讀快照,並附上 Wazuh 正式只讀路由的公開安全 aggregate 讀回;它不保存 raw Wazuh payload、不啟動掃描、不送訊息、不改主機。", + "subtitle": "這張板讀取後端彙整的只讀快照,並附上 Wazuh 正式只讀路由的公開安全彙總讀回;它不保存原始 Wazuh 載荷、不啟動掃描、不送訊息、不改主機。", "statusLabel": "讀回狀態", "statusDetail": "讀回成功只代表 IwoooS 能看見目前的證據邊界;runtime 寫入、主動回應、掃描、重啟、Nginx reload、workflow 修改與機密操作仍全部關閉。", "laneStatusLabel": "目前狀態", @@ -20391,7 +20391,19 @@ "status": { "loading": "正在讀取只讀資安總板", "failed": "只讀總板尚未部署或讀取失敗", - "readbackReady": "只讀總板已讀回,但 runtime 閘門仍關閉" + "readbackReady": "只讀總板已讀回,但執行期閘門仍關閉" + }, + "laneStatusValues": { + "wazuh_registry": "等待管理器清單交叉驗收", + "wazuh_live_route": "正式只讀路由已關閉,等待 IwoooS Wazuh 負責人閘門", + "wazuh_live_metadata_gate": "等待即時中繼資料負責人回覆", + "wazuh_owner_evidence_preflight": "負責人證據預檢已就緒,尚未授權執行期動作", + "wazuh_dashboard_api": "API 連線退化,禁止顯示綠燈", + "kali_intake": "部分執行期健康已整合,仍待完整驗收", + "alert_readability": "格式合約已就緒,尚未有實發收件證據", + "owner_dispatch": "負責人請求草案已就緒,尚未送出", + "intrusion_prevention": "僅為候選,尚未授權執行期圍堵", + "unknown": "待補狀態映射" }, "summary": { "controlPlane": { @@ -20407,7 +20419,7 @@ "detail": "管理器清單接受數仍為 0。" }, "wazuhLive": { - "label": "Wazuh live", + "label": "Wazuh 即時路由", "detail": "正式只讀路由若 disabled、空清單或低於預期,首屏直接顯示警示。" }, "metadataGate": { @@ -20423,13 +20435,13 @@ "detail": "active scan / execute 都維持 0。" }, "runtimeGate": { - "label": "Runtime Gate", + "label": "執行期閘門", "detail": "任何修復、封鎖、重啟或 reload 都還沒開門。" } }, "lanes": { "wazuh_registry": { - "title": "Wazuh manager registry", + "title": "Wazuh 管理器清單", "body": "必須拿到總數、在線、離線、從未連線與時間窗;transport 或儀表板可見不能代替驗收。" }, "wazuh_live_route": { diff --git a/apps/web/src/app/[locale]/governance/page.tsx b/apps/web/src/app/[locale]/governance/page.tsx index 4a07bdcd6..e46f2dcfc 100644 --- a/apps/web/src/app/[locale]/governance/page.tsx +++ b/apps/web/src/app/[locale]/governance/page.tsx @@ -13,6 +13,7 @@ * @created 2026-05-02 Claude Sonnet 4.6 — governance PR 2 */ +import { useEffect, useState } from 'react' import { useTranslations } from 'next-intl' import Link from 'next/link' import { @@ -33,12 +34,11 @@ import { AutomationInventoryTab } from './tabs/automation-inventory-tab' export default function GovernancePage({ params, - searchParams, }: { params: { locale: string } - searchParams?: { tab?: string | string[] } }) { const t = useTranslations('governance') + const [requestedTab, setRequestedTab] = useState(undefined) const governanceSections = [ { id: 'slo', order: '01', label: t('tabs.slo'), content: , Icon: Radar }, @@ -47,14 +47,16 @@ export default function GovernancePage({ { id: 'agent-market', order: '04', label: t('tabs.agentMarket'), content: , Icon: BrainCircuit }, { id: 'automation-inventory', order: '05', label: t('tabs.automationInventory'), content: , Icon: ShieldCheck }, ] - const requestedTab = Array.isArray(searchParams?.tab) ? searchParams?.tab[0] : searchParams?.tab const activeSection = governanceSections.find(section => section.id === requestedTab) ?? governanceSections[0] - const orderedSections = activeSection - ? [ - activeSection, - ...governanceSections.filter(section => section.id !== activeSection.id), - ] - : governanceSections + + useEffect(() => { + const tab = new URLSearchParams(window.location.search).get('tab') ?? undefined + setRequestedTab(tab) + + if (!tab) return + const section = document.getElementById(tab) + section?.scrollIntoView({ block: 'start' }) + }, []) return ( @@ -99,12 +101,12 @@ export default function GovernancePage({ })} -
- {orderedSections.map((section) => { +
+ {governanceSections.map((section) => { const Icon = section.Icon return ( -
-
+
+