proxilion 0.0.1__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 (94) hide show
  1. proxilion/__init__.py +136 -0
  2. proxilion/audit/__init__.py +133 -0
  3. proxilion/audit/base_exporters.py +527 -0
  4. proxilion/audit/compliance/__init__.py +130 -0
  5. proxilion/audit/compliance/base.py +457 -0
  6. proxilion/audit/compliance/eu_ai_act.py +603 -0
  7. proxilion/audit/compliance/iso27001.py +544 -0
  8. proxilion/audit/compliance/soc2.py +491 -0
  9. proxilion/audit/events.py +493 -0
  10. proxilion/audit/explainability.py +1173 -0
  11. proxilion/audit/exporters/__init__.py +58 -0
  12. proxilion/audit/exporters/aws_s3.py +636 -0
  13. proxilion/audit/exporters/azure_storage.py +608 -0
  14. proxilion/audit/exporters/cloud_base.py +468 -0
  15. proxilion/audit/exporters/gcp_storage.py +570 -0
  16. proxilion/audit/exporters/multi_exporter.py +498 -0
  17. proxilion/audit/hash_chain.py +652 -0
  18. proxilion/audit/logger.py +543 -0
  19. proxilion/caching/__init__.py +49 -0
  20. proxilion/caching/tool_cache.py +633 -0
  21. proxilion/context/__init__.py +73 -0
  22. proxilion/context/context_window.py +556 -0
  23. proxilion/context/message_history.py +505 -0
  24. proxilion/context/session.py +735 -0
  25. proxilion/contrib/__init__.py +51 -0
  26. proxilion/contrib/anthropic.py +609 -0
  27. proxilion/contrib/google.py +1012 -0
  28. proxilion/contrib/langchain.py +641 -0
  29. proxilion/contrib/mcp.py +893 -0
  30. proxilion/contrib/openai.py +646 -0
  31. proxilion/core.py +3058 -0
  32. proxilion/decorators.py +966 -0
  33. proxilion/engines/__init__.py +287 -0
  34. proxilion/engines/base.py +266 -0
  35. proxilion/engines/casbin_engine.py +412 -0
  36. proxilion/engines/opa_engine.py +493 -0
  37. proxilion/engines/simple.py +437 -0
  38. proxilion/exceptions.py +887 -0
  39. proxilion/guards/__init__.py +54 -0
  40. proxilion/guards/input_guard.py +522 -0
  41. proxilion/guards/output_guard.py +634 -0
  42. proxilion/observability/__init__.py +198 -0
  43. proxilion/observability/cost_tracker.py +866 -0
  44. proxilion/observability/hooks.py +683 -0
  45. proxilion/observability/metrics.py +798 -0
  46. proxilion/observability/session_cost_tracker.py +1063 -0
  47. proxilion/policies/__init__.py +67 -0
  48. proxilion/policies/base.py +304 -0
  49. proxilion/policies/builtin.py +486 -0
  50. proxilion/policies/registry.py +376 -0
  51. proxilion/providers/__init__.py +201 -0
  52. proxilion/providers/adapter.py +468 -0
  53. proxilion/providers/anthropic_adapter.py +330 -0
  54. proxilion/providers/gemini_adapter.py +391 -0
  55. proxilion/providers/openai_adapter.py +294 -0
  56. proxilion/py.typed +0 -0
  57. proxilion/resilience/__init__.py +81 -0
  58. proxilion/resilience/degradation.py +615 -0
  59. proxilion/resilience/fallback.py +555 -0
  60. proxilion/resilience/retry.py +554 -0
  61. proxilion/scheduling/__init__.py +57 -0
  62. proxilion/scheduling/priority_queue.py +419 -0
  63. proxilion/scheduling/scheduler.py +459 -0
  64. proxilion/security/__init__.py +244 -0
  65. proxilion/security/agent_trust.py +968 -0
  66. proxilion/security/behavioral_drift.py +794 -0
  67. proxilion/security/cascade_protection.py +869 -0
  68. proxilion/security/circuit_breaker.py +428 -0
  69. proxilion/security/cost_limiter.py +690 -0
  70. proxilion/security/idor_protection.py +460 -0
  71. proxilion/security/intent_capsule.py +849 -0
  72. proxilion/security/intent_validator.py +495 -0
  73. proxilion/security/memory_integrity.py +767 -0
  74. proxilion/security/rate_limiter.py +509 -0
  75. proxilion/security/scope_enforcer.py +680 -0
  76. proxilion/security/sequence_validator.py +636 -0
  77. proxilion/security/trust_boundaries.py +784 -0
  78. proxilion/streaming/__init__.py +70 -0
  79. proxilion/streaming/detector.py +761 -0
  80. proxilion/streaming/transformer.py +674 -0
  81. proxilion/timeouts/__init__.py +55 -0
  82. proxilion/timeouts/decorators.py +477 -0
  83. proxilion/timeouts/manager.py +545 -0
  84. proxilion/tools/__init__.py +69 -0
  85. proxilion/tools/decorators.py +493 -0
  86. proxilion/tools/registry.py +732 -0
  87. proxilion/types.py +339 -0
  88. proxilion/validation/__init__.py +93 -0
  89. proxilion/validation/pydantic_schema.py +351 -0
  90. proxilion/validation/schema.py +651 -0
  91. proxilion-0.0.1.dist-info/METADATA +872 -0
  92. proxilion-0.0.1.dist-info/RECORD +94 -0
  93. proxilion-0.0.1.dist-info/WHEEL +4 -0
  94. proxilion-0.0.1.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,544 @@
1
+ """
2
+ ISO 27001 compliance exporter.
3
+
4
+ Provides audit log export formats for ISO 27001 compliance,
5
+ mapping to Annex A controls including:
6
+ - A.9: Access Control
7
+ - A.12: Operations Security
8
+ - A.16: Information Security Incident Management
9
+
10
+ Example:
11
+ >>> from proxilion.audit import InMemoryAuditLogger
12
+ >>> from proxilion.audit.compliance import ISO27001Exporter
13
+ >>> from datetime import datetime, timedelta, timezone
14
+ >>>
15
+ >>> logger = InMemoryAuditLogger()
16
+ >>> # ... log events ...
17
+ >>>
18
+ >>> exporter = ISO27001Exporter(
19
+ ... logger,
20
+ ... organization="Acme Corp",
21
+ ... system_name="Enterprise API",
22
+ ... responsible_party="ISMS Manager",
23
+ ... )
24
+ >>>
25
+ >>> end = datetime.now(timezone.utc)
26
+ >>> start = end - timedelta(days=365)
27
+ >>>
28
+ >>> # Export access control evidence (A.9)
29
+ >>> access = exporter.export_access_control_a9(start, end)
30
+ >>>
31
+ >>> # Generate full ISO 27001 report
32
+ >>> report = exporter.generate_report(start, end)
33
+ """
34
+
35
+ from __future__ import annotations
36
+
37
+ from dataclasses import dataclass, field
38
+ from datetime import datetime, timezone # noqa: F401 (timezone used in docstring)
39
+ from typing import Any
40
+
41
+ from proxilion.audit.compliance.base import (
42
+ BaseComplianceExporter,
43
+ ComplianceEvidence,
44
+ ComplianceFramework,
45
+ ComplianceReport,
46
+ )
47
+ from proxilion.audit.events import EventType
48
+
49
+
50
+ @dataclass
51
+ class AccessControlA9Evidence:
52
+ """
53
+ Evidence for A.9 - Access Control.
54
+
55
+ Covers:
56
+ - A.9.1: Business requirements of access control
57
+ - A.9.2: User access management
58
+ - A.9.4: System and application access control
59
+ """
60
+ user_access_events: list[dict[str, Any]] = field(default_factory=list)
61
+ access_denied_events: list[dict[str, Any]] = field(default_factory=list)
62
+ privileged_access_events: list[dict[str, Any]] = field(default_factory=list)
63
+ unique_users: int = 0
64
+ unique_resources: int = 0
65
+ role_distribution: dict[str, int] = field(default_factory=dict)
66
+
67
+ def to_dict(self) -> dict[str, Any]:
68
+ """Convert to dictionary."""
69
+ total = len(self.user_access_events)
70
+ denied = len(self.access_denied_events)
71
+ return {
72
+ "user_access_events": self.user_access_events,
73
+ "access_denied_events": self.access_denied_events,
74
+ "privileged_access_events": self.privileged_access_events,
75
+ "summary": {
76
+ "total_access_events": total,
77
+ "access_denied": denied,
78
+ "privileged_access": len(self.privileged_access_events),
79
+ "unique_users": self.unique_users,
80
+ "unique_resources": self.unique_resources,
81
+ "denial_rate": denied / total if total > 0 else 0.0,
82
+ "role_distribution": self.role_distribution,
83
+ },
84
+ }
85
+
86
+
87
+ @dataclass
88
+ class OperationsSecurityA12Evidence:
89
+ """
90
+ Evidence for A.12 - Operations Security.
91
+
92
+ Covers:
93
+ - A.12.1: Operational procedures and responsibilities
94
+ - A.12.4: Logging and monitoring
95
+ - A.12.6: Technical vulnerability management
96
+ """
97
+ operational_events: list[dict[str, Any]] = field(default_factory=list)
98
+ logging_events: list[dict[str, Any]] = field(default_factory=list)
99
+ vulnerability_events: list[dict[str, Any]] = field(default_factory=list)
100
+ monitoring_active: bool = True
101
+
102
+ def to_dict(self) -> dict[str, Any]:
103
+ """Convert to dictionary."""
104
+ return {
105
+ "operational_events": self.operational_events,
106
+ "logging_events": self.logging_events,
107
+ "vulnerability_events": self.vulnerability_events,
108
+ "summary": {
109
+ "total_operations": len(self.operational_events),
110
+ "logging_events": len(self.logging_events),
111
+ "vulnerabilities_detected": len(self.vulnerability_events),
112
+ "monitoring_status": "Active" if self.monitoring_active else "Inactive",
113
+ },
114
+ }
115
+
116
+
117
+ @dataclass
118
+ class IncidentManagementA16Evidence:
119
+ """
120
+ Evidence for A.16 - Information Security Incident Management.
121
+
122
+ Covers:
123
+ - A.16.1: Management of security incidents
124
+ """
125
+ security_incidents: list[dict[str, Any]] = field(default_factory=list)
126
+ incident_responses: list[dict[str, Any]] = field(default_factory=list)
127
+ incident_by_severity: dict[str, int] = field(default_factory=dict)
128
+
129
+ def to_dict(self) -> dict[str, Any]:
130
+ """Convert to dictionary."""
131
+ return {
132
+ "security_incidents": self.security_incidents,
133
+ "incident_responses": self.incident_responses,
134
+ "summary": {
135
+ "total_incidents": len(self.security_incidents),
136
+ "incidents_responded": len(self.incident_responses),
137
+ "response_rate": (
138
+ len(self.incident_responses) / len(self.security_incidents)
139
+ if self.security_incidents else 1.0
140
+ ),
141
+ "by_severity": self.incident_by_severity,
142
+ },
143
+ }
144
+
145
+
146
+ class ISO27001Exporter(BaseComplianceExporter):
147
+ """
148
+ Export audit logs for ISO 27001 evidence.
149
+
150
+ Maps to Annex A controls:
151
+ - A.9: Access control
152
+ - A.12: Operations security
153
+ - A.16: Incident management
154
+
155
+ ISO 27001 is an international standard for information security
156
+ management systems (ISMS). This exporter produces evidence
157
+ for key controls related to access, operations, and incidents.
158
+
159
+ Example:
160
+ >>> exporter = ISO27001Exporter(
161
+ ... logger,
162
+ ... organization="Acme Corp",
163
+ ... system_name="Core Platform",
164
+ ... responsible_party="isms@acme.com",
165
+ ... )
166
+ >>>
167
+ >>> # Export A.9 Access Control evidence
168
+ >>> access = exporter.export_access_control_a9(start, end)
169
+ >>>
170
+ >>> # Export A.12 Operations Security evidence
171
+ >>> ops = exporter.export_operations_security_a12(start, end)
172
+ >>>
173
+ >>> # Export A.16 Incident Management evidence
174
+ >>> incidents = exporter.export_incident_management_a16(start, end)
175
+ """
176
+
177
+ @property
178
+ def framework(self) -> ComplianceFramework:
179
+ """Get the compliance framework."""
180
+ return ComplianceFramework.ISO27001
181
+
182
+ @property
183
+ def framework_version(self) -> str:
184
+ """Get the framework version."""
185
+ return "2022" # ISO 27001:2022
186
+
187
+ def export_access_control_a9(
188
+ self,
189
+ start: datetime,
190
+ end: datetime,
191
+ ) -> AccessControlA9Evidence:
192
+ """
193
+ Export A.9 - Access Control evidence.
194
+
195
+ A.9 covers:
196
+ - A.9.1.1: Access control policy
197
+ - A.9.2.1: User registration and de-registration
198
+ - A.9.2.2: User access provisioning
199
+ - A.9.2.3: Management of privileged access rights
200
+ - A.9.4.1: Information access restriction
201
+
202
+ Args:
203
+ start: Start of the reporting period.
204
+ end: End of the reporting period.
205
+
206
+ Returns:
207
+ AccessControlA9Evidence with categorized events.
208
+ """
209
+ events = self.filter_by_date_range(start, end)
210
+ evidence = AccessControlA9Evidence()
211
+
212
+ users = set()
213
+ resources = set()
214
+ role_counts: dict[str, int] = {}
215
+
216
+ for event in events:
217
+ event_dict = self.event_to_evidence_dict(event)
218
+ users.add(event.data.user_id)
219
+ resources.add(event.data.tool_name)
220
+
221
+ # Count roles
222
+ for role in event.data.user_roles:
223
+ role_counts[role] = role_counts.get(role, 0) + 1
224
+
225
+ # All authorization events are access control evidence
226
+ if event.data.event_type in [
227
+ EventType.AUTHORIZATION_GRANTED,
228
+ EventType.AUTHORIZATION_DENIED,
229
+ EventType.AUTHORIZATION_REQUEST,
230
+ ]:
231
+ evidence.user_access_events.append({
232
+ **event_dict,
233
+ "control": "A.9.4.1",
234
+ "access_type": "granted" if event.data.authorization_allowed else "denied",
235
+ })
236
+
237
+ # Denied access events
238
+ if event.data.event_type == EventType.AUTHORIZATION_DENIED:
239
+ evidence.access_denied_events.append({
240
+ **event_dict,
241
+ "control": "A.9.4.1",
242
+ "denial_reason": event.data.authorization_reason,
243
+ })
244
+
245
+ # Privileged access (admin roles or high-risk tools)
246
+ is_admin = "admin" in event.data.user_roles
247
+ is_high_risk = event.data.authorization_metadata.get("risk_level") == "high"
248
+ if is_admin or is_high_risk:
249
+ evidence.privileged_access_events.append({
250
+ **event_dict,
251
+ "control": "A.9.2.3",
252
+ "privilege_type": "admin" if is_admin else "high_risk_tool",
253
+ })
254
+
255
+ evidence.unique_users = len(users)
256
+ evidence.unique_resources = len(resources)
257
+ evidence.role_distribution = role_counts
258
+
259
+ return evidence
260
+
261
+ def export_operations_security_a12(
262
+ self,
263
+ start: datetime,
264
+ end: datetime,
265
+ ) -> OperationsSecurityA12Evidence:
266
+ """
267
+ Export A.12 - Operations Security evidence.
268
+
269
+ A.12 covers:
270
+ - A.12.1.1: Documented operating procedures
271
+ - A.12.4.1: Event logging
272
+ - A.12.4.3: Administrator and operator logs
273
+ - A.12.6.1: Management of technical vulnerabilities
274
+
275
+ Args:
276
+ start: Start of the reporting period.
277
+ end: End of the reporting period.
278
+
279
+ Returns:
280
+ OperationsSecurityA12Evidence with categorized events.
281
+ """
282
+ events = self.filter_by_date_range(start, end)
283
+ evidence = OperationsSecurityA12Evidence()
284
+
285
+ for event in events:
286
+ event_dict = self.event_to_evidence_dict(event)
287
+
288
+ # All events demonstrate logging (A.12.4.1)
289
+ evidence.logging_events.append({
290
+ **event_dict,
291
+ "control": "A.12.4.1",
292
+ "log_type": "authorization",
293
+ })
294
+
295
+ # Operational events (successful executions)
296
+ if event.data.event_type in [
297
+ EventType.TOOL_EXECUTION_SUCCESS,
298
+ EventType.AUTHORIZATION_GRANTED,
299
+ ]:
300
+ evidence.operational_events.append({
301
+ **event_dict,
302
+ "control": "A.12.1.1",
303
+ "operation_status": "success",
304
+ })
305
+
306
+ # Vulnerability-related events
307
+ if event.data.event_type in [
308
+ EventType.IDOR_VIOLATION,
309
+ EventType.SCHEMA_VALIDATION_FAILURE,
310
+ ]:
311
+ evidence.vulnerability_events.append({
312
+ **event_dict,
313
+ "control": "A.12.6.1",
314
+ "vulnerability_type": event.data.event_type.value,
315
+ "mitigation": "Request blocked by security control",
316
+ })
317
+
318
+ return evidence
319
+
320
+ def export_incident_management_a16(
321
+ self,
322
+ start: datetime,
323
+ end: datetime,
324
+ ) -> IncidentManagementA16Evidence:
325
+ """
326
+ Export A.16 - Incident Management evidence.
327
+
328
+ A.16 covers:
329
+ - A.16.1.1: Responsibilities and procedures
330
+ - A.16.1.2: Reporting information security events
331
+ - A.16.1.4: Assessment of and decision on security events
332
+ - A.16.1.5: Response to security incidents
333
+
334
+ Args:
335
+ start: Start of the reporting period.
336
+ end: End of the reporting period.
337
+
338
+ Returns:
339
+ IncidentManagementA16Evidence with categorized events.
340
+ """
341
+ events = self.filter_by_date_range(start, end)
342
+ evidence = IncidentManagementA16Evidence()
343
+
344
+ severity_counts: dict[str, int] = {
345
+ "low": 0,
346
+ "medium": 0,
347
+ "high": 0,
348
+ "critical": 0,
349
+ }
350
+
351
+ for event in events:
352
+ event_dict = self.event_to_evidence_dict(event)
353
+
354
+ # Security incidents
355
+ if event.data.event_type in [
356
+ EventType.RATE_LIMIT_EXCEEDED,
357
+ EventType.CIRCUIT_BREAKER_OPEN,
358
+ EventType.IDOR_VIOLATION,
359
+ EventType.SCHEMA_VALIDATION_FAILURE,
360
+ ]:
361
+ # Determine severity
362
+ if event.data.event_type == EventType.IDOR_VIOLATION:
363
+ severity = "critical"
364
+ elif event.data.event_type == EventType.CIRCUIT_BREAKER_OPEN:
365
+ severity = "high"
366
+ elif event.data.event_type == EventType.SCHEMA_VALIDATION_FAILURE:
367
+ severity = "medium"
368
+ else:
369
+ severity = "low"
370
+
371
+ severity_counts[severity] += 1
372
+
373
+ incident = {
374
+ **event_dict,
375
+ "control": "A.16.1.2",
376
+ "incident_type": event.data.event_type.value,
377
+ "severity": severity,
378
+ "reported_at": event.timestamp.isoformat(),
379
+ }
380
+ evidence.security_incidents.append(incident)
381
+
382
+ # All detected incidents have automated response
383
+ evidence.incident_responses.append({
384
+ **incident,
385
+ "control": "A.16.1.5",
386
+ "response_type": "automated_block",
387
+ "response_time_ms": 0, # Immediate
388
+ "resolution": "Request blocked by security control",
389
+ })
390
+
391
+ # Authorization denials are also security events
392
+ if event.data.event_type == EventType.AUTHORIZATION_DENIED:
393
+ severity_counts["low"] += 1
394
+ evidence.security_incidents.append({
395
+ **event_dict,
396
+ "control": "A.16.1.2",
397
+ "incident_type": "access_denied",
398
+ "severity": "low",
399
+ "reported_at": event.timestamp.isoformat(),
400
+ })
401
+ evidence.incident_responses.append({
402
+ **event_dict,
403
+ "control": "A.16.1.5",
404
+ "response_type": "access_blocked",
405
+ "response_time_ms": 0,
406
+ "resolution": event.data.authorization_reason,
407
+ })
408
+
409
+ evidence.incident_by_severity = severity_counts
410
+
411
+ return evidence
412
+
413
+ def generate_report(
414
+ self,
415
+ start: datetime,
416
+ end: datetime,
417
+ ) -> ComplianceReport:
418
+ """
419
+ Generate a complete ISO 27001 compliance report.
420
+
421
+ Args:
422
+ start: Start of the reporting period.
423
+ end: End of the reporting period.
424
+
425
+ Returns:
426
+ Complete compliance report.
427
+ """
428
+ metadata = self.create_metadata(start, end)
429
+ evidence_list = []
430
+ recommendations = []
431
+
432
+ # A.9: Access Control
433
+ access = self.export_access_control_a9(start, end)
434
+ access_data = access.to_dict()
435
+
436
+ a9_evidence = ComplianceEvidence(
437
+ control_id="A.9",
438
+ control_name="Access Control",
439
+ evidence_type="access_logs",
440
+ description=(
441
+ "Evidence of access control implementation covering user access "
442
+ "management (A.9.2), system and application access control (A.9.4), "
443
+ "and management of privileged access rights (A.9.2.3)."
444
+ ),
445
+ events=access.user_access_events[:50],
446
+ summary=access_data["summary"],
447
+ compliant=len(access.user_access_events) > 0,
448
+ notes=(
449
+ f"Monitoring {access.unique_users} users across "
450
+ f"{access.unique_resources} resources. "
451
+ f"{len(access.privileged_access_events)} privileged access events tracked."
452
+ ),
453
+ )
454
+ evidence_list.append(a9_evidence)
455
+
456
+ if access_data["summary"]["denial_rate"] > 0.3:
457
+ recommendations.append(
458
+ "High access denial rate detected. Review access policies and user permissions."
459
+ )
460
+
461
+ # A.12: Operations Security
462
+ ops = self.export_operations_security_a12(start, end)
463
+ ops_data = ops.to_dict()
464
+
465
+ a12_evidence = ComplianceEvidence(
466
+ control_id="A.12",
467
+ control_name="Operations Security",
468
+ evidence_type="operational_logs",
469
+ description=(
470
+ "Evidence of operations security including event logging (A.12.4.1), "
471
+ "operational procedures (A.12.1.1), and technical vulnerability "
472
+ "management (A.12.6.1)."
473
+ ),
474
+ events=ops.logging_events[:50],
475
+ summary=ops_data["summary"],
476
+ compliant=ops.monitoring_active,
477
+ notes=(
478
+ f"Logging is active with {len(ops.logging_events)} events recorded. "
479
+ f"{len(ops.vulnerability_events)} potential vulnerabilities detected and mitigated."
480
+ ),
481
+ )
482
+ evidence_list.append(a12_evidence)
483
+
484
+ if len(ops.vulnerability_events) > 10:
485
+ recommendations.append(
486
+ "Multiple vulnerability events detected. Conduct a security review "
487
+ "and consider additional input validation controls."
488
+ )
489
+
490
+ # A.16: Incident Management
491
+ incidents = self.export_incident_management_a16(start, end)
492
+ incidents_data = incidents.to_dict()
493
+
494
+ a16_evidence = ComplianceEvidence(
495
+ control_id="A.16",
496
+ control_name="Information Security Incident Management",
497
+ evidence_type="incident_logs",
498
+ description=(
499
+ "Evidence of incident management including security event reporting "
500
+ "(A.16.1.2) and incident response (A.16.1.5)."
501
+ ),
502
+ events=incidents.security_incidents[:50],
503
+ summary=incidents_data["summary"],
504
+ compliant=incidents_data["summary"]["response_rate"] >= 0.95,
505
+ notes=(
506
+ f"{len(incidents.security_incidents)} security events detected. "
507
+ f"Response rate: {incidents_data['summary']['response_rate']:.1%}. "
508
+ f"By severity: {incidents.incident_by_severity}"
509
+ ),
510
+ )
511
+ evidence_list.append(a16_evidence)
512
+
513
+ if incidents.incident_by_severity.get("critical", 0) > 0:
514
+ recommendations.append(
515
+ f"Critical incidents detected ({incidents.incident_by_severity['critical']}). "
516
+ "Review root causes and implement preventive controls."
517
+ )
518
+
519
+ # Overall summary
520
+ all_events = self.filter_by_date_range(start, end)
521
+ stats = self.compute_summary_stats(all_events)
522
+
523
+ summary = {
524
+ "reporting_period": f"{start.date()} to {end.date()}",
525
+ "framework_version": "ISO 27001:2022",
526
+ "total_events_analyzed": stats["total_events"],
527
+ "unique_users": stats["unique_users"],
528
+ "unique_resources": stats["unique_tools"],
529
+ "controls_assessed": 3,
530
+ "controls_compliant": sum(1 for e in evidence_list if e.compliant),
531
+ "security_incidents": len(incidents.security_incidents),
532
+ "incident_response_rate": f"{incidents_data['summary']['response_rate']:.1%}",
533
+ "privileged_access_events": len(access.privileged_access_events),
534
+ "overall_status": (
535
+ "Compliant" if all(e.compliant for e in evidence_list) else "Review Required"
536
+ ),
537
+ }
538
+
539
+ return ComplianceReport(
540
+ metadata=metadata,
541
+ evidence=evidence_list,
542
+ summary=summary,
543
+ recommendations=recommendations,
544
+ )