Merge remote-tracking branch 'origin/main' into codex/playwright-mcp-supply-20260715
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Has been cancelled
CD Pipeline / build-and-deploy (push) Has been cancelled
CD Pipeline / post-deploy-checks (push) Has been cancelled
MCP External Protocol Replay / replay-and-verify (push) Failing after 49s
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Has been cancelled
CD Pipeline / build-and-deploy (push) Has been cancelled
CD Pipeline / post-deploy-checks (push) Has been cancelled
MCP External Protocol Replay / replay-and-verify (push) Failing after 49s
This commit is contained in:
@@ -309,9 +309,13 @@ def _compliance_rows(rows: Iterable[Any]) -> list[dict[str, Any]]:
|
||||
|
||||
|
||||
def _automation_stage_rows(
|
||||
rows: Iterable[Any], accepted_ai_trace_count: int
|
||||
rows: Iterable[Any],
|
||||
accepted_ai_trace_count: int,
|
||||
*,
|
||||
runtime_receipt_counts: dict[str, int] | None = None,
|
||||
) -> list[dict[str, Any]]:
|
||||
source = list(rows)
|
||||
external_receipts = runtime_receipt_counts or {}
|
||||
stages: list[dict[str, Any]] = []
|
||||
for stage_id, label, operation_types in _AI_LOOP_STAGES:
|
||||
receipt_count = sum(
|
||||
@@ -320,6 +324,10 @@ def _automation_stage_rows(
|
||||
if str(_value(row, "operation_type", "")) in operation_types
|
||||
and str(_value(row, "status", "")) in {"success", "dry_run"}
|
||||
)
|
||||
receipt_count = max(
|
||||
receipt_count,
|
||||
max(0, int(external_receipts.get(stage_id, 0) or 0)),
|
||||
)
|
||||
if stage_id == "decide":
|
||||
receipt_count += accepted_ai_trace_count
|
||||
stages.append(
|
||||
@@ -809,8 +817,17 @@ def build_iwooos_security_asset_control_plane(
|
||||
compliance_unknown = sum(row["unknown_count"] for row in compliance)
|
||||
|
||||
accepted_ai_trace_count = int(_value(ai_trace_row, "accepted_trace_count", 0) or 0)
|
||||
runtime_receipt_counts = {
|
||||
"correlate": int(
|
||||
_value(siem_row, "correlated_controlled_route_count_24h", 0) or 0
|
||||
),
|
||||
"verify": int(_value(siem_row, "independent_verifier_pass_count_24h", 0) or 0),
|
||||
"learn": int(_value(siem_row, "learning_writeback_count_24h", 0) or 0),
|
||||
}
|
||||
automation_stages = _automation_stage_rows(
|
||||
automation_source, accepted_ai_trace_count
|
||||
automation_source,
|
||||
accepted_ai_trace_count,
|
||||
runtime_receipt_counts=runtime_receipt_counts,
|
||||
)
|
||||
observed_automation_stages = sum(
|
||||
1 for stage in automation_stages if stage["status"] == "observed"
|
||||
@@ -882,6 +899,9 @@ def build_iwooos_security_asset_control_plane(
|
||||
"normalized_event_count_24h": int(
|
||||
_value(siem_row, "normalized_event_count_24h", 0) or 0
|
||||
),
|
||||
"correlated_controlled_route_count_24h": runtime_receipt_counts["correlate"],
|
||||
"independent_verifier_pass_count_24h": runtime_receipt_counts["verify"],
|
||||
"learning_writeback_count_24h": runtime_receipt_counts["learn"],
|
||||
"mean_time_to_resolve_minutes_24h": (
|
||||
round(float(_value(siem_row, "mttr_minutes_24h")), 1)
|
||||
if _value(siem_row, "mttr_minutes_24h") is not None
|
||||
@@ -1103,14 +1123,18 @@ def build_iwooos_security_asset_control_plane(
|
||||
)
|
||||
)
|
||||
missing_ai_stages = len(_AI_LOOP_STAGES) - observed_automation_stages
|
||||
if missing_ai_stages > 0 or verified_receipts == 0:
|
||||
if (
|
||||
missing_ai_stages > 0
|
||||
or verified_receipts == 0
|
||||
or not same_run_closed_loop_proven
|
||||
):
|
||||
work_items.append(
|
||||
_work_item(
|
||||
"AIA-P0-008-01",
|
||||
"P0",
|
||||
"ai_security_automation",
|
||||
"完成 AI Agent 同 run 受控閉環",
|
||||
max(1, missing_ai_stages),
|
||||
max(1, missing_ai_stages + (0 if same_run_closed_loop_proven else 1)),
|
||||
"同 trace 串接 decision、check、bounded apply、verifier、rollback/no-write 與 learning。",
|
||||
)
|
||||
)
|
||||
@@ -1927,6 +1951,49 @@ class IwoooSSecurityAssetControlPlaneService:
|
||||
WHERE project_id = 'awoooi'
|
||||
AND received_at >= NOW() - INTERVAL '24 hours')
|
||||
AS normalized_event_count_24h,
|
||||
(SELECT count(*) FROM automation_operation_log route
|
||||
WHERE route.operation_type = 'ansible_candidate_matched'
|
||||
AND route.status IN ('success', 'dry_run')
|
||||
AND route.created_at >= NOW() - INTERVAL '24 hours'
|
||||
AND COALESCE(
|
||||
NULLIF(route.incident_id::text, ''),
|
||||
NULLIF(route.input ->> 'incident_id', '')
|
||||
) IS NOT NULL
|
||||
AND NULLIF(route.input ->> 'catalog_id', '') IS NOT NULL)
|
||||
AS correlated_controlled_route_count_24h,
|
||||
(SELECT count(*) FROM incident_evidence verifier
|
||||
WHERE verifier.collected_at >= NOW() - INTERVAL '24 hours'
|
||||
AND verifier.verification_result = 'success'
|
||||
AND NULLIF(
|
||||
verifier.post_execution_state ->> 'automation_run_id',
|
||||
''
|
||||
) IS NOT NULL
|
||||
AND NULLIF(
|
||||
verifier.post_execution_state ->> 'apply_op_id',
|
||||
''
|
||||
) IS NOT NULL
|
||||
AND verifier.post_execution_state
|
||||
->> 'all_postconditions_passed' = 'true'
|
||||
AND verifier.post_execution_state
|
||||
->> 'executor_returncode_trusted' = 'false')
|
||||
AS independent_verifier_pass_count_24h,
|
||||
(SELECT count(*) FROM automation_operation_log learning
|
||||
WHERE learning.operation_type
|
||||
= 'ansible_learning_writeback_recorded'
|
||||
AND learning.status = 'success'
|
||||
AND learning.created_at >= NOW() - INTERVAL '24 hours'
|
||||
AND NULLIF(
|
||||
learning.input ->> 'automation_run_id',
|
||||
''
|
||||
) IS NOT NULL
|
||||
AND NULLIF(
|
||||
learning.input ->> 'apply_op_id',
|
||||
''
|
||||
) IS NOT NULL
|
||||
AND learning.output ->> 'learning_recorded' = 'true'
|
||||
AND learning.output
|
||||
->> 'repository_readback_verified' = 'true')
|
||||
AS learning_writeback_count_24h,
|
||||
(SELECT avg(EXTRACT(EPOCH FROM (resolved_at - created_at)) / 60.0)
|
||||
FROM incidents
|
||||
WHERE project_id = 'awoooi'
|
||||
|
||||
@@ -31,6 +31,8 @@ def _ready_payload(
|
||||
*,
|
||||
discovery_status: str = "success",
|
||||
discovery_error: str | None = None,
|
||||
automation_rows: list[SimpleNamespace] | None = None,
|
||||
runtime_receipt_counts: dict[str, int] | None = None,
|
||||
) -> dict:
|
||||
now = datetime(2026, 7, 11, 4, 0, tzinfo=UTC)
|
||||
discovery = _row(
|
||||
@@ -79,16 +81,25 @@ def _ready_payload(
|
||||
"encryption_at_rest",
|
||||
)
|
||||
]
|
||||
automation = [
|
||||
_row(operation_type="asset_discovered", status="success", cnt=1),
|
||||
_row(operation_type="rule_matched", status="success", cnt=3),
|
||||
_row(operation_type="rule_created", status="success", cnt=2),
|
||||
_row(operation_type="ansible_check_mode_executed", status="dry_run", cnt=2),
|
||||
_row(operation_type="ansible_apply_executed", status="success", cnt=1),
|
||||
_row(operation_type="remediation_verified", status="success", cnt=1),
|
||||
_row(operation_type="km_created", status="success", cnt=1),
|
||||
_row(operation_type="ansible_apply_executed", status="failed", cnt=1),
|
||||
]
|
||||
automation = (
|
||||
automation_rows
|
||||
if automation_rows is not None
|
||||
else [
|
||||
_row(operation_type="asset_discovered", status="success", cnt=1),
|
||||
_row(operation_type="rule_matched", status="success", cnt=3),
|
||||
_row(operation_type="rule_created", status="success", cnt=2),
|
||||
_row(
|
||||
operation_type="ansible_check_mode_executed",
|
||||
status="dry_run",
|
||||
cnt=2,
|
||||
),
|
||||
_row(operation_type="ansible_apply_executed", status="success", cnt=1),
|
||||
_row(operation_type="remediation_verified", status="success", cnt=1),
|
||||
_row(operation_type="km_created", status="success", cnt=1),
|
||||
_row(operation_type="ansible_apply_executed", status="failed", cnt=1),
|
||||
]
|
||||
)
|
||||
runtime_counts = runtime_receipt_counts or {}
|
||||
return build_iwooos_security_asset_control_plane(
|
||||
discovery_row=discovery,
|
||||
inventory_rows=inventory,
|
||||
@@ -108,6 +119,9 @@ def _ready_payload(
|
||||
resolved_incident_count_24h=3,
|
||||
decision_chain_count_24h=5,
|
||||
normalized_event_count_24h=18,
|
||||
correlated_controlled_route_count_24h=runtime_counts.get("correlate", 0),
|
||||
independent_verifier_pass_count_24h=runtime_counts.get("verify", 0),
|
||||
learning_writeback_count_24h=runtime_counts.get("learn", 0),
|
||||
mttr_minutes_24h=14.25,
|
||||
),
|
||||
audit_row=_row(
|
||||
@@ -188,6 +202,9 @@ def test_builds_live_asset_siem_audit_and_ai_control_plane_without_false_closure
|
||||
assert any(
|
||||
item["work_item_id"] == "AIA-P1-001-01" for item in payload["work_items"]
|
||||
)
|
||||
assert any(
|
||||
item["work_item_id"] == "AIA-P0-008-01" for item in payload["work_items"]
|
||||
)
|
||||
|
||||
public_text = json.dumps(payload, ensure_ascii=False)
|
||||
assert "192.168." not in public_text
|
||||
@@ -197,6 +214,41 @@ def test_builds_live_asset_siem_audit_and_ai_control_plane_without_false_closure
|
||||
assert 'secret_value_collection_allowed": true' not in public_text.lower()
|
||||
|
||||
|
||||
def test_projects_canonical_runtime_receipts_without_false_same_run_closure() -> None:
|
||||
payload = _ready_payload(
|
||||
automation_rows=[
|
||||
_row(operation_type="asset_discovered", status="success", cnt=1),
|
||||
_row(operation_type="rule_matched", status="success", cnt=2),
|
||||
_row(operation_type="rule_created", status="success", cnt=2),
|
||||
_row(
|
||||
operation_type="ansible_check_mode_executed",
|
||||
status="dry_run",
|
||||
cnt=2,
|
||||
),
|
||||
_row(operation_type="ansible_apply_executed", status="success", cnt=1),
|
||||
_row(operation_type="remediation_verified", status="success", cnt=2),
|
||||
_row(operation_type="km_created", status="success", cnt=2),
|
||||
],
|
||||
runtime_receipt_counts={"correlate": 7, "verify": 5, "learn": 4},
|
||||
)
|
||||
|
||||
ai_stages = {
|
||||
stage["stage_id"]: stage for stage in payload["ai_automation"]["stages"]
|
||||
}
|
||||
assert ai_stages["correlate"]["receipt_count_24h"] == 7
|
||||
assert ai_stages["verify"]["receipt_count_24h"] == 5
|
||||
assert ai_stages["learn"]["receipt_count_24h"] == 4
|
||||
assert payload["summary"]["verified_remediation_receipt_count_24h"] == 5
|
||||
assert payload["summary"]["siem_stage_coverage_percent"] == 100
|
||||
assert payload["summary"]["ai_loop_stage_coverage_percent"] == 100
|
||||
assert payload["completion"]["strict_runtime_closure_percent"] == 0
|
||||
assert payload["ai_automation"]["same_run_closed_loop_proven"] is False
|
||||
|
||||
work_items = {item["work_item_id"]: item for item in payload["work_items"]}
|
||||
assert "AIA-P0-007-01" not in work_items
|
||||
assert work_items["AIA-P0-008-01"]["gap_count"] == 1
|
||||
|
||||
|
||||
def test_discovery_failure_exposes_only_allowlisted_collector_ids() -> None:
|
||||
raw_error = (
|
||||
"RuntimeError: asset_collector_failures=domain_tls_inventory,"
|
||||
@@ -687,6 +739,17 @@ def test_service_bounds_source_concurrency_for_database_budget(monkeypatch) -> N
|
||||
assert "digest_pinned" in inventory_query
|
||||
assert "live_tls_probe_evidenced" in inventory_query
|
||||
assert "live_tls_healthy" in inventory_query
|
||||
siem_query = next(
|
||||
statement for statement in statements if "FROM alert_rule_catalog" in statement
|
||||
)
|
||||
assert "correlated_controlled_route_count_24h" in siem_query
|
||||
assert "ansible_candidate_matched" in siem_query
|
||||
assert "independent_verifier_pass_count_24h" in siem_query
|
||||
assert "all_postconditions_passed" in siem_query
|
||||
assert "executor_returncode_trusted" in siem_query
|
||||
assert "learning_writeback_count_24h" in siem_query
|
||||
assert "ansible_learning_writeback_recorded" in siem_query
|
||||
assert "repository_readback_verified" in siem_query
|
||||
|
||||
|
||||
def test_public_api_returns_live_aggregate(monkeypatch) -> None:
|
||||
|
||||
Reference in New Issue
Block a user