Merge remote-tracking branch 'gitea/main' into codex/delivery-workbench-release-20260626-ffsync

This commit is contained in:
ogt
2026-06-27 00:13:56 +08:00
10 changed files with 717 additions and 37 deletions

View File

@@ -38,6 +38,8 @@ import {
type IwoooSRuntimeSecurityReadbackResponse,
type IwoooSSecurityControlCoverageDomain,
type IwoooSSecurityControlCoverageResponse,
type IwoooSWazuhLiveMetadataGateItem,
type IwoooSWazuhLiveMetadataGateResponse,
} from '@/lib/api-client'
type PostureMetric = {
@@ -326,7 +328,15 @@ type WazuhReadonlyStatusResponse = {
}
type RuntimeSecurityReadbackSummaryItem = {
key: 'controlPlane' | 'runtimeAcceptance' | 'wazuhRegistry' | 'wazuhLive' | 'ownerAccepted' | 'kaliRuntime' | 'runtimeGate'
key:
| 'controlPlane'
| 'runtimeAcceptance'
| 'wazuhRegistry'
| 'wazuhLive'
| 'metadataGate'
| 'ownerAccepted'
| 'kaliRuntime'
| 'runtimeGate'
value: string
icon: typeof ShieldCheck
tone: 'steady' | 'warn' | 'locked'
@@ -2275,13 +2285,6 @@ const wazuhIntrusionReadbackBoundaries = [
'not_authorization=true',
] as const
const wazuhLiveMetadataEnvGateSummary = [
{ key: 'routeReadback', value: '1', icon: Route, tone: 'steady' },
{ 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 wazuhReleaseGateSummary = [
{ key: 'source', value: '1', icon: CheckCircle2, tone: 'steady' },
{ key: 'branch', value: '1', icon: GitBranch, tone: 'steady' },
@@ -2325,6 +2328,15 @@ const wazuhLiveMetadataEnvGateItems: WazuhLiveMetadataEnvGateItem[] = [
{ key: 'postEnable', check: 'ENV-6', state: '待讀回驗證', icon: SearchCheck, tone: 'locked' },
] as const
const wazuhLiveMetadataEnvGateItemKeyById: Record<IwoooSWazuhLiveMetadataGateItem['item_id'], WazuhLiveMetadataEnvGateItem['key']> = {
release_readback: 'releaseReadback',
server_env_owner: 'serverEnv',
secret_metadata: 'secretMetadata',
manager_health: 'managerHealth',
readonly_scope: 'readonlyScope',
post_enable_readback: 'postEnable',
}
const wazuhLiveMetadataEnvGateBoundaries = [
'wazuh_live_metadata_env_gate_visible=true',
'wazuh_live_metadata_env_gate_server_side_env_key_count=4',
@@ -8130,6 +8142,12 @@ function IwoooSRuntimeSecurityReadbackBoard() {
icon: Route,
tone: summary && summary.wazuh_live_metadata_available_count === 1 && summary.wazuh_live_route_degraded_count === 0 ? 'steady' : 'warn',
},
{
key: 'metadataGate',
value: summary ? String(summary.wazuh_live_metadata_gate_live_query_authorized_count) : '...',
icon: ClipboardCheck,
tone: 'locked',
},
{
key: 'ownerAccepted',
value: summary ? `${summary.owner_response_accepted_count}/${summary.owner_response_received_count}` : '...',
@@ -8882,6 +8900,86 @@ function IwoooSWazuhReleaseGateBoard() {
function IwoooSWazuhLiveMetadataEnvGateBoard() {
const t = useTranslations('iwooos.wazuhLiveMetadataEnvGate')
const textWrap = { overflowWrap: 'anywhere' as const, wordBreak: 'break-word' as const }
const [data, setData] = useState<IwoooSWazuhLiveMetadataGateResponse | null>(null)
const [loading, setLoading] = useState(true)
const [failed, setFailed] = useState(false)
useEffect(() => {
let mounted = true
async function loadGate() {
setLoading(true)
setFailed(false)
try {
const payload = await apiClient.getIwoooSWazuhLiveMetadataGate()
if (mounted) {
setData(payload)
}
} catch {
if (mounted) {
setData(null)
setFailed(true)
}
} finally {
if (mounted) {
setLoading(false)
}
}
}
loadGate()
return () => {
mounted = false
}
}, [])
const summary = data?.summary
const summaryItems = [
{
key: 'routeReadback',
value: summary ? String(summary.production_route_readback_passed_count) : loading ? '...' : '0',
icon: Route,
tone: summary?.production_route_readback_passed_count === 1 ? 'steady' : 'warn',
},
{
key: 'owner',
value: summary ? String(summary.live_metadata_owner_response_accepted_count) : loading ? '...' : '0',
icon: ClipboardCheck,
tone: 'locked',
},
{
key: 'secretMeta',
value: summary ? String(summary.secret_source_metadata_accepted_count) : loading ? '...' : '0',
icon: Lock,
tone: 'locked',
},
{
key: 'liveQuery',
value: summary ? String(summary.wazuh_api_live_query_authorized_count) : loading ? '...' : '0',
icon: Radar,
tone: 'locked',
},
] as const
const gateItems = data?.items?.length
? data.items.map(item => {
const key = wazuhLiveMetadataEnvGateItemKeyById[item.item_id]
const fallback = wazuhLiveMetadataEnvGateItems.find(candidate => candidate.key === key)
return {
key,
check: item.check,
state: t(`states.${item.state_key}` as never),
icon: fallback?.icon ?? FileWarning,
tone: item.tone,
}
})
: wazuhLiveMetadataEnvGateItems
const boundaryMarkers = data?.boundary_markers?.length
? data.boundary_markers
: loading
? [t('loadingBoundary')]
: wazuhLiveMetadataEnvGateBoundaries
const statusText = loading ? t('status.loading') : failed ? t('status.failed') : t('status.ready')
const statusTone: 'steady' | 'warn' | 'locked' = loading || failed ? 'warn' : 'locked'
return (
<section
@@ -8899,10 +8997,14 @@ function IwoooSWazuhLiveMetadataEnvGateBoard() {
<p style={{ fontSize: 12, color: '#47683f', margin: '6px 0 0', lineHeight: 1.55, ...textWrap }}>
{t('subtitle')}
</p>
<div style={{ marginTop: 8, display: 'inline-flex', alignItems: 'center', gap: 8, color: toneColors[statusTone], fontSize: 12, fontWeight: 700, ...textWrap }}>
<ToneDot tone={statusTone} />
{statusText}
</div>
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(126px, 1fr))', gap: 8 }}>
{wazuhLiveMetadataEnvGateSummary.map(item => {
{summaryItems.map(item => {
const Icon = item.icon
return (
<div key={item.key} style={{ border: '0.5px solid #d2e4cf', borderRadius: 8, padding: 12, background: '#fff' }}>
@@ -8930,7 +9032,7 @@ function IwoooSWazuhLiveMetadataEnvGateBoard() {
gap: 10,
}}
>
{wazuhLiveMetadataEnvGateItems.map(item => {
{gateItems.map(item => {
const Icon = item.icon
return (
<div
@@ -8986,7 +9088,7 @@ function IwoooSWazuhLiveMetadataEnvGateBoard() {
{t('boundaryIntro')}
</p>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(230px, 1fr))', gap: 6 }}>
{wazuhLiveMetadataEnvGateBoundaries.map(item => (
{boundaryMarkers.map(item => (
<code
key={item}
style={{

View File

@@ -101,6 +101,7 @@ export interface IwoooSRuntimeSecurityReadbackLane {
lane_id:
| 'wazuh_registry'
| 'wazuh_live_route'
| 'wazuh_live_metadata_gate'
| 'wazuh_dashboard_api'
| 'kali_intake'
| 'alert_readability'
@@ -141,6 +142,12 @@ export interface IwoooSRuntimeSecurityReadbackResponse {
wazuh_live_below_expected_count: number
wazuh_live_metadata_available_count: number
wazuh_live_status: string
wazuh_live_metadata_gate_owner_accepted_count: number
wazuh_live_metadata_gate_secret_source_accepted_count: number
wazuh_live_metadata_gate_manager_health_accepted_count: number
wazuh_live_metadata_gate_readonly_scope_accepted_count: number
wazuh_live_metadata_gate_post_enable_readback_count: number
wazuh_live_metadata_gate_live_query_authorized_count: number
kali_active_scan_authorized_count: number
kali_execute_authorized_count: number
kali_finding_envelope_accepted_count: number
@@ -154,6 +161,55 @@ export interface IwoooSRuntimeSecurityReadbackResponse {
no_false_green_rules: string[]
}
export interface IwoooSWazuhLiveMetadataGateItem {
item_id:
| 'release_readback'
| 'server_env_owner'
| 'secret_metadata'
| 'manager_health'
| 'readonly_scope'
| 'post_enable_readback'
check: string
state_key: string
tone: IwoooSRuntimeSecurityReadbackTone
metrics: Record<string, number>
}
export interface IwoooSWazuhLiveMetadataGateResponse {
schema_version: 'iwooos_wazuh_live_metadata_gate_readback_v1'
status: string
mode: string
source_refs: string[]
summary: {
server_side_env_key_count: number
required_owner_field_count: number
reviewer_check_count: number
outcome_lane_count: number
blocked_action_count: number
production_route_readback_passed_count: number
live_metadata_owner_response_received_count: number
live_metadata_owner_response_accepted_count: number
secret_source_metadata_accepted_count: number
wazuh_manager_health_ref_accepted_count: number
readonly_account_scope_accepted_count: number
post_enable_readback_passed_count: number
wazuh_api_live_query_authorized_count: number
wazuh_active_response_authorized_count: number
host_write_authorized_count: number
runtime_gate_count: number
wazuh_live_route_http_status: number
wazuh_live_route_degraded_count: number
wazuh_live_readonly_api_enabled_count: number
wazuh_live_agent_total: number
wazuh_live_metadata_available_count: number
wazuh_live_status: string
}
items: IwoooSWazuhLiveMetadataGateItem[]
boundary_markers: string[]
boundaries: Record<string, boolean>
no_false_green_rules: string[]
}
export interface IwoooSSecurityControlCoverageDomain {
domain_id:
| 'high_value_asset_control'
@@ -259,6 +315,11 @@ export const apiClient = {
return handleResponse<IwoooSRuntimeSecurityReadbackResponse>(res)
},
async getIwoooSWazuhLiveMetadataGate() {
const res = await fetch(`${API_BASE_URL}/iwooos/wazuh-live-metadata-gate`, { cache: 'no-store' })
return handleResponse<IwoooSWazuhLiveMetadataGateResponse>(res)
},
async getIwoooSSecurityControlCoverage() {
const res = await fetch(`${API_BASE_URL}/iwooos/security-control-coverage`, { cache: 'no-store' })
return handleResponse<IwoooSSecurityControlCoverageResponse>(res)