Skip to main content
Version: Next

Audit and Record System

This document describes the audit logging system for compliance and security.

Overview

The audit system provides:

  • Complete operation history
  • Compliance reporting
  • Security monitoring
  • Forensic analysis

Architecture

Audit Entry Structure

pub struct AuditEntry {
pub id: AuditEntryId,
pub timestamp: DateTime<Utc>,
pub subject: SubjectId,
pub subject_type: SubjectType,
pub action: String,
pub object: String,
pub object_id: Option<String>,
pub outcome: AuditOutcome,
pub ip_address: Option<IpAddr>,
pub user_agent: Option<String>,
pub correlation_id: Option<Uuid>,
pub metadata: serde_json::Value,
}

pub enum SubjectType {
User,
System,
ApiClient,
}

pub enum AuditOutcome {
Success,
Failure,
Denied,
}

Audit Categories

CategoryDescriptionExamples
AuthenticationLogin/logout eventsUser login, session expiry
AuthorizationPermission decisionsAccess denied, role check
Data AccessRead operationsView customer, export report
Data ModificationWrite operationsCreate facility, update terms
System EventsBackground processesJob execution, sync completed

Integration Points

GraphQL Middleware

pub struct AuditMiddleware {
audit_service: Arc<AuditService>,
}

impl Extension for AuditMiddleware {
async fn execute(&self, ctx: &ExtensionContext<'_>, operation_name: Option<&str>, next: NextExecute<'_>) -> Response {
let start = Instant::now();
let subject = ctx.data::<SubjectId>().cloned();

let response = next.run(ctx, operation_name).await;

// Log the operation
if let Some(subject) = subject {
self.audit_service.log(AuditEntry {
subject,
action: operation_name.unwrap_or("unknown").to_string(),
outcome: if response.is_ok() { AuditOutcome::Success } else { AuditOutcome::Failure },
..Default::default()
}).await.ok();
}

response
}
}

Domain Service Auditing

impl CreditService {
pub async fn create_facility(
&self,
subject: &SubjectId,
input: CreateFacilityInput,
) -> Result<CreditFacility> {
let facility = self.do_create_facility(input).await?;

// Audit the operation
self.audit.log(AuditEntry {
subject: subject.clone(),
action: "create_facility".to_string(),
object: "credit_facility".to_string(),
object_id: Some(facility.id.to_string()),
outcome: AuditOutcome::Success,
metadata: json!({
"amount": facility.amount,
"customer_id": facility.customer_id,
}),
..Default::default()
}).await?;

Ok(facility)
}
}

Query API

GraphQL Query

query GetAuditLogs($filter: AuditFilter!, $first: Int, $after: String) {
auditEntries(filter: $filter, first: $first, after: $after) {
edges {
node {
id
timestamp
subject
action
object
objectId
outcome
metadata
}
}
pageInfo {
hasNextPage
endCursor
}
}
}

Filter Options

input AuditFilter {
subjectId: ID
action: String
object: String
outcome: AuditOutcome
startDate: DateTime
endDate: DateTime
}

Retention Policy

Data TypeRetention Period
Authentication logs2 years
Authorization logs2 years
Transaction logs7 years
System logs1 year

Compliance Reports

User Activity Report

query UserActivityReport($userId: ID!, $period: DateRange!) {
userActivityReport(userId: $userId, period: $period) {
totalActions
actionsByType {
action
count
}
timeline {
date
actions
}
}
}

Access Report

query AccessReport($objectType: String!, $period: DateRange!) {
accessReport(objectType: $objectType, period: $period) {
totalAccesses
uniqueUsers
byAction {
action
count
}
}
}

Security Monitoring

Anomaly Detection

Monitor for unusual patterns:

  • Multiple failed login attempts
  • Access outside normal hours
  • Bulk data exports
  • Privilege escalation attempts

Alerts

pub struct AuditAlertService {
audit_repo: AuditRepo,
notification_service: NotificationService,
}

impl AuditAlertService {
pub async fn check_for_anomalies(&self) -> Result<()> {
// Check for suspicious patterns
let failed_logins = self.audit_repo
.count_failed_logins_last_hour()
.await?;

if failed_logins > 10 {
self.notification_service
.send_security_alert("High number of failed logins detected")
.await?;
}

Ok(())
}
}