useAudit

Comprehensive audit logging for compliance, security monitoring, and forensic analysis.

Compliance Support: SOC 2, ISO 27001, HIPAA, PCI DSS audit requirements

Import

import { useAudit } from '@heliorim/sdk-react';

Type Signature

interface AuditState {
  logs: AuditLog[];
  filters: AuditFilters;
  isLoading: boolean;
  error: Error | null;
  retention: RetentionPolicy;
}

interface AuditActions {
  log: (event: AuditEvent) => Promise<void>;
  query: (filters: AuditFilters) => Promise<AuditLog[]>;
  export: (format: ExportFormat, filters?: AuditFilters) => Promise<Blob>;
  getRetention: () => Promise<RetentionPolicy>;
  setRetention: (policy: RetentionPolicy) => Promise<void>;
  archive: (before: Date) => Promise<void>;
  search: (query: string) => Promise<AuditLog[]>;
  getCompliance: (standard: ComplianceStandard) => Promise<ComplianceReport>;
}

interface AuditLog {
  id: string;
  timestamp: number;
  eventType: EventType;
  actor: Actor;
  action: string;
  resource: Resource;
  result: 'success' | 'failure' | 'error';
  metadata: Record<string, any>;
  ip: string;
  userAgent?: string;
  location?: GeoLocation;
  riskScore?: number;
}

interface AuditEvent {
  type: EventType;
  action: string;
  resource?: Resource;
  metadata?: Record<string, any>;
  severity?: 'low' | 'medium' | 'high' | 'critical';
}

interface Actor {
  id: string;
  type: 'user' | 'system' | 'api' | 'admin';
  email?: string;
  name?: string;
  roles?: string[];
}

interface Resource {
  type: string;
  id: string;
  name?: string;
  owner?: string;
}

interface AuditFilters {
  startDate?: Date;
  endDate?: Date;
  eventTypes?: EventType[];
  actors?: string[];
  resources?: string[];
  results?: ('success' | 'failure' | 'error')[];
  severity?: ('low' | 'medium' | 'high' | 'critical')[];
}

type EventType =
  | 'authentication'
  | 'authorization'
  | 'data_access'
  | 'data_modification'
  | 'configuration_change'
  | 'user_management'
  | 'security_event'
  | 'system_event';

type UseAuditReturn = AuditState & AuditActions;

Basic Usage

function AuditMonitoring() {
  const {
    logs,
    log,
    query,
    search,
    export: exportLogs
  } = useAudit();

  const { user } = useAuth();

  // Log authentication events
  useEffect(() => {
    if (user) {
      log({
        type: 'authentication',
        action: 'login_success',
        resource: {
          type: 'session',
          id: user.sessionId,
          owner: user.id
        },
        metadata: {
          method: 'passkey',
          deviceTrust: 85
        }
      });
    }
  }, [user]);

  // Log sensitive data access
  const accessSensitiveData = async (dataId: string) => {
    await log({
      type: 'data_access',
      action: 'view_sensitive_data',
      resource: {
        type: 'document',
        id: dataId,
        name: 'Financial Report Q4'
      },
      severity: 'high',
      metadata: {
        classification: 'confidential',
        reason: 'audit_review'
      }
    });

    // Perform the actual data access
    const data = await fetchSensitiveData(dataId);
    return data;
  };

  // Query recent security events
  const getSecurityEvents = async () => {
    const events = await query({
      eventTypes: ['security_event', 'authentication'],
      results: ['failure', 'error'],
      startDate: new Date(Date.now() - 24 * 60 * 60 * 1000), // Last 24 hours
      severity: ['high', 'critical']
    });

    return events;
  };

  // Export for compliance
  const generateComplianceReport = async () => {
    const blob = await exportLogs('csv', {
      startDate: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000), // Last 30 days
      eventTypes: ['authentication', 'authorization', 'data_access']
    });

    // Download the report
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `audit-report-${Date.now()}.csv`;
    a.click();
  };

  return (
    <div className="audit-monitoring">
      <h3>Audit Log Viewer</h3>

      <div className="filters">
        <button onClick={getSecurityEvents}>
          Show Security Events
        </button>
        <button onClick={generateComplianceReport}>
          Export Compliance Report
        </button>
      </div>

      <div className="audit-logs">
        <table>
          <thead>
            <tr>
              <th>Timestamp</th>
              <th>Event</th>
              <th>Actor</th>
              <th>Action</th>
              <th>Resource</th>
              <th>Result</th>
            </tr>
          </thead>
          <tbody>
            {logs.map(log => (
              <tr key={log.id} className={log.result === 'failure' ? 'error' : ''}>
                <td>{new Date(log.timestamp).toLocaleString()}</td>
                <td>{log.eventType}</td>
                <td>{log.actor.email ?? log.actor.id}</td>
                <td>{log.action}</td>
                <td>{log.resource?.name ?? log.resource?.id}</td>
                <td>{log.result}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

Event Logging Patterns

Authentication & Authorization

function AuthenticationAudit() {
  const { log } = useAudit();
  const { authenticate } = usePasskey();

  const auditedAuthentication = async () => {
    const startTime = Date.now();

    try {
      await authenticate();

      // Log successful authentication
      await log({
        type: 'authentication',
        action: 'passkey_authentication',
        metadata: {
          duration: Date.now() - startTime,
          userVerification: true,
          authenticatorType: 'platform'
        }
      });

    } catch (error: any) {
      // Log failed authentication
      await log({
        type: 'authentication',
        action: 'passkey_authentication_failed',
        severity: 'high',
        metadata: {
          duration: Date.now() - startTime,
          errorCode: error.name,
          errorMessage: error.message,
          attemptNumber: getAttemptCount()
        }
      });

      // Check for suspicious patterns
      if (getAttemptCount() > 3) {
        await log({
          type: 'security_event',
          action: 'multiple_failed_attempts',
          severity: 'critical',
          metadata: {
            attempts: getAttemptCount(),
            blockApplied: true
          }
        });
      }

      throw error;
    }
  };

  const auditedAuthorization = async (resource: string, action: string) => {
    const hasPermission = await checkPermission(resource, action);

    await log({
      type: 'authorization',
      action: hasPermission ? 'access_granted' : 'access_denied',
      resource: {
        type: 'api_endpoint',
        id: resource,
        name: action
      },
      metadata: {
        requiredPermission: action,
        userPermissions: getUserPermissions(),
        result: hasPermission
      }
    });

    if (!hasPermission) {
      throw new Error('Access denied');
    }
  };

  return { auditedAuthentication, auditedAuthorization };
}

Data Operations

function DataOperationAudit() {
  const { log } = useAudit();

  const auditedDataRead = async (dataId: string, classification: string) => {
    const data = await fetchData(dataId);

    await log({
      type: 'data_access',
      action: 'read',
      resource: {
        type: 'data_object',
        id: dataId,
        name: data.name
      },
      metadata: {
        classification,
        size: JSON.stringify(data).length,
        fields: Object.keys(data)
      },
      severity: classification === 'sensitive' ? 'high' : 'low'
    });

    return data;
  };

  const auditedDataModification = async (
    dataId: string,
    oldData: any,
    newData: any
  ) => {
    const changes = computeChanges(oldData, newData);

    await log({
      type: 'data_modification',
      action: 'update',
      resource: {
        type: 'data_object',
        id: dataId
      },
      metadata: {
        changeCount: changes.length,
        changes: changes.map(c => ({
          field: c.field,
          oldValue: maskSensitive(c.oldValue),
          newValue: maskSensitive(c.newValue)
        })),
        backup: createBackupReference(oldData)
      },
      severity: 'medium'
    });

    return await updateData(dataId, newData);
  };

  const auditedDataDeletion = async (dataId: string, reason: string) => {
    const data = await fetchData(dataId);

    // Create backup before deletion
    const backupId = await createBackup(data);

    await log({
      type: 'data_modification',
      action: 'delete',
      resource: {
        type: 'data_object',
        id: dataId,
        name: data.name
      },
      metadata: {
        reason,
        backupId,
        permanentDeletion: false,
        scheduledPurge: Date.now() + 30 * 24 * 60 * 60 * 1000 // 30 days
      },
      severity: 'high'
    });

    return await softDelete(dataId);
  };

  return { auditedDataRead, auditedDataModification, auditedDataDeletion };
}

Configuration Changes

function ConfigurationAudit() {
  const { log } = useAudit();

  const auditConfigChange = async (
    configType: string,
    oldConfig: any,
    newConfig: any,
    approvedBy?: string
  ) => {
    const changes = diff(oldConfig, newConfig);

    await log({
      type: 'configuration_change',
      action: 'update_configuration',
      resource: {
        type: 'configuration',
        id: configType,
        name: `${configType} Settings`
      },
      metadata: {
        changes,
        previousValues: oldConfig,
        newValues: newConfig,
        approvedBy,
        rollbackAvailable: true,
        validationPassed: await validateConfig(newConfig)
      },
      severity: isSecurityConfig(configType) ? 'high' : 'medium'
    });
  };

  const auditPermissionChange = async (
    userId: string,
    oldRoles: string[],
    newRoles: string[],
    reason: string
  ) => {
    const added = newRoles.filter(r => !oldRoles.includes(r));
    const removed = oldRoles.filter(r => !newRoles.includes(r));

    await log({
      type: 'user_management',
      action: 'permission_change',
      resource: {
        type: 'user',
        id: userId
      },
      metadata: {
        rolesAdded: added,
        rolesRemoved: removed,
        reason,
        approvalRequired: added.includes('admin'),
        effectiveDate: Date.now()
      },
      severity: added.includes('admin') ? 'critical' : 'medium'
    });
  };

  return { auditConfigChange, auditPermissionChange };
}

Compliance Reporting

Compliance Standards

function ComplianceReporting() {
  const { getCompliance, export: exportAudit } = useAudit();

  const generateSOC2Report = async () => {
    const report = await getCompliance('SOC2');

    return {
      period: report.period,
      controls: {
        security: report.controls.filter(c => c.category === 'security'),
        availability: report.controls.filter(c => c.category === 'availability'),
        integrity: report.controls.filter(c => c.category === 'integrity'),
        confidentiality: report.controls.filter(c => c.category === 'confidentiality'),
        privacy: report.controls.filter(c => c.category === 'privacy')
      },
      evidence: report.evidence,
      exceptions: report.exceptions,
      recommendations: report.recommendations
    };
  };

  const generateHIPAAReport = async () => {
    const report = await getCompliance('HIPAA');

    // Check for PHI access
    const phiAccess = await query({
      eventTypes: ['data_access'],
      metadata: { dataType: 'PHI' }
    });

    return {
      administrativeSafeguards: report.administrativeSafeguards,
      physicalSafeguards: report.physicalSafeguards,
      technicalSafeguards: report.technicalSafeguards,
      phiAccessLog: phiAccess,
      breachAssessment: report.breachAssessment,
      trainingCompliance: report.trainingRecords
    };
  };

  const generateGDPRReport = async () => {
    const report = await getCompliance('GDPR');

    return {
      dataProcessingActivities: report.processingActivities,
      consentRecords: report.consentManagement,
      dataSubjectRequests: report.subjectRequests,
      dataBreaches: report.breaches,
      privacyImpactAssessments: report.PIAs,
      crossBorderTransfers: report.transfers
    };
  };

  return (
    <div className="compliance-reporting">
      <h3>Compliance Reports</h3>

      <button onClick={generateSOC2Report}>
        Generate SOC 2 Report
      </button>
      <button onClick={generateHIPAAReport}>
        Generate HIPAA Report
      </button>
      <button onClick={generateGDPRReport}>
        Generate GDPR Report
      </button>
    </div>
  );
}

Advanced Features

Real-time Monitoring

function RealTimeMonitoring() {
  const { logs, log } = useAudit();
  const [alerts, setAlerts] = useState<Alert[]>([]);

  // Monitor for suspicious patterns
  useEffect(() => {
    const checkPatterns = () => {
      // Multiple failed attempts from same IP
      const recentFailures = logs.filter(l =>
        l.result === 'failure' &&
        l.timestamp > Date.now() - 5 * 60 * 1000 // Last 5 minutes
      );

      const ipCounts = recentFailures.reduce((acc, log) => {
        acc[log.ip] = (acc[log.ip] ?? 0) + 1;
        return acc;
      }, {} as Record<string, number>);

      Object.entries(ipCounts).forEach(([ip, count]) => {
        if (count > 5) {
          const alert: Alert = {
            type: 'brute_force',
            severity: 'critical',
            message: `Multiple failed attempts from IP: ${ip}`,
            timestamp: Date.now()
          };
          setAlerts(prev => [...prev, alert]);

          // Log security event
          log({
            type: 'security_event',
            action: 'brute_force_detected',
            severity: 'critical',
            metadata: { ip, attempts: count }
          });
        }
      });

      // Unusual access patterns
      const unusualHours = logs.filter(l => {
        const hour = new Date(l.timestamp).getHours();
        return (hour < 6 ?? hour > 22) && l.eventType === 'data_access';
      });

      if (unusualHours.length > 0) {
        setAlerts(prev => [...prev, {
          type: 'unusual_activity',
          severity: 'medium',
          message: 'Data access during unusual hours detected',
          timestamp: Date.now()
        }]);
      }
    };

    const interval = setInterval(checkPatterns, 30000); // Check every 30 seconds
    return () => clearInterval(interval);
  }, [logs]);

  return (
    <div className="real-time-monitoring">
      <h3>Security Alerts</h3>
      {alerts.map((alert, i) => (
        <div key={i} className={`alert ${alert.severity}`}>
          <span>{new Date(alert.timestamp).toLocaleString()}</span>
          <span>{alert.message}</span>
        </div>
      ))}
    </div>
  );
}

Retention Management

function RetentionManagement() {
  const { getRetention, setRetention, archive } = useAudit();
  const [policy, setPolicy] = useState<RetentionPolicy | null>(null);

  useEffect(() => {
    getRetention().then(setPolicy);
  }, []);

  const updateRetentionPolicy = async (newPolicy: Partial<RetentionPolicy>) => {
    await setRetention({
      ...policy!,
      ...newPolicy
    });
    setPolicy(await getRetention());
  };

  const archiveOldLogs = async () => {
    const cutoffDate = new Date();
    cutoffDate.setMonth(cutoffDate.getMonth() - policy!.archiveAfterMonths);

    await archive(cutoffDate);
    console.log(`Archived logs older than ${cutoffDate.toLocaleDateString()}`);
  };

  return (
    <div className="retention-management">
      <h3>Retention Policy</h3>

      {policy && (
        <div>
          <label>
            Retain logs for (days):
            <input
              type="number"
              value={policy.retentionDays}
              onChange={(e) => updateRetentionPolicy({
                retentionDays: parseInt(e.target.value)
              })}
            />
          </label>

          <label>
            Archive after (months):
            <input
              type="number"
              value={policy.archiveAfterMonths}
              onChange={(e) => updateRetentionPolicy({
                archiveAfterMonths: parseInt(e.target.value)
              })}
            />
          </label>

          <label>
            <input
              type="checkbox"
              checked={policy.compressArchives}
              onChange={(e) => updateRetentionPolicy({
                compressArchives: e.target.checked
              })}
            />
            Compress archived logs
          </label>

          <button onClick={archiveOldLogs}>
            Archive Old Logs Now
          </button>
        </div>
      )}
    </div>
  );
}

Security Considerations

Audit Log Protection:

  • Audit logs are immutable once written
  • Cryptographic signatures ensure integrity
  • Logs are encrypted at rest
  • Access requires special audit permissions
  • Deletion requires multiple approvals

Best Practices

✓ Recommended

  • Log all authentication attempts
  • Include sufficient context in metadata
  • Implement real-time alerting
  • Regular compliance report generation
  • Automated log archival
  • Separate audit log storage
  • Regular audit log reviews

⚠️ Avoid

  • Logging sensitive data in plaintext
  • Deleting audit logs prematurely
  • Ignoring failed authentication patterns
  • Manual log management
  • Insufficient log detail

Related Hooks