first
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
"""AuditEvent — append-only security & business audit trail.
|
||||
|
||||
Audit events are never mutated or deleted. They record WHO did WHAT to
|
||||
WHICH entity WHEN and from WHERE.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Optional, Dict
|
||||
from pydantic import Field
|
||||
|
||||
from asf_domain.base import (
|
||||
ASFBaseModel,
|
||||
TenantScopedModel,
|
||||
ASFFieldID,
|
||||
UTCDatetime,
|
||||
AuditAction,
|
||||
generate_id,
|
||||
)
|
||||
|
||||
|
||||
class AuditEventBase(ASFBaseModel):
|
||||
action: AuditAction = Field(..., description="What happened.")
|
||||
resource_type: str = Field(
|
||||
...,
|
||||
max_length=80,
|
||||
description="Affected entity kind (organization, project, artifact, job, api_key, …).",
|
||||
)
|
||||
resource_id: Optional[ASFFieldID] = Field(None, description="Affected entity id if applicable.")
|
||||
actor_id: Optional[ASFFieldID] = Field(
|
||||
None, description="User id that caused the event, or null for system actions."
|
||||
)
|
||||
actor_type: str = Field(
|
||||
"user",
|
||||
max_length=40,
|
||||
description="user | system | api_key | service — kind of actor that caused the event.",
|
||||
)
|
||||
success: bool = True
|
||||
reason: Optional[str] = Field(
|
||||
None, max_length=500, description="For failed events, why the action was rejected."
|
||||
)
|
||||
|
||||
|
||||
class AuditEventCreate(AuditEventBase):
|
||||
project_id: Optional[ASFFieldID] = None
|
||||
ip_address: Optional[str] = Field(None, max_length=64)
|
||||
user_agent: Optional[str] = Field(None, max_length=512)
|
||||
correlation_id: Optional[str] = Field(None, max_length=128)
|
||||
metadata: Dict[str, Any] = Field(
|
||||
default_factory=dict,
|
||||
description="Structured detail of the change. NEVER log secrets here.",
|
||||
)
|
||||
|
||||
|
||||
class AuditEvent(TenantScopedModel, AuditEventBase):
|
||||
id: ASFFieldID = Field(default_factory=generate_id)
|
||||
project_id: Optional[ASFFieldID] = None
|
||||
ip_address: Optional[str] = None
|
||||
user_agent: Optional[str] = None
|
||||
correlation_id: Optional[str] = None
|
||||
metadata: Dict[str, Any] = Field(default_factory=dict)
|
||||
created_at: UTCDatetime = ...
|
||||
Reference in New Issue
Block a user