SafeAI-Static-Analyzer 2.0.0__tar.gz → 2.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (199) hide show
  1. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/PKG-INFO +13 -1
  2. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/README.md +12 -0
  3. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/SafeAI_Static_Analyzer.egg-info/PKG-INFO +13 -1
  4. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/SafeAI_Static_Analyzer.egg-info/SOURCES.txt +1 -0
  5. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/version.py +1 -1
  6. safeai_static_analyzer-2.0.1/tests/test_compatibility.py +392 -0
  7. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/LICENSE +0 -0
  8. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/SafeAI_Static_Analyzer.egg-info/dependency_links.txt +0 -0
  9. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/SafeAI_Static_Analyzer.egg-info/entry_points.txt +0 -0
  10. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/SafeAI_Static_Analyzer.egg-info/requires.txt +0 -0
  11. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/SafeAI_Static_Analyzer.egg-info/top_level.txt +0 -0
  12. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/pyproject.toml +0 -0
  13. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/__init__.py +0 -0
  14. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/__main__.py +0 -0
  15. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analysis/__init__.py +0 -0
  16. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analysis/aggregation.py +0 -0
  17. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analysis/capabilities.py +0 -0
  18. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analysis/capability_diff.py +0 -0
  19. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analysis/component_diff.py +0 -0
  20. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analysis/component_graph.py +0 -0
  21. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analysis/components.py +0 -0
  22. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analysis/dependency_correlation.py +0 -0
  23. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analysis/escalation.py +0 -0
  24. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analysis/import_graph.py +0 -0
  25. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analysis/project_graph.py +0 -0
  26. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analysis/semantic.py +0 -0
  27. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analysis/target_taxonomy.py +0 -0
  28. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analysis/tool_identity.py +0 -0
  29. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analysis/tool_implementation.py +0 -0
  30. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analysis/tool_surface.py +0 -0
  31. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/__init__.py +0 -0
  32. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/capability/__init__.py +0 -0
  33. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/capability/analyzer.py +0 -0
  34. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/claude_code/__init__.py +0 -0
  35. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/claude_code/analyzer.py +0 -0
  36. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/data_leakage/__init__.py +0 -0
  37. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/data_leakage/analyzer.py +0 -0
  38. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/dataflow/__init__.py +0 -0
  39. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/dataflow/analyzer.py +0 -0
  40. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/env_dependency/__init__.py +0 -0
  41. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/env_dependency/analyzer.py +0 -0
  42. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/governance/__init__.py +0 -0
  43. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/governance/analyzer.py +0 -0
  44. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/mcp/__init__.py +0 -0
  45. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/mcp/analyzer.py +0 -0
  46. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/mcp/compatibility.py +0 -0
  47. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/mcp/schema.py +0 -0
  48. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/mcp/validators.py +0 -0
  49. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/model_config/__init__.py +0 -0
  50. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/model_config/analyzer.py +0 -0
  51. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/prompt/__init__.py +0 -0
  52. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/prompt/analyzer.py +0 -0
  53. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/prompt_file/__init__.py +0 -0
  54. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/prompt_file/analyzer.py +0 -0
  55. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/skill/__init__.py +0 -0
  56. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/skill/analyzer.py +0 -0
  57. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/tool_def/__init__.py +0 -0
  58. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/tool_def/analyzer.py +0 -0
  59. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/workflow/__init__.py +0 -0
  60. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/analyzers/workflow/analyzer.py +0 -0
  61. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/cmd/__init__.py +0 -0
  62. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/cmd/cli.py +0 -0
  63. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/cmd/postprocess.py +0 -0
  64. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/cmd/registry_cli.py +0 -0
  65. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/controls/__init__.py +0 -0
  66. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/controls/catalogs.py +0 -0
  67. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/controls/mappings.py +0 -0
  68. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/engine/__init__.py +0 -0
  69. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/engine/orchestrator.py +0 -0
  70. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/engine/scan.py +0 -0
  71. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/__init__.py +0 -0
  72. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/autogen/parser.py +0 -0
  73. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/azure_foundry/__init__.py +0 -0
  74. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/azure_foundry/parser.py +0 -0
  75. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/bedrock_agent/__init__.py +0 -0
  76. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/bedrock_agent/parser.py +0 -0
  77. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/claude_code/__init__.py +0 -0
  78. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/claude_code/commands.py +0 -0
  79. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/claude_code/parser.py +0 -0
  80. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/claude_code/permissions.py +0 -0
  81. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/claude_code/settings.py +0 -0
  82. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/crewai/__init__.py +0 -0
  83. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/crewai/parser.py +0 -0
  84. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/cursorrules/__init__.py +0 -0
  85. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/cursorrules/parser.py +0 -0
  86. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/dify/__init__.py +0 -0
  87. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/dify/parser.py +0 -0
  88. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/google_adk/__init__.py +0 -0
  89. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/google_adk/parser.py +0 -0
  90. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/haystack/__init__.py +0 -0
  91. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/haystack/parser.py +0 -0
  92. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/langchain/__init__.py +0 -0
  93. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/langchain/parser.py +0 -0
  94. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/langgraph/__init__.py +0 -0
  95. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/langgraph/parser.py +0 -0
  96. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/llamaindex/__init__.py +0 -0
  97. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/llamaindex/parser.py +0 -0
  98. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/mastra/__init__.py +0 -0
  99. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/mastra/parser.py +0 -0
  100. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/microsoft_agent/__init__.py +0 -0
  101. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/microsoft_agent/parser.py +0 -0
  102. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/n8n/__init__.py +0 -0
  103. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/n8n/parser.py +0 -0
  104. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/openai_agents/__init__.py +0 -0
  105. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/openai_agents/parser.py +0 -0
  106. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/semantic_kernel/__init__.py +0 -0
  107. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/semantic_kernel/parser.py +0 -0
  108. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/windsurf/__init__.py +0 -0
  109. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/frameworks/windsurf/parser.py +0 -0
  110. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/kya/__init__.py +0 -0
  111. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/kya/assurance.py +0 -0
  112. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/kya/baseline.py +0 -0
  113. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/kya/ci_context.py +0 -0
  114. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/kya/enrich.py +0 -0
  115. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/kya/exporter.py +0 -0
  116. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/kya/fingerprints.py +0 -0
  117. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/kya/identity.py +0 -0
  118. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/kya/manifest.py +0 -0
  119. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/kya/policy.py +0 -0
  120. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/kya/registry/__init__.py +0 -0
  121. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/kya/registry/connection.py +0 -0
  122. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/kya/registry/persist.py +0 -0
  123. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/kya/registry/queries.py +0 -0
  124. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/kya/registry/schema.py +0 -0
  125. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/kya/suppressions.py +0 -0
  126. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/kya/util.py +0 -0
  127. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/report/__init__.py +0 -0
  128. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/report/failure_matrix.py +0 -0
  129. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/report/html.py +0 -0
  130. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/report/html_kit.py +0 -0
  131. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/report/json_report.py +0 -0
  132. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/report/pr_comment.py +0 -0
  133. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/report/registry_html.py +0 -0
  134. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/report/sarif.py +0 -0
  135. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/report/terminal.py +0 -0
  136. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/rules/__init__.py +0 -0
  137. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/rules/base_rules.yaml +0 -0
  138. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/rules/loader.py +0 -0
  139. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/scorecard.py +0 -0
  140. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/scoring/__init__.py +0 -0
  141. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/scoring/engine.py +0 -0
  142. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/severity.py +0 -0
  143. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/telemetry/__init__.py +0 -0
  144. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/telemetry/client.py +0 -0
  145. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/telemetry/config.py +0 -0
  146. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/safeai/telemetry/schema.py +0 -0
  147. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/setup.cfg +0 -0
  148. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_adapter_dataflow.py +0 -0
  149. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_assurance.py +0 -0
  150. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_baseline.py +0 -0
  151. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_capability_detection.py +0 -0
  152. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_capability_diff_v2.py +0 -0
  153. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_ci_context.py +0 -0
  154. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_claude_code_deep.py +0 -0
  155. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_component_graph.py +0 -0
  156. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_component_hash.py +0 -0
  157. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_confidence_arbitration.py +0 -0
  158. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_control_mappings.py +0 -0
  159. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_crewai_framework.py +0 -0
  160. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_cursorrules_framework.py +0 -0
  161. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_env_dependency.py +0 -0
  162. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_escalation.py +0 -0
  163. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_evidence_type.py +0 -0
  164. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_fingerprints.py +0 -0
  165. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_github_action.py +0 -0
  166. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_governance_analyzer.py +0 -0
  167. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_html_report.py +0 -0
  168. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_init_and_rules.py +0 -0
  169. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_kya_integration.py +0 -0
  170. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_kya_manifest.py +0 -0
  171. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_langgraph_framework.py +0 -0
  172. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_llamaindex_framework.py +0 -0
  173. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_mcp_tool_poisoning.py +0 -0
  174. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_mcp_validation.py +0 -0
  175. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_n8n_workflow.py +0 -0
  176. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_parser_aggregation.py +0 -0
  177. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_phase15.py +0 -0
  178. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_policy.py +0 -0
  179. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_pr_comment.py +0 -0
  180. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_pr_comment_cli.py +0 -0
  181. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_registry.py +0 -0
  182. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_registry_cli.py +0 -0
  183. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_registry_html.py +0 -0
  184. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_release_fixes.py +0 -0
  185. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_release_validation.py +0 -0
  186. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_rules_loader_determinism.py +0 -0
  187. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_sarif.py +0 -0
  188. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_scan_phase11.py +0 -0
  189. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_scorecard.py +0 -0
  190. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_scoring.py +0 -0
  191. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_semantic.py +0 -0
  192. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_severity.py +0 -0
  193. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_suppressions.py +0 -0
  194. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_target_taxonomy_engine.py +0 -0
  195. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_telemetry.py +0 -0
  196. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_tool_identity.py +0 -0
  197. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_tool_implementation.py +0 -0
  198. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_version.py +0 -0
  199. {safeai_static_analyzer-2.0.0 → safeai_static_analyzer-2.0.1}/tests/test_windsurf_framework.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: SafeAI-Static-Analyzer
3
- Version: 2.0.0
3
+ Version: 2.0.1
4
4
  Summary: The lightweight, open-source Static AI Capability & Risk Analyzer for CI/CD pipelines.
5
5
  Author: IkarusCareer
6
6
  License-Expression: Apache-2.0
@@ -785,6 +785,18 @@ See [CONTRIBUTING.md](./CONTRIBUTING.md) for how to get involved.
785
785
 
786
786
  ---
787
787
 
788
+ ## Documentation
789
+
790
+ - [Release Notes](./RELEASE_NOTES.md) — changelog for all versions
791
+ - [Upgrade Guide](./UPGRADE.md) — v1.x → v2.0.0 migration
792
+ - [Support Matrix](./SUPPORT_MATRIX.md) — Python versions, platforms, adapters, CI
793
+ - [Release Channels](./RELEASE_CHANNELS.md) — main, stable, prerelease, maintenance
794
+ - [Security Policy](./SECURITY.md) — vulnerability reporting and response targets
795
+ - [Known Limitations](./KNOWN_LIMITATIONS.md) — what SafeAI does and does not do
796
+ - [Roadmap](./ROADMAP.md) — future plans and feature requests
797
+
798
+ ---
799
+
788
800
  ## License
789
801
 
790
802
  SafeAI is released under the Apache 2.0 License.
@@ -754,6 +754,18 @@ See [CONTRIBUTING.md](./CONTRIBUTING.md) for how to get involved.
754
754
 
755
755
  ---
756
756
 
757
+ ## Documentation
758
+
759
+ - [Release Notes](./RELEASE_NOTES.md) — changelog for all versions
760
+ - [Upgrade Guide](./UPGRADE.md) — v1.x → v2.0.0 migration
761
+ - [Support Matrix](./SUPPORT_MATRIX.md) — Python versions, platforms, adapters, CI
762
+ - [Release Channels](./RELEASE_CHANNELS.md) — main, stable, prerelease, maintenance
763
+ - [Security Policy](./SECURITY.md) — vulnerability reporting and response targets
764
+ - [Known Limitations](./KNOWN_LIMITATIONS.md) — what SafeAI does and does not do
765
+ - [Roadmap](./ROADMAP.md) — future plans and feature requests
766
+
767
+ ---
768
+
757
769
  ## License
758
770
 
759
771
  SafeAI is released under the Apache 2.0 License.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: SafeAI-Static-Analyzer
3
- Version: 2.0.0
3
+ Version: 2.0.1
4
4
  Summary: The lightweight, open-source Static AI Capability & Risk Analyzer for CI/CD pipelines.
5
5
  Author: IkarusCareer
6
6
  License-Expression: Apache-2.0
@@ -785,6 +785,18 @@ See [CONTRIBUTING.md](./CONTRIBUTING.md) for how to get involved.
785
785
 
786
786
  ---
787
787
 
788
+ ## Documentation
789
+
790
+ - [Release Notes](./RELEASE_NOTES.md) — changelog for all versions
791
+ - [Upgrade Guide](./UPGRADE.md) — v1.x → v2.0.0 migration
792
+ - [Support Matrix](./SUPPORT_MATRIX.md) — Python versions, platforms, adapters, CI
793
+ - [Release Channels](./RELEASE_CHANNELS.md) — main, stable, prerelease, maintenance
794
+ - [Security Policy](./SECURITY.md) — vulnerability reporting and response targets
795
+ - [Known Limitations](./KNOWN_LIMITATIONS.md) — what SafeAI does and does not do
796
+ - [Roadmap](./ROADMAP.md) — future plans and feature requests
797
+
798
+ ---
799
+
788
800
  ## License
789
801
 
790
802
  SafeAI is released under the Apache 2.0 License.
@@ -149,6 +149,7 @@ tests/test_capability_detection.py
149
149
  tests/test_capability_diff_v2.py
150
150
  tests/test_ci_context.py
151
151
  tests/test_claude_code_deep.py
152
+ tests/test_compatibility.py
152
153
  tests/test_component_graph.py
153
154
  tests/test_component_hash.py
154
155
  tests/test_confidence_arbitration.py
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
 
4
4
  import sys
5
5
 
6
- SAFEAI_VERSION = "2.0.0"
6
+ SAFEAI_VERSION = "2.0.1"
7
7
  VERSION_FLAGS = ("--version", "-V")
8
8
 
9
9
 
@@ -0,0 +1,392 @@
1
+ """Golden fixture integration tests.
2
+
3
+ Each supported framework family has a representative fixture that exercises
4
+ the full scan pipeline: detection, parsing, capability extraction, and
5
+ finding generation. These tests serve as regression anchors — if a fixture
6
+ starts failing, it signals a breaking change in the adapter or engine.
7
+
8
+ Add new fixtures for each framework by:
9
+ 1. Creating a directory under tests/fixtures/<framework>/representative/
10
+ 2. Adding a representative source file for that framework
11
+ 3. Adding a test class below following the existing pattern
12
+ """
13
+
14
+ import json
15
+ import os
16
+
17
+ from safeai.engine.scan import run_scan
18
+ from safeai.report.sarif import write_sarif
19
+
20
+ FIXTURES = os.path.join(os.path.dirname(__file__), "fixtures")
21
+
22
+
23
+ def _scan(fixture_name):
24
+ return run_scan(os.path.join(FIXTURES, fixture_name, "representative"))
25
+
26
+
27
+ # ── Framework golden fixtures ──────────────────────────────────────────
28
+
29
+
30
+ class TestClaudeCodeGolden:
31
+ """Claude Code config-file adapter (settings.json + CLAUDE.md + .mcp.json)."""
32
+
33
+ FIXTURE = os.path.join(FIXTURES, "claude_code", "compatibility")
34
+
35
+ def test_detection(self):
36
+ report = run_scan(self.FIXTURE)
37
+ assert "claude_code" in report["detected_frameworks"]
38
+
39
+ def test_artifacts_present(self):
40
+ report = run_scan(self.FIXTURE)
41
+ model = next(
42
+ m for m in report["unified_models"]
43
+ if "claude_code" in m.get("frameworks", [])
44
+ )
45
+ assert model["artifacts"]["tools"]
46
+
47
+ def test_capabilities_detected(self):
48
+ report = run_scan(self.FIXTURE)
49
+ model = next(
50
+ m for m in report["unified_models"]
51
+ if "claude_code" in m.get("frameworks", [])
52
+ )
53
+ cap_names = {c["name"] for c in model["capabilities"]}
54
+ assert "mcp" in cap_names
55
+
56
+
57
+ class TestCrewAIGolden:
58
+ """CrewAI framework adapter."""
59
+
60
+ def test_detection(self):
61
+ report = _scan("crewai")
62
+ assert "crewai" in report["detected_frameworks"]
63
+
64
+ def test_agents_and_tasks(self):
65
+ report = _scan("crewai")
66
+ model = next(
67
+ m for m in report["unified_models"]
68
+ if "crewai" in m.get("frameworks", [])
69
+ )
70
+ artifacts = model["artifacts"]
71
+ assert any("Agent" in a["name"] for a in artifacts["agents"])
72
+ assert any("Task" in t["name"] for t in artifacts["workflows"])
73
+
74
+ def test_memory_detected(self):
75
+ report = _scan("crewai")
76
+ model = next(
77
+ m for m in report["unified_models"]
78
+ if "crewai" in m.get("frameworks", [])
79
+ )
80
+ assert any("Memory" in mem["name"] for mem in model["artifacts"]["memory"])
81
+
82
+
83
+ class TestLangGraphGolden:
84
+ """LangGraph framework adapter."""
85
+
86
+ def test_detection(self):
87
+ report = _scan("langgraph")
88
+ assert "langgraph" in report["detected_frameworks"]
89
+
90
+ def test_graph_and_tools(self):
91
+ report = _scan("langgraph")
92
+ model = next(
93
+ m for m in report["unified_models"]
94
+ if "langgraph" in m.get("frameworks", [])
95
+ )
96
+ artifacts = model["artifacts"]
97
+ assert any("ToolNode" in t["name"] for t in artifacts["tools"])
98
+
99
+ def test_memory_saver(self):
100
+ report = _scan("langgraph")
101
+ model = next(
102
+ m for m in report["unified_models"]
103
+ if "langgraph" in m.get("frameworks", [])
104
+ )
105
+ assert any(
106
+ mem["name"] == "MemorySaver"
107
+ for mem in model["artifacts"]["memory"]
108
+ )
109
+
110
+
111
+ class TestCursorRulesGolden:
112
+ """Cursor config-file adapter (.cursorrules)."""
113
+
114
+ def test_detection(self):
115
+ report = _scan("cursorrules")
116
+ assert "cursorrules" in report["detected_frameworks"]
117
+
118
+ def test_tools_and_model(self):
119
+ report = _scan("cursorrules")
120
+ model = next(
121
+ m for m in report["unified_models"]
122
+ if "cursorrules" in m.get("frameworks", [])
123
+ )
124
+ tool_names = {t["name"] for t in model["artifacts"]["tools"]}
125
+ assert "read_file" in tool_names
126
+ model_names = {m["name"] for m in model["artifacts"]["models"]}
127
+ assert "claude-sonnet-4-5" in model_names
128
+
129
+
130
+ class TestWindsurfGolden:
131
+ """Windsurf config-file adapter (.windsurfrules)."""
132
+
133
+ def test_detection(self):
134
+ report = _scan("windsurf")
135
+ assert "windsurf" in report["detected_frameworks"]
136
+
137
+ def test_capabilities(self):
138
+ report = _scan("windsurf")
139
+ model = next(
140
+ m for m in report["unified_models"]
141
+ if "windsurf" in m.get("frameworks", [])
142
+ )
143
+ assert model["capabilities"]
144
+
145
+
146
+ class TestN8NGolden:
147
+ """n8n workflow adapter."""
148
+
149
+ def test_detection(self):
150
+ report = _scan("n8n")
151
+ assert "n8n" in report["detected_frameworks"]
152
+
153
+ def test_workflow_parsed(self):
154
+ report = _scan("n8n")
155
+ model = next(
156
+ m for m in report["unified_models"]
157
+ if "n8n" in m.get("frameworks", [])
158
+ )
159
+ assert model["artifacts"]["workflows"]
160
+
161
+
162
+ class TestLlamaIndexGolden:
163
+ """LlamaIndex framework adapter."""
164
+
165
+ def test_detection(self):
166
+ report = _scan("llamaindex")
167
+ assert "llamaindex" in report["detected_frameworks"]
168
+
169
+ def test_agent_detected(self):
170
+ report = _scan("llamaindex")
171
+ model = next(
172
+ m for m in report["unified_models"]
173
+ if "llamaindex" in m.get("frameworks", [])
174
+ )
175
+ assert model["artifacts"]["agents"]
176
+
177
+
178
+ # ── JSON report contract ───────────────────────────────────────────────
179
+
180
+
181
+ class TestJSONReportContract:
182
+ """Verify the JSON report contains all required top-level keys."""
183
+
184
+ REQUIRED_KEYS = [
185
+ "findings", "counts", "detected_frameworks", "tool_surface",
186
+ "assurance_boundary", "unified_models",
187
+ ]
188
+
189
+ def test_required_keys_present(self):
190
+ report = _scan("crewai")
191
+ for key in self.REQUIRED_KEYS:
192
+ assert key in report, f"Missing key: {key}"
193
+
194
+ def test_findings_are_dicts(self):
195
+ report = _scan("crewai")
196
+ for f in report["findings"]:
197
+ assert isinstance(f, dict)
198
+ assert "rule_id" in f
199
+ assert "file" in f
200
+ assert "line" in f
201
+ assert "severity" in f
202
+
203
+ def test_counts_has_severity_keys(self):
204
+ report = _scan("crewai")
205
+ counts = report["counts"]
206
+ assert isinstance(counts, dict)
207
+
208
+
209
+ # ── SARIF output contract ──────────────────────────────────────────────
210
+
211
+
212
+ class TestSARIFContract:
213
+ """Verify SARIF output is valid and contains required fields."""
214
+
215
+ def test_sarif_version(self, tmp_path):
216
+ report = _scan("crewai")
217
+ out = tmp_path / "out.sarif"
218
+ write_sarif(report, str(out))
219
+ data = json.loads(out.read_text())
220
+ assert data["version"] == "2.1.0"
221
+
222
+ def test_sarif_has_runs(self, tmp_path):
223
+ report = _scan("crewai")
224
+ out = tmp_path / "out.sarif"
225
+ write_sarif(report, str(out))
226
+ data = json.loads(out.read_text())
227
+ assert len(data["runs"]) >= 1
228
+
229
+ def test_sarif_run_has_rules_and_results(self, tmp_path):
230
+ report = _scan("claude_code/compatibility")
231
+ out = tmp_path / "out.sarif"
232
+ write_sarif(report, str(out))
233
+ data = json.loads(out.read_text())
234
+ run = data["runs"][0]
235
+ assert "tool" in run
236
+ assert "results" in run
237
+
238
+ def test_sarif_rule_has_required_fields(self, tmp_path):
239
+ report = _scan("claude_code/compatibility")
240
+ out = tmp_path / "out.sarif"
241
+ write_sarif(report, str(out))
242
+ data = json.loads(out.read_text())
243
+ run = data["runs"][0]
244
+ for rule in run["tool"]["driver"]["rules"]:
245
+ assert "id" in rule
246
+ assert "shortDescription" in rule
247
+
248
+ def test_sarif_result_has_locations(self, tmp_path):
249
+ report = _scan("claude_code/compatibility")
250
+ out = tmp_path / "out.sarif"
251
+ write_sarif(report, str(out))
252
+ data = json.loads(out.read_text())
253
+ run = data["runs"][0]
254
+ for result in run.get("results", []):
255
+ assert "ruleId" in result
256
+ assert "locations" in result
257
+
258
+
259
+ # ── CLI behavior contract ──────────────────────────────────────────────
260
+
261
+
262
+ class TestCLIContract:
263
+ """Verify CLI exit codes and output flags work as documented."""
264
+
265
+ def test_zero_exit_on_clean_project(self, tmp_path):
266
+ from safeai.cmd.cli import main
267
+ (tmp_path / "clean.py").write_text("print('hello')\n")
268
+ code = main(["scan", str(tmp_path), "--sarif", "", "--fail-on", "critical"])
269
+ assert code == 0
270
+
271
+ def test_nonzero_exit_on_threshold_breach(self, tmp_path):
272
+ from safeai.cmd.cli import main
273
+ (tmp_path / "risky.py").write_text('api_key = "sk-1234567890abcdef1234"\n')
274
+ code = main(["scan", str(tmp_path), "--sarif", "", "--fail-on", "high"])
275
+ assert code == 1
276
+
277
+ def test_json_output_flag(self, tmp_path):
278
+ from safeai.cmd.cli import main
279
+ (tmp_path / "app.py").write_text("print('hello')\n")
280
+ json_path = str(tmp_path / "out.json")
281
+ code = main(["scan", str(tmp_path), "--json", json_path, "--fail-on", "critical"])
282
+ assert code == 0
283
+ data = json.loads((tmp_path / "out.json").read_text())
284
+ assert "findings" in data
285
+
286
+ def test_sarif_output_flag(self, tmp_path):
287
+ from safeai.cmd.cli import main
288
+ (tmp_path / "app.py").write_text("print('hello')\n")
289
+ sarif_path = str(tmp_path / "out.sarif")
290
+ code = main(["scan", str(tmp_path), "--sarif", sarif_path, "--fail-on", "critical"])
291
+ assert code == 0
292
+ data = json.loads((tmp_path / "out.sarif").read_text())
293
+ assert data["version"] == "2.1.0"
294
+
295
+ def test_html_output_flag(self, tmp_path):
296
+ from safeai.cmd.cli import main
297
+ (tmp_path / "app.py").write_text("print('hello')\n")
298
+ html_path = str(tmp_path / "out.html")
299
+ code = main(["scan", str(tmp_path), "--html", html_path, "--fail-on", "critical"])
300
+ assert code == 0
301
+ assert (tmp_path / "out.html").exists()
302
+ content = (tmp_path / "out.html").read_text()[:100].lower()
303
+ assert "doctype" in content
304
+
305
+
306
+ # ── Action inputs/outputs contract ─────────────────────────────────────
307
+
308
+
309
+ class TestActionContract:
310
+ """Verify GitHub Action input/output mapping is stable."""
311
+
312
+ def test_action_yaml_has_all_inputs(self):
313
+ import yaml
314
+ action_path = os.path.join(
315
+ os.path.dirname(__file__), os.pardir, "action.yml"
316
+ )
317
+ with open(action_path) as f:
318
+ action = yaml.safe_load(f)
319
+ inputs = action["inputs"]
320
+ expected = [
321
+ "path", "version", "fail-on", "sarif", "rules", "baseline",
322
+ "fail-on-new", "fail-on-escalation", "no-registry", "extra-args",
323
+ "scorecard", "scorecard-json", "scorecard-summary", "scorecard-fail-under",
324
+ ]
325
+ for name in expected:
326
+ assert name in inputs, f"Missing action input: {name}"
327
+
328
+ def test_action_yaml_has_all_outputs(self):
329
+ import yaml
330
+ action_path = os.path.join(
331
+ os.path.dirname(__file__), os.pardir, "action.yml"
332
+ )
333
+ with open(action_path) as f:
334
+ action = yaml.safe_load(f)
335
+ outputs = action["outputs"]
336
+ expected = ["sarif-path", "scorecard-path", "safeai-version"]
337
+ for name in expected:
338
+ assert name in outputs, f"Missing action output: {name}"
339
+
340
+
341
+ # ── Adapter contract ───────────────────────────────────────────────────
342
+
343
+
344
+ class TestAdapterContract:
345
+ """Every registered parser must implement detect() and parse().
346
+ Parsers that don't match the file return minimal results — we only
347
+ validate the contract for parsers that do match."""
348
+
349
+ REQUIRED_PARSE_KEYS = {
350
+ "framework", "capabilities", "tools", "models",
351
+ "detection_evidence",
352
+ }
353
+
354
+ def _get_all_parsers(self):
355
+ from safeai.frameworks import discover_parsers
356
+ return discover_parsers()
357
+
358
+ def test_all_parsers_implement_detect(self):
359
+ for parser in self._get_all_parsers():
360
+ assert hasattr(parser, "detect"), (
361
+ f"{type(parser).__name__} missing detect()"
362
+ )
363
+ assert callable(parser.detect)
364
+
365
+ def test_all_parsers_implement_parse(self):
366
+ for parser in self._get_all_parsers():
367
+ assert hasattr(parser, "parse"), (
368
+ f"{type(parser).__name__} missing parse()"
369
+ )
370
+ assert callable(parser.parse)
371
+
372
+ def test_parse_returns_framework_key(self):
373
+ """Parsers that produce output must include a 'framework' key."""
374
+ for parser in self._get_all_parsers():
375
+ result = parser.parse("test.py", "")
376
+ if result: # only check parsers that return non-empty
377
+ assert "framework" in result, (
378
+ f"{type(parser).__name__}.parse() missing 'framework' key"
379
+ )
380
+
381
+ def test_parse_capabilities_are_list(self):
382
+ """Parsers that detect capabilities return them as a list."""
383
+ for parser in self._get_all_parsers():
384
+ result = parser.parse("test.py", "")
385
+ if not isinstance(result, dict):
386
+ continue
387
+ caps = result.get("capabilities")
388
+ if caps is not None:
389
+ assert isinstance(caps, list)
390
+ for cap in caps:
391
+ assert isinstance(cap, dict)
392
+ assert "name" in cap