Publish curated ITWorx-ModelForge source from 990401737f96c8d46a9f7b0d84994516cadcb6a0
This commit is contained in:
1 parent
7082ab955a
commit
848f0d8f8a
434 files changed
+67298
-4315
No files matched your search
@@ -0,0 +1,69 @@
|
||||
"""Typed, bounded query and response models for the operator audit timeline."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import timedelta
|
||||
from uuid import UUID
|
||||
|
||||
from pydantic import AwareDatetime, BaseModel, ConfigDict, Field, model_validator
|
||||
|
||||
AUDIT_TIMELINE_MAX_PAGE_SIZE = 100
|
||||
AUDIT_TIMELINE_MAX_TIME_RANGE = timedelta(days=366)
|
||||
|
||||
|
||||
class AuditTimelineRequest(BaseModel):
|
||||
"""Validated filters for one bounded page of audit events.
|
||||
|
||||
Text filters are case-insensitive substring matches. A time filter must specify both ends,
|
||||
and its window is limited to one year plus one leap day.
|
||||
"""
|
||||
|
||||
model_config = ConfigDict(extra="forbid", str_strip_whitespace=True)
|
||||
|
||||
principal: str | None = Field(default=None, min_length=1, max_length=255)
|
||||
action: str | None = Field(default=None, min_length=1, max_length=128)
|
||||
resource: str | None = Field(default=None, min_length=1, max_length=128)
|
||||
outcome: str | None = Field(default=None, min_length=1, max_length=32)
|
||||
occurred_after: AwareDatetime | None = None
|
||||
occurred_before: AwareDatetime | None = None
|
||||
correlation_id: str | None = Field(default=None, min_length=1, max_length=64)
|
||||
limit: int = Field(default=50, ge=1, le=AUDIT_TIMELINE_MAX_PAGE_SIZE)
|
||||
cursor: str | None = Field(default=None, min_length=1, max_length=256)
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_time_window(self) -> AuditTimelineRequest:
|
||||
if (self.occurred_after is None) != (self.occurred_before is None):
|
||||
raise ValueError("occurred_after and occurred_before must be supplied together")
|
||||
if self.occurred_after is not None and self.occurred_before is not None:
|
||||
if self.occurred_after >= self.occurred_before:
|
||||
raise ValueError("occurred_after must be earlier than occurred_before")
|
||||
if self.occurred_before - self.occurred_after > AUDIT_TIMELINE_MAX_TIME_RANGE:
|
||||
raise ValueError("audit time range exceeds the 366-day maximum")
|
||||
return self
|
||||
|
||||
|
||||
class AuditTimelineEvent(BaseModel):
|
||||
"""Safe event fields returned to the operator console."""
|
||||
|
||||
model_config = ConfigDict(frozen=True)
|
||||
|
||||
id: UUID
|
||||
sequence: int = Field(ge=1)
|
||||
occurred_at: AwareDatetime
|
||||
correlation_id: str
|
||||
actor_type: str
|
||||
actor_id: str
|
||||
action: str
|
||||
resource_type: str
|
||||
resource_id: str | None
|
||||
outcome: str
|
||||
|
||||
|
||||
class AuditTimelineResponse(BaseModel):
|
||||
"""One page of audit events and an opaque keyset cursor for the next page."""
|
||||
|
||||
model_config = ConfigDict(frozen=True)
|
||||
|
||||
events: list[AuditTimelineEvent]
|
||||
next_cursor: str | None
|
||||
limit: int = Field(ge=1, le=AUDIT_TIMELINE_MAX_PAGE_SIZE)
|
||||
Reference in new issue
Block a user