Skip to main content

Overview

Audit logs provide a complete, immutable record of all system activities in NeoSC. Every user action, security event, and resource change is tracked with timestamps, IP addresses, and detailed context for compliance and security monitoring.

Audit Log Model

Each audit log entry captures comprehensive event information:
backend/server.py:93
class AuditLog(BaseModel):
    id: str                    # Unique log entry identifier
    user_id: str              # User who performed the action
    user_email: str           # User email address
    action: str               # Action type (login, launch_workspace, etc.)
    resource: str             # Resource affected (workspace:ws-123, policy:pol-456)
    details: str              # Human-readable action description
    ip_address: str           # Source IP address
    timestamp: datetime       # When the action occurred
    success: bool = True      # Whether the action succeeded

Tracked Actions

NeoSC automatically logs the following action types:

Authentication Events

User account registration
{
  "action": "register",
  "resource": "auth",
  "details": "User registered successfully"
}
Successful user login (local or SSO)
{
  "action": "login",
  "resource": "auth",
  "details": "User logged in successfully"
}
SSO authentication via Zitadel
{
  "action": "sso_login",
  "resource": "auth",
  "details": "SSO login via zitadel as admin"
}
User logout event
{
  "action": "logout",
  "resource": "auth",
  "details": "User logged out"
}

Workspace Events

Workspace launch and session creation
{
  "action": "launch_workspace",
  "resource": "workspace:ws-sap-neogenesys",
  "details": "Launched SAP Neogénesys"
}
Workspace stop and session termination
{
  "action": "stop_workspace",
  "resource": "workspace:ws-sap-neogenesys",
  "details": "Workspace stopped"
}
New workspace creation (admin only)
{
  "action": "create_workspace",
  "resource": "workspace:ws-custom-123",
  "details": "Created workspace: Development Environment"
}
Workspace configuration changes
{
  "action": "update_workspace",
  "resource": "workspace:ws-sap-neogenesys",
  "details": "Updated workspace: {cpu: '8 vCPU', memory: '16 GB'}"
}
Workspace deletion
{
  "action": "delete_workspace",
  "resource": "workspace:ws-old-123",
  "details": "Workspace deleted"
}
Reset all workspaces to defaults
{
  "action": "reset_workspaces",
  "resource": "workspaces",
  "details": "Reset to default workspaces"
}

Session Events

Session disconnection by user
{
  "action": "disconnect_session",
  "resource": "session:550e8400-e29b-41d4",
  "details": "Session disconnected"
}

Policy Events

Security policy enabled/disabled
{
  "action": "toggle_policy",
  "resource": "policy:pol-mfa-required",
  "details": "Policy disabled"
}

Retrieving Audit Logs

Fetch audit logs for the authenticated user:
curl -X GET "https://api.neosc.com/api/audit-logs" \
  -H "Authorization: Bearer YOUR_TOKEN"

Access Control

backend/server.py:739
@api_router.get("/audit-logs")
async def get_audit_logs(user: dict = Depends(get_current_user)):
    # Admins can see all logs, users see only their own
    query = {} if user.get('role') == 'admin' else {"user_id": user['id']}
    
    logs = await db.audit_logs.find(query, {"_id": 0})
        .sort("timestamp", -1)
        .to_list(500)
    
    return logs
Admin users can view all audit logs across the organization. Regular users can only view their own activity logs.

Response Example

[
  {
    "id": "log-550e8400-e29b-41d4",
    "user_id": "user-123",
    "user_email": "john@neogenesys.com",
    "action": "launch_workspace",
    "resource": "workspace:ws-sap-neogenesys",
    "details": "Launched SAP Neogénesys",
    "ip_address": "192.168.1.100",
    "timestamp": "2026-03-05T14:30:00Z",
    "success": true
  },
  {
    "id": "log-660f9511-f39c-52e5",
    "user_id": "user-123",
    "user_email": "john@neogenesys.com",
    "action": "login",
    "resource": "auth",
    "details": "User logged in successfully",
    "ip_address": "192.168.1.100",
    "timestamp": "2026-03-05T14:25:00Z",
    "success": true
  }
]

Creating Audit Logs

Audit logs are created automatically throughout the system:
backend/server.py:726
async def create_audit_log(
    user_id: str, 
    user_email: str, 
    action: str, 
    resource: str, 
    details: str, 
    success: bool = True
):
    log = AuditLog(
        user_id=user_id,
        user_email=user_email,
        action=action,
        resource=resource,
        details=details,
        success=success
    )
    
    log_doc = log.model_dump()
    log_doc['timestamp'] = log_doc['timestamp'].isoformat()
    
    await db.audit_logs.insert_one(log_doc)

Example: Workspace Launch

backend/server.py:642
@api_router.post("/workspaces/{workspace_id}/launch")
async def launch_workspace(workspace_id: str, user: dict = Depends(get_current_user)):
    # ... launch workspace logic
    
    # Create audit log
    await create_audit_log(
        user['id'], 
        user['email'], 
        "launch_workspace", 
        f"workspace:{workspace_id}", 
        f"Launched {workspace['name']}"
    )
    
    return {"session_id": session.id, ...}

Example: Policy Toggle

backend/server.py:814
@api_router.patch("/policies/{policy_id}")
async def toggle_policy(policy_id: str, user: dict = Depends(get_current_user)):
    new_status = not policy.get('enabled', True)
    await db.policies.update_one({"id": policy_id}, {"$set": {"enabled": new_status}})
    
    await create_audit_log(
        user['id'], 
        user['email'], 
        "toggle_policy",
        f"policy:{policy_id}", 
        f"Policy {'enabled' if new_status else 'disabled'}"
    )

Audit Log UI

The frontend displays audit logs in a sortable, filterable table:
frontend/src/pages/AuditLogsPage.jsx:74
<table className="data-table">
  <thead>
    <tr>
      <th>Timestamp</th>
      <th>User</th>
      <th>Action</th>
      <th>Resource</th>
      <th>Details</th>
      <th>IP Address</th>
      <th>Status</th>
    </tr>
  </thead>
  <tbody>
    {logs.map((log) => {
      const ActionIcon = getActionIcon(log.action);
      
      return (
        <tr key={log.id}>
          <td className="mono text-xs">
            {new Date(log.timestamp).toLocaleString()}
          </td>
          <td>{log.user_email}</td>
          <td>
            <div className="flex items-center gap-2">
              <ActionIcon className="w-4 h-4" />
              <span className="capitalize">
                {log.action.replace(/_/g, ' ')}
              </span>
            </div>
          </td>
          <td className="mono text-xs">{log.resource}</td>
          <td className="truncate max-w-[200px]">{log.details}</td>
          <td className="mono text-xs">{log.ip_address}</td>
          <td>
            {log.success ? (
              <Badge variant="outline" className="bg-green-500/10 text-green-400">
                <CheckCircle className="w-3 h-3 mr-1" />
                Success
              </Badge>
            ) : (
              <Badge variant="outline" className="bg-red-500/10 text-red-400">
                <XCircle className="w-3 h-3 mr-1" />
                Failed
              </Badge>
            )}
          </td>
        </tr>
      );
    })}
  </tbody>
</table>

Action Icons

frontend/src/pages/AuditLogsPage.jsx:21
const actionIcons = {
  login: LogIn,
  logout: LogOut,
  register: FileText,
  launch_workspace: Play,
  stop_workspace: Square,
  disconnect_session: XCircle,
  toggle_policy: Settings,
};

const getActionIcon = (action) => {
  return actionIcons[action] || FileText;
};

Failed Actions

Audit logs track both successful and failed actions:
Example: Failed Login
await create_audit_log(
    user_id="attempted-user-id",
    user_email="attacker@example.com",
    action="login",
    resource="auth",
    details="Invalid credentials",
    success=False  # Mark as failed
)
Failed login attempts with success: false may indicate brute force attacks or unauthorized access attempts.

Resource Identifiers

The resource field uses a consistent naming scheme:
Resource TypeFormatExample
Workspaceworkspace:{id}workspace:ws-sap-neogenesys
Sessionsession:{id}session:550e8400-e29b-41d4
Policypolicy:{id}policy:pol-mfa-required
Authauthauth
Systemworkspaces, users, etc.workspaces

Querying and Filtering

Filter by User (Admin)

Query Example
logs = await db.audit_logs.find(
    {"user_email": "john@neogenesys.com"},
    {"_id": 0}
).sort("timestamp", -1).to_list(100)

Filter by Action

Query Example
logs = await db.audit_logs.find(
    {"action": "launch_workspace"},
    {"_id": 0}
).sort("timestamp", -1).to_list(100)

Filter by Date Range

Query Example
from datetime import datetime, timedelta

start_date = datetime.now(timezone.utc) - timedelta(days=7)
logs = await db.audit_logs.find(
    {"timestamp": {"$gte": start_date.isoformat()}},
    {"_id": 0}
).sort("timestamp", -1).to_list(500)

Filter by Success Status

Query Failed Actions
logs = await db.audit_logs.find(
    {"success": False},
    {"_id": 0}
).sort("timestamp", -1).to_list(100)

Compliance Use Cases

SOC 2 Compliance

1

Access Monitoring

Track all user authentication and authorization events
2

Change Management

Log all configuration and policy changes with user attribution
3

Audit Trail

Maintain immutable logs with timestamps and IP addresses
4

Retention

Store logs for minimum 90 days (configurable)

GDPR Compliance

  • Right to Access: Users can view their own audit logs
  • Data Minimization: Only necessary information is logged
  • Purpose Limitation: Logs are used solely for security and compliance
  • Retention: Configurable retention periods with automatic deletion

HIPAA Compliance

  • Access Logs: Track all access to protected resources
  • User Attribution: Every action is tied to a specific user
  • Integrity Controls: Immutable logs prevent tampering
  • Audit Reports: Generate compliance reports from logs

Retention and Archival

Configure log retention policies:
Retention Example
retention_days = 90  # SOC 2 minimum
cutoff_date = datetime.now(timezone.utc) - timedelta(days=retention_days)

# Archive old logs before deletion
old_logs = await db.audit_logs.find(
    {"timestamp": {"$lt": cutoff_date.isoformat()}}
).to_list(10000)

# Export to cold storage (S3, etc.)
await archive_logs_to_s3(old_logs)

# Delete from active database
await db.audit_logs.delete_many(
    {"timestamp": {"$lt": cutoff_date.isoformat()}}
)

Security Incident Investigation

Use audit logs to investigate security incidents:
Investigation Example
# Find all actions by suspicious user
suspicious_activity = await db.audit_logs.find(
    {"user_email": "suspicious@example.com"},
    {"_id": 0}
).sort("timestamp", -1).to_list(1000)

# Find failed login attempts
failed_logins = await db.audit_logs.find(
    {"action": "login", "success": False},
    {"_id": 0}
).sort("timestamp", -1).to_list(100)

# Find actions from unusual IP
unusual_ip = await db.audit_logs.find(
    {"ip_address": "suspicious.ip.address"},
    {"_id": 0}
).sort("timestamp", -1).to_list(100)

Export and Reporting

CSV Export

Export to CSV
import csv
from io import StringIO

logs = await db.audit_logs.find({}, {"_id": 0}).to_list(10000)

output = StringIO()
writer = csv.DictWriter(output, fieldnames=logs[0].keys())
writer.writeheader()
writer.writerows(logs)

return output.getvalue()

SIEM Integration

Forward logs to SIEM systems (Splunk, ELK, etc.):
SIEM Forward Example
import asyncio
import aiohttp

async def forward_to_siem(log_entry):
    async with aiohttp.ClientSession() as session:
        await session.post(
            "https://siem.example.com/ingest",
            json=log_entry,
            headers={"Authorization": f"Bearer {SIEM_TOKEN}"}
        )

# Forward logs in real-time
await forward_to_siem(log_doc)

Best Practices

  • Log all security-relevant events
  • Include sufficient context in details field
  • Use consistent resource naming conventions
  • Mark failed actions with success: false
  • Never log passwords or sensitive credentials
  • Hash or redact PII where possible
  • Encrypt logs at rest and in transit
  • Implement strict access controls
  • Use async logging to avoid blocking
  • Batch log writes for high-volume events
  • Index timestamp and user_id fields
  • Archive old logs to cold storage
  • Set up alerts for failed login attempts
  • Monitor unusual activity patterns
  • Review admin actions regularly
  • Generate weekly audit reports

Security Policies

Configure security rules and enforcement

Sessions

Session activity tracking

Workspaces

Workspace usage monitoring

Organizations

Organization-level audit trails

Build docs developers (and LLMs) love