From af71ba48af69c5b6005556575dfc2ec3676c407f Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 11 Jun 2026 14:54:29 +0800 Subject: [PATCH] =?UTF-8?q?feat(security):=20=E9=A1=AF=E7=A4=BA=20AwoooP?= =?UTF-8?q?=20owner=20packet=20=E5=8F=AA=E8=AE=80=E7=8B=80=E6=85=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/messages/en.json | 34 ++++ apps/web/messages/zh-TW.json | 34 ++++ apps/web/src/app/[locale]/awooop/page.tsx | 182 ++++++++++++++++++ .../iwooos_posture_projection_v1.schema.json | 40 ++++ .../iwooos-posture-projection.snapshot.json | 15 ++ .../security-mirror-progress-guard.py | 126 ++++++++++++ 6 files changed, 431 insertions(+) diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index 157ea6225..22720d2bc 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -3914,6 +3914,40 @@ "detail": "7 條結果分流只導向補證、隔離、拒收或等待後續閘門。" } } + }, + "highValueConfigOwnerPacket": { + "title": "高價值配置 Owner Packet", + "subtitle": "AwoooP 首頁只讀顯示 IwoooS 產生的高價值配置 owner packet 草案;目前只是收件候選狀態,不送 request、不標記收到或接受,也不開任何執行期入口。", + "badge": "只讀 packet", + "openIwooos": "開啟 IwoooS", + "refsTitle": "Owner packet 參照", + "boundaryLabel": "高價值配置收件邊界", + "boundaryTitle": "AwoooP 只顯示草案,不建立動作", + "boundaryDetail": "這個面板只消費 committed snapshot 與 IwoooS projection;不能被解讀成已送出 owner request、已收到回覆、已接受回覆、Nginx reload、workflow 修改、secret rotation、agent-bounty runtime 或任何主機操作授權。", + "metrics": { + "packetDrafts": { + "label": "Packet 草案", + "detail": "目前只有 1 包草案可供 owner 後續判讀。" + }, + "c0Packets": { + "label": "C0 packet", + "detail": "目前 C0 仍為 0,不升高 runtime。" + }, + "responses": { + "label": "已收 / 已接受", + "detail": "兩者皆為 0,AwoooP 不得代替 owner 回覆。" + }, + "runtimeGate": { + "label": "執行期閘門", + "detail": "仍為 0,不產生 request、received 或 accepted 按鈕。" + } + }, + "refs": { + "packetDraft": "高價值配置 owner packet 草案已由分類 Gate 產生,但尚未送出。", + "c0Scope": "目前快照沒有 C0 packet;若未來碰 Nginx / DNS / K8s / secret,仍需另行 owner gate。", + "s49Envelope": "欄位沿用 S4.9 canonical owner response envelope,但收件與接受計數仍是 0。", + "runtimeBoundary": "IwoooS projection 固定 runtime gate 0,AwoooP 只能鏡像狀態。" + } } }, "workItems": { diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index 157ea6225..22720d2bc 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -3914,6 +3914,40 @@ "detail": "7 條結果分流只導向補證、隔離、拒收或等待後續閘門。" } } + }, + "highValueConfigOwnerPacket": { + "title": "高價值配置 Owner Packet", + "subtitle": "AwoooP 首頁只讀顯示 IwoooS 產生的高價值配置 owner packet 草案;目前只是收件候選狀態,不送 request、不標記收到或接受,也不開任何執行期入口。", + "badge": "只讀 packet", + "openIwooos": "開啟 IwoooS", + "refsTitle": "Owner packet 參照", + "boundaryLabel": "高價值配置收件邊界", + "boundaryTitle": "AwoooP 只顯示草案,不建立動作", + "boundaryDetail": "這個面板只消費 committed snapshot 與 IwoooS projection;不能被解讀成已送出 owner request、已收到回覆、已接受回覆、Nginx reload、workflow 修改、secret rotation、agent-bounty runtime 或任何主機操作授權。", + "metrics": { + "packetDrafts": { + "label": "Packet 草案", + "detail": "目前只有 1 包草案可供 owner 後續判讀。" + }, + "c0Packets": { + "label": "C0 packet", + "detail": "目前 C0 仍為 0,不升高 runtime。" + }, + "responses": { + "label": "已收 / 已接受", + "detail": "兩者皆為 0,AwoooP 不得代替 owner 回覆。" + }, + "runtimeGate": { + "label": "執行期閘門", + "detail": "仍為 0,不產生 request、received 或 accepted 按鈕。" + } + }, + "refs": { + "packetDraft": "高價值配置 owner packet 草案已由分類 Gate 產生,但尚未送出。", + "c0Scope": "目前快照沒有 C0 packet;若未來碰 Nginx / DNS / K8s / secret,仍需另行 owner gate。", + "s49Envelope": "欄位沿用 S4.9 canonical owner response envelope,但收件與接受計數仍是 0。", + "runtimeBoundary": "IwoooS projection 固定 runtime gate 0,AwoooP 只能鏡像狀態。" + } } }, "workItems": { diff --git a/apps/web/src/app/[locale]/awooop/page.tsx b/apps/web/src/app/[locale]/awooop/page.tsx index 16116a726..bf89cbbdf 100644 --- a/apps/web/src/app/[locale]/awooop/page.tsx +++ b/apps/web/src/app/[locale]/awooop/page.tsx @@ -102,6 +102,20 @@ type OwnerResponseValidationCheck = { tone: "good" | "warn" | "neutral"; }; +type HighValueConfigOwnerPacketMetric = { + key: string; + value: string; + icon: typeof ShieldCheck; + tone: "good" | "warn" | "neutral"; +}; + +type HighValueConfigOwnerPacketRef = { + key: string; + contract: string; + status: string; + tone: "good" | "warn" | "neutral"; +}; + type QualityVerdict = { verdict: string; total: number; @@ -296,6 +310,58 @@ const ownerResponseValidationBoundaries = [ "action_buttons_allowed=false", ]; +const highValueConfigOwnerPacketMetrics: HighValueConfigOwnerPacketMetric[] = [ + { key: "packetDrafts", value: "1", icon: FileText, tone: "warn" }, + { key: "c0Packets", value: "0", icon: Lock, tone: "neutral" }, + { key: "responses", value: "0 / 0", icon: ShieldCheck, tone: "warn" }, + { key: "runtimeGate", value: "0", icon: Lock, tone: "neutral" }, +]; + +const highValueConfigOwnerPacketRefs: HighValueConfigOwnerPacketRef[] = [ + { + key: "packetDraft", + contract: "high_value_config_owner_packet_v1", + status: "草案 1", + tone: "warn", + }, + { + key: "c0Scope", + contract: "high_value_config_change_gate_v1", + status: "C0 0", + tone: "neutral", + }, + { + key: "s49Envelope", + contract: "source_control_owner_response_validation_rollup_v1", + status: "0 / 0", + tone: "warn", + }, + { + key: "runtimeBoundary", + contract: "iwooos_posture_projection_v1", + status: "gate 0", + tone: "neutral", + }, +]; + +const highValueConfigOwnerPacketBoundaries = [ + "awooop_high_value_config_owner_packet_summary_count=4", + "awooop_high_value_config_owner_packet_ref_count=4", + "high_value_config_owner_packet_count=1", + "high_value_config_owner_packet_c0_packet_count=0", + "high_value_config_owner_packet_request_sent_count=0", + "high_value_config_owner_packet_received_response_count=0", + "high_value_config_owner_packet_accepted_response_count=0", + "runtime_execution_authorized=false", + "action_buttons_allowed=false", + "send_owner_request_allowed=false", + "mark_received_allowed=false", + "mark_accepted_allowed=false", + "nginx_reload_authorized=false", + "workflow_modification_authorized=false", + "agent_bounty_runtime_authorized=false", +]; + function numberValue(value: unknown): number { return typeof value === "number" && Number.isFinite(value) ? value : 0; } @@ -1106,6 +1172,120 @@ function OwnerResponseValidationRollupPanel() { ); } +function HighValueConfigOwnerPacketHomePanel() { + const t = useTranslations("awooop.home.highValueConfigOwnerPacket"); + + return ( +
+
+
+
+
+ + {t("badge")} + + + {t("openIwooos")} +
+
+ +
+ {highValueConfigOwnerPacketMetrics.map((metric) => { + const Icon = metric.icon; + return ( +
+
+
+

+ {t(`metrics.${metric.key}.label` as never)} +

+

+ {metric.value} +

+
+ + +
+

+ {t(`metrics.${metric.key}.detail` as never)} +

+
+ ); + })} +
+ +
+
+
+ {t("refsTitle")} +
+
+ {highValueConfigOwnerPacketRefs.map((ref) => ( +
+
+

+ {ref.contract} +

+

+ {t(`refs.${ref.key}` as never)} +

+
+
+ + {ref.status} + +
+
+ ))} +
+
+ +
+

{t("boundaryLabel")}

+

{t("boundaryTitle")}

+

{t("boundaryDetail")}

+
+ {highValueConfigOwnerPacketBoundaries.map((boundary) => ( + {boundary} + ))} +
+
+
+
+ ); +} + function AutomationQualityPanel({ summary, error, @@ -1465,6 +1645,8 @@ export default function AwoooPPage() { + +
diff --git a/docs/schemas/iwooos_posture_projection_v1.schema.json b/docs/schemas/iwooos_posture_projection_v1.schema.json index a18e60f2c..8c3303d41 100644 --- a/docs/schemas/iwooos_posture_projection_v1.schema.json +++ b/docs/schemas/iwooos_posture_projection_v1.schema.json @@ -171,6 +171,14 @@ "high_value_config_owner_packet_received_response_count", "high_value_config_owner_packet_accepted_response_count", "high_value_config_owner_packet_runtime_gate_count", + "awooop_high_value_config_owner_packet_first_layer", + "awooop_high_value_config_owner_packet_summary_count", + "awooop_high_value_config_owner_packet_ref_count", + "awooop_high_value_config_owner_packet_boundary_count", + "awooop_high_value_config_owner_packet_request_sent_count", + "awooop_high_value_config_owner_packet_received_response_count", + "awooop_high_value_config_owner_packet_accepted_response_count", + "awooop_high_value_config_owner_packet_runtime_gate_count", "action_buttons_allowed", "owner_response_next_action_focus_item_count", "s4_9_owner_response_preflight_check_count", @@ -448,6 +456,38 @@ "type": "integer", "const": 0 }, + "awooop_high_value_config_owner_packet_first_layer": { + "type": "boolean", + "const": true + }, + "awooop_high_value_config_owner_packet_summary_count": { + "type": "integer", + "const": 4 + }, + "awooop_high_value_config_owner_packet_ref_count": { + "type": "integer", + "const": 4 + }, + "awooop_high_value_config_owner_packet_boundary_count": { + "type": "integer", + "const": 15 + }, + "awooop_high_value_config_owner_packet_request_sent_count": { + "type": "integer", + "const": 0 + }, + "awooop_high_value_config_owner_packet_received_response_count": { + "type": "integer", + "const": 0 + }, + "awooop_high_value_config_owner_packet_accepted_response_count": { + "type": "integer", + "const": 0 + }, + "awooop_high_value_config_owner_packet_runtime_gate_count": { + "type": "integer", + "const": 0 + }, "owner_response_next_action_focus_item_count": { "type": "integer", "const": 4 diff --git a/docs/security/iwooos-posture-projection.snapshot.json b/docs/security/iwooos-posture-projection.snapshot.json index 8ee2ca512..b1ff9b537 100644 --- a/docs/security/iwooos-posture-projection.snapshot.json +++ b/docs/security/iwooos-posture-projection.snapshot.json @@ -214,6 +214,14 @@ "high_value_config_owner_packet_received_response_count": 0, "high_value_config_owner_packet_accepted_response_count": 0, "high_value_config_owner_packet_runtime_gate_count": 0, + "awooop_high_value_config_owner_packet_first_layer": true, + "awooop_high_value_config_owner_packet_summary_count": 4, + "awooop_high_value_config_owner_packet_ref_count": 4, + "awooop_high_value_config_owner_packet_boundary_count": 15, + "awooop_high_value_config_owner_packet_request_sent_count": 0, + "awooop_high_value_config_owner_packet_received_response_count": 0, + "awooop_high_value_config_owner_packet_accepted_response_count": 0, + "awooop_high_value_config_owner_packet_runtime_gate_count": 0, "existing_frontend_surface_count": 10, "frontend_surface_reverse_bridge_status_count": 10, "frontend_surface_coverage_group_count": 4, @@ -1489,6 +1497,7 @@ "display_agent_bounty_security_onboarding", "display_rollout_risk_read_only", "display_high_value_config_owner_packet", + "display_awooop_high_value_config_owner_packet_read_only", "display_awooop_read_only_landing_readiness", "display_awooop_cross_session_handoff_packets", "display_progress_hold_movement_gates", @@ -1554,6 +1563,12 @@ "reload_nginx_from_owner_packet", "rotate_secret_from_owner_packet", "run_agent_bounty_runtime_from_owner_packet", + "send_owner_request_from_awooop_high_value_config_packet", + "mark_owner_packet_received_from_awooop", + "mark_owner_packet_accepted_from_awooop", + "open_runtime_gate_from_awooop_high_value_config_packet", + "reload_nginx_from_awooop_owner_packet", + "run_agent_bounty_runtime_from_awooop_owner_packet", "enable_runner", "switch_github_primary", "ssh_to_host", diff --git a/scripts/security/security-mirror-progress-guard.py b/scripts/security/security-mirror-progress-guard.py index 07a1afcf7..6960135c9 100755 --- a/scripts/security/security-mirror-progress-guard.py +++ b/scripts/security/security-mirror-progress-guard.py @@ -2362,6 +2362,36 @@ def validate(root: Path) -> None: iwooos_projection["summary"][key], 0, ) + assert_true( + "iwooos_projection.summary.awooop_high_value_config_owner_packet_first_layer", + iwooos_projection["summary"]["awooop_high_value_config_owner_packet_first_layer"], + ) + assert_equal( + "iwooos_projection.summary.awooop_high_value_config_owner_packet_summary_count", + iwooos_projection["summary"]["awooop_high_value_config_owner_packet_summary_count"], + 4, + ) + assert_equal( + "iwooos_projection.summary.awooop_high_value_config_owner_packet_ref_count", + iwooos_projection["summary"]["awooop_high_value_config_owner_packet_ref_count"], + 4, + ) + assert_equal( + "iwooos_projection.summary.awooop_high_value_config_owner_packet_boundary_count", + iwooos_projection["summary"]["awooop_high_value_config_owner_packet_boundary_count"], + 15, + ) + for key in [ + "awooop_high_value_config_owner_packet_request_sent_count", + "awooop_high_value_config_owner_packet_received_response_count", + "awooop_high_value_config_owner_packet_accepted_response_count", + "awooop_high_value_config_owner_packet_runtime_gate_count", + ]: + assert_equal( + f"iwooos_projection.summary.{key}", + iwooos_projection["summary"][key], + 0, + ) expected_iwooos_surface_ids = [ "security_compliance", "legacy_security", @@ -7074,6 +7104,7 @@ def validate(root: Path) -> None: "display_agent_bounty_security_onboarding", "display_rollout_risk_read_only", "display_high_value_config_owner_packet", + "display_awooop_high_value_config_owner_packet_read_only", ]: assert_contains("iwooos_projection.allowed_frontend_outputs", iwooos_projection["allowed_frontend_outputs"], output) for output in [ @@ -7088,6 +7119,12 @@ def validate(root: Path) -> None: "reload_nginx_from_owner_packet", "rotate_secret_from_owner_packet", "run_agent_bounty_runtime_from_owner_packet", + "send_owner_request_from_awooop_high_value_config_packet", + "mark_owner_packet_received_from_awooop", + "mark_owner_packet_accepted_from_awooop", + "open_runtime_gate_from_awooop_high_value_config_packet", + "reload_nginx_from_awooop_owner_packet", + "run_agent_bounty_runtime_from_awooop_owner_packet", "enable_runner", "ssh_to_host", "open_ssh_session", @@ -7434,6 +7471,95 @@ def validate(root: Path) -> None: key, ) + assert_text_contains( + "awooop_home_page.high_value_config_owner_packet_panel", + awooop_home_page, + "HighValueConfigOwnerPacketHomePanel", + ) + assert_text_contains( + "awooop_home_page.high_value_config_owner_packet_metrics", + awooop_home_page, + "highValueConfigOwnerPacketMetrics", + ) + assert_text_contains( + "awooop_home_page.high_value_config_owner_packet_refs", + awooop_home_page, + "highValueConfigOwnerPacketRefs", + ) + assert_text_contains( + "awooop_home_page.high_value_config_owner_packet_testid", + awooop_home_page, + 'data-testid="awooop-high-value-config-owner-packet-board"', + ) + assert_text_contains( + "awooop_home_page.high_value_config_owner_packet_boundary_testid", + awooop_home_page, + 'data-testid="awooop-high-value-config-owner-packet-boundaries"', + ) + assert_text_contains("awooop_home_page.high_value_config_owner_packet_iwooos_link", awooop_home_page, 'href="/iwooos"') + for text in [ + "awooop_high_value_config_owner_packet_summary_count=4", + "awooop_high_value_config_owner_packet_ref_count=4", + "high_value_config_owner_packet_count=1", + "high_value_config_owner_packet_c0_packet_count=0", + "high_value_config_owner_packet_request_sent_count=0", + "high_value_config_owner_packet_received_response_count=0", + "high_value_config_owner_packet_accepted_response_count=0", + "runtime_execution_authorized=false", + "action_buttons_allowed=false", + "send_owner_request_allowed=false", + "mark_received_allowed=false", + "mark_accepted_allowed=false", + "nginx_reload_authorized=false", + "workflow_modification_authorized=false", + "agent_bounty_runtime_authorized=false", + ]: + assert_text_contains("awooop_home_page.high_value_config_owner_packet_boundary", awooop_home_page, text) + for key in [ + "title", + "subtitle", + "badge", + "openIwooos", + "refsTitle", + "boundaryLabel", + "boundaryTitle", + "boundaryDetail", + "metrics", + "refs", + ]: + assert_contains( + "web_messages.zh-TW.awooop.home.highValueConfigOwnerPacket", + list(web_messages_zh["awooop"]["home"]["highValueConfigOwnerPacket"].keys()), + key, + ) + assert_contains( + "web_messages.en.awooop.home.highValueConfigOwnerPacket", + list(web_messages_en["awooop"]["home"]["highValueConfigOwnerPacket"].keys()), + key, + ) + for key in ["packetDrafts", "c0Packets", "responses", "runtimeGate"]: + assert_contains( + "web_messages.zh-TW.awooop.home.highValueConfigOwnerPacket.metrics", + list(web_messages_zh["awooop"]["home"]["highValueConfigOwnerPacket"]["metrics"].keys()), + key, + ) + assert_contains( + "web_messages.en.awooop.home.highValueConfigOwnerPacket.metrics", + list(web_messages_en["awooop"]["home"]["highValueConfigOwnerPacket"]["metrics"].keys()), + key, + ) + for key in ["packetDraft", "c0Scope", "s49Envelope", "runtimeBoundary"]: + assert_contains( + "web_messages.zh-TW.awooop.home.highValueConfigOwnerPacket.refs", + list(web_messages_zh["awooop"]["home"]["highValueConfigOwnerPacket"]["refs"].keys()), + key, + ) + assert_contains( + "web_messages.en.awooop.home.highValueConfigOwnerPacket.refs", + list(web_messages_en["awooop"]["home"]["highValueConfigOwnerPacket"]["refs"].keys()), + key, + ) + assert_text_contains("awooop_work_items_page.security_mirror_item", awooop_work_items_page, "iwooosSecurityMirror") assert_text_contains("awooop_work_items_page.github_primary_item", awooop_work_items_page, "githubPrimaryReadiness") assert_text_contains("awooop_work_items_page.owner_response_validation_item", awooop_work_items_page, "ownerResponseValidation")