feat(iwooos): 顯示 Wazuh 即時中繼資料閘門
This commit is contained in:
@@ -19003,6 +19003,59 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"wazuhLiveMetadataEnvGate": {
|
||||
"eyebrow": "Wazuh 即時中繼資料環境閘門",
|
||||
"title": "Wazuh 查詢要等正式路由、負責人與機密中繼資料都過關",
|
||||
"subtitle": "這張卡把 Wazuh 即時中繼資料啟用前的條件拆開:正式路由讀回、伺服端環境變數負責人、機密來源中繼資料、管理節點健康、唯讀帳號範圍與啟用後讀回都要先補齊;目前即時查詢、主動回應、主機寫入與執行期閘門都是 0。",
|
||||
"checkLabel": "檢核",
|
||||
"stateLabel": "狀態",
|
||||
"boundaryTitle": "即時中繼資料環境邊界",
|
||||
"boundaryIntro": "以下鍵值固定:正式路由 200、Wazuh 已建置或 UI 可見都不能直接代表可以查 Wazuh 即時中繼資料;不得收機密明文值、不得改 K8s 機密、不得用 Nginx 或主機操作繞過釋出閘門。",
|
||||
"summary": {
|
||||
"routeReadback": {
|
||||
"label": "路由讀回",
|
||||
"detail": "正式部署後讀回尚未通過,因此仍不能啟用即時中繼資料。"
|
||||
},
|
||||
"owner": {
|
||||
"label": "負責人回覆",
|
||||
"detail": "伺服端環境變數與啟用責任尚未被審查者接受。"
|
||||
},
|
||||
"secretMeta": {
|
||||
"label": "機密中繼資料",
|
||||
"detail": "只允許機密來源中繼資料與負責人,不收密碼、權杖或雜湊值。"
|
||||
},
|
||||
"liveQuery": {
|
||||
"label": "即時查詢",
|
||||
"detail": "Wazuh API 即時查詢授權目前維持 0。"
|
||||
}
|
||||
},
|
||||
"items": {
|
||||
"releaseReadback": {
|
||||
"title": "先等正式路由不再 404",
|
||||
"body": "部署後必須用正式讀回指令驗證 `/api/iwooos/wazuh`,不能用部署前 404 或閘道繞路當成功。"
|
||||
},
|
||||
"serverEnv": {
|
||||
"title": "伺服端環境變數需負責人",
|
||||
"body": "IWOOOS_WAZUH_READONLY_ENABLED 與 Wazuh API 環境變數只能由正式伺服端流程注入,不能寫到前端 bundle。"
|
||||
},
|
||||
"secretMetadata": {
|
||||
"title": "機密只收中繼資料",
|
||||
"body": "只記錄注入來源、負責人、維護窗口與回滾路徑;不得貼密碼、權杖、Cookie、工作階段或任何機密片段。"
|
||||
},
|
||||
"managerHealth": {
|
||||
"title": "Wazuh 管理節點健康待參照",
|
||||
"body": "需要管理節點、API 與 TLS 健康狀態的脫敏參照;不能只用 Wazuh 已安裝或儀表板可見判斷。"
|
||||
},
|
||||
"readonlyScope": {
|
||||
"title": "唯讀帳號範圍待驗",
|
||||
"body": "只允許中繼資料查詢範圍;主動回應、規則變更、解碼器變更與主機操作必須留在另一個閘門。"
|
||||
},
|
||||
"postEnable": {
|
||||
"title": "啟用後還要讀回",
|
||||
"body": "即使未來環境變數啟用,也必須再驗證不回傳原始載荷、代理端原名、內網 IP 或機密。"
|
||||
}
|
||||
}
|
||||
},
|
||||
"socSiemKaliWazuhIntegration": {
|
||||
"eyebrow": "SOC / SIEM / Kali 112 整合控制",
|
||||
"title": "把 Wazuh、Kali、告警鏈與主流資安機制接成同一條證據線",
|
||||
|
||||
@@ -19003,6 +19003,59 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"wazuhLiveMetadataEnvGate": {
|
||||
"eyebrow": "Wazuh 即時中繼資料環境閘門",
|
||||
"title": "Wazuh 查詢要等正式路由、負責人與機密中繼資料都過關",
|
||||
"subtitle": "這張卡把 Wazuh 即時中繼資料啟用前的條件拆開:正式路由讀回、伺服端環境變數負責人、機密來源中繼資料、管理節點健康、唯讀帳號範圍與啟用後讀回都要先補齊;目前即時查詢、主動回應、主機寫入與執行期閘門都是 0。",
|
||||
"checkLabel": "檢核",
|
||||
"stateLabel": "狀態",
|
||||
"boundaryTitle": "即時中繼資料環境邊界",
|
||||
"boundaryIntro": "以下鍵值固定:正式路由 200、Wazuh 已建置或 UI 可見都不能直接代表可以查 Wazuh 即時中繼資料;不得收機密明文值、不得改 K8s 機密、不得用 Nginx 或主機操作繞過釋出閘門。",
|
||||
"summary": {
|
||||
"routeReadback": {
|
||||
"label": "路由讀回",
|
||||
"detail": "正式部署後讀回尚未通過,因此仍不能啟用即時中繼資料。"
|
||||
},
|
||||
"owner": {
|
||||
"label": "負責人回覆",
|
||||
"detail": "伺服端環境變數與啟用責任尚未被審查者接受。"
|
||||
},
|
||||
"secretMeta": {
|
||||
"label": "機密中繼資料",
|
||||
"detail": "只允許機密來源中繼資料與負責人,不收密碼、權杖或雜湊值。"
|
||||
},
|
||||
"liveQuery": {
|
||||
"label": "即時查詢",
|
||||
"detail": "Wazuh API 即時查詢授權目前維持 0。"
|
||||
}
|
||||
},
|
||||
"items": {
|
||||
"releaseReadback": {
|
||||
"title": "先等正式路由不再 404",
|
||||
"body": "部署後必須用正式讀回指令驗證 `/api/iwooos/wazuh`,不能用部署前 404 或閘道繞路當成功。"
|
||||
},
|
||||
"serverEnv": {
|
||||
"title": "伺服端環境變數需負責人",
|
||||
"body": "IWOOOS_WAZUH_READONLY_ENABLED 與 Wazuh API 環境變數只能由正式伺服端流程注入,不能寫到前端 bundle。"
|
||||
},
|
||||
"secretMetadata": {
|
||||
"title": "機密只收中繼資料",
|
||||
"body": "只記錄注入來源、負責人、維護窗口與回滾路徑;不得貼密碼、權杖、Cookie、工作階段或任何機密片段。"
|
||||
},
|
||||
"managerHealth": {
|
||||
"title": "Wazuh 管理節點健康待參照",
|
||||
"body": "需要管理節點、API 與 TLS 健康狀態的脫敏參照;不能只用 Wazuh 已安裝或儀表板可見判斷。"
|
||||
},
|
||||
"readonlyScope": {
|
||||
"title": "唯讀帳號範圍待驗",
|
||||
"body": "只允許中繼資料查詢範圍;主動回應、規則變更、解碼器變更與主機操作必須留在另一個閘門。"
|
||||
},
|
||||
"postEnable": {
|
||||
"title": "啟用後還要讀回",
|
||||
"body": "即使未來環境變數啟用,也必須再驗證不回傳原始載荷、代理端原名、內網 IP 或機密。"
|
||||
}
|
||||
}
|
||||
},
|
||||
"socSiemKaliWazuhIntegration": {
|
||||
"eyebrow": "SOC / SIEM / Kali 112 整合控制",
|
||||
"title": "把 Wazuh、Kali、告警鏈與主流資安機制接成同一條證據線",
|
||||
|
||||
@@ -271,6 +271,14 @@ type WazuhIntrusionReadbackItem = {
|
||||
tone: 'steady' | 'warn' | 'locked'
|
||||
}
|
||||
|
||||
type WazuhLiveMetadataEnvGateItem = {
|
||||
key: string
|
||||
check: string
|
||||
state: string
|
||||
icon: typeof ShieldCheck
|
||||
tone: 'steady' | 'warn' | 'locked'
|
||||
}
|
||||
|
||||
type SocSiemKaliWazuhIntegrationItem = {
|
||||
key: string
|
||||
check: string
|
||||
@@ -2182,6 +2190,50 @@ const wazuhIntrusionReadbackBoundaries = [
|
||||
'not_authorization=true',
|
||||
] as const
|
||||
|
||||
const wazuhLiveMetadataEnvGateSummary = [
|
||||
{ key: 'routeReadback', value: '0', icon: Route, tone: 'locked' },
|
||||
{ key: 'owner', value: '0', icon: ClipboardCheck, tone: 'locked' },
|
||||
{ key: 'secretMeta', value: '0', icon: Lock, tone: 'locked' },
|
||||
{ key: 'liveQuery', value: '0', icon: Radar, tone: 'locked' },
|
||||
] as const
|
||||
|
||||
const wazuhLiveMetadataEnvGateItems: WazuhLiveMetadataEnvGateItem[] = [
|
||||
{ key: 'releaseReadback', check: 'ENV-1', state: '待部署驗證', icon: Route, tone: 'locked' },
|
||||
{ key: 'serverEnv', check: 'ENV-2', state: '待負責人', icon: Server, tone: 'warn' },
|
||||
{ key: 'secretMetadata', check: 'ENV-3', state: '只收中繼資料', icon: Lock, tone: 'locked' },
|
||||
{ key: 'managerHealth', check: 'ENV-4', state: '待健康參照', icon: Activity, tone: 'warn' },
|
||||
{ key: 'readonlyScope', check: 'ENV-5', state: '待範圍參照', icon: ShieldCheck, tone: 'warn' },
|
||||
{ key: 'postEnable', check: 'ENV-6', state: '待讀回驗證', icon: SearchCheck, tone: 'locked' },
|
||||
] as const
|
||||
|
||||
const wazuhLiveMetadataEnvGateBoundaries = [
|
||||
'wazuh_live_metadata_env_gate_visible=true',
|
||||
'wazuh_live_metadata_env_gate_server_side_env_key_count=4',
|
||||
'wazuh_live_metadata_env_gate_required_owner_field_count=15',
|
||||
'wazuh_live_metadata_env_gate_reviewer_check_count=15',
|
||||
'wazuh_live_metadata_env_gate_outcome_lane_count=10',
|
||||
'wazuh_live_metadata_env_gate_blocked_action_count=23',
|
||||
'wazuh_live_metadata_env_gate_production_route_readback_passed_count=0',
|
||||
'wazuh_live_metadata_env_gate_live_metadata_owner_response_accepted_count=0',
|
||||
'wazuh_live_metadata_env_gate_secret_source_metadata_accepted_count=0',
|
||||
'wazuh_live_metadata_env_gate_wazuh_manager_health_ref_accepted_count=0',
|
||||
'wazuh_live_metadata_env_gate_readonly_account_scope_accepted_count=0',
|
||||
'wazuh_live_metadata_env_gate_post_enable_readback_passed_count=0',
|
||||
'wazuh_live_metadata_env_gate_wazuh_api_live_query_authorized_count=0',
|
||||
'wazuh_live_metadata_env_gate_wazuh_active_response_authorized_count=0',
|
||||
'wazuh_live_metadata_env_gate_runtime_gate_count=0',
|
||||
'secret_value_collection_allowed=false',
|
||||
'raw_wazuh_payload_storage_allowed=false',
|
||||
'k8s_secret_patch_authorized=false',
|
||||
'argocd_sync_authorized=false',
|
||||
'docker_restart_authorized=false',
|
||||
'nginx_gateway_workaround_authorized=false',
|
||||
'firewall_change_authorized=false',
|
||||
'host_write_authorized=false',
|
||||
'kali_active_scan_authorized=false',
|
||||
'not_authorization=true',
|
||||
] as const
|
||||
|
||||
const socSiemKaliWazuhIntegrationSummary = [
|
||||
{ key: 'frameworks', value: '7', icon: ClipboardCheck, tone: 'steady' },
|
||||
{ key: 'domains', value: '16', icon: Network, tone: 'steady' },
|
||||
@@ -7669,6 +7721,137 @@ function IwoooSWazuhIntrusionReadbackBoard() {
|
||||
)
|
||||
}
|
||||
|
||||
function IwoooSWazuhLiveMetadataEnvGateBoard() {
|
||||
const t = useTranslations('iwooos.wazuhLiveMetadataEnvGate')
|
||||
const textWrap = { overflowWrap: 'anywhere' as const, wordBreak: 'break-word' as const }
|
||||
|
||||
return (
|
||||
<section
|
||||
style={{ marginBottom: 14, maxWidth: '100%', overflow: 'hidden' }}
|
||||
data-testid="iwooos-wazuh-live-metadata-env-gate-board"
|
||||
>
|
||||
<div style={{ ...band, padding: 16, background: '#f8fbf7', borderColor: '#c7dec4' }}>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(min(100%, 300px), 1fr))', gap: 14 }}>
|
||||
<div style={{ minWidth: 0 }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 8, color: '#3f6d3c', fontSize: 12, fontWeight: 700 }}>
|
||||
<Server size={17} color="#4b7d47" />
|
||||
{t('eyebrow')}
|
||||
</div>
|
||||
<h2 style={{ fontSize: 17, margin: '8px 0 0', color: '#141413' }}>{t('title')}</h2>
|
||||
<p style={{ fontSize: 12, color: '#47683f', margin: '6px 0 0', lineHeight: 1.55, ...textWrap }}>
|
||||
{t('subtitle')}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(126px, 1fr))', gap: 8 }}>
|
||||
{wazuhLiveMetadataEnvGateSummary.map(item => {
|
||||
const Icon = item.icon
|
||||
return (
|
||||
<div key={item.key} style={{ border: '0.5px solid #d2e4cf', borderRadius: 8, padding: 12, background: '#fff' }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8 }}>
|
||||
<span style={{ fontSize: 11, color: '#607a5c' }}>{t(`summary.${item.key}.label` as never)}</span>
|
||||
<Icon size={16} color={toneColors[item.tone]} />
|
||||
</div>
|
||||
<div style={{ fontSize: 19, fontWeight: 700, color: toneColors[item.tone], lineHeight: 1.1, marginTop: 8, ...textWrap }}>
|
||||
{item.value}
|
||||
</div>
|
||||
<p style={{ fontSize: 11, color: '#47683f', lineHeight: 1.45, margin: '8px 0 0', ...textWrap }}>
|
||||
{t(`summary.${item.key}.detail` as never)}
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
marginTop: 14,
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(auto-fit, minmax(min(100%, 210px), 1fr))',
|
||||
gap: 10,
|
||||
}}
|
||||
>
|
||||
{wazuhLiveMetadataEnvGateItems.map(item => {
|
||||
const Icon = item.icon
|
||||
return (
|
||||
<div
|
||||
key={item.key}
|
||||
style={{
|
||||
border: '0.5px solid #d2e4cf',
|
||||
borderRadius: 8,
|
||||
background: item.tone === 'locked' ? '#f5f8f4' : '#fff',
|
||||
padding: 13,
|
||||
minHeight: 158,
|
||||
display: 'grid',
|
||||
alignContent: 'space-between',
|
||||
minWidth: 0,
|
||||
...textWrap,
|
||||
}}
|
||||
>
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8 }}>
|
||||
<span style={{ color: toneColors[item.tone], fontSize: 12, fontWeight: 700 }}>
|
||||
{t('checkLabel')} {item.check}
|
||||
</span>
|
||||
<Icon size={18} color={toneColors[item.tone]} />
|
||||
</div>
|
||||
<div style={{ minWidth: 0 }}>
|
||||
<div style={{ fontSize: 15, fontWeight: 700, color: '#141413', lineHeight: 1.25 }}>
|
||||
{t(`items.${item.key}.title` as never)}
|
||||
</div>
|
||||
<div style={{ fontSize: 12, color: toneColors[item.tone], fontWeight: 700, marginTop: 5 }}>
|
||||
{t('stateLabel')}:{item.state}
|
||||
</div>
|
||||
</div>
|
||||
<p style={{ fontSize: 11, color: '#47683f', lineHeight: 1.45, margin: 0, ...textWrap }}>
|
||||
{t(`items.${item.key}.body` as never)}
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
<details
|
||||
data-testid="iwooos-wazuh-live-metadata-env-gate-boundaries"
|
||||
style={{
|
||||
marginTop: 12,
|
||||
border: '0.5px solid #d2e4cf',
|
||||
borderRadius: 8,
|
||||
background: '#fff',
|
||||
padding: '8px 10px',
|
||||
}}
|
||||
>
|
||||
<summary style={{ cursor: 'pointer', fontSize: 12, fontWeight: 700, color: '#3f6d3c' }}>
|
||||
{t('boundaryTitle')}
|
||||
</summary>
|
||||
<p style={{ fontSize: 11, color: '#47683f', lineHeight: 1.5, margin: '8px 0', ...textWrap }}>
|
||||
{t('boundaryIntro')}
|
||||
</p>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(230px, 1fr))', gap: 6 }}>
|
||||
{wazuhLiveMetadataEnvGateBoundaries.map(item => (
|
||||
<code
|
||||
key={item}
|
||||
style={{
|
||||
border: '0.5px solid #d2e4cf',
|
||||
borderRadius: 8,
|
||||
padding: '6px 8px',
|
||||
color: '#47683f',
|
||||
fontSize: 11,
|
||||
lineHeight: 1.4,
|
||||
background: '#f8fbf7',
|
||||
overflowWrap: 'anywhere',
|
||||
}}
|
||||
>
|
||||
{item}
|
||||
</code>
|
||||
))}
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
function IwoooSSocSiemKaliWazuhIntegrationBoard() {
|
||||
const t = useTranslations('iwooos.socSiemKaliWazuhIntegration')
|
||||
const textWrap = { overflowWrap: 'anywhere' as const, wordBreak: 'break-word' as const }
|
||||
@@ -20592,6 +20775,7 @@ export default function IwoooSPage({ params }: { params: { locale: string } }) {
|
||||
<IwoooSAgentBountySecurityOnboardingBoard />
|
||||
<IwoooSRolloutRiskReadOnlyBoard />
|
||||
<IwoooSWazuhIntrusionReadbackBoard />
|
||||
<IwoooSWazuhLiveMetadataEnvGateBoard />
|
||||
<IwoooSSocSiemKaliWazuhIntegrationBoard />
|
||||
<IwoooSSecurityAssetControlLedgerBoard />
|
||||
<IwoooSExternalHostIntrusionPreventionControlBoard />
|
||||
|
||||
@@ -35,6 +35,41 @@
|
||||
|
||||
**邊界**:本輪沒有手動 import、沒有 Drive write、沒有 DB restore / truncate、沒有 Docker / Nginx / firewall / K8s / ArgoCD runtime 寫入,沒有 Wazuh / SOC 修改,沒有使用聊天中的密碼,也沒有讀取或保存 secret。
|
||||
|
||||
## 2026-06-24|IwoooS Wazuh 即時中繼資料環境閘門前台驗證
|
||||
|
||||
**背景**:Wazuh 只讀 API source-side 修補、release gate、release lane preflight、owner request / acceptance 與 live metadata env gate 已完成,但 production 尚未部署,`/api/iwooos/wazuh` 仍不可用來代表 Wazuh runtime 狀態。本輪補上 IwoooS 前台可視化卡片,讓使用者在 `/zh-TW/iwooos` 直接看到「正式路由讀回、伺服端環境變數負責人、機密中繼資料、管理節點健康、唯讀帳號範圍、啟用後讀回」全部仍為 `0`,避免把 Wazuh 已建置或 UI 可見誤判為可查 live metadata。
|
||||
|
||||
**Source-side 完成**:
|
||||
- `apps/web/src/app/[locale]/iwooos/page.tsx` 新增 `IwoooSWazuhLiveMetadataEnvGateBoard`,位置在 Wazuh 入侵 readback 與 SOC / SIEM / Kali 整合卡之間。
|
||||
- `apps/web/messages/zh-TW.json` 與 `apps/web/messages/en.json` 新增同一份繁中鏡像文案;前台文案改為「負責人回覆、路由讀回、機密中繼資料、即時查詢」等產品治理語,不放工作視窗逐字稿、委派 XML、聊天內容或個人英文名稱。
|
||||
- 卡片邊界固定:`wazuh_live_metadata_env_gate_visible=true`、`production_route_readback_passed_count=0`、`live_metadata_owner_response_accepted_count=0`、`secret_source_metadata_accepted_count=0`、`wazuh_api_live_query_authorized_count=0`、`wazuh_active_response_authorized_count=0`、`runtime_gate_count=0`、`secret_value_collection_allowed=false`、`host_write_authorized=false`、`kali_active_scan_authorized=false`。
|
||||
|
||||
**驗證**:
|
||||
- `node -e "JSON.parse(...zh-TW...); JSON.parse(...en...)"`:通過。
|
||||
- `cmp -s apps/web/messages/zh-TW.json apps/web/messages/en.json`:通過,維持繁中鏡像。
|
||||
- `pytest apps/api/tests/test_iwooos_wazuh_api.py`:`4 passed`。
|
||||
- `python3 scripts/security/security-mirror-progress-guard.py --root .`:`SECURITY_MIRROR_PROGRESS_GUARD_OK`。
|
||||
- `python3 scripts/security/wazuh-readonly-route-boundary-guard.py --root .`:`route=2 public_ui_files=1 forbidden=0 runtime_gate=0`。
|
||||
- `python3 scripts/security/wazuh-readonly-release-gate.py --root .`:`source=1 push=0 deploy=0 readback=0 runtime_gate=0`。
|
||||
- `python3 scripts/security/wazuh-readonly-release-lane-preflight.py --root .`:`ready=0 acks=0/6 evidence=0/6 runtime_gate=0`。
|
||||
- `python3 scripts/security/wazuh-readonly-release-owner-request.py --root .`:`drafts=1 sent=0 accepted=0 runtime_gate=0`。
|
||||
- `python3 scripts/security/wazuh-readonly-release-owner-response-acceptance.py --root .`:`received=0 accepted=0 acks=0/6 evidence=0/6 runtime_gate=0`。
|
||||
- `python3 scripts/security/wazuh-readonly-live-metadata-env-gate.py --root .`:`route_readback=0 owner=0 secret_meta=0 live_query=0 runtime_gate=0`。
|
||||
- `pnpm --filter @awoooi/web typecheck`:通過。
|
||||
- 首次未帶 `NEXT_PUBLIC_API_URL` 的 build 依既有前端禁令在 prerender 階段 fail;重跑 `NEXT_PUBLIC_API_URL=https://awoooi.wooo.work NEXT_PRIVATE_BUILD_WORKER_COUNT=1 SENTRY_SUPPRESS_GLOBAL_ERROR_HANDLER_FILE_WARNING=1 pnpm --filter @awoooi/web build` 通過,`92/92` static pages,`/zh-TW/iwooos` route size `61.8 kB`、First Load JS `292 kB`。
|
||||
- 本機 preview `http://localhost:3137/zh-TW/iwooos?_v=wazuh-live-metadata-env-local` 桌機寬度:卡片可見、`scrollWidth=clientWidth=1434`、水平溢出 `false`、未命中工作視窗、委派、來源執行緒、外部對話與通知暱稱等內部協作詞;卡片也未命中英文流程裸字。
|
||||
- 本機 preview 手機寬度 `390x844`:卡片可見、`scrollWidth=clientWidth=384`、水平溢出 `false`,同樣未命中工作視窗字樣與英文流程裸字。
|
||||
|
||||
**完成度**:
|
||||
- Wazuh live metadata env gate source / guard:`100%`。
|
||||
- IwoooS 前台卡片 source / 本機桌機與手機驗證:`100%`。
|
||||
- Production deploy:`0%`。
|
||||
- Production `/api/iwooos/wazuh` readback:`0%`,部署前仍只允許 `predeploy_404_observed`。
|
||||
- Wazuh server-side env enable:`0%`。
|
||||
- Wazuh live query、active response、host write、Kali active scan、SOAR action:全部維持 `0 / false`。
|
||||
|
||||
**邊界**:本輪沒有 push、沒有 deploy、沒有 Nginx / Docker / K8s / firewall / Wazuh manager / secret / runtime 寫入,沒有 active scan,沒有收集或保存任何 secret value;只做 source、docs、guard、本機 build 與本機瀏覽器驗證。
|
||||
|
||||
## 2026-06-24|22:40 MOMO source absence readback 與資料 freshness blocker 定位
|
||||
|
||||
**背景**:22:17 已完成 MOMO import-boundary production deploy 驗證與 full cold-start refresh,但 cold-start 仍因 `MOMO_DAILY_FRESHNESS 7|2026-06-17` 保持 `BLOCKED=1`。本輪只做 MOMO scheduler / DB / import metadata 的 read-only 追查,目標是判斷資料停更是服務、版本、DB 同步、排程或來源缺席。
|
||||
|
||||
@@ -40,6 +40,9 @@
|
||||
- `docs/security/wazuh-readonly-release-owner-request.snapshot.json`
|
||||
- `docs/security/wazuh-readonly-release-owner-response-acceptance.snapshot.json`
|
||||
- `docs/security/wazuh-readonly-live-metadata-env-gate.snapshot.json`
|
||||
- `apps/web/src/app/[locale]/iwooos/page.tsx`
|
||||
- `apps/web/messages/zh-TW.json`
|
||||
- `apps/web/messages/en.json`
|
||||
- `docs/LOGBOOK.md`
|
||||
|
||||
完成內容:
|
||||
@@ -57,6 +60,7 @@
|
||||
- 新增 release lane preflight snapshot 與 guard,固定正式 release 前必須選擇 `formal_gitea_merge`、`formal_patch_apply` 或 `maintainer_local_push_with_safe_credential` 其中一條合規 lane,且 owner ack / evidence 未到齊前不得 push、deploy、force push、使用明文 token workaround 或改 runtime。
|
||||
- 新增 release owner request 草稿與 owner response acceptance 帳本,將 required ack flags、required evidence fields、allowed release methods、blocked actions、forbidden payloads 與 reviewer checks 機器可讀化;目前 request sent、response received / accepted、release ready、runtime gate 全部維持 `0`。
|
||||
- 新增 live metadata env gate,固定部署後要先通過 production route readback、server-side env owner response、secret source metadata、Wazuh manager health ref、readonly account scope、post-enable readback、rollback 與 no-secret / no-raw-payload attestation;目前 live query authorized 仍為 `0`。
|
||||
- 新增 IwoooS 前台「Wazuh 即時中繼資料環境閘門」卡片,公開顯示上述 gate 的 `0 / false` 邊界;文案全部為繁體中文治理語,不放工作視窗逐字稿、委派 XML、聊天內容或個人英文名稱。
|
||||
|
||||
## 已完成驗證
|
||||
|
||||
@@ -74,6 +78,10 @@ python3 scripts/security/security-mirror-progress-guard.py --root .
|
||||
python3 scripts/ops/doc-secrets-sanity-check.py docs apps/api/src/api/v1/iwooos.py apps/web/src/app/api/iwooos/wazuh/route.ts scripts/security/wazuh-readonly-route-boundary-guard.py scripts/security/wazuh-readonly-production-readback.py scripts/security/wazuh-readonly-release-gate.py scripts/security/wazuh-readonly-release-lane-preflight.py scripts/security/wazuh-readonly-release-owner-request.py scripts/security/wazuh-readonly-release-owner-response-acceptance.py scripts/security/wazuh-readonly-live-metadata-env-gate.py
|
||||
python3 -m py_compile apps/api/src/api/v1/iwooos.py scripts/security/wazuh-readonly-route-boundary-guard.py scripts/security/wazuh-readonly-production-readback.py scripts/security/wazuh-readonly-release-gate.py scripts/security/wazuh-readonly-release-lane-preflight.py scripts/security/wazuh-readonly-release-owner-request.py scripts/security/wazuh-readonly-release-owner-response-acceptance.py scripts/security/wazuh-readonly-live-metadata-env-gate.py scripts/security/security-mirror-progress-guard.py
|
||||
git diff --check
|
||||
node -e "JSON.parse(require('fs').readFileSync('apps/web/messages/zh-TW.json','utf8')); JSON.parse(require('fs').readFileSync('apps/web/messages/en.json','utf8')); console.log('i18n json ok')"
|
||||
cmp -s apps/web/messages/zh-TW.json apps/web/messages/en.json
|
||||
pnpm --filter @awoooi/web typecheck
|
||||
NEXT_PUBLIC_API_URL=https://awoooi.wooo.work NEXT_PRIVATE_BUILD_WORKER_COUNT=1 SENTRY_SUPPRESS_GLOBAL_ERROR_HANDLER_FILE_WARNING=1 pnpm --filter @awoooi/web build
|
||||
```
|
||||
|
||||
驗證結果:
|
||||
@@ -89,6 +97,12 @@ git diff --check
|
||||
- `doc-secrets-sanity-check`:`DOC_SECRET_SANITY_OK scanned_files=973`。
|
||||
- `py_compile`:通過。
|
||||
- `git diff --check`:通過。
|
||||
- i18n JSON parse:通過。
|
||||
- `zh-TW` / `en` messages mirror:通過。
|
||||
- `pnpm --filter @awoooi/web typecheck`:通過。
|
||||
- Web production build:通過,`92/92` static pages,`/zh-TW/iwooos` route size `61.8 kB`、First Load JS `292 kB`;build env 使用公網 `NEXT_PUBLIC_API_URL=https://awoooi.wooo.work`,未使用內網 IP。
|
||||
- 本機 preview desktop:`/zh-TW/iwooos` 卡片可見,水平溢出 `false`,沒有工作視窗 / 委派 / 對話字樣,卡片沒有英文流程裸字。
|
||||
- 本機 preview mobile `390x844`:卡片可見,水平溢出 `false`,同樣沒有工作視窗 / 委派 / 對話字樣。
|
||||
|
||||
## 乾淨套用 Proof
|
||||
|
||||
@@ -185,6 +199,7 @@ python3 scripts/security/wazuh-readonly-production-readback.py --json
|
||||
| Wazuh release lane preflight | `100%` | 已完成;owner acks `0/6`、evidence `0/6`、正式 release ready `0` |
|
||||
| Wazuh release owner request / acceptance | `100%` | 已完成只讀草稿與收件帳本;request sent `0`、response accepted `0` |
|
||||
| Wazuh live metadata env gate | `100%` | 已完成只讀 gate;route readback / owner / secret metadata / live query 仍 `0` |
|
||||
| IwoooS 前台 Wazuh live metadata env gate 卡片 | `100%` | source-side 與本機桌機 / 手機驗證完成;production deploy 仍 `0` |
|
||||
| 乾淨套用 proof | `100%` | patch set 可落在最新 `gitea/main` 並通過同組 guard;最終 hash 以 release 前 readback 為準 |
|
||||
| Gitea push | `0%` | 受控 workspace HTTPS credential 缺失 |
|
||||
| Production deploy / readback | `0%` | 等待 release lane |
|
||||
|
||||
Reference in New Issue
Block a user