atlas-chat 0.1.0__py3-none-any.whl

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 (250) hide show
  1. atlas/__init__.py +40 -0
  2. atlas/application/__init__.py +7 -0
  3. atlas/application/chat/__init__.py +7 -0
  4. atlas/application/chat/agent/__init__.py +10 -0
  5. atlas/application/chat/agent/act_loop.py +179 -0
  6. atlas/application/chat/agent/factory.py +142 -0
  7. atlas/application/chat/agent/protocols.py +46 -0
  8. atlas/application/chat/agent/react_loop.py +338 -0
  9. atlas/application/chat/agent/think_act_loop.py +171 -0
  10. atlas/application/chat/approval_manager.py +151 -0
  11. atlas/application/chat/elicitation_manager.py +191 -0
  12. atlas/application/chat/events/__init__.py +1 -0
  13. atlas/application/chat/events/agent_event_relay.py +112 -0
  14. atlas/application/chat/modes/__init__.py +1 -0
  15. atlas/application/chat/modes/agent.py +125 -0
  16. atlas/application/chat/modes/plain.py +74 -0
  17. atlas/application/chat/modes/rag.py +81 -0
  18. atlas/application/chat/modes/tools.py +179 -0
  19. atlas/application/chat/orchestrator.py +213 -0
  20. atlas/application/chat/policies/__init__.py +1 -0
  21. atlas/application/chat/policies/tool_authorization.py +99 -0
  22. atlas/application/chat/preprocessors/__init__.py +1 -0
  23. atlas/application/chat/preprocessors/message_builder.py +92 -0
  24. atlas/application/chat/preprocessors/prompt_override_service.py +104 -0
  25. atlas/application/chat/service.py +454 -0
  26. atlas/application/chat/utilities/__init__.py +6 -0
  27. atlas/application/chat/utilities/error_handler.py +367 -0
  28. atlas/application/chat/utilities/event_notifier.py +546 -0
  29. atlas/application/chat/utilities/file_processor.py +613 -0
  30. atlas/application/chat/utilities/tool_executor.py +789 -0
  31. atlas/atlas_chat_cli.py +347 -0
  32. atlas/atlas_client.py +238 -0
  33. atlas/core/__init__.py +0 -0
  34. atlas/core/auth.py +205 -0
  35. atlas/core/authorization_manager.py +27 -0
  36. atlas/core/capabilities.py +123 -0
  37. atlas/core/compliance.py +215 -0
  38. atlas/core/domain_whitelist.py +147 -0
  39. atlas/core/domain_whitelist_middleware.py +82 -0
  40. atlas/core/http_client.py +28 -0
  41. atlas/core/log_sanitizer.py +102 -0
  42. atlas/core/metrics_logger.py +59 -0
  43. atlas/core/middleware.py +131 -0
  44. atlas/core/otel_config.py +242 -0
  45. atlas/core/prompt_risk.py +200 -0
  46. atlas/core/rate_limit.py +0 -0
  47. atlas/core/rate_limit_middleware.py +64 -0
  48. atlas/core/security_headers_middleware.py +51 -0
  49. atlas/domain/__init__.py +37 -0
  50. atlas/domain/chat/__init__.py +1 -0
  51. atlas/domain/chat/dtos.py +85 -0
  52. atlas/domain/errors.py +96 -0
  53. atlas/domain/messages/__init__.py +12 -0
  54. atlas/domain/messages/models.py +160 -0
  55. atlas/domain/rag_mcp_service.py +664 -0
  56. atlas/domain/sessions/__init__.py +7 -0
  57. atlas/domain/sessions/models.py +36 -0
  58. atlas/domain/unified_rag_service.py +371 -0
  59. atlas/infrastructure/__init__.py +10 -0
  60. atlas/infrastructure/app_factory.py +135 -0
  61. atlas/infrastructure/events/__init__.py +1 -0
  62. atlas/infrastructure/events/cli_event_publisher.py +140 -0
  63. atlas/infrastructure/events/websocket_publisher.py +140 -0
  64. atlas/infrastructure/sessions/in_memory_repository.py +56 -0
  65. atlas/infrastructure/transport/__init__.py +7 -0
  66. atlas/infrastructure/transport/websocket_connection_adapter.py +33 -0
  67. atlas/init_cli.py +226 -0
  68. atlas/interfaces/__init__.py +15 -0
  69. atlas/interfaces/events.py +134 -0
  70. atlas/interfaces/llm.py +54 -0
  71. atlas/interfaces/rag.py +40 -0
  72. atlas/interfaces/sessions.py +75 -0
  73. atlas/interfaces/tools.py +57 -0
  74. atlas/interfaces/transport.py +24 -0
  75. atlas/main.py +564 -0
  76. atlas/mcp/api_key_demo/README.md +76 -0
  77. atlas/mcp/api_key_demo/main.py +172 -0
  78. atlas/mcp/api_key_demo/run.sh +56 -0
  79. atlas/mcp/basictable/main.py +147 -0
  80. atlas/mcp/calculator/main.py +149 -0
  81. atlas/mcp/code-executor/execution_engine.py +98 -0
  82. atlas/mcp/code-executor/execution_environment.py +95 -0
  83. atlas/mcp/code-executor/main.py +528 -0
  84. atlas/mcp/code-executor/result_processing.py +276 -0
  85. atlas/mcp/code-executor/script_generation.py +195 -0
  86. atlas/mcp/code-executor/security_checker.py +140 -0
  87. atlas/mcp/corporate_cars/main.py +437 -0
  88. atlas/mcp/csv_reporter/main.py +545 -0
  89. atlas/mcp/duckduckgo/main.py +182 -0
  90. atlas/mcp/elicitation_demo/README.md +171 -0
  91. atlas/mcp/elicitation_demo/main.py +262 -0
  92. atlas/mcp/env-demo/README.md +158 -0
  93. atlas/mcp/env-demo/main.py +199 -0
  94. atlas/mcp/file_size_test/main.py +284 -0
  95. atlas/mcp/filesystem/main.py +348 -0
  96. atlas/mcp/image_demo/main.py +113 -0
  97. atlas/mcp/image_demo/requirements.txt +4 -0
  98. atlas/mcp/logging_demo/README.md +72 -0
  99. atlas/mcp/logging_demo/main.py +103 -0
  100. atlas/mcp/many_tools_demo/main.py +50 -0
  101. atlas/mcp/order_database/__init__.py +0 -0
  102. atlas/mcp/order_database/main.py +369 -0
  103. atlas/mcp/order_database/signal_data.csv +1001 -0
  104. atlas/mcp/pdfbasic/main.py +394 -0
  105. atlas/mcp/pptx_generator/main.py +760 -0
  106. atlas/mcp/pptx_generator/requirements.txt +13 -0
  107. atlas/mcp/pptx_generator/run_test.sh +1 -0
  108. atlas/mcp/pptx_generator/test_pptx_generator_security.py +169 -0
  109. atlas/mcp/progress_demo/main.py +167 -0
  110. atlas/mcp/progress_updates_demo/QUICKSTART.md +273 -0
  111. atlas/mcp/progress_updates_demo/README.md +120 -0
  112. atlas/mcp/progress_updates_demo/main.py +497 -0
  113. atlas/mcp/prompts/main.py +222 -0
  114. atlas/mcp/public_demo/main.py +189 -0
  115. atlas/mcp/sampling_demo/README.md +169 -0
  116. atlas/mcp/sampling_demo/main.py +234 -0
  117. atlas/mcp/thinking/main.py +77 -0
  118. atlas/mcp/tool_planner/main.py +240 -0
  119. atlas/mcp/ui-demo/badmesh.png +0 -0
  120. atlas/mcp/ui-demo/main.py +383 -0
  121. atlas/mcp/ui-demo/templates/button_demo.html +32 -0
  122. atlas/mcp/ui-demo/templates/data_visualization.html +32 -0
  123. atlas/mcp/ui-demo/templates/form_demo.html +28 -0
  124. atlas/mcp/username-override-demo/README.md +320 -0
  125. atlas/mcp/username-override-demo/main.py +308 -0
  126. atlas/modules/__init__.py +0 -0
  127. atlas/modules/config/__init__.py +34 -0
  128. atlas/modules/config/cli.py +231 -0
  129. atlas/modules/config/config_manager.py +1096 -0
  130. atlas/modules/file_storage/__init__.py +22 -0
  131. atlas/modules/file_storage/cli.py +330 -0
  132. atlas/modules/file_storage/content_extractor.py +290 -0
  133. atlas/modules/file_storage/manager.py +295 -0
  134. atlas/modules/file_storage/mock_s3_client.py +402 -0
  135. atlas/modules/file_storage/s3_client.py +417 -0
  136. atlas/modules/llm/__init__.py +19 -0
  137. atlas/modules/llm/caller.py +287 -0
  138. atlas/modules/llm/litellm_caller.py +675 -0
  139. atlas/modules/llm/models.py +19 -0
  140. atlas/modules/mcp_tools/__init__.py +17 -0
  141. atlas/modules/mcp_tools/client.py +2123 -0
  142. atlas/modules/mcp_tools/token_storage.py +556 -0
  143. atlas/modules/prompts/prompt_provider.py +130 -0
  144. atlas/modules/rag/__init__.py +24 -0
  145. atlas/modules/rag/atlas_rag_client.py +336 -0
  146. atlas/modules/rag/client.py +129 -0
  147. atlas/routes/admin_routes.py +865 -0
  148. atlas/routes/config_routes.py +484 -0
  149. atlas/routes/feedback_routes.py +361 -0
  150. atlas/routes/files_routes.py +274 -0
  151. atlas/routes/health_routes.py +40 -0
  152. atlas/routes/mcp_auth_routes.py +223 -0
  153. atlas/server_cli.py +164 -0
  154. atlas/tests/conftest.py +20 -0
  155. atlas/tests/integration/test_mcp_auth_integration.py +152 -0
  156. atlas/tests/manual_test_sampling.py +87 -0
  157. atlas/tests/modules/mcp_tools/test_client_auth.py +226 -0
  158. atlas/tests/modules/mcp_tools/test_client_env.py +191 -0
  159. atlas/tests/test_admin_mcp_server_management_routes.py +141 -0
  160. atlas/tests/test_agent_roa.py +135 -0
  161. atlas/tests/test_app_factory_smoke.py +47 -0
  162. atlas/tests/test_approval_manager.py +439 -0
  163. atlas/tests/test_atlas_client.py +188 -0
  164. atlas/tests/test_atlas_rag_client.py +447 -0
  165. atlas/tests/test_atlas_rag_integration.py +224 -0
  166. atlas/tests/test_attach_file_flow.py +287 -0
  167. atlas/tests/test_auth_utils.py +165 -0
  168. atlas/tests/test_backend_public_url.py +185 -0
  169. atlas/tests/test_banner_logging.py +287 -0
  170. atlas/tests/test_capability_tokens_and_injection.py +203 -0
  171. atlas/tests/test_compliance_level.py +54 -0
  172. atlas/tests/test_compliance_manager.py +253 -0
  173. atlas/tests/test_config_manager.py +617 -0
  174. atlas/tests/test_config_manager_paths.py +12 -0
  175. atlas/tests/test_core_auth.py +18 -0
  176. atlas/tests/test_core_utils.py +190 -0
  177. atlas/tests/test_docker_env_sync.py +202 -0
  178. atlas/tests/test_domain_errors.py +329 -0
  179. atlas/tests/test_domain_whitelist.py +359 -0
  180. atlas/tests/test_elicitation_manager.py +408 -0
  181. atlas/tests/test_elicitation_routing.py +296 -0
  182. atlas/tests/test_env_demo_server.py +88 -0
  183. atlas/tests/test_error_classification.py +113 -0
  184. atlas/tests/test_error_flow_integration.py +116 -0
  185. atlas/tests/test_feedback_routes.py +333 -0
  186. atlas/tests/test_file_content_extraction.py +1134 -0
  187. atlas/tests/test_file_extraction_routes.py +158 -0
  188. atlas/tests/test_file_library.py +107 -0
  189. atlas/tests/test_file_manager_unit.py +18 -0
  190. atlas/tests/test_health_route.py +49 -0
  191. atlas/tests/test_http_client_stub.py +8 -0
  192. atlas/tests/test_imports_smoke.py +30 -0
  193. atlas/tests/test_interfaces_llm_response.py +9 -0
  194. atlas/tests/test_issue_access_denied_fix.py +136 -0
  195. atlas/tests/test_llm_env_expansion.py +836 -0
  196. atlas/tests/test_log_level_sensitive_data.py +285 -0
  197. atlas/tests/test_mcp_auth_routes.py +341 -0
  198. atlas/tests/test_mcp_client_auth.py +331 -0
  199. atlas/tests/test_mcp_data_injection.py +270 -0
  200. atlas/tests/test_mcp_get_authorized_servers.py +95 -0
  201. atlas/tests/test_mcp_hot_reload.py +512 -0
  202. atlas/tests/test_mcp_image_content.py +424 -0
  203. atlas/tests/test_mcp_logging.py +172 -0
  204. atlas/tests/test_mcp_progress_updates.py +313 -0
  205. atlas/tests/test_mcp_prompt_override_system_prompt.py +102 -0
  206. atlas/tests/test_mcp_prompts_server.py +39 -0
  207. atlas/tests/test_mcp_tool_result_parsing.py +296 -0
  208. atlas/tests/test_metrics_logger.py +56 -0
  209. atlas/tests/test_middleware_auth.py +379 -0
  210. atlas/tests/test_prompt_risk_and_acl.py +141 -0
  211. atlas/tests/test_rag_mcp_aggregator.py +204 -0
  212. atlas/tests/test_rag_mcp_service.py +224 -0
  213. atlas/tests/test_rate_limit_middleware.py +45 -0
  214. atlas/tests/test_routes_config_smoke.py +60 -0
  215. atlas/tests/test_routes_files_download_token.py +41 -0
  216. atlas/tests/test_routes_files_health.py +18 -0
  217. atlas/tests/test_runtime_imports.py +53 -0
  218. atlas/tests/test_sampling_integration.py +482 -0
  219. atlas/tests/test_security_admin_routes.py +61 -0
  220. atlas/tests/test_security_capability_tokens.py +65 -0
  221. atlas/tests/test_security_file_stats_scope.py +21 -0
  222. atlas/tests/test_security_header_injection.py +191 -0
  223. atlas/tests/test_security_headers_and_filename.py +63 -0
  224. atlas/tests/test_shared_session_repository.py +101 -0
  225. atlas/tests/test_system_prompt_loading.py +181 -0
  226. atlas/tests/test_token_storage.py +505 -0
  227. atlas/tests/test_tool_approval_config.py +93 -0
  228. atlas/tests/test_tool_approval_utils.py +356 -0
  229. atlas/tests/test_tool_authorization_group_filtering.py +223 -0
  230. atlas/tests/test_tool_details_in_config.py +108 -0
  231. atlas/tests/test_tool_planner.py +300 -0
  232. atlas/tests/test_unified_rag_service.py +398 -0
  233. atlas/tests/test_username_override_in_approval.py +258 -0
  234. atlas/tests/test_websocket_auth_header.py +168 -0
  235. atlas/version.py +6 -0
  236. atlas_chat-0.1.0.data/data/.env.example +253 -0
  237. atlas_chat-0.1.0.data/data/config/defaults/compliance-levels.json +44 -0
  238. atlas_chat-0.1.0.data/data/config/defaults/domain-whitelist.json +123 -0
  239. atlas_chat-0.1.0.data/data/config/defaults/file-extractors.json +74 -0
  240. atlas_chat-0.1.0.data/data/config/defaults/help-config.json +198 -0
  241. atlas_chat-0.1.0.data/data/config/defaults/llmconfig-buggy.yml +11 -0
  242. atlas_chat-0.1.0.data/data/config/defaults/llmconfig.yml +19 -0
  243. atlas_chat-0.1.0.data/data/config/defaults/mcp.json +138 -0
  244. atlas_chat-0.1.0.data/data/config/defaults/rag-sources.json +17 -0
  245. atlas_chat-0.1.0.data/data/config/defaults/splash-config.json +16 -0
  246. atlas_chat-0.1.0.dist-info/METADATA +236 -0
  247. atlas_chat-0.1.0.dist-info/RECORD +250 -0
  248. atlas_chat-0.1.0.dist-info/WHEEL +5 -0
  249. atlas_chat-0.1.0.dist-info/entry_points.txt +4 -0
  250. atlas_chat-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,54 @@
1
+ """Test compliance level functionality for MCP servers and data sources."""
2
+
3
+ from atlas.modules.config.config_manager import MCPConfig, MCPServerConfig
4
+
5
+
6
+ def test_mcp_server_config_with_compliance_level():
7
+ """Test that MCPServerConfig accepts and stores compliance_level."""
8
+ config = MCPServerConfig(
9
+ description="Test server",
10
+ compliance_level="SOC2"
11
+ )
12
+ assert config.compliance_level == "SOC2"
13
+
14
+
15
+ def test_mcp_server_config_without_compliance_level():
16
+ """Test that MCPServerConfig works without compliance_level (backward compatible)."""
17
+ config = MCPServerConfig(
18
+ description="Test server"
19
+ )
20
+ assert config.compliance_level is None
21
+
22
+
23
+ def test_mcp_config_from_dict_with_compliance():
24
+ """Test that MCPConfig properly parses servers with compliance levels."""
25
+ data = {
26
+ "servers": {
27
+ "test_server": {
28
+ "description": "Test description",
29
+ "compliance_level": "HIPAA"
30
+ }
31
+ }
32
+ }
33
+ config = MCPConfig(**data)
34
+ assert "test_server" in config.servers
35
+ assert config.servers["test_server"].compliance_level == "HIPAA"
36
+
37
+
38
+ def test_compliance_level_in_config_response():
39
+ """Test that /api/config returns compliance_level in tools response."""
40
+ # This is an integration test that would require full app setup
41
+ # For now, we verify the model supports it
42
+ config_dict = {
43
+ "description": "PDF processor",
44
+ "author": "Test",
45
+ "compliance_level": "SOC2",
46
+ "groups": ["users"],
47
+ "enabled": True
48
+ }
49
+ server_config = MCPServerConfig(**config_dict)
50
+
51
+ # Verify it can be serialized to dict (as done in API responses)
52
+ as_dict = server_config.model_dump()
53
+ assert as_dict["compliance_level"] == "SOC2"
54
+ assert as_dict["description"] == "PDF processor"
@@ -0,0 +1,253 @@
1
+ """Comprehensive tests for ComplianceLevelManager."""
2
+
3
+ import json
4
+ from pathlib import Path
5
+ from tempfile import TemporaryDirectory
6
+
7
+ import pytest
8
+
9
+ from atlas.core.compliance import ComplianceLevelManager
10
+
11
+
12
+ @pytest.fixture
13
+ def sample_compliance_config():
14
+ """Sample compliance level configuration."""
15
+ return {
16
+ "version": "2.0",
17
+ "mode": "explicit_allowlist",
18
+ "levels": [
19
+ {
20
+ "name": "Public",
21
+ "description": "Publicly accessible",
22
+ "aliases": ["public"],
23
+ "allowed_with": ["Public"]
24
+ },
25
+ {
26
+ "name": "External",
27
+ "description": "External services",
28
+ "aliases": ["ext"],
29
+ "allowed_with": ["External"]
30
+ },
31
+ {
32
+ "name": "Internal",
33
+ "description": "Internal systems",
34
+ "aliases": ["int"],
35
+ "allowed_with": ["Internal"]
36
+ },
37
+ {
38
+ "name": "SOC2",
39
+ "description": "SOC 2 compliant",
40
+ "aliases": ["SOC-2", "SOC 2"],
41
+ "allowed_with": ["SOC2"]
42
+ },
43
+ {
44
+ "name": "HIPAA",
45
+ "description": "HIPAA compliant",
46
+ "aliases": ["HIPAA-Compliant"],
47
+ "allowed_with": ["HIPAA", "SOC2"]
48
+ },
49
+ {
50
+ "name": "FedRAMP",
51
+ "description": "FedRAMP authorized",
52
+ "aliases": ["FedRAMP-Moderate"],
53
+ "allowed_with": ["FedRAMP", "SOC2"]
54
+ }
55
+ ]
56
+ }
57
+
58
+
59
+ @pytest.fixture
60
+ def temp_compliance_config(sample_compliance_config):
61
+ """Create a temporary compliance config file."""
62
+ with TemporaryDirectory() as tmpdir:
63
+ config_path = Path(tmpdir) / "compliance-levels.json"
64
+ with open(config_path, 'w', encoding='utf-8') as f:
65
+ json.dump(sample_compliance_config, f)
66
+ yield config_path
67
+
68
+
69
+ class TestComplianceLevelManager:
70
+ """Tests for ComplianceLevelManager class."""
71
+
72
+ def test_load_config_success(self, temp_compliance_config):
73
+ """Test loading a valid compliance configuration."""
74
+ manager = ComplianceLevelManager(temp_compliance_config)
75
+
76
+ assert len(manager.levels) == 6
77
+ assert "Public" in manager.levels
78
+ assert "HIPAA" in manager.levels
79
+ assert "FedRAMP" in manager.levels
80
+ assert manager.mode == "explicit_allowlist"
81
+
82
+ def test_load_config_missing_file(self):
83
+ """Test handling of missing config file."""
84
+ manager = ComplianceLevelManager(Path("/nonexistent/path.json"))
85
+
86
+ # Should not crash, should have empty levels
87
+ assert len(manager.levels) == 0
88
+
89
+ def test_get_canonical_name_exact_match(self, temp_compliance_config):
90
+ """Test getting canonical name with exact match."""
91
+ manager = ComplianceLevelManager(temp_compliance_config)
92
+
93
+ assert manager.get_canonical_name("Public") == "Public"
94
+ assert manager.get_canonical_name("HIPAA") == "HIPAA"
95
+ assert manager.get_canonical_name("SOC2") == "SOC2"
96
+
97
+ def test_get_canonical_name_alias(self, temp_compliance_config):
98
+ """Test getting canonical name from alias."""
99
+ manager = ComplianceLevelManager(temp_compliance_config)
100
+
101
+ assert manager.get_canonical_name("SOC 2") == "SOC2"
102
+ assert manager.get_canonical_name("SOC-2") == "SOC2"
103
+ assert manager.get_canonical_name("HIPAA-Compliant") == "HIPAA"
104
+ assert manager.get_canonical_name("FedRAMP-Moderate") == "FedRAMP"
105
+
106
+ def test_get_canonical_name_invalid(self, temp_compliance_config):
107
+ """Test getting canonical name for invalid level."""
108
+ manager = ComplianceLevelManager(temp_compliance_config)
109
+
110
+ assert manager.get_canonical_name("Invalid") is None
111
+ assert manager.get_canonical_name("SOCII") is None
112
+ assert manager.get_canonical_name(None) is None
113
+
114
+ def test_validate_compliance_level_valid(self, temp_compliance_config):
115
+ """Test validation of valid compliance levels."""
116
+ manager = ComplianceLevelManager(temp_compliance_config)
117
+
118
+ assert manager.validate_compliance_level("Public") == "Public"
119
+ assert manager.validate_compliance_level("HIPAA") == "HIPAA"
120
+ assert manager.validate_compliance_level("SOC2") == "SOC2"
121
+
122
+ def test_validate_compliance_level_alias(self, temp_compliance_config):
123
+ """Test validation with alias (should return canonical name)."""
124
+ manager = ComplianceLevelManager(temp_compliance_config)
125
+
126
+ assert manager.validate_compliance_level("SOC 2") == "SOC2"
127
+ assert manager.validate_compliance_level("SOC-2") == "SOC2"
128
+ assert manager.validate_compliance_level("HIPAA-Compliant") == "HIPAA"
129
+
130
+ def test_validate_compliance_level_invalid(self, temp_compliance_config):
131
+ """Test validation of invalid compliance level (should return None and log)."""
132
+ manager = ComplianceLevelManager(temp_compliance_config)
133
+
134
+ assert manager.validate_compliance_level("InvalidLevel") is None
135
+ assert manager.validate_compliance_level("SOCII") is None
136
+ assert manager.validate_compliance_level("") is None
137
+ assert manager.validate_compliance_level(None) is None
138
+
139
+ def test_is_accessible_same_level(self, temp_compliance_config):
140
+ """Test access control when user and resource have same level."""
141
+ manager = ComplianceLevelManager(temp_compliance_config)
142
+
143
+ # Each level can access itself
144
+ assert manager.is_accessible("Public", "Public") is True
145
+ assert manager.is_accessible("Internal", "Internal") is True
146
+ assert manager.is_accessible("HIPAA", "HIPAA") is True
147
+
148
+ def test_is_accessible_different_level_not_allowed(self, temp_compliance_config):
149
+ """Test access control when different levels are not in allowlist."""
150
+ manager = ComplianceLevelManager(temp_compliance_config)
151
+
152
+ # Public cannot access HIPAA
153
+ assert manager.is_accessible("Public", "HIPAA") is False
154
+
155
+ # HIPAA cannot access Public (security!)
156
+ assert manager.is_accessible("HIPAA", "Public") is False
157
+
158
+ # Internal cannot access External
159
+ assert manager.is_accessible("Internal", "External") is False
160
+
161
+ def test_is_accessible_allowlist_grants_access(self, temp_compliance_config):
162
+ """Test access control when allowlist grants access."""
163
+ manager = ComplianceLevelManager(temp_compliance_config)
164
+
165
+ # HIPAA can access SOC2 (in allowlist)
166
+ assert manager.is_accessible("HIPAA", "SOC2") is True
167
+
168
+ # FedRAMP can access SOC2 (in allowlist)
169
+ assert manager.is_accessible("FedRAMP", "SOC2") is True
170
+
171
+ def test_is_accessible_one_sided_allowlist(self, temp_compliance_config):
172
+ """Test that allowlist is not bidirectional."""
173
+ manager = ComplianceLevelManager(temp_compliance_config)
174
+
175
+ # HIPAA can access SOC2
176
+ assert manager.is_accessible("HIPAA", "SOC2") is True
177
+
178
+ # But SOC2 cannot access HIPAA (not in SOC2's allowlist)
179
+ assert manager.is_accessible("SOC2", "HIPAA") is False
180
+
181
+ def test_is_accessible_none_is_permissive(self, temp_compliance_config):
182
+ """Test that None (unset) compliance level is always accessible."""
183
+ manager = ComplianceLevelManager(temp_compliance_config)
184
+
185
+ # None user can access any resource
186
+ assert manager.is_accessible(None, "HIPAA") is True
187
+ assert manager.is_accessible(None, "Public") is True
188
+
189
+ # Any user can access None resource
190
+ assert manager.is_accessible("HIPAA", None) is True
191
+ assert manager.is_accessible("Public", None) is True
192
+
193
+ # None to None
194
+ assert manager.is_accessible(None, None) is True
195
+
196
+ def test_get_accessible_levels_public(self, temp_compliance_config):
197
+ """Test getting accessible levels for Public."""
198
+ manager = ComplianceLevelManager(temp_compliance_config)
199
+
200
+ accessible = manager.get_accessible_levels("Public")
201
+
202
+ assert accessible == {"Public"}
203
+
204
+ def test_get_accessible_levels_hipaa(self, temp_compliance_config):
205
+ """Test getting accessible levels for HIPAA."""
206
+ manager = ComplianceLevelManager(temp_compliance_config)
207
+
208
+ accessible = manager.get_accessible_levels("HIPAA")
209
+
210
+ assert accessible == {"HIPAA", "SOC2"}
211
+
212
+ def test_get_accessible_levels_fedramp(self, temp_compliance_config):
213
+ """Test getting accessible levels for FedRAMP."""
214
+ manager = ComplianceLevelManager(temp_compliance_config)
215
+
216
+ accessible = manager.get_accessible_levels("FedRAMP")
217
+
218
+ assert accessible == {"FedRAMP", "SOC2"}
219
+
220
+ def test_get_accessible_levels_none(self, temp_compliance_config):
221
+ """Test getting accessible levels when user level is None."""
222
+ manager = ComplianceLevelManager(temp_compliance_config)
223
+
224
+ accessible = manager.get_accessible_levels(None)
225
+
226
+ # Should return all levels
227
+ assert len(accessible) == 6
228
+ assert "Public" in accessible
229
+ assert "HIPAA" in accessible
230
+
231
+ def test_get_all_levels(self, temp_compliance_config):
232
+ """Test getting all defined compliance levels."""
233
+ manager = ComplianceLevelManager(temp_compliance_config)
234
+
235
+ all_levels = manager.get_all_levels()
236
+
237
+ assert len(all_levels) == 6
238
+ assert "Public" in all_levels
239
+ assert "External" in all_levels
240
+ assert "Internal" in all_levels
241
+ assert "SOC2" in all_levels
242
+ assert "HIPAA" in all_levels
243
+ assert "FedRAMP" in all_levels
244
+
245
+ def test_permissive_mode_no_config(self):
246
+ """Test permissive mode when no config is loaded."""
247
+ manager = ComplianceLevelManager(Path("/nonexistent"))
248
+
249
+ # Should validate anything in permissive mode
250
+ assert manager.validate_compliance_level("AnyLevel") == "AnyLevel"
251
+
252
+ # Should allow all access
253
+ assert manager.is_accessible("Level1", "Level2") is True