feat(web): add IwoooS security mesh matrix
All checks were successful
CD Pipeline / tests (push) Successful in 1m31s
Code Review / ai-code-review (push) Successful in 14s
CD Pipeline / build-and-deploy (push) Successful in 5m1s
CD Pipeline / post-deploy-checks (push) Successful in 2m2s

This commit is contained in:
Your Name
2026-05-31 21:27:59 +08:00
parent 537faf6427
commit 70dfb2eec3
6 changed files with 549 additions and 0 deletions

View File

@@ -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": "先把缺口收齊,不急著加管制",

View File

@@ -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": "先把缺口收齊,不急著加管制",

View File

@@ -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 (
<section
style={{ marginBottom: 14, maxWidth: '100%', overflow: 'hidden' }}
data-testid="iwooos-global-security-mesh-matrix-board"
>
<div style={{ ...band, padding: 16, background: '#f7fbfa', borderColor: '#cfe2d8' }}>
<div
style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(min(100%, 300px), 1fr))',
gap: 14,
alignItems: 'start',
}}
>
<div style={{ minWidth: 0 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, color: '#405f4f', fontSize: 12, fontWeight: 700 }}>
<Radar size={17} color="#1f7a4d" />
{t('eyebrow')}
</div>
<h2 style={{ fontSize: 17, margin: '8px 0 0', color: '#141413' }}>{t('title')}</h2>
<p style={{ fontSize: 12, color: '#405f4f', margin: '6px 0 0', lineHeight: 1.55, ...textWrap }}>
{t('subtitle')}
</p>
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(118px, 1fr))', gap: 8 }}>
{globalSecurityMeshMatrixSummary.map(item => {
const Icon = item.icon
return (
<div key={item.key} style={{ border: '0.5px solid #cfe2d8', borderRadius: 8, padding: 11, background: '#fff' }}>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8 }}>
<span style={{ fontSize: 11, color: '#607466' }}>{t(`summary.${item.key}.label` as never)}</span>
<Icon size={15} color={toneColors[item.tone]} />
</div>
<div style={{ fontSize: 19, fontWeight: 700, color: toneColors[item.tone], marginTop: 8, lineHeight: 1.1 }}>
{item.value}
</div>
<p style={{ fontSize: 11, color: '#405f4f', margin: '7px 0 0', lineHeight: 1.45, ...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%, 250px), 1fr))',
gap: 10,
}}
>
{globalSecurityMeshMatrixItems.map(item => {
const Icon = item.icon
return (
<div
key={item.key}
style={{
border: '0.5px solid #cfe2d8',
borderRadius: 8,
background: '#fff',
padding: 12,
minHeight: 184,
display: 'grid',
alignContent: 'space-between',
gap: 9,
minWidth: 0,
...textWrap,
}}
>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 10 }}>
<div style={{ minWidth: 0 }}>
<div style={{ fontSize: 11, color: '#607466', fontWeight: 700 }}>{item.code}</div>
<h3 style={{ fontSize: 14, margin: '5px 0 0', color: '#141413', lineHeight: 1.3 }}>
{t(`items.${item.key}.title` as never)}
</h3>
<p style={{ fontSize: 11, color: '#607466', margin: '5px 0 0', lineHeight: 1.4, ...textWrap }}>
{t(`items.${item.key}.layer` as never)}
</p>
</div>
<Icon size={18} color={toneColors[item.coverageTone]} />
</div>
<div style={{ display: 'grid', gap: 6 }}>
{[
{ 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 => (
<div
key={row.label}
style={{
display: 'grid',
gridTemplateColumns: '66px minmax(0, 1fr)',
gap: 8,
alignItems: 'center',
}}
>
<span style={{ fontSize: 10, color: '#7c847c' }}>{row.label}</span>
<span
style={{
border: `0.5px solid ${row.tone === 'steady' ? '#cfe2d8' : row.tone === 'warn' ? '#e6c8b8' : '#dad7ce'}`,
borderRadius: 999,
padding: '4px 8px',
color: toneColors[row.tone],
background: row.tone === 'steady' ? '#f7fbfa' : row.tone === 'warn' ? '#fffaf7' : '#f8f7f3',
fontSize: 11,
lineHeight: 1.2,
...textWrap,
}}
>
{row.value}
</span>
</div>
))}
</div>
<p style={{ fontSize: 11, color: '#405f4f', margin: 0, lineHeight: 1.45, ...textWrap }}>
<strong>{t('nextLabel')}</strong>{t(`items.${item.key}.next` as never)}
</p>
</div>
)
})}
</div>
<details
data-testid="iwooos-global-security-mesh-matrix-boundaries"
style={{
marginTop: 12,
border: '0.5px solid #cfe2d8',
borderRadius: 8,
background: '#fff',
padding: '8px 10px',
}}
>
<summary style={{ cursor: 'pointer', fontSize: 12, fontWeight: 700, color: '#405f4f' }}>
{t('boundaryTitle')}
</summary>
<p style={{ fontSize: 11, color: '#405f4f', lineHeight: 1.5, margin: '8px 0', ...textWrap }}>
{t('boundaryIntro')}
</p>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(230px, 1fr))', gap: 6 }}>
{globalSecurityMeshMatrixBoundaries.map(item => (
<code
key={item}
style={{
border: '0.5px solid #d9eadf',
borderRadius: 8,
padding: '6px 8px',
color: '#405f4f',
fontSize: 11,
lineHeight: 1.4,
background: '#f7fbfa',
overflowWrap: 'anywhere',
}}
>
{item}
</code>
))}
</div>
</details>
</div>
</section>
)
}
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 } }) {
<IwoooSVisualCommandDashboard />
<IwoooSProfessionalSecurityExperience />
<IwoooSConcreteWorkSnapshot />
<IwoooSGlobalSecurityMeshMatrixBoard />
<IwoooSVibeWorkSecurityOnboardingBoard />
<IwoooSSectionGroup

View File

@@ -1,3 +1,31 @@
## 2026-05-31IwoooS 全域資安納管矩陣首層化
**背景**
- 使用者批准繼續,並持續要求資安工作要看得懂、能知道哪些產品、主機、網站與工具已被納入。
- 前一輪已把 VibeWork 新專案收件卡放到首層;本輪把所有主要資產整理成同一張只讀矩陣,避免使用者必須在多個區塊之間拼湊狀態。
- 維持 Gate 0 與低摩擦策略:只呈現納管範圍、證據狀態與人工閘門,不新增掃描、修復、主機變更、部署或版本來源變更。
**本次調整**
- `/zh-TW/iwooos` 新增 `全域資安納管矩陣`
- 八類資產同表AwoooI 核心產品、AwoooP 工作流、IwoooS 資安入口、公開網站群、VibeWork、Kali 192.168.0.112、開發主機 192.168.0.111 / 192.168.0.168、GitHub / Gitea 版本來源。
- 每列固定顯示三個欄位:覆蓋、證據、執行;使用者能直接看到「已納入但執行期仍鎖住」。
- 摘要卡固定顯示 `8` 類資產、`8` 類只讀納管、`0` 個執行期閘門、下一閘門 `S4.9`
- `apps/web/messages/zh-TW.json``apps/web/messages/en.json` 維持繁體中文鏡像。
- `docs/security/iwooos-posture-projection.snapshot.json` 新增:
- `global_security_mesh_matrix_first_layer=true`
- `global_security_mesh_matrix_asset_count=8`
- `global_security_mesh_matrix_read_only_count=8`
- `global_security_mesh_matrix_runtime_gate_count=0`
- `display_global_security_mesh_matrix`
- `scripts/security/security-mirror-progress-guard.py` 新增矩陣頁面、文案、snapshot 與禁止開閘邊界檢查。
**進度邊界**
- 整體進度仍維持 `61%`;這是使用者理解度、前台可視化與納管清楚度前進,不是執行期開閘。
- Kali、開發主機與版本來源仍只讀納管沒有 `/execute`、沒有主機更新、沒有掃描、沒有 repo / refs / workflow / secret 變更。
## 2026-05-31VibeWork 新專案收件卡與只讀納管
**背景**

View File

@@ -52,6 +52,10 @@
"all_product_coverage_snapshot_runtime_ready_count": 0,
"all_product_coverage_snapshot_default_summary_mode": "compact_first",
"all_product_coverage_snapshot_detail_ledger_collapsed": true,
"global_security_mesh_matrix_first_layer": true,
"global_security_mesh_matrix_asset_count": 8,
"global_security_mesh_matrix_read_only_count": 8,
"global_security_mesh_matrix_runtime_gate_count": 0,
"vibework_security_onboarding_first_layer": true,
"vibework_security_onboarding_item_count": 6,
"vibework_security_onboarding_runtime_gate_count": 0,
@@ -259,6 +263,7 @@
"display_visual_command_dashboard",
"display_professional_security_experience",
"display_concrete_work_snapshot",
"display_global_security_mesh_matrix",
"display_vibework_security_onboarding",
"display_awooop_read_only_landing_readiness",
"display_awooop_cross_session_handoff_packets",

View File

@@ -1415,6 +1415,25 @@ def validate(root: Path) -> 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,