feat(iwooos): 強化告警鏈路 no-false-green gate
This commit is contained in:
@@ -141,8 +141,8 @@ CONTROL_STATUS_BY_CATEGORY = {
|
||||
"next_owner_action": "補 repo owner、external agent owner、treasury owner、runtime gate owner、maintenance window、rollback owner 與 validation plan。",
|
||||
},
|
||||
"monitoring_alerting_observability": {
|
||||
"coverage_status": "owner_response_acceptance_ledger_ready_needs_live_route_evidence",
|
||||
"coverage_percent": 66,
|
||||
"coverage_status": "alert_chain_no_false_green_backfill_ready_needs_live_evidence_receipt",
|
||||
"coverage_percent": 68,
|
||||
"evidence_refs": [
|
||||
"docs/security/IWOOOS-CONFIG-CONTROL-INVENTORY.md",
|
||||
"docs/security/MONITORING-ALERTING-OBSERVABILITY-INVENTORY.md",
|
||||
@@ -153,8 +153,8 @@ CONTROL_STATUS_BY_CATEGORY = {
|
||||
"docs/security/monitoring-owner-response-acceptance.snapshot.json",
|
||||
"docs/schemas/monitoring_alerting_observability_inventory_v1.schema.json",
|
||||
],
|
||||
"current_gap": "已固定 60 份 monitoring / alerting / observability owner response acceptance candidate;仍缺 owner response、live config hash、rule diff、receiver diff、reload owner、route smoke、receipt proof、noise budget owner 與 maintenance window。",
|
||||
"next_owner_action": "補 Prometheus / Alertmanager / Grafana / SigNoz / Sentry / Langfuse / Telegram owner、live drift evidence、reload window、receiver owner、route smoke plan、noise budget、rollback owner 與 no-secret-value evidence。",
|
||||
"current_gap": "已固定 60 份 monitoring / alerting / observability owner response acceptance candidate,並新增告警鏈路 no-false-green 回補欄位;仍缺 owner response、live config hash、rule diff、receiver diff、receipt proof、stale / silence review、post-reload readback、noise budget owner 與 maintenance window。",
|
||||
"next_owner_action": "補 Prometheus / Alertmanager / Grafana / SigNoz / Sentry / Langfuse / Telegram owner、live drift evidence、reload window、receiver owner、receipt proof、stale alert review、silence / dedup review、route smoke plan、noise budget、rollback owner 與 no-secret-value evidence。",
|
||||
},
|
||||
"docker_compose_systemd_host_config": {
|
||||
"coverage_status": "incident_recovery_backfill_ready_needs_live_owner_evidence",
|
||||
@@ -382,6 +382,7 @@ def build_report(root: Path, generated_at: str | None) -> dict[str, Any]:
|
||||
"restore_recovery_backfill_ready_needs_owner_live_evidence",
|
||||
"owner_response_acceptance_ledger_ready_needs_network_owner",
|
||||
"owner_response_acceptance_ledger_ready_needs_live_route_evidence",
|
||||
"alert_chain_no_false_green_backfill_ready_needs_live_evidence_receipt",
|
||||
"change_evidence_acceptance_ready_needs_network_owner_evidence",
|
||||
"incident_change_evidence_acceptance_ready_needs_network_owner_evidence",
|
||||
"policy_ready_needs_drift_evidence",
|
||||
|
||||
@@ -25,7 +25,7 @@ EXPECTED_CATEGORIES = {
|
||||
"public_admin_api_runtime_config": 66,
|
||||
"backup_restore_credential": 64,
|
||||
"agent_bounty_protocol_runtime": 68,
|
||||
"monitoring_alerting_observability": 66,
|
||||
"monitoring_alerting_observability": 68,
|
||||
"docker_compose_systemd_host_config": 58,
|
||||
"ssh_firewall_network_access": 62,
|
||||
"ai_provider_model_routing": 60,
|
||||
@@ -356,16 +356,21 @@ ARTIFACT_SPECS = [
|
||||
"status": "owner_response_acceptance_ledger_ready_no_runtime_action",
|
||||
"list_counts": {
|
||||
"acceptance_candidates": 60,
|
||||
"blocked_actions": 28,
|
||||
"reviewer_checks": 15,
|
||||
"outcome_lanes": 7,
|
||||
"blocked_actions": 34,
|
||||
"reviewer_checks": 23,
|
||||
"outcome_lanes": 12,
|
||||
"required_owner_fields": 14,
|
||||
},
|
||||
"summary_counts": {
|
||||
"acceptance_candidate_count": 60,
|
||||
"write_capable_acceptance_candidate_count": 11,
|
||||
"acceptance_field_count": 38,
|
||||
"reviewer_check_count": 23,
|
||||
"outcome_lane_count": 12,
|
||||
"blocked_action_count": 34,
|
||||
"owner_response_received_count": 0,
|
||||
"owner_response_accepted_count": 0,
|
||||
"false_green_risk_review_accepted_count": 0,
|
||||
"runtime_gate_count": 0,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -48,6 +48,14 @@ ACCEPTANCE_FIELDS = [
|
||||
"reload_owner",
|
||||
"receiver_owner",
|
||||
"route_smoke_plan",
|
||||
"incident_context_ref",
|
||||
"alert_chain_health_ref",
|
||||
"receiver_receipt_proof_ref",
|
||||
"stale_alert_review",
|
||||
"silence_or_dedup_review",
|
||||
"false_green_risk_review",
|
||||
"post_reload_readback_plan",
|
||||
"cross_project_notification_ref",
|
||||
"maintenance_window",
|
||||
"rollback_owner",
|
||||
"validation_plan",
|
||||
@@ -67,6 +75,14 @@ REVIEWER_CHECKS = [
|
||||
{"check_id": "reload_owner_present", "instruction": "Prometheus / Alertmanager / OTEL / Sentry 類變更必須有 reload / deploy owner。"},
|
||||
{"check_id": "receiver_owner_present", "instruction": "receiver route、Telegram receipt 與 notification policy 必須有 receiver owner。"},
|
||||
{"check_id": "route_smoke_plan_present", "instruction": "route smoke / receipt proof 必須是計畫或脫敏證據 ref,不得直接 fire alert。"},
|
||||
{"check_id": "incident_context_present", "instruction": "事故回補必須有 incident / change / outage context ref;不得只寫服務已恢復。"},
|
||||
{"check_id": "alert_chain_health_not_route_only", "instruction": "告警鏈路健康不得只用 public route 200 或 UI 可見判定,必須包含 rule、state、receiver 與 receipt/ref。"},
|
||||
{"check_id": "receiver_receipt_proof_metadata_only", "instruction": "receiver receipt proof 只能是脫敏 ref、hash、message id 或 ticket,不得貼 raw notification payload。"},
|
||||
{"check_id": "stale_alert_review_present", "instruction": "必須確認告警是否 stale、pending、resolved 未清或資料來源停止更新。"},
|
||||
{"check_id": "silence_or_dedup_review_present", "instruction": "必須確認 silence、mute、dedup、inhibit 或 maintenance rule 是否造成 false green。"},
|
||||
{"check_id": "false_green_risk_review_present", "instruction": "必須列 no-false-green 判定,避免把 route up、容器 up 或 dashboard up 當作告警鏈路 up。"},
|
||||
{"check_id": "post_reload_readback_plan_present", "instruction": "若後續有 reload / deploy,必須先有 post-reload readback plan 與 stop condition。"},
|
||||
{"check_id": "cross_project_notification_present", "instruction": "若影響 AwoooP、IwoooS、agent-bounty、StockPlatform、公開網站或監控,需有跨專案通知 ref。"},
|
||||
{"check_id": "noise_budget_owner_present", "instruction": "告警噪音、silence、dedup 與測試通知必須有 noise budget owner。"},
|
||||
{"check_id": "maintenance_window_present", "instruction": "reload、deploy、route change、smoke 或 notification send 必須另有維護窗口。"},
|
||||
{"check_id": "rollback_owner_present", "instruction": "rollback owner、rollback ref 或 disable path 必須存在。"},
|
||||
@@ -81,6 +97,11 @@ OUTCOME_LANES = [
|
||||
{"lane_id": "reject_execution_request", "meaning": "夾帶 reload、deploy、route change、Telegram send、fire alert、SSH 或 kubectl 要求時拒收。"},
|
||||
{"lane_id": "request_supplement", "meaning": "欄位不足、scope 不清、reload / receiver / route smoke / rollback / noise owner 缺失時要求補件。"},
|
||||
{"lane_id": "ready_for_monitoring_review", "meaning": "metadata 合格後,只能進 monitoring reviewer review。"},
|
||||
{"lane_id": "incident_recovery_backfill_required", "meaning": "事故後只看到服務恢復時,要求補 incident context、receiver receipt、stale / silence review 與 post-check refs。"},
|
||||
{"lane_id": "no_false_green_supplement_required", "meaning": "只用 route 200、container up、dashboard up 或 UI 可見代表告警健康時,要求補 no-false-green 證據。"},
|
||||
{"lane_id": "receiver_receipt_gap_required", "meaning": "缺 Telegram / webhook / receiver receipt proof 或 delivery state 時,不得接受告警鏈路健康。"},
|
||||
{"lane_id": "stale_or_silenced_alert_review_required", "meaning": "缺 stale alert、silence、dedup、inhibit 或 maintenance rule review 時,要求補件。"},
|
||||
{"lane_id": "post_reload_readback_required", "meaning": "reload / deploy / rule change 後必須有 readback、metrics、receipt 與 rollback stop condition。"},
|
||||
{"lane_id": "owner_review_only_update", "meaning": "只允許更新只讀 owner review ledger,不得 reload、send Telegram 或 fire alert。"},
|
||||
{"lane_id": "waiting_runtime_gate", "meaning": "即使 owner response accepted,runtime gate 仍等待獨立人工批准。"},
|
||||
]
|
||||
@@ -113,6 +134,12 @@ BLOCKED_ACTIONS = [
|
||||
"raw_monitoring_payload_storage",
|
||||
"accept_secret_value_evidence",
|
||||
"mark_owner_response_accepted_without_reviewer_record",
|
||||
"mark_route_200_as_alert_chain_healthy",
|
||||
"mark_receiver_healthy_without_receipt",
|
||||
"accept_silence_without_owner",
|
||||
"accept_stale_alert_without_review",
|
||||
"accept_reload_without_postcheck",
|
||||
"store_raw_alert_payload",
|
||||
"add_action_button",
|
||||
]
|
||||
|
||||
@@ -162,6 +189,14 @@ def acceptance_candidate(request: dict[str, Any]) -> dict[str, Any]:
|
||||
"reload_owner": "pending_owner_response",
|
||||
"receiver_owner": "pending_owner_response",
|
||||
"route_smoke_plan": "pending_owner_response",
|
||||
"incident_context_ref": None,
|
||||
"alert_chain_health_ref": None,
|
||||
"receiver_receipt_proof_ref": None,
|
||||
"stale_alert_review": "pending_owner_response",
|
||||
"silence_or_dedup_review": "pending_owner_response",
|
||||
"false_green_risk_review": "pending_owner_response",
|
||||
"post_reload_readback_plan": "pending_owner_response",
|
||||
"cross_project_notification_ref": None,
|
||||
"maintenance_window": "pending_owner_response",
|
||||
"rollback_owner": "pending_owner_response",
|
||||
"validation_plan": "pending_owner_response",
|
||||
@@ -186,6 +221,14 @@ def acceptance_candidate(request: dict[str, Any]) -> dict[str, Any]:
|
||||
"reload_owner_accepted": False,
|
||||
"receiver_owner_accepted": False,
|
||||
"route_smoke_accepted": False,
|
||||
"incident_context_accepted": False,
|
||||
"alert_chain_health_accepted": False,
|
||||
"receiver_receipt_proof_accepted": False,
|
||||
"stale_alert_review_accepted": False,
|
||||
"silence_or_dedup_review_accepted": False,
|
||||
"false_green_risk_review_accepted": False,
|
||||
"post_reload_readback_plan_accepted": False,
|
||||
"cross_project_notification_accepted": False,
|
||||
"maintenance_window_accepted": False,
|
||||
"rollback_owner_accepted": False,
|
||||
"validation_plan_accepted": False,
|
||||
@@ -262,6 +305,14 @@ def build_report(
|
||||
"reload_owner_accepted_count": 0,
|
||||
"receiver_owner_accepted_count": 0,
|
||||
"route_smoke_accepted_count": 0,
|
||||
"incident_context_accepted_count": 0,
|
||||
"alert_chain_health_accepted_count": 0,
|
||||
"receiver_receipt_proof_accepted_count": 0,
|
||||
"stale_alert_review_accepted_count": 0,
|
||||
"silence_or_dedup_review_accepted_count": 0,
|
||||
"false_green_risk_review_accepted_count": 0,
|
||||
"post_reload_readback_plan_accepted_count": 0,
|
||||
"cross_project_notification_accepted_count": 0,
|
||||
"maintenance_window_accepted_count": 0,
|
||||
"rollback_owner_accepted_count": 0,
|
||||
"validation_plan_accepted_count": 0,
|
||||
@@ -320,6 +371,10 @@ def build_report(
|
||||
"active_scan_authorized": False,
|
||||
"production_write_authorized": False,
|
||||
"runtime_execution_authorized": False,
|
||||
"route_200_alert_chain_health_accepted": False,
|
||||
"receiver_health_without_receipt_accepted": False,
|
||||
"false_green_acceptance_authorized": False,
|
||||
"raw_alert_payload_storage_allowed": False,
|
||||
"action_buttons_allowed": False,
|
||||
"not_authorization": True,
|
||||
},
|
||||
|
||||
@@ -3252,12 +3252,12 @@ def validate(root: Path) -> None:
|
||||
assert_equal(
|
||||
"high_value_config_coverage.coverage_categories.monitoring.coverage_percent",
|
||||
monitoring_category["coverage_percent"],
|
||||
66,
|
||||
68,
|
||||
)
|
||||
assert_equal(
|
||||
"high_value_config_coverage.coverage_categories.monitoring.coverage_status",
|
||||
monitoring_category["coverage_status"],
|
||||
"owner_response_acceptance_ledger_ready_needs_live_route_evidence",
|
||||
"alert_chain_no_false_green_backfill_ready_needs_live_evidence_receipt",
|
||||
)
|
||||
for evidence_ref in [
|
||||
"docs/security/MONITORING-ALERTING-OBSERVABILITY-INVENTORY.md",
|
||||
@@ -5218,11 +5218,11 @@ def validate(root: Path) -> None:
|
||||
"acceptance_candidate_count": 60,
|
||||
"write_capable_acceptance_candidate_count": 11,
|
||||
"live_evidence_required_candidate_count": 60,
|
||||
"acceptance_field_count": 30,
|
||||
"acceptance_field_count": 38,
|
||||
"required_owner_field_count": 14,
|
||||
"reviewer_check_count": 15,
|
||||
"outcome_lane_count": 7,
|
||||
"blocked_action_count": 28,
|
||||
"reviewer_check_count": 23,
|
||||
"outcome_lane_count": 12,
|
||||
"blocked_action_count": 34,
|
||||
"request_sent_count": 0,
|
||||
"recipient_confirmed_count": 0,
|
||||
"owner_response_received_count": 0,
|
||||
@@ -5235,6 +5235,14 @@ def validate(root: Path) -> None:
|
||||
"reload_owner_accepted_count": 0,
|
||||
"receiver_owner_accepted_count": 0,
|
||||
"route_smoke_accepted_count": 0,
|
||||
"incident_context_accepted_count": 0,
|
||||
"alert_chain_health_accepted_count": 0,
|
||||
"receiver_receipt_proof_accepted_count": 0,
|
||||
"stale_alert_review_accepted_count": 0,
|
||||
"silence_or_dedup_review_accepted_count": 0,
|
||||
"false_green_risk_review_accepted_count": 0,
|
||||
"post_reload_readback_plan_accepted_count": 0,
|
||||
"cross_project_notification_accepted_count": 0,
|
||||
"maintenance_window_accepted_count": 0,
|
||||
"rollback_owner_accepted_count": 0,
|
||||
"validation_plan_accepted_count": 0,
|
||||
@@ -5301,23 +5309,23 @@ def validate(root: Path) -> None:
|
||||
assert_equal(
|
||||
"monitoring_owner_response_acceptance.reviewer_checks.count",
|
||||
len(monitoring_owner_response_acceptance["reviewer_checks"]),
|
||||
15,
|
||||
23,
|
||||
)
|
||||
assert_equal(
|
||||
"monitoring_owner_response_acceptance.outcome_lanes.count",
|
||||
len(monitoring_owner_response_acceptance["outcome_lanes"]),
|
||||
7,
|
||||
12,
|
||||
)
|
||||
assert_equal(
|
||||
"monitoring_owner_response_acceptance.blocked_actions.count",
|
||||
len(monitoring_owner_response_acceptance["blocked_actions"]),
|
||||
28,
|
||||
34,
|
||||
)
|
||||
for item in monitoring_owner_response_acceptance["acceptance_candidates"]:
|
||||
assert_equal(
|
||||
f"monitoring_owner_response_acceptance.{item['acceptance_candidate_id']}.acceptance_fields",
|
||||
len(item["acceptance_fields"]),
|
||||
30,
|
||||
38,
|
||||
)
|
||||
assert_equal(
|
||||
f"monitoring_owner_response_acceptance.{item['acceptance_candidate_id']}.required_owner_fields",
|
||||
@@ -5327,17 +5335,17 @@ def validate(root: Path) -> None:
|
||||
assert_equal(
|
||||
f"monitoring_owner_response_acceptance.{item['acceptance_candidate_id']}.reviewer_checks",
|
||||
len(item["reviewer_checks"]),
|
||||
15,
|
||||
23,
|
||||
)
|
||||
assert_equal(
|
||||
f"monitoring_owner_response_acceptance.{item['acceptance_candidate_id']}.outcome_lanes",
|
||||
len(item["outcome_lanes"]),
|
||||
7,
|
||||
12,
|
||||
)
|
||||
assert_equal(
|
||||
f"monitoring_owner_response_acceptance.{item['acceptance_candidate_id']}.blocked_actions",
|
||||
len(item["blocked_actions"]),
|
||||
28,
|
||||
34,
|
||||
)
|
||||
assert_true(
|
||||
f"monitoring_owner_response_acceptance.{item['acceptance_candidate_id']}.not_approval",
|
||||
@@ -6669,6 +6677,19 @@ def validate(root: Path) -> None:
|
||||
"monitoring_alerting_observability_inventory_action_button_count": 0,
|
||||
"monitoring_alerting_observability_inventory_coverage_percent_before_inventory": 56,
|
||||
"monitoring_alerting_observability_inventory_coverage_percent_after_inventory": 62,
|
||||
"monitoring_owner_response_acceptance_candidate_count": 60,
|
||||
"monitoring_owner_response_acceptance_acceptance_field_count": 38,
|
||||
"monitoring_owner_response_acceptance_reviewer_check_count": 23,
|
||||
"monitoring_owner_response_acceptance_outcome_lane_count": 12,
|
||||
"monitoring_owner_response_acceptance_blocked_action_count": 34,
|
||||
"monitoring_owner_response_acceptance_receiver_receipt_proof_accepted_count": 0,
|
||||
"monitoring_owner_response_acceptance_stale_alert_review_accepted_count": 0,
|
||||
"monitoring_owner_response_acceptance_silence_or_dedup_review_accepted_count": 0,
|
||||
"monitoring_owner_response_acceptance_false_green_risk_review_accepted_count": 0,
|
||||
"monitoring_owner_response_acceptance_post_reload_readback_plan_accepted_count": 0,
|
||||
"monitoring_owner_response_acceptance_cross_project_notification_accepted_count": 0,
|
||||
"monitoring_owner_response_acceptance_runtime_gate_count": 0,
|
||||
"monitoring_owner_response_acceptance_coverage_percent_after_backfill": 68,
|
||||
}
|
||||
for key, expected in expected_monitoring_alerting_observability_projection_summary.items():
|
||||
assert_equal(
|
||||
@@ -16313,7 +16334,7 @@ def validate(root: Path) -> None:
|
||||
assert_text_contains(
|
||||
"iwooos_page.high_value_config_control_coverage_monitoring_percent",
|
||||
iwooos_projection_page,
|
||||
"{ key: 'monitoring', rank: 'P1-4', value: '62%'",
|
||||
"{ key: 'monitoring', rank: 'P1-4', value: '68%'",
|
||||
)
|
||||
assert_text_before(
|
||||
"iwooos_page.high_value_config_control_coverage_before_owner_packet",
|
||||
@@ -16467,6 +16488,16 @@ def validate(root: Path) -> None:
|
||||
"monitoring_alerting_observability_inventory_reload_owner_accepted_count=0",
|
||||
"monitoring_alerting_observability_inventory_receiver_owner_accepted_count=0",
|
||||
"monitoring_alerting_observability_inventory_route_smoke_accepted_count=0",
|
||||
"monitoring_alerting_observability_coverage_percent=68",
|
||||
"monitoring_owner_response_acceptance_reviewer_check_count=23",
|
||||
"monitoring_owner_response_acceptance_outcome_lane_count=12",
|
||||
"monitoring_owner_response_acceptance_blocked_action_count=34",
|
||||
"monitoring_owner_response_acceptance_false_green_risk_review_accepted_count=0",
|
||||
"monitoring_owner_response_acceptance_receiver_receipt_proof_accepted_count=0",
|
||||
"monitoring_owner_response_acceptance_stale_alert_review_accepted_count=0",
|
||||
"monitoring_owner_response_acceptance_silence_or_dedup_review_accepted_count=0",
|
||||
"monitoring_owner_response_acceptance_post_reload_readback_plan_accepted_count=0",
|
||||
"monitoring_owner_response_acceptance_runtime_gate_count=0",
|
||||
"docker_compose_action_authorized=false",
|
||||
"systemctl_action_authorized=false",
|
||||
"repair_bot_execution_authorized=false",
|
||||
|
||||
Reference in New Issue
Block a user