# `Concord.AuditLog`
[🔗](https://github.com/gsmlg-dev/concord/blob/main/lib/concord/audit_log.ex#L1)

Comprehensive audit logging for Concord operations.

Provides an immutable audit trail of all data-modifying operations
for compliance, security, and debugging purposes. Audit logs are
append-only and stored in structured JSON format.

## Features

- Immutable append-only log storage
- Structured JSON format for easy parsing
- Automatic log rotation and retention
- Query and export API
- Minimal performance impact (async writes)
- Integration with authentication and telemetry

## Configuration

    config :concord,
      audit_log: [
        enabled: true,
        log_dir: "./audit_logs",
        rotation_size_mb: 100,      # Rotate at 100MB
        retention_days: 90,          # Keep logs for 90 days
        log_reads: false,            # Don't log read operations
        sensitive_keys: false        # Don't log actual key values
      ]

## Audit Log Format

Each audit log entry is a JSON object with the following fields:

    {
      "timestamp": "2025-10-23T08:30:45.123456Z",
      "event_id": "550e8400-e29b-41d4-a716-446655440000",
      "operation": "put",
      "key": "user:123",  # Only if sensitive_keys: true
      "key_hash": "sha256:abc123...",  # Always present
      "result": "ok",
      "user": "token:sk_concord_...",  # If authenticated
      "node": "node1@127.0.0.1",
      "metadata": {
        "has_ttl": true,
        "ttl_seconds": 3600,
        "compressed": false
      },
      "trace_id": "a1b2c3d4...",  # If tracing enabled
      "span_id": "e5f6g7h8..."
    }

## Usage

Audit logging is automatic for all operations when enabled.
You can also manually log custom events:

    Concord.AuditLog.log(%{
      operation: "custom_action",
      key: "resource:id",
      result: :ok,
      metadata: %{action: "import", count: 100}
    })

## Querying Logs

    # Get recent audit logs
    {:ok, logs} = Concord.AuditLog.query(limit: 100)

    # Filter by operation
    {:ok, logs} = Concord.AuditLog.query(operation: "put", limit: 50)

    # Filter by time range
    {:ok, logs} = Concord.AuditLog.query(
      from: ~U[2025-10-23 00:00:00Z],
      to: ~U[2025-10-23 23:59:59Z]
    )

## Compliance

Audit logs support compliance requirements including:
- PCI-DSS: Tracking and monitoring all access to cardholder data
- HIPAA: Audit controls for PHI access
- GDPR: Data processing activity logs
- SOC 2: Detailed audit trails for security events

# `event`

```elixir
@type event() :: %{
  timestamp: DateTime.t(),
  event_id: String.t(),
  operation: String.t(),
  key: String.t() | nil,
  key_hash: String.t(),
  result: atom() | String.t(),
  user: String.t() | nil,
  node: atom(),
  metadata: map(),
  trace_id: String.t() | nil,
  span_id: String.t() | nil
}
```

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `cleanup`

Cleans up old audit logs based on retention policy.

# `export`

Exports audit logs to a file.

## Examples

    :ok = Concord.AuditLog.export("/tmp/audit_export.jsonl")

# `log`

Logs an audit event.

## Examples

    Concord.AuditLog.log(%{
      operation: "put",
      key: "user:123",
      result: :ok
    })

# `query`

Queries audit logs with optional filters.

## Options

- `:limit` - Maximum number of entries to return (default: 100)
- `:operation` - Filter by operation type
- `:from` - Start datetime (DateTime struct)
- `:to` - End datetime (DateTime struct)
- `:user` - Filter by user/token
- `:result` - Filter by result (`:ok`, `:error`)

## Examples

    {:ok, logs} = Concord.AuditLog.query(operation: "put", limit: 50)

# `rotate`

Manually triggers log rotation.

# `start_link`

Starts the audit log GenServer.

# `stats`

Returns current audit log statistics.

## Examples

    iex> Concord.AuditLog.stats()
    %{
      current_log_size: 45678912,
      total_files: 5,
      oldest_log: ~U[2025-07-23 00:00:00Z],
      entries_today: 1234
    }

