From 79ab8e3f88cd589b51dd51fa14f5a06fb0f22fc2 Mon Sep 17 00:00:00 2001 From: Your Name Date: Tue, 19 May 2026 21:06:58 +0800 Subject: [PATCH] feat(web): add IwoooS host coverage --- apps/web/messages/en.json | 22 ++++++ apps/web/messages/zh-TW.json | 22 ++++++ apps/web/src/app/[locale]/iwooos/page.tsx | 61 +++++++++++++++ docs/LOGBOOK.md | 14 ++++ .../iwooos_posture_projection_v1.schema.json | 76 +++++++++++++++++++ docs/security/IWOOOS-POSTURE-PROJECTION.md | 16 +++- .../security/SECURITY-MIRROR-STATUS-ROLLUP.md | 3 +- .../SECURITY-SUPPLY-CHAIN-PROGRESS.md | 4 +- .../iwooos-posture-projection.snapshot.json | 54 ++++++++++++- ...ecurity-mirror-status-rollup.snapshot.json | 12 +++ .../security-mirror-progress-guard.py | 52 +++++++++++++ 11 files changed, 332 insertions(+), 4 deletions(-) diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index c1e6e6ccc..ca7f38c39 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -1260,6 +1260,28 @@ } } }, + "hostCoverage": { + "title": "Host Coverage View", + "subtitle": "Places Kali and the two development hosts inside the visible IwoooS security scope. This only shows coverage and gate state; it does not create SSH, scan, update, or blocking controls.", + "stateLabel": "Current state", + "items": { + "kali112": { + "title": "Kali security host", + "body": "192.168.0.112 is the Kali node for the security mesh and is visible in posture and evidence refs as observe-only integration.", + "state": "in scope; active scan, /execute, and host updates still require separate approval" + }, + "dev168": { + "title": "Development host 168", + "body": "192.168.0.168 is included in IwoooS observe-only development host coverage for future scope approval and finding correlation.", + "state": "scope declared; credentialed scan and runtime control are not approved" + }, + "dev111": { + "title": "Development host 111", + "body": "192.168.0.111 is included in IwoooS observe-only development host coverage and stays paired with 168 for phased tightening.", + "state": "scope declared; credentialed scan and runtime control are not approved" + } + } + }, "nextGate": { "title": "Next High-level Gate", "body": "S4.9 Gitea owner attestation response is the recommended next owner evidence. Headline progress should only increase after owner responses, redacted payload ingestion, active runtime gates, or GitHub primary readiness actually change." diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index 6418e030c..30742937a 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -1261,6 +1261,28 @@ } } }, + "hostCoverage": { + "title": "主機覆蓋視圖", + "subtitle": "把 Kali 與兩台開發主機放進 IwoooS 的可見資安範圍。這裡只顯示納管與 gate 狀態,不建立 SSH、掃描、更新或阻擋控制。", + "stateLabel": "目前狀態", + "items": { + "kali112": { + "title": "Kali 資安主機", + "body": "192.168.0.112 是資安網的 Kali 節點,已在 posture 與 evidence refs 中作為 observe-only 整合面。", + "state": "已納入視野;active scan、/execute、主機更新仍需獨立批准" + }, + "dev168": { + "title": "開發主機 168", + "body": "192.168.0.168 納入 IwoooS 的 observe-only 開發主機覆蓋,用於後續 scope approval 與 finding 關聯。", + "state": "scope declared;尚未批准 credentialed scan 或 runtime control" + }, + "dev111": { + "title": "開發主機 111", + "body": "192.168.0.111 納入 IwoooS 的 observe-only 開發主機覆蓋,與 168 一起維持低摩擦分階段收斂。", + "state": "scope declared;尚未批准 credentialed scan 或 runtime control" + } + } + }, "nextGate": { "title": "下一個高層 Gate", "body": "S4.9 Gitea owner attestation response 是目前建議先收的 owner evidence。任何 headline 提升都要等 owner response、redacted payload ingestion、active runtime gate 或 GitHub primary readiness 有真實變化。" diff --git a/apps/web/src/app/[locale]/iwooos/page.tsx b/apps/web/src/app/[locale]/iwooos/page.tsx index 4fa2407da..01dd5316f 100644 --- a/apps/web/src/app/[locale]/iwooos/page.tsx +++ b/apps/web/src/app/[locale]/iwooos/page.tsx @@ -74,6 +74,13 @@ type EvidenceReadinessItem = { tone: 'steady' | 'warn' | 'locked' } +type HostCoverageItem = { + key: string + address: string + icon: typeof ShieldCheck + tone: 'steady' | 'warn' | 'locked' +} + const postureMetrics: PostureMetric[] = [ { key: 'overall', value: '58%', tone: 'warn' }, { key: 'framework', value: '80-85%', tone: 'steady' }, @@ -170,6 +177,12 @@ const evidenceReadinessItems: EvidenceReadinessItem[] = [ { key: 'followupRuntimeGate', lane: 'S3.4', icon: ShieldCheck, tone: 'locked' }, ] +const hostCoverageItems: HostCoverageItem[] = [ + { key: 'kali112', address: '192.168.0.112', icon: Activity, tone: 'steady' }, + { key: 'dev168', address: '192.168.0.168', icon: Radar, tone: 'warn' }, + { key: 'dev111', address: '192.168.0.111', icon: Radar, tone: 'warn' }, +] + const evidenceItems = [ 'iwooos-posture-projection.snapshot.json', 'security-rollout-policy.snapshot.json', @@ -416,6 +429,34 @@ function EvidenceReadinessCard({ item, index }: { item: EvidenceReadinessItem; i ) } +function HostCoverageCard({ item, index }: { item: HostCoverageItem; index: number }) { + const t = useTranslations('iwooos.hostCoverage') + const Icon = item.icon + return ( +
+
+
+ + {item.address} +
+ {String(index + 1).padStart(2, '0')} +
+

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

+

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

+
+
{t('stateLabel')}
+
+ {t(`items.${item.key}.state` as never)} +
+
+
+ ) +} + export default function IwoooSPage({ params }: { params: { locale: string } }) { const t = useTranslations('iwooos') @@ -488,6 +529,26 @@ export default function IwoooSPage({ params }: { params: { locale: string } }) { +
+
+

{t('hostCoverage.title')}

+

+ {t('hostCoverage.subtitle')} +

+
+
+ {hostCoverageItems.map((item, index) => ( + + ))} +
+
+
None: "s2_11_iwooos_surface_coverage_boundary_matrix", "s2_12_iwooos_operator_journey_projection", "s2_13_iwooos_owner_evidence_readiness_board", + "s2_14_iwooos_host_coverage_view", ] assert_equal( "progress_delta_ledger.delta_ids", @@ -333,6 +334,11 @@ def validate(root: Path) -> None: "s1_6_kali_scan_scope_approval", "s3_4_followup_runtime_gate", ] + expected_iwooos_host_coverage_item_ids = [ + "kali_112_security_host", + "dev_168_development_host", + "dev_111_development_host", + ] assert_equal( "iwooos_projection.summary.frontend_surface_coverage_group_count", iwooos_projection["summary"]["frontend_surface_coverage_group_count"], @@ -353,6 +359,11 @@ def validate(root: Path) -> None: iwooos_projection["summary"]["owner_evidence_readiness_item_count"], len(expected_iwooos_evidence_readiness_item_ids), ) + assert_equal( + "iwooos_projection.summary.host_coverage_item_count", + iwooos_projection["summary"]["host_coverage_item_count"], + len(expected_iwooos_host_coverage_item_ids), + ) iwooos_progress = iwooos_projection["progress"] assert_equal("iwooos_projection.progress.overall_percent", iwooos_progress["overall_percent"], progress["overall_percent"]) assert_equal( @@ -555,6 +566,43 @@ def validate(root: Path) -> None: f"iwooos_projection.owner_evidence_readiness_items.{item['item_id']}.not_authorization", item["not_authorization"], ) + iwooos_host_coverage = iwooos_projection["host_coverage_items"] + assert_equal( + "iwooos_projection.host_coverage_items.ids", + [item["host_id"] for item in iwooos_host_coverage], + expected_iwooos_host_coverage_item_ids, + ) + assert_equal( + "iwooos_projection.host_coverage_items.display_order", + [item["display_order"] for item in iwooos_host_coverage], + list(range(1, len(expected_iwooos_host_coverage_item_ids) + 1)), + ) + for item in iwooos_host_coverage: + assert_equal( + f"iwooos_projection.host_coverage_items.{item['host_id']}.display_mode", + item["display_mode"], + "coverage_only", + ) + assert_false( + f"iwooos_projection.host_coverage_items.{item['host_id']}.active_scan_authorized", + item["active_scan_authorized"], + ) + assert_false( + f"iwooos_projection.host_coverage_items.{item['host_id']}.ssh_change_authorized", + item["ssh_change_authorized"], + ) + assert_false( + f"iwooos_projection.host_coverage_items.{item['host_id']}.runtime_execution_authorized", + item["runtime_execution_authorized"], + ) + assert_false( + f"iwooos_projection.host_coverage_items.{item['host_id']}.action_buttons_allowed", + item["action_buttons_allowed"], + ) + assert_true( + f"iwooos_projection.host_coverage_items.{item['host_id']}.not_authorization", + item["not_authorization"], + ) assert_equal( "iwooos_projection.non_blocking_lane_ids", iwooos_projection["non_blocking_lane_ids"], @@ -577,6 +625,7 @@ def validate(root: Path) -> None: "display_frontend_surface_conflict_controls", "display_operator_journey_steps", "display_owner_evidence_readiness_board", + "display_host_coverage_view", "display_evidence_refs", "display_forbidden_actions", ]: @@ -591,6 +640,9 @@ def validate(root: Path) -> None: "sync_git_refs", "modify_workflow_or_secret", "enable_runner", + "ssh_to_host", + "update_kali_host", + "credentialed_scan_host", "switch_github_primary", "production_deploy", "treat_progress_as_authorization",