# agent/tests/test_agent/test_agent_confirmation_v2.py # #region Test.Agent.ConfirmationV2 [C:3] [TYPE Module] [SEMANTICS test,agent-chat,confirmation,guardrails,hitl] # @BRIEF Contract tests for confirmation_metadata_for_tool and build_confirmation_contract_v2 — three-axis risk, env resolution, permission denied. # @RELATION BINDS_TO -> [AgentChat.Confirmation] # @TEST_FIXTURE: deploy_prod -> guarded + prod env_context # @TEST_FIXTURE: deploy_staging -> guarded + staging env_context # @TEST_FIXTURE: deploy_dev -> guarded + dev env_context # @TEST_FIXTURE: delete_any -> dangerous risk_level # @TEST_FIXTURE: read_only -> safe risk_level # @TEST_FIXTURE: analyst_deploy -> permission_granted=false # @TEST_FIXTURE: env_resolution -> tool_args.env_id > target_env > None from ss_tools.agent._confirmation import ( _resolve_env_tier, build_confirmation_contract_v2, confirmation_metadata_for_tool, permission_denied_payload, ) # ── _resolve_env_tier ─────────────────────────────────────────────── # #region test_env_resolution_from_tool_args [C:2] [TYPE Function] def test_resolve_env_tier_from_tool_args_env_id(): """env_id in tool_args takes highest priority.""" assert _resolve_env_tier({"env_id": "prod-01"}, None) == "prod" assert _resolve_env_tier({"env_id": "prod-01"}, "staging") == "prod" # tool_args wins # #endregion test_env_resolution_from_tool_args # #region test_env_resolution_from_environment_id [C:2] [TYPE Function] def test_resolve_env_tier_from_environment_id(): """environment_id in tool_args (alternative key) works.""" assert _resolve_env_tier({"environment_id": "staging-v2"}, None) == "staging" # #endregion test_env_resolution_from_environment_id # #region test_env_resolution_from_target_env [C:2] [TYPE Function] def test_resolve_env_tier_from_target_env(): """target_env fallback when tool_args has no env.""" assert _resolve_env_tier({}, "ss-dev") == "dev" assert _resolve_env_tier({"query": "test"}, "prod-v2") == "prod" # #endregion test_env_resolution_from_target_env # #region test_env_resolution_null_when_no_env [C:2] [TYPE Function] def test_resolve_env_tier_null_when_no_env(): """When neither tool_args nor target_env provides env, return None.""" assert _resolve_env_tier({}, None) is None assert _resolve_env_tier({"dashboard_id": 42}, None) is None # #endregion test_env_resolution_null_when_no_env # #region test_env_resolution_ambiguous_names [C:2] [TYPE Function] def test_resolve_env_tier_ambiguous_names(): """Environment names containing stag/test/local/dev are correctly tiered.""" assert _resolve_env_tier({"env_id": "autotest"}, None) == "staging" # "test" in autotest assert _resolve_env_tier({"env_id": "localhost"}, None) == "dev" # "local" in localhost # #endregion test_env_resolution_ambiguous_names # ── build_confirmation_contract_v2 ─────────────────────────────────── # #region test_deploy_to_prod_is_guarded_with_prod_context [C:2] [TYPE Function] def test_deploy_to_prod_is_guarded_with_prod_context(): """Deploy to production → guarded risk + prod env_context.""" contract = build_confirmation_contract_v2( "deploy_dashboard", {"env_id": "prod-01"}, "admin", "prod-01", ) assert contract["risk"] == "write" assert contract["risk_level"] == "guarded" assert contract["dangerous"] is False assert contract["env_context"] == "prod" assert contract["permission_granted"] is True # #endregion test_deploy_to_prod_is_guarded_with_prod_context # #region test_deploy_to_staging_is_guarded_with_staging_context [C:2] [TYPE Function] def test_deploy_to_staging_is_guarded_with_staging_context(): """Deploy to staging → guarded risk + staging env_context.""" contract = build_confirmation_contract_v2( "deploy_dashboard", {"env_id": "staging-v2"}, "admin", "staging-v2", ) assert contract["risk"] == "write" assert contract["risk_level"] == "guarded" assert contract["env_context"] == "staging" # #endregion test_deploy_to_staging_is_guarded_with_staging_context # #region test_deploy_to_dev_is_guarded_with_dev_context [C:2] [TYPE Function] def test_deploy_to_dev_is_guarded_with_dev_context(): """Deploy to dev → guarded risk + dev env_context.""" contract = build_confirmation_contract_v2( "deploy_dashboard", {"env_id": "my-dev-env"}, "admin", "my-dev-env", ) assert contract["risk"] == "write" assert contract["risk_level"] == "guarded" assert contract["env_context"] == "dev" # #endregion test_deploy_to_dev_is_guarded_with_dev_context # #region test_delete_operation_is_dangerous [C:2] [TYPE Function] def test_delete_operation_is_dangerous(): """Delete-prefixed tools should be classified as dangerous.""" contract = build_confirmation_contract_v2( "delete_dashboard", {}, "admin", ) assert contract["risk"] == "write" assert contract["risk_level"] == "dangerous" assert contract["dangerous"] is True # #endregion test_delete_operation_is_dangerous # #region test_read_only_tool_is_safe [C:2] [TYPE Function] def test_read_only_tool_is_safe(): """Search/list/get tools should be classified as safe/read.""" contract = build_confirmation_contract_v2( "search_dashboards", {"env_id": "prod"}, "admin", "prod", ) assert contract["risk"] == "read" assert contract["risk_level"] == "safe" assert contract["dangerous"] is False # #endregion test_read_only_tool_is_safe # #region test_viewer_gets_permission_denied [C:2] [TYPE Function] def test_viewer_permission_denied_for_write_tools(): """Viewer role should be denied permission for write tools.""" contract = build_confirmation_contract_v2( "deploy_dashboard", {"env_id": "prod"}, "viewer", "prod", ) assert contract["permission_granted"] is False assert contract["required_role"] == "admin" assert contract["alternatives"] is not None assert len(contract["alternatives"]) >= 1 # #endregion test_viewer_gets_permission_denied # #region test_analyst_permission_denied_specific_tools [C:2] [TYPE Function] def test_analyst_permission_denied_for_admin_tools(): """Analyst/editor role should be denied for admin-only tools.""" for tool_name in ("deploy_dashboard", "execute_migration", "run_backup"): contract = build_confirmation_contract_v2(tool_name, {}, "analyst") assert contract["permission_granted"] is False, f"{tool_name} should be denied for analyst" # #endregion test_analyst_permission_denied_specific_tools # #region test_admin_write_tool_permission_granted [C:2] [TYPE Function] def test_admin_write_tool_permission_granted(): """Admin role should always have permission_granted=True for guarded tools.""" write_tools = ["deploy_dashboard", "commit_changes", "execute_migration"] for tool_name in write_tools: contract = build_confirmation_contract_v2(tool_name, {}, "admin") assert contract["permission_granted"] is True, f"{tool_name} should be allowed for admin" # #endregion test_admin_write_tool_permission_granted # ── confirmation_metadata_for_tool ──────────────────────────────────── # #region test_metadata_for_tool_contains_required_fields [C:2] [TYPE Function] def test_metadata_for_tool_contains_all_required_fields(): """confirmation_metadata_for_tool should produce a complete metadata dict.""" meta = confirmation_metadata_for_tool( "conv-123", "deploy_dashboard", {"env_id": "prod-01"}, "admin", "prod-01", ) required_fields = [ "type", "thread_id", "prompt", "tool_name", "tool_args", "risk", "risk_level", "requires_confirmation", "dangerous", "env_context", ] for field in required_fields: assert field in meta, f"Missing field '{field}' in metadata" assert meta["type"] == "confirm_required" assert meta["thread_id"] == "conv-123" assert meta["tool_name"] == "deploy_dashboard" assert meta["risk"] == "write" assert meta["risk_level"] == "guarded" assert meta["requires_confirmation"] is True # #endregion test_metadata_for_tool_contains_required_fields # ── permission_denied_payload ───────────────────────────────────────── # #region test_permission_denied_payload_structure [C:2] [TYPE Function] def test_permission_denied_payload_structure(): """permission_denied_payload should produce valid JSON with correct type.""" import json payload_str = permission_denied_payload("deploy_dashboard", "admin", "viewer") payload = json.loads(payload_str) assert payload["content"] == "⛔ Недостаточно прав для deploy_dashboard" assert payload["metadata"]["type"] == "permission_denied" assert payload["metadata"]["tool_name"] == "deploy_dashboard" assert payload["metadata"]["required_role"] == "admin" assert payload["metadata"]["user_role"] == "viewer" assert payload["metadata"]["alternatives"] == [] # #endregion test_permission_denied_payload_structure # #region test_permission_denied_payload_with_alternatives [C:2] [TYPE Function] def test_permission_denied_payload_with_alternatives(): """Alternatives list should be preserved in the payload.""" import json alternatives = [{"action": "get_health_summary", "prompt": "Check system health"}] payload_str = permission_denied_payload( "deploy_dashboard", "admin", "viewer", alternatives, ) payload = json.loads(payload_str) assert payload["metadata"]["alternatives"] == alternatives # #endregion test_permission_denied_payload_with_alternatives # ── Unknown/null tool ───────────────────────────────────────────────── # #region test_null_tool_name_handled [C:2] [TYPE Function] def test_null_tool_name_handled_gracefully(): """Null tool_name should produce 'unknown_action' fallback.""" contract = build_confirmation_contract_v2(None) assert contract["operation"] == "unknown_action" assert contract["risk_level"] == "safe" # #endregion test_null_tool_name_handled # #region test_execute_migration_is_guarded [C:2] [TYPE Function] def test_execute_migration_is_guarded(): """execute_migration should be classified as guarded (write).""" contract = build_confirmation_contract_v2("execute_migration", {}) assert contract["risk"] == "write" assert contract["risk_level"] == "guarded" # #endregion test_execute_migration_is_guarded # #region test_commit_changes_is_guarded [C:2] [TYPE Function] def test_commit_changes_is_guarded(): """commit_changes should be classified as guarded (write).""" contract = build_confirmation_contract_v2("commit_changes", {}) assert contract["risk"] == "write" assert contract["risk_level"] == "guarded" # #endregion test_commit_changes_is_guarded # #endregion Test.Agent.ConfirmationV2