test(iwooos): 強化 gateway 變更 metadata gate [skip ci]

This commit is contained in:
Your Name
2026-06-15 07:59:45 +08:00
parent 04728d36fe
commit 5c26e58632
8 changed files with 217 additions and 27 deletions

View File

@@ -112,10 +112,10 @@ ARTIFACT_SPECS = [
"status": "owner_response_acceptance_ledger_ready_no_runtime_action",
"list_counts": {
"acceptance_candidates": 3,
"blocked_actions": 18,
"reviewer_checks": 12,
"blocked_actions": 22,
"reviewer_checks": 16,
"outcome_lanes": 7,
"required_owner_response_fields": 12,
"required_owner_response_fields": 16,
},
"summary_counts": {
"acceptance_candidate_count": 3,

View File

@@ -42,6 +42,10 @@ ACCEPTANCE_FIELDS = [
"maintenance_window",
"rollback_owner",
"postcheck_plan",
"change_actor_or_source_ref",
"change_time_window",
"cross_project_impact_ref",
"communication_sync_ref",
"reviewer_outcome",
"followup_owner",
"not_approval",
@@ -59,6 +63,10 @@ REQUIRED_OWNER_RESPONSE_FIELDS = [
"maintenance_window",
"rollback_owner",
"postcheck_plan",
"change_actor_or_source_ref",
"change_time_window",
"cross_project_impact_ref",
"communication_sync_ref",
"followup_owner",
]
@@ -107,6 +115,22 @@ REVIEWER_CHECKS = [
"check_id": "rollback_owner_present",
"instruction": "rollback owner 與 rollback ref 必須存在,且不可指向 raw secret。",
},
{
"check_id": "change_actor_or_source_ref_present",
"instruction": "若曾有手動或緊急變更,必須提供脫敏 actor / source ref不得要求個人帳密或 raw shell history。",
},
{
"check_id": "change_time_window_present",
"instruction": "必須提供變更或事故時間窗,讓 route smoke、告警與跨專案影響可對齊。",
},
{
"check_id": "cross_project_impact_review_present",
"instruction": "必須提供跨產品 / 跨專案影響 ref避免只修單一路由卻讓其他服務斷線。",
},
{
"check_id": "communication_sync_ref_present",
"instruction": "必須提供通知或協調 ref證明相關專案 owner 已收到影響與回復狀態。",
},
{
"check_id": "counts_transition_safe",
"instruction": "只有 reviewer record 可更新 received / accepted / rejected不得同時開 runtime gate。",
@@ -161,6 +185,10 @@ BLOCKED_ACTIONS = [
"modify_dns_tls_config",
"change_public_route",
"write_production_host",
"accept_unknown_change_actor",
"accept_missing_change_time_window",
"skip_cross_project_impact_review",
"skip_incident_communication_sync",
"open_runtime_gate",
"add_action_button",
]
@@ -208,6 +236,10 @@ def acceptance_candidate(diff_gate: dict[str, Any]) -> dict[str, Any]:
"maintenance_window": "pending_owner_response",
"rollback_owner": "pending_owner_response",
"postcheck_plan": "pending_owner_response",
"change_actor_or_source_ref": None,
"change_time_window": "pending_owner_response",
"cross_project_impact_ref": None,
"communication_sync_ref": None,
"reviewer_outcome": "waiting_owner_response",
"followup_owner": "pending_owner_response",
"acceptance_fields": ACCEPTANCE_FIELDS,
@@ -300,6 +332,10 @@ def build_report(
"certbot_renew_authorized_count": 0,
"maintenance_window_accepted_count": 0,
"rollback_owner_accepted_count": 0,
"change_actor_identified_count": 0,
"change_time_window_accepted_count": 0,
"cross_project_impact_accepted_count": 0,
"communication_sync_accepted_count": 0,
"runtime_gate_count": 0,
"action_button_count": 0,
},
@@ -333,6 +369,7 @@ def build_report(
"等待 owner response未收到前不得更新 accepted count。",
"收到回覆後先走 raw payload / secret / scope / evidence ref 檢查,不合格即隔離、拒收或補件。",
"metadata 合格也只能進 rendered diff reviewer review`nginx -t`、reload、route smoke 與 production write 仍需獨立人工批准。",
"若涉及手動或緊急 gateway 變更,必須先補 change actor/source、time window、cross-project impact 與 communication sync refs。",
],
}

View File

@@ -5574,11 +5574,11 @@ def validate(root: Path) -> None:
"acceptance_candidate_count": 3,
"c0_acceptance_candidate_count": 2,
"c1_acceptance_candidate_count": 1,
"acceptance_field_count": 23,
"required_owner_response_field_count": 12,
"reviewer_check_count": 12,
"acceptance_field_count": 27,
"required_owner_response_field_count": 16,
"reviewer_check_count": 16,
"outcome_lane_count": 7,
"blocked_action_count": 18,
"blocked_action_count": 22,
"request_sent_count": 0,
"recipient_confirmed_count": 0,
"owner_response_received_count": 0,
@@ -5600,6 +5600,10 @@ def validate(root: Path) -> None:
"certbot_renew_authorized_count": 0,
"maintenance_window_accepted_count": 0,
"rollback_owner_accepted_count": 0,
"change_actor_identified_count": 0,
"change_time_window_accepted_count": 0,
"cross_project_impact_accepted_count": 0,
"communication_sync_accepted_count": 0,
"runtime_gate_count": 0,
"action_button_count": 0,
}
@@ -5639,6 +5643,10 @@ def validate(root: Path) -> None:
"route_smoke_plan_present",
"maintenance_window_present",
"rollback_owner_present",
"change_actor_or_source_ref_present",
"change_time_window_present",
"cross_project_impact_review_present",
"communication_sync_ref_present",
"counts_transition_safe",
]
assert_equal(
@@ -5677,6 +5685,10 @@ def validate(root: Path) -> None:
"modify_dns_tls_config",
"change_public_route",
"write_production_host",
"accept_unknown_change_actor",
"accept_missing_change_time_window",
"skip_cross_project_impact_review",
"skip_incident_communication_sync",
"open_runtime_gate",
"add_action_button",
]
@@ -5689,17 +5701,17 @@ def validate(root: Path) -> None:
assert_equal(
f"public_gateway_owner_response_acceptance.{item['acceptance_candidate_id']}.field_count",
len(item["acceptance_fields"]),
23,
27,
)
assert_equal(
f"public_gateway_owner_response_acceptance.{item['acceptance_candidate_id']}.required_owner_response_fields",
len(item["required_owner_response_fields"]),
12,
16,
)
assert_equal(
f"public_gateway_owner_response_acceptance.{item['acceptance_candidate_id']}.reviewer_checks",
len(item["reviewer_checks"]),
12,
16,
)
assert_equal(
f"public_gateway_owner_response_acceptance.{item['acceptance_candidate_id']}.outcome_lanes",
@@ -5709,7 +5721,7 @@ def validate(root: Path) -> None:
assert_equal(
f"public_gateway_owner_response_acceptance.{item['acceptance_candidate_id']}.blocked_actions",
len(item["blocked_actions"]),
18,
22,
)
assert_true(
f"public_gateway_owner_response_acceptance.{item['acceptance_candidate_id']}.not_approval",