PaperTrail
Model versioning and audit trail library for Ruby on Rails — tracks every change to ActiveRecord models in a versions table with before/after data. PaperTrail features: `has_paper_trail` macro enables versioning on any model, versions table stores changeset as JSON, `object_changes` column records before/after values, `whodunnit` stores user ID for each change, `reify` method reconstructs model at any past version. Supports custom metadata (request IP, session ID), ignoring certain attributes, and disabling versioning per-request. Used for compliance audit trails, undo functionality, change history displays, and regulatory requirements.
Score Breakdown
⚙ Agent Friendliness
🔒 Security
Never track sensitive agent attributes (API keys, passwords, tokens) — use skip: [:api_key] to exclude from versions table. Versions table contains historical PII; apply same data retention policies as source tables. Whodunnit stores user ID as string — ensure it cannot be spoofed via mass assignment.
⚡ Reliability
Best When
Your Rails agent app needs compliance audit trails, undo functionality, or change history displays — PaperTrail adds complete versioning to any ActiveRecord model with one line.
Avoid When
Your models change extremely frequently (high write volume), you need non-ActiveRecord versioning, or your audit requirements need separate tamper-proof storage.
Use Cases
- • Audit trail for agent configuration changes — has_paper_trail on AgentConfig model records every change with whodunnit set to current_user.id for compliance and debugging agent behavior changes
- • Undo last change to agent settings — agent.versions.last.reify restores previous AgentConfig state; agent.save! reverts to prior configuration without manual diff calculation
- • Display agent change history — agent.versions.map { |v| v.changeset } shows field-level diffs for audit log UI showing who changed what agent configuration and when
- • Track agent document modifications — PaperTrail on Document model records edit history; version.event (:create/:update/:destroy) plus whodunnit enables document audit compliance for regulated agent workflows
- • Reconstruct agent state at point in time — agent.version_at(2.weeks.ago) returns PaperTrail::Version that can reify to show exact agent configuration during an incident investigation
Not For
- • High-volume append-only events — PaperTrail versions table grows quickly for frequently-updated models; for agent action logs (millions of events), use append-only event log table instead
- • Non-ActiveRecord persistence — PaperTrail is ActiveRecord-specific; use event sourcing or custom audit logging for agent services using MongoDB, Redis, or non-ORM persistence
- • Real-time change streams — PaperTrail stores versions synchronously in same transaction; for real-time agent change notifications, combine with ActiveRecord::Observer or webhooks
Interface
Authentication
No auth — library integrates with application auth to set whodunnit. Set PaperTrail.request.whodunnit = current_user&.id in ApplicationController before_action.
Pricing
PaperTrail is MIT licensed, actively maintained. Free for all use.
Agent Metadata
Known Gotchas
- ⚠ whodunnit must be set per-request — PaperTrail.request.whodunnit defaults to nil; without setting in before_action, all agent model versions show nil author; use ApplicationController before_action { PaperTrail.request.whodunnit = current_user&.id.to_s }
- ⚠ versions table schema requires migration — paper_trail:install generator creates versions table; missing migration on deploy causes PaperTrail::Version.create failures silently or raises ActiveRecord::StatementInvalid depending on version; always run migrations before enabling has_paper_trail
- ⚠ Reify does not restore associations — version.reify restores the model's scalar attributes but not has_many associations; agent models with complex associations need custom reification logic to fully restore associated records from their own version history
- ⚠ ignore vs skip have different semantics — ignore: [:updated_at] prevents version creation when ONLY ignored attributes change; skip: [:api_key] excludes attribute from version data; confusing the two causes either missing versions or sensitive agent data leaking into versions table
- ⚠ Large object_changes column impacts query performance — PaperTrail stores full before/after JSON in object_changes; for agent models with large text fields (documents, prompts), use paper_trail_options only: [:status, :name] to limit which attributes are tracked and prevent versions table bloat
- ⚠ PaperTrail disabled block affects nested transactions — PaperTrail.request.disable_model(Agent) inside a block disables versioning; if block wraps a transaction that creates other versioned models, those also lose versioning; scope disable/enable carefully for agent bulk operations
Alternatives
Full Evaluation Report
Detailed scoring breakdown, competitive positioning, security analysis, and improvement recommendations for PaperTrail.
Scores are editorial opinions as of 2026-03-06.