agent_os_kernel 3.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 (337) hide show
  1. agent_control_plane/__init__.py +662 -0
  2. agent_control_plane/a2a_adapter.py +543 -0
  3. agent_control_plane/adapter.py +417 -0
  4. agent_control_plane/agent_hibernation.py +394 -0
  5. agent_control_plane/agent_kernel.py +470 -0
  6. agent_control_plane/compliance.py +720 -0
  7. agent_control_plane/constraint_graphs.py +478 -0
  8. agent_control_plane/control_plane.py +854 -0
  9. agent_control_plane/example_executors.py +195 -0
  10. agent_control_plane/execution_engine.py +231 -0
  11. agent_control_plane/flight_recorder.py +846 -0
  12. agent_control_plane/governance_layer.py +435 -0
  13. agent_control_plane/hf_utils.py +563 -0
  14. agent_control_plane/interfaces/__init__.py +55 -0
  15. agent_control_plane/interfaces/kernel_interface.py +361 -0
  16. agent_control_plane/interfaces/plugin_interface.py +497 -0
  17. agent_control_plane/interfaces/protocol_interfaces.py +387 -0
  18. agent_control_plane/kernel_space.py +1009 -0
  19. agent_control_plane/langchain_adapter.py +424 -0
  20. agent_control_plane/lifecycle.py +3113 -0
  21. agent_control_plane/mcp_adapter.py +653 -0
  22. agent_control_plane/ml_safety.py +563 -0
  23. agent_control_plane/multimodal.py +727 -0
  24. agent_control_plane/mute_agent.py +422 -0
  25. agent_control_plane/observability.py +787 -0
  26. agent_control_plane/orchestrator.py +482 -0
  27. agent_control_plane/plugin_registry.py +750 -0
  28. agent_control_plane/policy_engine.py +954 -0
  29. agent_control_plane/process_isolation.py +777 -0
  30. agent_control_plane/shadow_mode.py +310 -0
  31. agent_control_plane/signals.py +493 -0
  32. agent_control_plane/supervisor_agents.py +430 -0
  33. agent_control_plane/time_travel_debugger.py +557 -0
  34. agent_control_plane/tool_registry.py +452 -0
  35. agent_control_plane/vfs.py +697 -0
  36. agent_kernel/__init__.py +69 -0
  37. agent_kernel/analyzer.py +435 -0
  38. agent_kernel/auditor.py +36 -0
  39. agent_kernel/completeness_auditor.py +237 -0
  40. agent_kernel/detector.py +203 -0
  41. agent_kernel/kernel.py +744 -0
  42. agent_kernel/memory_manager.py +85 -0
  43. agent_kernel/models.py +374 -0
  44. agent_kernel/nudge_mechanism.py +263 -0
  45. agent_kernel/outcome_analyzer.py +338 -0
  46. agent_kernel/patcher.py +582 -0
  47. agent_kernel/semantic_analyzer.py +316 -0
  48. agent_kernel/semantic_purge.py +349 -0
  49. agent_kernel/simulator.py +449 -0
  50. agent_kernel/teacher.py +85 -0
  51. agent_kernel/triage.py +152 -0
  52. agent_os/__init__.py +409 -0
  53. agent_os/_adversarial_impl.py +200 -0
  54. agent_os/_circuit_breaker_impl.py +232 -0
  55. agent_os/_mcp_metrics.py +193 -0
  56. agent_os/adversarial.py +20 -0
  57. agent_os/agents_compat.py +490 -0
  58. agent_os/audit_logger.py +135 -0
  59. agent_os/base_agent.py +651 -0
  60. agent_os/circuit_breaker.py +34 -0
  61. agent_os/cli/__init__.py +659 -0
  62. agent_os/cli/cmd_audit.py +128 -0
  63. agent_os/cli/cmd_init.py +152 -0
  64. agent_os/cli/cmd_policy.py +41 -0
  65. agent_os/cli/cmd_policy_gen.py +180 -0
  66. agent_os/cli/cmd_validate.py +258 -0
  67. agent_os/cli/mcp_scan.py +265 -0
  68. agent_os/cli/output.py +192 -0
  69. agent_os/cli/policy_checker.py +330 -0
  70. agent_os/compat.py +74 -0
  71. agent_os/constraint_graph.py +234 -0
  72. agent_os/content_governance.py +140 -0
  73. agent_os/context_budget.py +305 -0
  74. agent_os/credential_redactor.py +224 -0
  75. agent_os/diff_policy.py +89 -0
  76. agent_os/egress_policy.py +159 -0
  77. agent_os/escalation.py +276 -0
  78. agent_os/event_bus.py +124 -0
  79. agent_os/exceptions.py +180 -0
  80. agent_os/execution_context_policy.py +141 -0
  81. agent_os/github_enterprise.py +96 -0
  82. agent_os/health.py +20 -0
  83. agent_os/integrations/__init__.py +279 -0
  84. agent_os/integrations/a2a_adapter.py +279 -0
  85. agent_os/integrations/agent_lightning/__init__.py +30 -0
  86. agent_os/integrations/anthropic_adapter.py +420 -0
  87. agent_os/integrations/autogen_adapter.py +620 -0
  88. agent_os/integrations/base.py +1137 -0
  89. agent_os/integrations/compat.py +229 -0
  90. agent_os/integrations/config.py +98 -0
  91. agent_os/integrations/conversation_guardian.py +957 -0
  92. agent_os/integrations/crewai_adapter.py +467 -0
  93. agent_os/integrations/drift_detector.py +425 -0
  94. agent_os/integrations/dry_run.py +124 -0
  95. agent_os/integrations/escalation.py +582 -0
  96. agent_os/integrations/gemini_adapter.py +364 -0
  97. agent_os/integrations/google_adk_adapter.py +633 -0
  98. agent_os/integrations/guardrails_adapter.py +394 -0
  99. agent_os/integrations/health.py +197 -0
  100. agent_os/integrations/langchain_adapter.py +654 -0
  101. agent_os/integrations/llamafirewall.py +343 -0
  102. agent_os/integrations/llamaindex_adapter.py +188 -0
  103. agent_os/integrations/logging.py +191 -0
  104. agent_os/integrations/maf_adapter.py +631 -0
  105. agent_os/integrations/mistral_adapter.py +365 -0
  106. agent_os/integrations/openai_adapter.py +816 -0
  107. agent_os/integrations/openai_agents_sdk.py +406 -0
  108. agent_os/integrations/policy_compose.py +171 -0
  109. agent_os/integrations/profiling.py +144 -0
  110. agent_os/integrations/pydantic_ai_adapter.py +420 -0
  111. agent_os/integrations/rate_limiter.py +130 -0
  112. agent_os/integrations/rbac.py +143 -0
  113. agent_os/integrations/registry.py +113 -0
  114. agent_os/integrations/scope_guard.py +303 -0
  115. agent_os/integrations/semantic_kernel_adapter.py +769 -0
  116. agent_os/integrations/smolagents_adapter.py +629 -0
  117. agent_os/integrations/templates.py +178 -0
  118. agent_os/integrations/token_budget.py +134 -0
  119. agent_os/integrations/tool_aliases.py +190 -0
  120. agent_os/integrations/webhooks.py +177 -0
  121. agent_os/lite.py +208 -0
  122. agent_os/mcp_gateway.py +385 -0
  123. agent_os/mcp_message_signer.py +273 -0
  124. agent_os/mcp_protocols.py +161 -0
  125. agent_os/mcp_response_scanner.py +232 -0
  126. agent_os/mcp_security.py +924 -0
  127. agent_os/mcp_session_auth.py +231 -0
  128. agent_os/mcp_sliding_rate_limiter.py +184 -0
  129. agent_os/memory_guard.py +409 -0
  130. agent_os/metrics.py +134 -0
  131. agent_os/mute.py +428 -0
  132. agent_os/mute_agent.py +209 -0
  133. agent_os/policies/__init__.py +77 -0
  134. agent_os/policies/async_evaluator.py +275 -0
  135. agent_os/policies/backends.py +670 -0
  136. agent_os/policies/bridge.py +169 -0
  137. agent_os/policies/budget.py +85 -0
  138. agent_os/policies/cli.py +294 -0
  139. agent_os/policies/conflict_resolution.py +270 -0
  140. agent_os/policies/data_classification.py +252 -0
  141. agent_os/policies/evaluator.py +239 -0
  142. agent_os/policies/policy_schema.json +228 -0
  143. agent_os/policies/rate_limiting.py +145 -0
  144. agent_os/policies/schema.py +115 -0
  145. agent_os/policies/shared.py +331 -0
  146. agent_os/prompt_injection.py +694 -0
  147. agent_os/providers.py +182 -0
  148. agent_os/py.typed +0 -0
  149. agent_os/retry.py +81 -0
  150. agent_os/reversibility.py +251 -0
  151. agent_os/sandbox.py +432 -0
  152. agent_os/sandbox_provider.py +140 -0
  153. agent_os/secure_codegen.py +525 -0
  154. agent_os/security_skills.py +538 -0
  155. agent_os/semantic_policy.py +422 -0
  156. agent_os/server/__init__.py +15 -0
  157. agent_os/server/__main__.py +25 -0
  158. agent_os/server/app.py +277 -0
  159. agent_os/server/models.py +104 -0
  160. agent_os/shift_left_metrics.py +130 -0
  161. agent_os/stateless.py +742 -0
  162. agent_os/supervisor.py +148 -0
  163. agent_os/task_outcome.py +148 -0
  164. agent_os/transparency.py +181 -0
  165. agent_os/trust_root.py +128 -0
  166. agent_os_kernel-3.1.0.dist-info/METADATA +1269 -0
  167. agent_os_kernel-3.1.0.dist-info/RECORD +337 -0
  168. agent_os_kernel-3.1.0.dist-info/WHEEL +4 -0
  169. agent_os_kernel-3.1.0.dist-info/entry_points.txt +2 -0
  170. agent_os_kernel-3.1.0.dist-info/licenses/LICENSE +21 -0
  171. agent_os_observability/__init__.py +27 -0
  172. agent_os_observability/dashboards.py +898 -0
  173. agent_os_observability/metrics.py +398 -0
  174. agent_os_observability/server.py +223 -0
  175. agent_os_observability/tracer.py +232 -0
  176. agent_primitives/__init__.py +24 -0
  177. agent_primitives/failures.py +84 -0
  178. agent_primitives/py.typed +0 -0
  179. amb_core/__init__.py +177 -0
  180. amb_core/adapters/__init__.py +57 -0
  181. amb_core/adapters/aws_sqs_broker.py +376 -0
  182. amb_core/adapters/azure_servicebus_broker.py +340 -0
  183. amb_core/adapters/kafka_broker.py +260 -0
  184. amb_core/adapters/nats_broker.py +285 -0
  185. amb_core/adapters/rabbitmq_broker.py +235 -0
  186. amb_core/adapters/redis_broker.py +262 -0
  187. amb_core/broker.py +145 -0
  188. amb_core/bus.py +481 -0
  189. amb_core/cloudevents.py +509 -0
  190. amb_core/dlq.py +345 -0
  191. amb_core/hf_utils.py +536 -0
  192. amb_core/memory_broker.py +410 -0
  193. amb_core/models.py +141 -0
  194. amb_core/persistence.py +529 -0
  195. amb_core/schema.py +294 -0
  196. amb_core/tracing.py +358 -0
  197. atr/__init__.py +640 -0
  198. atr/access.py +348 -0
  199. atr/composition.py +645 -0
  200. atr/decorator.py +357 -0
  201. atr/executor.py +384 -0
  202. atr/health.py +557 -0
  203. atr/hf_utils.py +449 -0
  204. atr/injection.py +422 -0
  205. atr/metrics.py +440 -0
  206. atr/policies.py +403 -0
  207. atr/py.typed +2 -0
  208. atr/registry.py +452 -0
  209. atr/schema.py +480 -0
  210. atr/tools/safe/__init__.py +75 -0
  211. atr/tools/safe/calculator.py +467 -0
  212. atr/tools/safe/datetime_tool.py +443 -0
  213. atr/tools/safe/file_reader.py +402 -0
  214. atr/tools/safe/http_client.py +316 -0
  215. atr/tools/safe/json_parser.py +374 -0
  216. atr/tools/safe/text_tool.py +537 -0
  217. atr/tools/safe/toolkit.py +175 -0
  218. caas/__init__.py +162 -0
  219. caas/api/__init__.py +7 -0
  220. caas/api/server.py +1328 -0
  221. caas/caching.py +834 -0
  222. caas/cli.py +210 -0
  223. caas/conversation.py +223 -0
  224. caas/decay.py +72 -0
  225. caas/detection/__init__.py +9 -0
  226. caas/detection/detector.py +238 -0
  227. caas/enrichment.py +130 -0
  228. caas/gateway/__init__.py +27 -0
  229. caas/gateway/trust_gateway.py +474 -0
  230. caas/hf_utils.py +479 -0
  231. caas/ingestion/__init__.py +23 -0
  232. caas/ingestion/processors.py +253 -0
  233. caas/ingestion/structure_parser.py +188 -0
  234. caas/models.py +356 -0
  235. caas/pragmatic_truth.py +444 -0
  236. caas/routing/__init__.py +10 -0
  237. caas/routing/heuristic_router.py +58 -0
  238. caas/storage/__init__.py +9 -0
  239. caas/storage/store.py +389 -0
  240. caas/triad.py +213 -0
  241. caas/tuning/__init__.py +9 -0
  242. caas/tuning/tuner.py +329 -0
  243. caas/vfs/__init__.py +14 -0
  244. caas/vfs/filesystem.py +452 -0
  245. cmvk/__init__.py +218 -0
  246. cmvk/audit.py +402 -0
  247. cmvk/benchmarks.py +478 -0
  248. cmvk/constitutional.py +904 -0
  249. cmvk/hf_utils.py +301 -0
  250. cmvk/metrics.py +473 -0
  251. cmvk/profiles.py +300 -0
  252. cmvk/py.typed +0 -0
  253. cmvk/types.py +12 -0
  254. cmvk/verification.py +956 -0
  255. emk/__init__.py +89 -0
  256. emk/causal.py +352 -0
  257. emk/hf_utils.py +421 -0
  258. emk/indexer.py +83 -0
  259. emk/py.typed +0 -0
  260. emk/schema.py +204 -0
  261. emk/sleep_cycle.py +347 -0
  262. emk/store.py +281 -0
  263. iatp/__init__.py +166 -0
  264. iatp/attestation.py +461 -0
  265. iatp/cli.py +317 -0
  266. iatp/hf_utils.py +472 -0
  267. iatp/ipc_pipes.py +580 -0
  268. iatp/main.py +412 -0
  269. iatp/models/__init__.py +447 -0
  270. iatp/policy_engine.py +337 -0
  271. iatp/py.typed +2 -0
  272. iatp/recovery.py +321 -0
  273. iatp/security/__init__.py +270 -0
  274. iatp/sidecar/__init__.py +519 -0
  275. iatp/telemetry/__init__.py +164 -0
  276. iatp/tests/__init__.py +1 -0
  277. iatp/tests/test_attestation.py +370 -0
  278. iatp/tests/test_cli.py +131 -0
  279. iatp/tests/test_ed25519_attestation.py +211 -0
  280. iatp/tests/test_models.py +130 -0
  281. iatp/tests/test_policy_engine.py +347 -0
  282. iatp/tests/test_recovery.py +281 -0
  283. iatp/tests/test_security.py +222 -0
  284. iatp/tests/test_sidecar.py +167 -0
  285. iatp/tests/test_telemetry.py +175 -0
  286. mcp_kernel_server/__init__.py +28 -0
  287. mcp_kernel_server/cli.py +274 -0
  288. mcp_kernel_server/resources.py +217 -0
  289. mcp_kernel_server/server.py +564 -0
  290. mcp_kernel_server/tools.py +1174 -0
  291. mute_agent/__init__.py +68 -0
  292. mute_agent/core/__init__.py +1 -0
  293. mute_agent/core/execution_agent.py +166 -0
  294. mute_agent/core/handshake_protocol.py +201 -0
  295. mute_agent/core/reasoning_agent.py +238 -0
  296. mute_agent/knowledge_graph/__init__.py +1 -0
  297. mute_agent/knowledge_graph/graph_elements.py +65 -0
  298. mute_agent/knowledge_graph/multidimensional_graph.py +170 -0
  299. mute_agent/knowledge_graph/subgraph.py +224 -0
  300. mute_agent/listener/__init__.py +43 -0
  301. mute_agent/listener/adapters/__init__.py +31 -0
  302. mute_agent/listener/adapters/base_adapter.py +189 -0
  303. mute_agent/listener/adapters/caas_adapter.py +344 -0
  304. mute_agent/listener/adapters/control_plane_adapter.py +436 -0
  305. mute_agent/listener/adapters/iatp_adapter.py +332 -0
  306. mute_agent/listener/adapters/scak_adapter.py +251 -0
  307. mute_agent/listener/listener.py +610 -0
  308. mute_agent/listener/state_observer.py +436 -0
  309. mute_agent/listener/threshold_config.py +313 -0
  310. mute_agent/super_system/__init__.py +1 -0
  311. mute_agent/super_system/router.py +204 -0
  312. mute_agent/visualization/__init__.py +10 -0
  313. mute_agent/visualization/graph_debugger.py +502 -0
  314. nexus/README.md +60 -0
  315. nexus/__init__.py +51 -0
  316. nexus/arbiter.py +359 -0
  317. nexus/client.py +466 -0
  318. nexus/dmz.py +444 -0
  319. nexus/escrow.py +430 -0
  320. nexus/exceptions.py +286 -0
  321. nexus/pyproject.toml +36 -0
  322. nexus/registry.py +393 -0
  323. nexus/reputation.py +425 -0
  324. nexus/schemas/__init__.py +51 -0
  325. nexus/schemas/compliance.py +276 -0
  326. nexus/schemas/escrow.py +251 -0
  327. nexus/schemas/manifest.py +225 -0
  328. nexus/schemas/receipt.py +208 -0
  329. nexus/tests/__init__.py +0 -0
  330. nexus/tests/conftest.py +146 -0
  331. nexus/tests/test_arbiter.py +192 -0
  332. nexus/tests/test_dmz.py +194 -0
  333. nexus/tests/test_escrow.py +276 -0
  334. nexus/tests/test_exceptions.py +225 -0
  335. nexus/tests/test_registry.py +232 -0
  336. nexus/tests/test_reputation.py +328 -0
  337. nexus/tests/test_schemas.py +295 -0
nexus/dmz.py ADDED
@@ -0,0 +1,444 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
3
+ """
4
+ DMZ Protocol
5
+
6
+ Extension of IATP for secure data handoff between agents.
7
+ Implements the REQUEST_ESCROW verb and data handling policies.
8
+ """
9
+
10
+ from datetime import datetime, timedelta, timezone
11
+ from typing import Optional, Literal
12
+ from pydantic import BaseModel, Field
13
+ import hashlib
14
+ import uuid
15
+ from dataclasses import dataclass, field
16
+
17
+
18
+ class DataHandlingPolicy(BaseModel):
19
+ """
20
+ Policy that receiving agent must sign before getting decryption key.
21
+
22
+ Ensures data handling compliance between agents.
23
+ """
24
+
25
+ policy_id: str = Field(
26
+ default_factory=lambda: f"policy_{uuid.uuid4().hex[:12]}"
27
+ )
28
+
29
+ # Retention
30
+ max_retention_seconds: int = Field(
31
+ default=3600,
32
+ ge=0,
33
+ le=2592000, # 30 days max
34
+ description="Maximum time to retain data (0 = process and delete)"
35
+ )
36
+
37
+ # Permissions
38
+ allow_persistence: bool = Field(
39
+ default=False,
40
+ description="Whether data can be persisted to storage"
41
+ )
42
+ allow_training: bool = Field(
43
+ default=False,
44
+ description="Whether data can be used for model training"
45
+ )
46
+ allow_forwarding: bool = Field(
47
+ default=False,
48
+ description="Whether data can be forwarded to other agents"
49
+ )
50
+ allow_logging: bool = Field(
51
+ default=True,
52
+ description="Whether metadata can be logged (not content)"
53
+ )
54
+
55
+ # Audit
56
+ audit_required: bool = Field(
57
+ default=True,
58
+ description="Whether all data access must be audited"
59
+ )
60
+
61
+ # Encryption
62
+ require_encryption_at_rest: bool = Field(
63
+ default=True,
64
+ description="Whether data must be encrypted when stored"
65
+ )
66
+
67
+ def compute_hash(self) -> str:
68
+ """Compute deterministic policy hash."""
69
+ data = self.model_dump(exclude={"policy_id"})
70
+ import json
71
+ canonical = json.dumps(data, sort_keys=True)
72
+ return hashlib.sha256(canonical.encode()).hexdigest()
73
+
74
+
75
+ class DMZRequest(BaseModel):
76
+ """Request to share data through the secure DMZ."""
77
+
78
+ verb: Literal["REQUEST_ESCROW"] = "REQUEST_ESCROW"
79
+ request_id: str = Field(
80
+ default_factory=lambda: f"dmz_{uuid.uuid4().hex[:16]}"
81
+ )
82
+
83
+ # Parties
84
+ sender_did: str
85
+ receiver_did: str
86
+
87
+ # Data (only hash, not actual content)
88
+ data_hash: str = Field(
89
+ ...,
90
+ description="SHA-256 hash of the actual data"
91
+ )
92
+ data_size_bytes: int = Field(
93
+ ...,
94
+ ge=0,
95
+ description="Size of the data in bytes"
96
+ )
97
+ data_classification: Literal["public", "internal", "confidential", "pii"] = Field(
98
+ default="internal",
99
+ description="Classification level of the data"
100
+ )
101
+
102
+ # Policy
103
+ required_policy: DataHandlingPolicy
104
+
105
+ # Encryption
106
+ encrypted_data_location: Optional[str] = Field(
107
+ default=None,
108
+ description="URL/URI where encrypted data is stored"
109
+ )
110
+ encryption_algorithm: str = Field(
111
+ default="AES-256-GCM",
112
+ description="Encryption algorithm used"
113
+ )
114
+
115
+ # Timestamps
116
+ created_at: datetime = Field(default_factory=datetime.utcnow)
117
+ expires_at: Optional[datetime] = Field(
118
+ default=None,
119
+ description="When this request expires"
120
+ )
121
+
122
+
123
+ @dataclass
124
+ class SignedPolicy:
125
+ """A policy that has been signed by the receiving agent."""
126
+
127
+ policy: DataHandlingPolicy
128
+ policy_hash: str
129
+
130
+ # Signer
131
+ signer_did: str
132
+ signed_at: datetime = field(default_factory=datetime.utcnow)
133
+
134
+ # Signature
135
+ signature: str = ""
136
+
137
+ # Verification
138
+ verified: bool = False
139
+ verified_at: Optional[datetime] = None
140
+
141
+
142
+ @dataclass
143
+ class DMZTransfer:
144
+ """Record of a DMZ data transfer."""
145
+
146
+ transfer_id: str
147
+ request: DMZRequest
148
+
149
+ # Policy signing
150
+ policy_signed: bool = False
151
+ signed_policy: Optional[SignedPolicy] = None
152
+
153
+ # Key release
154
+ key_released: bool = False
155
+ key_released_at: Optional[datetime] = None
156
+
157
+ # Data access
158
+ data_accessed: bool = False
159
+ data_accessed_at: Optional[datetime] = None
160
+
161
+ # Completion
162
+ completed: bool = False
163
+ completed_at: Optional[datetime] = None
164
+
165
+ # Audit
166
+ audit_trail: list[dict] = field(default_factory=list)
167
+
168
+
169
+ class DMZProtocol:
170
+ """
171
+ Implements the DMZ (Demilitarized Zone) protocol for secure data sharing.
172
+
173
+ Flow:
174
+ 1. Agent A sends REQUEST_ESCROW with data hash to Nexus
175
+ 2. Nexus holds the encrypted data reference
176
+ 3. Agent B signs the DataHandlingPolicy
177
+ 4. Nexus releases decryption key to Agent B
178
+ 5. All operations are logged for compliance
179
+ """
180
+
181
+ def __init__(self):
182
+ # Storage
183
+ self._transfers: dict[str, DMZTransfer] = {}
184
+ self._signed_policies: dict[str, SignedPolicy] = {}
185
+ self._encryption_keys: dict[str, bytes] = {} # transfer_id -> key
186
+
187
+ async def initiate_transfer(
188
+ self,
189
+ sender_did: str,
190
+ receiver_did: str,
191
+ data: bytes,
192
+ classification: Literal["public", "internal", "confidential", "pii"],
193
+ policy: DataHandlingPolicy,
194
+ expiry_hours: int = 24,
195
+ ) -> DMZRequest:
196
+ """
197
+ Initiate a secure data transfer through DMZ.
198
+
199
+ Args:
200
+ sender_did: DID of sending agent
201
+ receiver_did: DID of receiving agent
202
+ data: The actual data to transfer (will be encrypted)
203
+ classification: Data classification level
204
+ policy: Required data handling policy
205
+ expiry_hours: Hours until request expires
206
+ """
207
+ # Compute data hash
208
+ data_hash = hashlib.sha256(data).hexdigest()
209
+
210
+ # Generate encryption key
211
+ import secrets
212
+ encryption_key = secrets.token_bytes(32) # AES-256
213
+
214
+ # Encrypt data (placeholder - would use proper encryption)
215
+ encrypted_data = self._encrypt_data(data, encryption_key)
216
+
217
+ # Create request
218
+ request = DMZRequest(
219
+ sender_did=sender_did,
220
+ receiver_did=receiver_did,
221
+ data_hash=data_hash,
222
+ data_size_bytes=len(data),
223
+ data_classification=classification,
224
+ required_policy=policy,
225
+ expires_at=datetime.now(timezone.utc) + timedelta(hours=expiry_hours),
226
+ )
227
+
228
+ # Create transfer record
229
+ transfer = DMZTransfer(
230
+ transfer_id=request.request_id,
231
+ request=request,
232
+ )
233
+
234
+ # Store
235
+ self._transfers[request.request_id] = transfer
236
+ self._encryption_keys[request.request_id] = encryption_key
237
+
238
+ # Add audit entry
239
+ transfer.audit_trail.append({
240
+ "event": "transfer_initiated",
241
+ "timestamp": datetime.now(timezone.utc).isoformat(),
242
+ "sender": sender_did,
243
+ "receiver": receiver_did,
244
+ "data_hash": data_hash,
245
+ })
246
+
247
+ return request
248
+
249
+ async def sign_policy(
250
+ self,
251
+ transfer_id: str,
252
+ signer_did: str,
253
+ signature: str,
254
+ ) -> SignedPolicy:
255
+ """
256
+ Sign a data handling policy to receive access.
257
+
258
+ The receiving agent must sign the policy before getting
259
+ the decryption key.
260
+ """
261
+ if transfer_id not in self._transfers:
262
+ raise ValueError(f"Transfer not found: {transfer_id}")
263
+
264
+ transfer = self._transfers[transfer_id]
265
+ request = transfer.request
266
+
267
+ # Verify signer is the intended receiver
268
+ if signer_did != request.receiver_did:
269
+ raise ValueError("Only intended receiver can sign policy")
270
+
271
+ # Verify transfer hasn't expired
272
+ if request.expires_at and datetime.now(timezone.utc) > request.expires_at:
273
+ raise ValueError("Transfer has expired")
274
+
275
+ # Create signed policy
276
+ signed = SignedPolicy(
277
+ policy=request.required_policy,
278
+ policy_hash=request.required_policy.compute_hash(),
279
+ signer_did=signer_did,
280
+ signature=signature,
281
+ verified=True, # Would verify signature in production
282
+ verified_at=datetime.now(timezone.utc),
283
+ )
284
+
285
+ # Update transfer
286
+ transfer.policy_signed = True
287
+ transfer.signed_policy = signed
288
+
289
+ # Add audit entry
290
+ transfer.audit_trail.append({
291
+ "event": "policy_signed",
292
+ "timestamp": datetime.now(timezone.utc).isoformat(),
293
+ "signer": signer_did,
294
+ "policy_hash": signed.policy_hash,
295
+ })
296
+
297
+ # Store signed policy
298
+ self._signed_policies[f"{transfer_id}:{signer_did}"] = signed
299
+
300
+ return signed
301
+
302
+ async def release_key(
303
+ self,
304
+ transfer_id: str,
305
+ requester_did: str,
306
+ ) -> bytes:
307
+ """
308
+ Release decryption key after policy is signed.
309
+
310
+ Only releases key if:
311
+ 1. Requester is the intended receiver
312
+ 2. Policy has been signed
313
+ 3. Transfer hasn't expired
314
+ """
315
+ if transfer_id not in self._transfers:
316
+ raise ValueError(f"Transfer not found: {transfer_id}")
317
+
318
+ transfer = self._transfers[transfer_id]
319
+ request = transfer.request
320
+
321
+ # Verify requester
322
+ if requester_did != request.receiver_did:
323
+ raise ValueError("Only intended receiver can get key")
324
+
325
+ # Verify policy signed
326
+ if not transfer.policy_signed:
327
+ raise ValueError("Policy must be signed before key release")
328
+
329
+ # Verify not expired
330
+ if request.expires_at and datetime.now(timezone.utc) > request.expires_at:
331
+ raise ValueError("Transfer has expired")
332
+
333
+ # Get key
334
+ if transfer_id not in self._encryption_keys:
335
+ raise ValueError("Encryption key not found")
336
+
337
+ key = self._encryption_keys[transfer_id]
338
+
339
+ # Update transfer
340
+ transfer.key_released = True
341
+ transfer.key_released_at = datetime.now(timezone.utc)
342
+
343
+ # Add audit entry
344
+ transfer.audit_trail.append({
345
+ "event": "key_released",
346
+ "timestamp": datetime.now(timezone.utc).isoformat(),
347
+ "recipient": requester_did,
348
+ })
349
+
350
+ return key
351
+
352
+ async def record_data_access(
353
+ self,
354
+ transfer_id: str,
355
+ accessor_did: str,
356
+ ) -> None:
357
+ """Record that data was accessed (for audit)."""
358
+ if transfer_id not in self._transfers:
359
+ raise ValueError(f"Transfer not found: {transfer_id}")
360
+
361
+ transfer = self._transfers[transfer_id]
362
+ transfer.data_accessed = True
363
+ transfer.data_accessed_at = datetime.now(timezone.utc)
364
+
365
+ transfer.audit_trail.append({
366
+ "event": "data_accessed",
367
+ "timestamp": datetime.now(timezone.utc).isoformat(),
368
+ "accessor": accessor_did,
369
+ })
370
+
371
+ async def complete_transfer(
372
+ self,
373
+ transfer_id: str,
374
+ ) -> DMZTransfer:
375
+ """Mark transfer as complete."""
376
+ if transfer_id not in self._transfers:
377
+ raise ValueError(f"Transfer not found: {transfer_id}")
378
+
379
+ transfer = self._transfers[transfer_id]
380
+ transfer.completed = True
381
+ transfer.completed_at = datetime.now(timezone.utc)
382
+
383
+ transfer.audit_trail.append({
384
+ "event": "transfer_completed",
385
+ "timestamp": datetime.now(timezone.utc).isoformat(),
386
+ })
387
+
388
+ # Clean up key (data should be deleted per policy)
389
+ if transfer_id in self._encryption_keys:
390
+ del self._encryption_keys[transfer_id]
391
+
392
+ return transfer
393
+
394
+ def get_transfer(self, transfer_id: str) -> DMZTransfer:
395
+ """Get transfer by ID."""
396
+ if transfer_id not in self._transfers:
397
+ raise ValueError(f"Transfer not found: {transfer_id}")
398
+ return self._transfers[transfer_id]
399
+
400
+ def get_audit_trail(self, transfer_id: str) -> list[dict]:
401
+ """Get audit trail for a transfer."""
402
+ transfer = self.get_transfer(transfer_id)
403
+ return transfer.audit_trail
404
+
405
+ def has_signed_policy(self, transfer_id: str, agent_did: str) -> bool:
406
+ """Check if agent has signed policy for a transfer."""
407
+ key = f"{transfer_id}:{agent_did}"
408
+ return key in self._signed_policies
409
+
410
+ def _encrypt_data(self, data: bytes, key: bytes) -> bytes:
411
+ """Encrypt data with AES-256-GCM.
412
+
413
+ Requires the ``cryptography`` package (``pip install cryptography``).
414
+ Falls back to a clearly-marked no-op if not installed.
415
+ """
416
+ try:
417
+ from cryptography.hazmat.primitives.ciphers.aead import AESGCM
418
+ except ImportError:
419
+ raise ImportError(
420
+ "DMZ encryption requires the 'cryptography' package. "
421
+ "Install with: pip install cryptography"
422
+ )
423
+
424
+ # Derive a 256-bit key via SHA-256 to ensure correct length
425
+ derived = hashlib.sha256(key).digest()
426
+ nonce = hashlib.sha256(data[:16] + key).digest()[:12] # 96-bit nonce
427
+ aesgcm = AESGCM(derived)
428
+ return nonce + aesgcm.encrypt(nonce, data, None)
429
+
430
+ def _decrypt_data(self, encrypted: bytes, key: bytes) -> bytes:
431
+ """Decrypt data encrypted with AES-256-GCM."""
432
+ try:
433
+ from cryptography.hazmat.primitives.ciphers.aead import AESGCM
434
+ except ImportError:
435
+ raise ImportError(
436
+ "DMZ decryption requires the 'cryptography' package. "
437
+ "Install with: pip install cryptography"
438
+ )
439
+
440
+ derived = hashlib.sha256(key).digest()
441
+ nonce = encrypted[:12]
442
+ ciphertext = encrypted[12:]
443
+ aesgcm = AESGCM(derived)
444
+ return aesgcm.decrypt(nonce, ciphertext, None)