use crate::internal::domain::{
AccountIdHash, AuditEventId, ErrorCode, LocalUserId, RequestId, SessionId,
};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::BTreeMap;
use time::OffsetDateTime;
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AuditEventType {
ToolCalled,
ToolDeniedScope,
ToolCompleted,
ToolFailed,
ToolRefused,
BackendSessionChanged,
BackendSessionChecked,
OrderIntentReceived,
OrderRiskChecked,
OrderPreviewCreated,
OrderPreviewRefused,
PaperApprovalRecorded,
PaperOrderSubmitted,
PaperOrderCancelled,
PaperOrderLifecycleChanged,
LiveOrderLifecycleChanged,
RemoteAuthSucceeded,
RemoteAuthDenied,
SidecarRelayForwarded,
SidecarRelayFailed,
}
impl AuditEventType {
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Self::ToolCalled => "tool_called",
Self::ToolDeniedScope => "tool_denied_scope",
Self::ToolCompleted => "tool_completed",
Self::ToolFailed => "tool_failed",
Self::ToolRefused => "tool_refused",
Self::BackendSessionChanged => "backend_session_changed",
Self::BackendSessionChecked => "backend_session_checked",
Self::OrderIntentReceived => "order_intent_received",
Self::OrderRiskChecked => "order_risk_checked",
Self::OrderPreviewCreated => "order_preview_created",
Self::OrderPreviewRefused => "order_preview_refused",
Self::PaperApprovalRecorded => "paper_approval_recorded",
Self::PaperOrderSubmitted => "paper_order_submitted",
Self::PaperOrderCancelled => "paper_order_cancelled",
Self::PaperOrderLifecycleChanged => "paper_order_lifecycle_changed",
Self::LiveOrderLifecycleChanged => "live_order_lifecycle_changed",
Self::RemoteAuthSucceeded => "remote_auth_succeeded",
Self::RemoteAuthDenied => "remote_auth_denied",
Self::SidecarRelayForwarded => "sidecar_relay_forwarded",
Self::SidecarRelayFailed => "sidecar_relay_failed",
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AuditDecision {
Allow,
Deny,
Refuse,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AuditResultStatus {
Called,
Completed,
Failed,
Refused,
DeniedScope,
Authenticated,
DeniedAuth,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct RedactionRecord {
pub field_path: String,
pub reason: String,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct AuditEvent {
pub event_id: AuditEventId,
pub event_type: AuditEventType,
#[serde(with = "time::serde::rfc3339")]
pub timestamp: OffsetDateTime,
pub user_id: LocalUserId,
pub session_id: SessionId,
pub request_id: RequestId,
pub account_id_hash: Option<AccountIdHash>,
pub tool_name: Option<String>,
pub scopes: Vec<String>,
pub decision: AuditDecision,
pub result_status: AuditResultStatus,
pub error_code: Option<ErrorCode>,
pub input_hash: Option<String>,
pub output_hash: Option<String>,
pub redactions: Vec<RedactionRecord>,
pub metadata: BTreeMap<String, Value>,
}