diff --git a/apps/api/src/services/ai_agent_autonomous_runtime_control.py b/apps/api/src/services/ai_agent_autonomous_runtime_control.py index c43e5d043..5bf28a645 100644 --- a/apps/api/src/services/ai_agent_autonomous_runtime_control.py +++ b/apps/api/src/services/ai_agent_autonomous_runtime_control.py @@ -4496,6 +4496,72 @@ def _runtime_truthy(value: Any) -> bool: return str(value or "").strip().lower() == "true" +def _build_runtime_source_compatibility( + *, + runtime: Mapping[str, Any], + source_boundary: Mapping[str, Any], + runtime_schema_version: str, + source_boundary_schema_version: str, + runtime_source_sha: str, + deployed_source_sha: str, +) -> dict[str, Any]: + """Separate runtime contract proof from exact deploy-SHA freshness. + + A newer unrelated deployment must not force another production apply just + to refresh a receipt SHA. The live runtime chain still has to satisfy the + versioned runtime contract, while the currently deployed source must pass + its independently verified source boundary. + """ + + exact_sha_match = bool( + runtime_source_sha + and deployed_source_sha + and runtime_source_sha == deployed_source_sha + ) + runtime_contract_verified = bool( + runtime.get("schema_version") == runtime_schema_version + and runtime.get("runtime_evidence_ready") is True + and runtime_source_sha + ) + deployed_source_boundary_verified = bool( + source_boundary.get("schema_version") == source_boundary_schema_version + and source_boundary.get("status") == "verified_ready" + and source_boundary.get("source_boundary_verified") is True + and source_boundary.get("source_sha_matches_deployment") is True + and not list(source_boundary.get("active_blockers") or []) + and deployed_source_sha + ) + compatible = bool( + runtime_contract_verified and deployed_source_boundary_verified + ) + return { + "schema_version": "awoooi_runtime_source_compatibility_v1", + "status": ( + "exact_sha_match" + if compatible and exact_sha_match + else "contract_compatible" + if compatible + else "unverified" + ), + "runtime_contract_schema_version": runtime_schema_version, + "deployed_source_boundary_schema_version": ( + source_boundary_schema_version + ), + "runtime_source_sha": runtime_source_sha or None, + "deployed_source_sha": deployed_source_sha or None, + "exact_sha_match": exact_sha_match, + "runtime_contract_verified": runtime_contract_verified, + "deployed_source_boundary_verified": ( + deployed_source_boundary_verified + ), + "runtime_contract_compatible_with_deployed_source_boundary": ( + compatible + ), + "completion_requires_exact_sha_match": False, + "writes_on_read": False, + } + + def _build_autonomous_single_writer_runtime_readback( *, operation_latest_rows: Iterable[Mapping[str, Any] | Any], @@ -6695,15 +6761,27 @@ def _attach_autonomous_single_writer_readback( boundary_readback.get("deployed_source_sha") or "" ).lower() router_source_sha = str(runtime.get("router_source_sha") or "").lower() + source_compatibility = _build_runtime_source_compatibility( + runtime=runtime, + source_boundary=source_boundary, + runtime_schema_version="awoooi_autonomous_single_writer_runtime_v1", + source_boundary_schema_version=( + "awoooi_autonomous_single_writer_source_boundary_v1" + ), + runtime_source_sha=router_source_sha, + deployed_source_sha=deployed_source_sha, + ) controls = { "strict_runtime_same_run_closed": bool( strict_runtime.get("closed") is True and runtime_run_id and runtime_run_id == strict_run_id ), - "router_source_sha_matches_deployment": bool( - deployed_source_sha - and router_source_sha == deployed_source_sha + "runtime_contract_compatible_with_deployed_source_boundary": bool( + source_compatibility.get( + "runtime_contract_compatible_with_deployed_source_boundary" + ) + is True ), **{ str(control_id): verified is True @@ -6738,6 +6816,7 @@ def _attach_autonomous_single_writer_readback( "apply_op_id": runtime.get("apply_op_id"), "source_receipt_ref": source_boundary.get("receipt_ref"), "source_verifier": source_boundary.get("verifier"), + "source_compatibility": source_compatibility, "controls": controls, "active_blockers": blockers, "writes_on_read": False, @@ -6780,15 +6859,29 @@ def _attach_independent_post_verifier_readback( verifier_source_sha = str( runtime.get("verifier_source_sha") or "" ).lower() + source_compatibility = _build_runtime_source_compatibility( + runtime=runtime, + source_boundary=source_boundary, + runtime_schema_version=( + "awoooi_independent_post_verifier_runtime_v1" + ), + source_boundary_schema_version=( + "awoooi_independent_post_verifier_source_boundary_v1" + ), + runtime_source_sha=verifier_source_sha, + deployed_source_sha=deployed_source_sha, + ) controls = { "strict_runtime_same_run_closed": bool( strict_runtime.get("closed") is True and runtime_run_id and runtime_run_id == strict_run_id ), - "verifier_source_sha_matches_deployment": bool( - deployed_source_sha - and verifier_source_sha == deployed_source_sha + "runtime_contract_compatible_with_deployed_source_boundary": bool( + source_compatibility.get( + "runtime_contract_compatible_with_deployed_source_boundary" + ) + is True ), **{ str(control_id): verified is True @@ -6831,6 +6924,7 @@ def _attach_independent_post_verifier_readback( ), "source_receipt_ref": source_boundary.get("receipt_ref"), "source_verifier": source_boundary.get("verifier"), + "source_compatibility": source_compatibility, "controls": controls, "active_blockers": blockers, "writes_on_read": False, @@ -6881,15 +6975,27 @@ def _attach_canonical_learning_readback( writer_source_sha = str( runtime.get("writer_source_sha") or "" ).lower() + source_compatibility = _build_runtime_source_compatibility( + runtime=runtime, + source_boundary=source_boundary, + runtime_schema_version="awoooi_canonical_learning_runtime_v1", + source_boundary_schema_version=( + "awoooi_canonical_learning_source_boundary_v1" + ), + runtime_source_sha=writer_source_sha, + deployed_source_sha=deployed_source_sha, + ) controls = { "strict_runtime_same_run_closed": bool( strict_runtime.get("closed") is True and runtime_run_id and runtime_run_id == strict_run_id ), - "writer_source_sha_matches_deployment": bool( - deployed_source_sha - and writer_source_sha == deployed_source_sha + "runtime_contract_compatible_with_deployed_source_boundary": bool( + source_compatibility.get( + "runtime_contract_compatible_with_deployed_source_boundary" + ) + is True ), **{ str(control_id): verified is True @@ -6930,6 +7036,7 @@ def _attach_canonical_learning_readback( ), "source_receipt_ref": source_boundary.get("receipt_ref"), "source_verifier": source_boundary.get("verifier"), + "source_compatibility": source_compatibility, "controls": controls, "active_blockers": blockers, "writes_on_read": False, diff --git a/apps/api/src/services/awoooi_priority_work_order_readback.py b/apps/api/src/services/awoooi_priority_work_order_readback.py index 09f5fc6c5..26d39975e 100644 --- a/apps/api/src/services/awoooi_priority_work_order_readback.py +++ b/apps/api/src/services/awoooi_priority_work_order_readback.py @@ -273,7 +273,7 @@ _AI_AUTOMATION_PROGRAM_DEPENDENCIES = { } _AI_SINGLE_WRITER_REQUIRED_CONTROL_IDS = ( "strict_runtime_same_run_closed", - "router_source_sha_matches_deployment", + "runtime_contract_compatible_with_deployed_source_boundary", "controlled_queue_decision_path", "single_writer_executor", "candidate_idempotency_key_present", @@ -293,7 +293,7 @@ _AI_SINGLE_WRITER_REQUIRED_CONTROL_IDS = ( ) _AI_INDEPENDENT_POST_VERIFIER_REQUIRED_CONTROL_IDS = ( "strict_runtime_same_run_closed", - "verifier_source_sha_matches_deployment", + "runtime_contract_compatible_with_deployed_source_boundary", "same_run_verifier_receipt", "verification_result_success", "asset_post_verifier_schema", @@ -314,7 +314,7 @@ _AI_INDEPENDENT_POST_VERIFIER_REQUIRED_CONTROL_IDS = ( ) _AI_CANONICAL_LEARNING_REQUIRED_CONTROL_IDS = ( "strict_runtime_same_run_closed", - "writer_source_sha_matches_deployment", + "runtime_contract_compatible_with_deployed_source_boundary", "same_run_learning_operation", "learning_operation_success", "learning_parent_apply_matches", @@ -7502,6 +7502,9 @@ def _apply_ai_automation_program_ledger(payload: dict[str, Any]) -> None: "controls": single_writer_controls, "missing": list(dict.fromkeys(single_writer_blockers)), "runtime_closed": single_writer_closed, + "source_compatibility": _dict( + summary.get("ai_agent_single_writer_source_compatibility") + ), } if single_writer_closed and all(single_writer_controls.values()): single_writer_work_item["status"] = "done" @@ -7529,6 +7532,9 @@ def _apply_ai_automation_program_ledger(payload: dict[str, Any]) -> None: summary.get("ai_agent_single_writer_apply_op_id") or "" ), "single_writer_executor": "awoooi-ansible-executor-broker", + "source_compatibility": _dict( + summary.get("ai_agent_single_writer_source_compatibility") + ), } single_writer_work_item["runtime_evidence_refs"] = [ "automation-run:" @@ -7580,6 +7586,11 @@ def _apply_ai_automation_program_ledger(payload: dict[str, Any]) -> None: "controls": post_verifier_controls, "missing": list(dict.fromkeys(post_verifier_blockers)), "runtime_closed": post_verifier_closed, + "source_compatibility": _dict( + summary.get( + "ai_agent_independent_post_verifier_source_compatibility" + ) + ), } if ( single_writer_work_item["status"] == "done" @@ -7634,6 +7645,11 @@ def _apply_ai_automation_program_ledger(payload: dict[str, Any]) -> None: ) ), "verifier": "asset_specific_read_only_host_postconditions", + "source_compatibility": _dict( + summary.get( + "ai_agent_independent_post_verifier_source_compatibility" + ) + ), } post_verifier_work_item["runtime_evidence_refs"] = [ "automation-run:" @@ -7694,6 +7710,9 @@ def _apply_ai_automation_program_ledger(payload: dict[str, Any]) -> None: "controls": canonical_learning_controls, "missing": list(dict.fromkeys(canonical_learning_blockers)), "runtime_closed": canonical_learning_closed, + "source_compatibility": _dict( + summary.get("ai_agent_canonical_learning_source_compatibility") + ), } if ( post_verifier_work_item["status"] == "done" @@ -7753,6 +7772,9 @@ def _apply_ai_automation_program_ledger(payload: dict[str, Any]) -> None: ) or "" ), + "source_compatibility": _dict( + summary.get("ai_agent_canonical_learning_source_compatibility") + ), } canonical_learning_work_item["runtime_evidence_refs"] = [ "automation-run:" @@ -8287,6 +8309,9 @@ def apply_ai_automation_live_closure_readbacks( ) summary["ai_agent_single_writer_runtime_closed"] = single_writer_closed summary["ai_agent_single_writer_controls"] = single_writer_controls + summary["ai_agent_single_writer_source_compatibility"] = _dict( + autonomous_single_writer.get("source_compatibility") + ) summary["ai_agent_single_writer_active_blockers"] = list( autonomous_single_writer.get("active_blockers") or [] ) @@ -8336,6 +8361,11 @@ def apply_ai_automation_live_closure_readbacks( summary["ai_agent_independent_post_verifier_controls"] = ( independent_post_verifier_controls ) + summary[ + "ai_agent_independent_post_verifier_source_compatibility" + ] = _dict( + autonomous_independent_post_verifier.get("source_compatibility") + ) summary["ai_agent_independent_post_verifier_active_blockers"] = list( autonomous_independent_post_verifier.get("active_blockers") or [] ) @@ -8396,6 +8426,9 @@ def apply_ai_automation_live_closure_readbacks( summary["ai_agent_canonical_learning_controls"] = ( canonical_learning_controls ) + summary["ai_agent_canonical_learning_source_compatibility"] = _dict( + autonomous_canonical_learning.get("source_compatibility") + ) summary["ai_agent_canonical_learning_active_blockers"] = list( autonomous_canonical_learning.get("active_blockers") or [] ) diff --git a/apps/api/tests/test_ai_agent_autonomous_runtime_control.py b/apps/api/tests/test_ai_agent_autonomous_runtime_control.py index 11a61f01f..7a12bdddd 100644 --- a/apps/api/tests/test_ai_agent_autonomous_runtime_control.py +++ b/apps/api/tests/test_ai_agent_autonomous_runtime_control.py @@ -1130,7 +1130,7 @@ def test_runtime_receipt_auxiliary_sql_keeps_source_family_counts_schema_safe(): assert "channel_chat_id LIKE 'alert-group:%'" in _RUNTIME_GROUPED_ALERT_EVENT_COUNTS_SQL -def test_autonomous_single_writer_requires_same_run_runtime_and_deployed_source() -> None: +def test_autonomous_single_writer_requires_same_run_and_deployed_contract_boundary() -> None: run_id = "11111111-1111-4111-8111-111111111111" rows = [ { @@ -1193,6 +1193,12 @@ def test_autonomous_single_writer_requires_same_run_runtime_and_deployed_source( boundary_readback={ "deployed_source_sha": "source123", "autonomous_single_writer_source_boundary": { + "schema_version": ( + "awoooi_autonomous_single_writer_source_boundary_v1" + ), + "status": "verified_ready", + "source_boundary_verified": True, + "source_sha_matches_deployment": True, "receipt_ref": "configmap:awoooi-prod/boundary", "verifier": "cd_tests_and_production_source_sha_v1", "controls": source_controls, @@ -1204,6 +1210,34 @@ def test_autonomous_single_writer_requires_same_run_runtime_and_deployed_source( assert payload["autonomous_single_writer"]["closed"] is True assert payload["autonomous_single_writer"]["active_blockers"] == [] assert payload["rollups"]["autonomous_single_writer_closed_count"] == 1 + assert payload["autonomous_single_writer"]["source_compatibility"][ + "exact_sha_match" + ] is True + + runtime_control_module._attach_autonomous_single_writer_readback( + payload, + readback={"autonomous_single_writer_runtime": runtime}, + boundary_readback={ + "deployed_source_sha": "newer-source", + "autonomous_single_writer_source_boundary": { + "schema_version": ( + "awoooi_autonomous_single_writer_source_boundary_v1" + ), + "status": "verified_ready", + "source_boundary_verified": True, + "source_sha_matches_deployment": True, + "controls": source_controls, + "active_blockers": [], + }, + }, + ) + assert payload["autonomous_single_writer"]["closed"] is True + assert payload["autonomous_single_writer"]["source_compatibility"][ + "status" + ] == "contract_compatible" + assert payload["autonomous_single_writer"]["source_compatibility"][ + "exact_sha_match" + ] is False payload["strict_runtime_completion"]["automation_run_id"] = "other-run" runtime_control_module._attach_autonomous_single_writer_readback( @@ -1212,6 +1246,12 @@ def test_autonomous_single_writer_requires_same_run_runtime_and_deployed_source( boundary_readback={ "deployed_source_sha": "source123", "autonomous_single_writer_source_boundary": { + "schema_version": ( + "awoooi_autonomous_single_writer_source_boundary_v1" + ), + "status": "verified_ready", + "source_boundary_verified": True, + "source_sha_matches_deployment": True, "controls": source_controls, "active_blockers": [], }, @@ -1223,7 +1263,7 @@ def test_autonomous_single_writer_requires_same_run_runtime_and_deployed_source( ]["active_blockers"] -def test_independent_post_verifier_requires_same_run_and_deployed_source() -> None: +def test_independent_post_verifier_requires_same_run_and_deployed_contract_boundary() -> None: run_id = "11111111-1111-4111-8111-111111111111" apply_op_id = "33333333-3333-4333-8333-333333333333" runtime = ( @@ -1283,6 +1323,12 @@ def test_independent_post_verifier_requires_same_run_and_deployed_source() -> No boundary_readback={ "deployed_source_sha": "source123", "independent_post_verifier_source_boundary": { + "schema_version": ( + "awoooi_independent_post_verifier_source_boundary_v1" + ), + "status": "verified_ready", + "source_boundary_verified": True, + "source_sha_matches_deployment": True, "receipt_ref": "configmap:awoooi-prod/boundary", "verifier": "cd_tests_and_production_source_sha_v1", "controls": source_controls, @@ -1304,19 +1350,49 @@ def test_independent_post_verifier_requires_same_run_and_deployed_source() -> No boundary_readback={ "deployed_source_sha": "different-source", "independent_post_verifier_source_boundary": { + "schema_version": ( + "awoooi_independent_post_verifier_source_boundary_v1" + ), + "status": "verified_ready", + "source_boundary_verified": True, + "source_sha_matches_deployment": True, "controls": source_controls, "active_blockers": [], }, }, ) verifier = payload["autonomous_independent_post_verifier"] + assert verifier["closed"] is True + assert verifier["source_compatibility"]["status"] == "contract_compatible" + assert verifier["source_compatibility"]["exact_sha_match"] is False + + runtime_control_module._attach_independent_post_verifier_readback( + payload, + readback={"independent_post_verifier_runtime": runtime}, + boundary_readback={ + "deployed_source_sha": "different-source", + "independent_post_verifier_source_boundary": { + "schema_version": ( + "awoooi_independent_post_verifier_source_boundary_v1" + ), + "status": "in_progress", + "source_boundary_verified": False, + "source_sha_matches_deployment": False, + "controls": source_controls, + "active_blockers": ["source_sha_not_deployed"], + }, + }, + ) + verifier = payload["autonomous_independent_post_verifier"] assert verifier["closed"] is False - assert "verifier_source_sha_matches_deployment_not_verified" in verifier[ - "active_blockers" - ] + assert "source_sha_not_deployed" in verifier["active_blockers"] + assert ( + "runtime_contract_compatible_with_deployed_source_boundary_not_verified" + in verifier["active_blockers"] + ) -def test_canonical_learning_requires_row_readback_and_deployed_source() -> None: +def test_canonical_learning_requires_row_readback_and_deployed_contract_boundary() -> None: run_id = "11111111-1111-4111-8111-111111111111" apply_op_id = "33333333-3333-4333-8333-333333333333" catalog_id = "ansible:188-momo-backup-user" @@ -1404,6 +1480,12 @@ def test_canonical_learning_requires_row_readback_and_deployed_source() -> None: boundary_readback={ "deployed_source_sha": "source123", "canonical_learning_source_boundary": { + "schema_version": ( + "awoooi_canonical_learning_source_boundary_v1" + ), + "status": "verified_ready", + "source_boundary_verified": True, + "source_sha_matches_deployment": True, "receipt_ref": "configmap:awoooi-prod/boundary", "verifier": "cd_tests_and_production_source_sha_v1", "controls": source_controls, @@ -1427,16 +1509,46 @@ def test_canonical_learning_requires_row_readback_and_deployed_source() -> None: boundary_readback={ "deployed_source_sha": "different-source", "canonical_learning_source_boundary": { + "schema_version": ( + "awoooi_canonical_learning_source_boundary_v1" + ), + "status": "verified_ready", + "source_boundary_verified": True, + "source_sha_matches_deployment": True, "controls": source_controls, "active_blockers": [], }, }, ) learning = payload["autonomous_canonical_learning_writeback"] + assert learning["closed"] is True + assert learning["source_compatibility"]["status"] == "contract_compatible" + assert learning["source_compatibility"]["exact_sha_match"] is False + + runtime_control_module._attach_canonical_learning_readback( + payload, + readback={"canonical_learning_runtime": runtime}, + boundary_readback={ + "deployed_source_sha": "different-source", + "canonical_learning_source_boundary": { + "schema_version": ( + "awoooi_canonical_learning_source_boundary_v1" + ), + "status": "in_progress", + "source_boundary_verified": False, + "source_sha_matches_deployment": False, + "controls": source_controls, + "active_blockers": ["source_sha_not_deployed"], + }, + }, + ) + learning = payload["autonomous_canonical_learning_writeback"] assert learning["closed"] is False - assert "writer_source_sha_matches_deployment_not_verified" in learning[ - "active_blockers" - ] + assert "source_sha_not_deployed" in learning["active_blockers"] + assert ( + "runtime_contract_compatible_with_deployed_source_boundary_not_verified" + in learning["active_blockers"] + ) def test_ai_agent_autonomous_runtime_control_uses_current_owner_directive(): diff --git a/apps/api/tests/test_awoooi_priority_work_order_readback_api.py b/apps/api/tests/test_awoooi_priority_work_order_readback_api.py index 3f1615bb1..519f31243 100644 --- a/apps/api/tests/test_awoooi_priority_work_order_readback_api.py +++ b/apps/api/tests/test_awoooi_priority_work_order_readback_api.py @@ -165,10 +165,16 @@ def _autonomous_runtime_control_single_writer_closed() -> dict: "configmap:awoooi-prod/awoooi-executor-boundary-verification" ), "source_verifier": "cd_tests_and_production_source_sha_v1", - "controls": { - control_id: True - for control_id in priority_service._AI_SINGLE_WRITER_REQUIRED_CONTROL_IDS + "source_compatibility": { + "schema_version": "awoooi_runtime_source_compatibility_v1", + "status": "contract_compatible", + "exact_sha_match": False, + "runtime_contract_compatible_with_deployed_source_boundary": True, }, + "controls": dict.fromkeys( + priority_service._AI_SINGLE_WRITER_REQUIRED_CONTROL_IDS, + True, + ), "active_blockers": [], } return payload @@ -193,13 +199,16 @@ def _autonomous_runtime_control_independent_post_verifier_closed() -> dict: "configmap:awoooi-prod/awoooi-executor-boundary-verification" ), "source_verifier": "cd_tests_and_production_source_sha_v1", - "controls": { - control_id: True - for control_id in ( - priority_service - ._AI_INDEPENDENT_POST_VERIFIER_REQUIRED_CONTROL_IDS - ) + "source_compatibility": { + "schema_version": "awoooi_runtime_source_compatibility_v1", + "status": "contract_compatible", + "exact_sha_match": False, + "runtime_contract_compatible_with_deployed_source_boundary": True, }, + "controls": dict.fromkeys( + priority_service._AI_INDEPENDENT_POST_VERIFIER_REQUIRED_CONTROL_IDS, + True, + ), "active_blockers": [], } return payload @@ -227,12 +236,16 @@ def _autonomous_runtime_control_canonical_learning_closed() -> dict: "configmap:awoooi-prod/awoooi-executor-boundary-verification" ), "source_verifier": "cd_tests_and_production_source_sha_v1", - "controls": { - control_id: True - for control_id in ( - priority_service._AI_CANONICAL_LEARNING_REQUIRED_CONTROL_IDS - ) + "source_compatibility": { + "schema_version": "awoooi_runtime_source_compatibility_v1", + "status": "contract_compatible", + "exact_sha_match": False, + "runtime_contract_compatible_with_deployed_source_boundary": True, }, + "controls": dict.fromkeys( + priority_service._AI_CANONICAL_LEARNING_REQUIRED_CONTROL_IDS, + True, + ), "active_blockers": [], } return payload @@ -2143,6 +2156,12 @@ def test_ai_automation_single_writer_runtime_receipt_advances_order() -> None: assert single_writer["completion_evidence"]["single_writer_executor"] == ( "awoooi-ansible-executor-broker" ) + assert single_writer["completion_evidence"]["source_compatibility"][ + "status" + ] == "contract_compatible" + assert single_writer["runtime_progress"]["source_compatibility"][ + "exact_sha_match" + ] is False assert program["summary"]["next_work_item_id"] == "AIA-P0-003" assert program["summary"]["done_count"] == 3 assert program["summary"]["completion_percent"] == 15 @@ -2176,6 +2195,9 @@ def test_ai_automation_independent_post_verifier_advances_order() -> None: ) assert verifier["completion_evidence"]["required_postcondition_count"] == 5 assert verifier["completion_evidence"]["passed_postcondition_count"] == 5 + assert verifier["completion_evidence"]["source_compatibility"][ + "status" + ] == "contract_compatible" assert program["summary"]["next_work_item_id"] == "AIA-P0-004" assert program["summary"]["done_count"] == 4 assert program["summary"]["completion_percent"] == 20 @@ -2235,6 +2257,9 @@ def test_ai_automation_canonical_learning_receipt_advances_order() -> None: "PB-ANSIBLE-188-MOMO-BACKUP-USER" ) assert learning["completion_evidence"]["playbook_row_version"] == 2 + assert learning["completion_evidence"]["source_compatibility"][ + "status" + ] == "contract_compatible" assert program["summary"]["next_work_item_id"] == "AIA-P0-005" assert program["summary"]["done_count"] == 5 assert program["summary"]["completion_percent"] == 25 diff --git a/apps/api/tests/test_executor_network_policy_boundary.py b/apps/api/tests/test_executor_network_policy_boundary.py index f4633df9f..d27479b04 100644 --- a/apps/api/tests/test_executor_network_policy_boundary.py +++ b/apps/api/tests/test_executor_network_policy_boundary.py @@ -90,7 +90,10 @@ def test_cd_applies_rolls_back_and_verifies_network_boundary() -> None: assert "02-network-policy.yaml" in workflow assert "NETWORK_POLICY_ROLLBACK_FILE" in workflow assert "get networkpolicy ${NETWORK_POLICY_NAMES[*]}" in workflow - assert "rollback_network_policy_on_exit" in workflow + assert "rollback_deploy_controls_on_exit" in workflow + assert "restore_deploy_controls" in workflow + assert "restore_workload_database_projection" in workflow + assert "restore_network_policy" in workflow assert "git show HEAD^:k8s/awoooi-prod/02-network-policy.yaml" not in workflow assert "BROKER_POLICY_EXISTED" in workflow assert "NETWORK_POLICY_NAMES" in workflow