from __future__ import annotations import pytest from trace2mcp.models import ( TraceEvent, TraceValidationError, Workflow, WorkflowValidationError, ) def test_deserialized_workflow_missing_security_metadata_is_fail_closed(): workflow = Workflow.from_dict( {"name": "hostile", "inputs": {}, "nodes": [{"id": "a", "tool": "custom"}]} ) assert workflow.safety == "unsafe" assert workflow.nodes[0].side_effect == "unknown" def test_model_rejects_control_characters_and_invalid_effects(): with pytest.raises(TraceValidationError, match="unsafe tool name"): TraceEvent("a", "tool\nname", {}, None) with pytest.raises(TraceValidationError, match="unsupported side_effect"): TraceEvent("a", "tool", {}, None, side_effect="harmless") with pytest.raises(WorkflowValidationError, match="control characters"): Workflow.from_dict( { "name": "bad", "safety": "safe", "nodes": [{"id": "a", "tool": "x\u0000y", "side_effect": "read"}], } )