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,457 @@
1
+ """
2
+ Base classes for compliance audit exporters.
3
+
4
+ Provides common infrastructure for exporting audit logs in
5
+ compliance-ready formats for various regulatory frameworks.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ from abc import ABC, abstractmethod
12
+ from dataclasses import dataclass, field
13
+ from datetime import datetime, timezone
14
+ from enum import Enum
15
+ from typing import Any, Protocol, runtime_checkable
16
+
17
+ from proxilion.audit.events import AuditEventV2, EventType
18
+
19
+
20
+ class ComplianceFramework(Enum):
21
+ """Supported compliance frameworks."""
22
+ EU_AI_ACT = "eu_ai_act"
23
+ SOC2 = "soc2"
24
+ ISO27001 = "iso27001"
25
+ NIST_AI_RMF = "nist_ai_rmf"
26
+ HIPAA = "hipaa"
27
+ GDPR = "gdpr"
28
+
29
+
30
+ @dataclass
31
+ class ComplianceMetadata:
32
+ """
33
+ Metadata for compliance reports.
34
+
35
+ Attributes:
36
+ framework: The compliance framework this report targets.
37
+ version: Version of the framework (e.g., "2024").
38
+ organization: Name of the organization.
39
+ system_name: Name of the AI system being audited.
40
+ responsible_party: Contact person/team.
41
+ export_timestamp: When the report was generated.
42
+ period_start: Start of the audit period.
43
+ period_end: End of the audit period.
44
+ additional_info: Any additional metadata.
45
+ """
46
+ framework: ComplianceFramework
47
+ version: str
48
+ organization: str
49
+ system_name: str
50
+ responsible_party: str
51
+ export_timestamp: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
52
+ period_start: datetime | None = None
53
+ period_end: datetime | None = None
54
+ additional_info: dict[str, Any] = field(default_factory=dict)
55
+
56
+ def to_dict(self) -> dict[str, Any]:
57
+ """Convert to dictionary."""
58
+ return {
59
+ "framework": self.framework.value,
60
+ "version": self.version,
61
+ "organization": self.organization,
62
+ "system_name": self.system_name,
63
+ "responsible_party": self.responsible_party,
64
+ "export_timestamp": self.export_timestamp.isoformat(),
65
+ "period_start": self.period_start.isoformat() if self.period_start else None,
66
+ "period_end": self.period_end.isoformat() if self.period_end else None,
67
+ "additional_info": self.additional_info,
68
+ }
69
+
70
+
71
+ @dataclass
72
+ class ComplianceEvidence:
73
+ """
74
+ A piece of evidence for compliance reporting.
75
+
76
+ Attributes:
77
+ control_id: The control/article this evidence supports.
78
+ control_name: Human-readable control name.
79
+ evidence_type: Type of evidence (e.g., "log", "configuration").
80
+ description: Description of what this evidence shows.
81
+ events: Relevant audit events.
82
+ summary: Summary statistics.
83
+ compliant: Whether this control appears compliant.
84
+ notes: Additional notes or observations.
85
+ """
86
+ control_id: str
87
+ control_name: str
88
+ evidence_type: str
89
+ description: str
90
+ events: list[dict[str, Any]] = field(default_factory=list)
91
+ summary: dict[str, Any] = field(default_factory=dict)
92
+ compliant: bool | None = None
93
+ notes: str | None = None
94
+
95
+ def to_dict(self) -> dict[str, Any]:
96
+ """Convert to dictionary."""
97
+ return {
98
+ "control_id": self.control_id,
99
+ "control_name": self.control_name,
100
+ "evidence_type": self.evidence_type,
101
+ "description": self.description,
102
+ "event_count": len(self.events),
103
+ "events": self.events,
104
+ "summary": self.summary,
105
+ "compliant": self.compliant,
106
+ "notes": self.notes,
107
+ }
108
+
109
+
110
+ @dataclass
111
+ class ComplianceReport:
112
+ """
113
+ A complete compliance report.
114
+
115
+ Attributes:
116
+ metadata: Report metadata.
117
+ evidence: List of evidence items.
118
+ summary: Overall summary.
119
+ recommendations: Suggested improvements.
120
+ """
121
+ metadata: ComplianceMetadata
122
+ evidence: list[ComplianceEvidence] = field(default_factory=list)
123
+ summary: dict[str, Any] = field(default_factory=dict)
124
+ recommendations: list[str] = field(default_factory=list)
125
+
126
+ def to_dict(self) -> dict[str, Any]:
127
+ """Convert to dictionary."""
128
+ return {
129
+ "metadata": self.metadata.to_dict(),
130
+ "evidence": [e.to_dict() for e in self.evidence],
131
+ "summary": self.summary,
132
+ "recommendations": self.recommendations,
133
+ }
134
+
135
+ def to_json(self, pretty: bool = True) -> str:
136
+ """Convert to JSON string."""
137
+ if pretty:
138
+ return json.dumps(self.to_dict(), indent=2, default=str)
139
+ return json.dumps(self.to_dict(), default=str)
140
+
141
+
142
+ @runtime_checkable
143
+ class EventSource(Protocol):
144
+ """Protocol for audit event sources."""
145
+
146
+ @property
147
+ def events(self) -> list[AuditEventV2]:
148
+ """Get all events."""
149
+ ...
150
+
151
+
152
+ class BaseComplianceExporter(ABC):
153
+ """
154
+ Base class for compliance exporters.
155
+
156
+ Provides common infrastructure for filtering events,
157
+ generating reports, and formatting output.
158
+
159
+ Subclasses should implement framework-specific export methods.
160
+ """
161
+
162
+ def __init__(
163
+ self,
164
+ event_source: EventSource | list[AuditEventV2],
165
+ organization: str = "",
166
+ system_name: str = "",
167
+ responsible_party: str = "",
168
+ ) -> None:
169
+ """
170
+ Initialize the exporter.
171
+
172
+ Args:
173
+ event_source: Source of audit events (logger or list).
174
+ organization: Organization name for reports.
175
+ system_name: AI system name for reports.
176
+ responsible_party: Responsible party for reports.
177
+ """
178
+ self._event_source = event_source
179
+ self._organization = organization
180
+ self._system_name = system_name
181
+ self._responsible_party = responsible_party
182
+
183
+ @property
184
+ @abstractmethod
185
+ def framework(self) -> ComplianceFramework:
186
+ """Get the compliance framework this exporter targets."""
187
+ ...
188
+
189
+ @property
190
+ @abstractmethod
191
+ def framework_version(self) -> str:
192
+ """Get the version of the compliance framework."""
193
+ ...
194
+
195
+ def get_events(self) -> list[AuditEventV2]:
196
+ """Get all events from the source."""
197
+ if isinstance(self._event_source, list):
198
+ return self._event_source
199
+ return self._event_source.events
200
+
201
+ def filter_events(
202
+ self,
203
+ start: datetime | None = None,
204
+ end: datetime | None = None,
205
+ event_types: list[EventType] | None = None,
206
+ user_id: str | None = None,
207
+ tool_name: str | None = None,
208
+ ) -> list[AuditEventV2]:
209
+ """
210
+ Filter events by various criteria.
211
+
212
+ Args:
213
+ start: Filter events after this timestamp.
214
+ end: Filter events before this timestamp.
215
+ event_types: Filter by event types.
216
+ user_id: Filter by user ID.
217
+ tool_name: Filter by tool name.
218
+
219
+ Returns:
220
+ Filtered list of events.
221
+ """
222
+ events = self.get_events()
223
+ filtered = []
224
+
225
+ for event in events:
226
+ # Time range filter
227
+ if start and event.timestamp < start:
228
+ continue
229
+ if end and event.timestamp > end:
230
+ continue
231
+
232
+ # Event type filter
233
+ if event_types and event.data.event_type not in event_types:
234
+ continue
235
+
236
+ # User filter
237
+ if user_id and event.data.user_id != user_id:
238
+ continue
239
+
240
+ # Tool filter
241
+ if tool_name and event.data.tool_name != tool_name:
242
+ continue
243
+
244
+ filtered.append(event)
245
+
246
+ return filtered
247
+
248
+ def filter_by_date_range(
249
+ self,
250
+ start: datetime,
251
+ end: datetime,
252
+ ) -> list[AuditEventV2]:
253
+ """Filter events by date range."""
254
+ return self.filter_events(start=start, end=end)
255
+
256
+ def get_authorization_events(
257
+ self,
258
+ start: datetime | None = None,
259
+ end: datetime | None = None,
260
+ ) -> list[AuditEventV2]:
261
+ """Get authorization-related events."""
262
+ return self.filter_events(
263
+ start=start,
264
+ end=end,
265
+ event_types=[
266
+ EventType.AUTHORIZATION_GRANTED,
267
+ EventType.AUTHORIZATION_DENIED,
268
+ EventType.AUTHORIZATION_REQUEST,
269
+ ],
270
+ )
271
+
272
+ def get_denied_events(
273
+ self,
274
+ start: datetime | None = None,
275
+ end: datetime | None = None,
276
+ ) -> list[AuditEventV2]:
277
+ """Get denied authorization events."""
278
+ return self.filter_events(
279
+ start=start,
280
+ end=end,
281
+ event_types=[EventType.AUTHORIZATION_DENIED],
282
+ )
283
+
284
+ def get_security_events(
285
+ self,
286
+ start: datetime | None = None,
287
+ end: datetime | None = None,
288
+ ) -> list[AuditEventV2]:
289
+ """Get security-related events."""
290
+ return self.filter_events(
291
+ start=start,
292
+ end=end,
293
+ event_types=[
294
+ EventType.RATE_LIMIT_EXCEEDED,
295
+ EventType.CIRCUIT_BREAKER_OPEN,
296
+ EventType.IDOR_VIOLATION,
297
+ EventType.SCHEMA_VALIDATION_FAILURE,
298
+ ],
299
+ )
300
+
301
+ def event_to_evidence_dict(self, event: AuditEventV2) -> dict[str, Any]:
302
+ """Convert an event to an evidence dictionary."""
303
+ return {
304
+ "event_id": event.event_id,
305
+ "timestamp": event.timestamp.isoformat(),
306
+ "event_type": event.data.event_type.value,
307
+ "user_id": event.data.user_id,
308
+ "user_roles": event.data.user_roles,
309
+ "tool_name": event.data.tool_name,
310
+ "authorized": event.data.authorization_allowed,
311
+ "reason": event.data.authorization_reason,
312
+ "policies": event.data.policies_evaluated,
313
+ }
314
+
315
+ def create_metadata(
316
+ self,
317
+ period_start: datetime | None = None,
318
+ period_end: datetime | None = None,
319
+ ) -> ComplianceMetadata:
320
+ """Create metadata for a report."""
321
+ return ComplianceMetadata(
322
+ framework=self.framework,
323
+ version=self.framework_version,
324
+ organization=self._organization,
325
+ system_name=self._system_name,
326
+ responsible_party=self._responsible_party,
327
+ period_start=period_start,
328
+ period_end=period_end,
329
+ )
330
+
331
+ def compute_summary_stats(
332
+ self,
333
+ events: list[AuditEventV2],
334
+ ) -> dict[str, Any]:
335
+ """Compute summary statistics for a list of events."""
336
+ if not events:
337
+ return {
338
+ "total_events": 0,
339
+ "unique_users": 0,
340
+ "unique_tools": 0,
341
+ "authorization_granted": 0,
342
+ "authorization_denied": 0,
343
+ "grant_rate": 0.0,
344
+ }
345
+
346
+ granted = sum(1 for e in events if e.data.authorization_allowed)
347
+ denied = sum(1 for e in events if not e.data.authorization_allowed)
348
+ users = {e.data.user_id for e in events}
349
+ tools = {e.data.tool_name for e in events}
350
+
351
+ return {
352
+ "total_events": len(events),
353
+ "unique_users": len(users),
354
+ "unique_tools": len(tools),
355
+ "authorization_granted": granted,
356
+ "authorization_denied": denied,
357
+ "grant_rate": granted / len(events) if events else 0.0,
358
+ "period_start": min(e.timestamp for e in events).isoformat(),
359
+ "period_end": max(e.timestamp for e in events).isoformat(),
360
+ }
361
+
362
+ @abstractmethod
363
+ def generate_report(
364
+ self,
365
+ start: datetime,
366
+ end: datetime,
367
+ ) -> ComplianceReport:
368
+ """
369
+ Generate a compliance report for the given period.
370
+
371
+ Args:
372
+ start: Start of the reporting period.
373
+ end: End of the reporting period.
374
+
375
+ Returns:
376
+ Complete compliance report.
377
+ """
378
+ ...
379
+
380
+ def export_json(
381
+ self,
382
+ start: datetime,
383
+ end: datetime,
384
+ pretty: bool = True,
385
+ ) -> str:
386
+ """Export report as JSON."""
387
+ report = self.generate_report(start, end)
388
+ return report.to_json(pretty=pretty)
389
+
390
+ def export_markdown(
391
+ self,
392
+ start: datetime,
393
+ end: datetime,
394
+ ) -> str:
395
+ """Export report as Markdown."""
396
+ report = self.generate_report(start, end)
397
+ return self._report_to_markdown(report)
398
+
399
+ def _report_to_markdown(self, report: ComplianceReport) -> str:
400
+ """Convert a report to Markdown format."""
401
+ lines = [
402
+ f"# {report.metadata.framework.value.upper()} Compliance Report",
403
+ "",
404
+ "## Metadata",
405
+ "",
406
+ f"- **Organization:** {report.metadata.organization}",
407
+ f"- **System:** {report.metadata.system_name}",
408
+ f"- **Responsible Party:** {report.metadata.responsible_party}",
409
+ f"- **Report Generated:** {report.metadata.export_timestamp.isoformat()}",
410
+ f"- **Period:** "
411
+ f"{report.metadata.period_start.isoformat() if report.metadata.period_start else 'N/A'}"
412
+ f" to "
413
+ f"{report.metadata.period_end.isoformat() if report.metadata.period_end else 'N/A'}",
414
+ "",
415
+ "## Summary",
416
+ "",
417
+ ]
418
+
419
+ for key, value in report.summary.items():
420
+ lines.append(f"- **{key.replace('_', ' ').title()}:** {value}")
421
+
422
+ lines.extend(["", "## Evidence", ""])
423
+
424
+ for evidence in report.evidence:
425
+ lines.extend([
426
+ f"### {evidence.control_id}: {evidence.control_name}",
427
+ "",
428
+ f"**Type:** {evidence.evidence_type}",
429
+ "",
430
+ evidence.description,
431
+ "",
432
+ f"**Events:** {len(evidence.events)}",
433
+ "",
434
+ ])
435
+
436
+ if evidence.summary:
437
+ lines.append("**Summary:**")
438
+ for key, value in evidence.summary.items():
439
+ lines.append(f"- {key}: {value}")
440
+ lines.append("")
441
+
442
+ if evidence.compliant is not None:
443
+ status = "Compliant" if evidence.compliant else "Non-Compliant"
444
+ lines.append(f"**Status:** {status}")
445
+ lines.append("")
446
+
447
+ if evidence.notes:
448
+ lines.append(f"**Notes:** {evidence.notes}")
449
+ lines.append("")
450
+
451
+ if report.recommendations:
452
+ lines.extend(["## Recommendations", ""])
453
+ for i, rec in enumerate(report.recommendations, 1):
454
+ lines.append(f"{i}. {rec}")
455
+ lines.append("")
456
+
457
+ return "\n".join(lines)