Skip to content
This page was generated and translated with the assistance of AI. If you spot any inaccuracies, feel free to help improve it. Edit on GitHub

Audit Logging

PRX includes a built-in audit logging system that records all security-relevant operations. The AuditLogger tracks who did what, when, and whether it succeeded -- providing a tamper-evident trail for compliance, incident response, and forensic analysis.

Overview

The audit system captures structured events for every security-sensitive action:

  • Authentication attempts (success and failure)
  • Authorization decisions (allow and deny)
  • Configuration changes
  • Tool executions and sandbox events
  • Memory access and modification
  • Channel connections and disconnections
  • Evolution proposals and applications
  • Plugin lifecycle events

Every audit event includes a timestamp, actor identity, action description, target resource, and outcome.

Audit Event Structure

Each audit event is a structured record with the following fields:

FieldTypeDescription
timestampDateTime<Utc>When the event occurred (UTC, nanosecond precision)
event_idStringUnique identifier for the event (UUIDv7, time-ordered)
actorActorWho performed the action (user, agent, system, or plugin)
actionStringWhat was done (e.g., auth.login, tool.execute, config.update)
targetStringThe resource acted upon (e.g., session ID, config key, file path)
outcomeOutcomeResult: success, failure, or denied
metadataMap<String, Value>Additional context (IP address, reason for denial, etc.)
session_idOption<String>Associated agent session, if any
severitySeverityEvent severity: info, warning, critical

Actor Types

Actor TypeDescriptionExample
userA human user identified by channel or API authuser:telegram:123456789
agentThe PRX agent itselfagent:default
systemInternal system processes (cron, evolution)system:evolution
pluginA WASM pluginplugin:my-plugin:v1.2.0

Action Categories

Actions follow a dot-separated namespace convention:

CategoryActionsSeverity
auth.*auth.login, auth.logout, auth.token_refresh, auth.pairinginfo / warning
authz.*authz.allow, authz.deny, authz.policy_checkinfo / warning
config.*config.update, config.reload, config.hot_reloadwarning
tool.*tool.execute, tool.sandbox_escape_attempt, tool.timeoutinfo / critical
memory.*memory.store, memory.recall, memory.delete, memory.compactinfo
channel.*channel.connect, channel.disconnect, channel.errorinfo / warning
evolution.*evolution.propose, evolution.apply, evolution.rollbackwarning / critical
plugin.*plugin.load, plugin.unload, plugin.error, plugin.permission_deniedinfo / warning
session.*session.create, session.terminate, session.timeoutinfo

Configuration

toml
[security.audit]
enabled = true
min_severity = "info"           # minimum severity to log: "info", "warning", "critical"

[security.audit.file]
enabled = true
path = "~/.local/share/openprx/audit.log"
format = "jsonl"                # "jsonl" or "csv"
max_size_mb = 100               # rotate when file exceeds this size
max_files = 10                  # keep up to 10 rotated files
compress_rotated = true         # gzip rotated files

[security.audit.database]
enabled = false
backend = "sqlite"              # "sqlite" or "postgres"
path = "~/.local/share/openprx/audit.db"
retention_days = 90             # auto-delete events older than 90 days

Configuration Reference

FieldTypeDefaultDescription
enabledbooltrueEnable or disable audit logging globally
min_severityString"info"Minimum severity level to record
file.enabledbooltrueWrite audit events to a log file
file.pathString"~/.local/share/openprx/audit.log"Path to the audit log file
file.formatString"jsonl"Log format: "jsonl" (one JSON object per line) or "csv"
file.max_size_mbu64100Maximum file size before rotation (MB)
file.max_filesu3210Number of rotated files to retain
file.compress_rotatedbooltrueCompress rotated log files with gzip
database.enabledboolfalseWrite audit events to a database
database.backendString"sqlite"Database backend: "sqlite" or "postgres"
database.pathString""Database path (SQLite) or connection URL (PostgreSQL)
database.retention_daysu6490Auto-delete events older than N days. 0 = keep forever

Storage Backends

File (JSONL)

The default backend writes one JSON object per line to a log file. This format is compatible with standard log analysis tools (jq, grep, Elasticsearch ingest).

Example log entry:

json
{
  "timestamp": "2026-03-21T10:15:30.123456789Z",
  "event_id": "019520a8-1234-7000-8000-000000000001",
  "actor": {"type": "user", "id": "user:telegram:123456789"},
  "action": "tool.execute",
  "target": "shell:ls -la /tmp",
  "outcome": "success",
  "metadata": {"sandbox": "bubblewrap", "duration_ms": 45},
  "session_id": "sess_abc123",
  "severity": "info"
}

Database (SQLite / PostgreSQL)

The database backend stores events in a structured table with indexes on timestamp, actor, action, and severity for efficient querying.

Querying Audit Trails

CLI Queries

bash
# View recent audit events
prx audit log --tail 50

# Filter by action category
prx audit log --action "auth.*" --last 24h

# Filter by severity
prx audit log --severity critical --last 7d

# Filter by actor
prx audit log --actor "user:telegram:123456789"

# Export to JSON
prx audit log --last 30d --format json > audit_export.json

Database Queries

When using the database backend, you can query directly with SQL:

sql
-- Failed authentication attempts in the last 24 hours
SELECT * FROM audit_events
WHERE action LIKE 'auth.%'
  AND outcome = 'failure'
  AND timestamp > datetime('now', '-24 hours')
ORDER BY timestamp DESC;

-- Tool execution by a specific user
SELECT action, target, outcome, timestamp
FROM audit_events
WHERE actor_id = 'user:telegram:123456789'
  AND action LIKE 'tool.%'
ORDER BY timestamp DESC
LIMIT 100;

-- Critical events summary
SELECT action, COUNT(*) as count
FROM audit_events
WHERE severity = 'critical'
  AND timestamp > datetime('now', '-7 days')
GROUP BY action
ORDER BY count DESC;

Compliance

The audit logging system is designed to support compliance requirements:

  • Immutability -- log files are append-only; rotated files can be integrity-checked with checksums
  • Completeness -- all security-relevant operations are logged by default at the info level
  • Retention -- configurable retention periods with automatic rotation and deletion
  • Non-repudiation -- every event includes an actor identity and timestamp
  • Availability -- dual output (file + database) ensures events are not lost if one backend fails
toml
[security.audit]
enabled = true
min_severity = "info"

[security.audit.file]
enabled = true
format = "jsonl"
max_size_mb = 500
max_files = 50
compress_rotated = true

[security.audit.database]
enabled = true
backend = "postgres"
path = "postgresql://audit_user:password@localhost/prx_audit"
retention_days = 365

Performance

The audit logger is designed for minimal overhead:

  • Events are written asynchronously via a bounded channel (default capacity: 10,000 events)
  • File writes are buffered and flushed periodically (every 1 second or every 100 events)
  • Database writes are batched (default batch size: 50 events)
  • If the event channel is full, events are dropped with a warning counter (never blocks the main agent loop)

Limitations

  • The file backend does not provide built-in tamper detection (consider external integrity monitoring for high-security deployments)
  • Audit events from plugin code are logged by the host; plugins cannot bypass the audit system
  • The CSV format does not support nested metadata fields (use JSONL for full fidelity)
  • Database retention cleanup runs once per hour; events may persist slightly beyond the configured retention period

Released under the Apache-2.0 License.