collectiveidea/audited
Audited (formerly acts_as_audited) is an ORM extension that logs all changes to your Rails models.
Healthy across all four use cases
Permissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 6mo ago
- ✓20 active contributors
- ✓MIT licensed
Show 4 more →Show less
- ✓CI configured
- ✓Tests present
- ⚠Slowing — last commit 6mo ago
- ⚠Concentrated ownership — top contributor handles 52% of recent commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/collectiveidea/audited)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/collectiveidea/audited on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: collectiveidea/audited
Generated by RepoPilot · 2026-05-10 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/collectiveidea/audited shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across all four use cases
- Last commit 6mo ago
- 20 active contributors
- MIT licensed
- CI configured
- Tests present
- ⚠ Slowing — last commit 6mo ago
- ⚠ Concentrated ownership — top contributor handles 52% of recent commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live collectiveidea/audited
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/collectiveidea/audited.
What it runs against: a local clone of collectiveidea/audited — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in collectiveidea/audited | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch main exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 202 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of collectiveidea/audited. If you don't
# have one yet, run these first:
#
# git clone https://github.com/collectiveidea/audited.git
# cd audited
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of collectiveidea/audited and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "collectiveidea/audited(\\.git)?\\b" \\
&& ok "origin remote is collectiveidea/audited" \\
|| miss "origin remote is not collectiveidea/audited (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
&& ok "default branch main exists" \\
|| miss "default branch main no longer exists"
# 4. Critical files exist
test -f "lib/audited.rb" \\
&& ok "lib/audited.rb" \\
|| miss "missing critical file: lib/audited.rb"
test -f "lib/audited/auditor.rb" \\
&& ok "lib/audited/auditor.rb" \\
|| miss "missing critical file: lib/audited/auditor.rb"
test -f "lib/audited/audit.rb" \\
&& ok "lib/audited/audit.rb" \\
|| miss "missing critical file: lib/audited/audit.rb"
test -f "lib/audited/railtie.rb" \\
&& ok "lib/audited/railtie.rb" \\
|| miss "missing critical file: lib/audited/railtie.rb"
test -f "lib/generators/audited/install_generator.rb" \\
&& ok "lib/generators/audited/install_generator.rb" \\
|| miss "missing critical file: lib/generators/audited/install_generator.rb"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 202 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~172d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/collectiveidea/audited"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Audited is an ActiveRecord extension that automatically logs all changes made to Rails models into an audits table, capturing who changed what, when, and optionally why (via comments). It converts model mutations into versioned audit records with support for YAML, JSON, or JSONB storage formats, enabling full change history and compliance tracking without manual instrumentation. Monolithic gem structure: core audit logic in lib/audited/auditor.rb (the mixin), lib/audited/audit.rb (the audit record model), lib/audited/sweeper.rb (Rails integration), and generators in lib/generators/audited/ for schema creation. Test suite mirrors this structure under spec/audited/ with rspec matchers provided via lib/audited-rspec.rb.
👥Who it's for
Rails developers building applications requiring change tracking, audit trails, or compliance logging—typically those in healthcare, finance, or regulated industries who need to answer 'what changed and who did it' for any model instance at any point in time.
🌱Maturity & risk
Highly mature and production-ready. The gem (currently v5.6) is actively maintained with CI/CD pipelines testing across Rails 5.2–8.0 and Ruby 2.3–3.3, comprehensive spec coverage, and semantic versioning. Latest structure suggests active development with multi-version Appraisals gemfiles for testing against diverse Rails targets.
Low risk for well-tested use cases, but note the single-maintainer concentration risk (collectiveidea organization). No external dependencies visible in file list suggests minimal supply-chain risk. Breaking changes are possible across major Rails versions (hence separate gemfiles per Rails version), so version pinning is essential. Last activity level unclear from static file list alone.
Active areas of work
Active maintenance on Rails 7.2/8.0 compatibility and multi-version testing (evidenced by 8 Appraisals gemfiles). CI workflows in .github/workflows/ suggest automated testing, linting (StandardRb per .standard.yml), and gem publishing pipelines. No specific PRs/milestones visible in file data, but upgrade generator and migrations suggest ongoing schema evolution.
🚀Get running
git clone https://github.com/collectiveidea/audited.git
cd audited
bundle install
bundle exec rake spec
Daily commands:
bundle exec rake spec # Run full test suite
bundle exec appraisal rails72 rake # Test against specific Rails version
bundle exec standardrb # Lint code
🗺️Map of the codebase
lib/audited.rb— Main entry point that requires and initializes the Audited gem; every contributor must understand this to see how the library is loaded.lib/audited/auditor.rb— Core module that provides theauditedDSL and audit lifecycle hooks; essential for understanding how models are instrumented to track changes.lib/audited/audit.rb— ActiveRecord model representing individual audit records; defines the schema and querying interface for all recorded changes.lib/audited/railtie.rb— Rails integration layer that hooks Audited into the Rails initialization and request lifecycle.lib/generators/audited/install_generator.rb— Installation generator that creates the audits table and configures the gem; guides new users through initial setup.spec/support/active_record/models.rb— Test models that demonstrate and validate the audited DSL usage patterns.CHANGELOG.md— Historical record of breaking changes and Rails version compatibility requirements; critical for maintaining version awareness.
🧩Components & responsibilities
- Auditor — undefined
🛠️How to make changes
Add Auditing to a New Model
- In your Rails model (e.g.,
app/models/user.rb), add theauditeddeclaration to enable change tracking (spec/support/active_record/models.rb (seeclass Userexample)) - Configure audit options:
audited only: [:email], except: [:password], comment_required: true(lib/audited/auditor.rb (see Auditor::ClassMethods#audited method)) - Ensure the
auditstable exists by runningrails generate audited:installorrails db:migrate(lib/generators/audited/install_generator.rb) - Access audit history via
user.auditsassociation; query changes withuser.audits.map(&:audited_changes)(lib/audited/audit.rb (see Audit model and associations))
Add a Custom Audit Field or Column
- Generate and run a migration using the upgrade generator:
rails generate audited:upgrade --add-<field>(lib/generators/audited/upgrade_generator.rb) - Choose a template matching your field (e.g.,
add_comment_to_audits.rbfor comment support) (lib/generators/audited/templates/ (e.g., add_comment_to_audits.rb, add_remote_address_to_audits.rb)) - In your models, populate the new field via
audited user_id: current_user.idor callbacks (lib/audited/auditor.rb (see #write_audit method and options handling))
Write Tests Using Audited RSpec Matchers
- Require the RSpec matchers in your
spec_helper.rbor spec file:require 'audited-rspec'(lib/audited-rspec.rb) - Use matchers in your specs:
expect(user).to have_audited(:email, :name)orexpect { user.update }.to change { user.audits.count }(lib/audited/rspec_matchers.rb (see HaveAudited matcher definition)) - Verify audit content in callbacks:
user.audits.last.audited_changesreturns{ 'email' => [old, new] }(spec/audited/rspec_matchers_spec.rb (see test examples))
Migrate or Upgrade Audited Between Versions
- Run the upgrade generator to detect schema version:
rails generate audited:upgrade(lib/generators/audited/upgrade_generator.rb) - Review and apply generated migration files from templates (rename_changes_to_audited_changes.rb, etc.) (
lib/generators/audited/templates/ (version-specific migrations)) - Update your Gemfile to the target Audited version and run
bundle install && rails db:migrate(audited.gemspec and CHANGELOG.md (for version compatibility matrix))
🔧Why these technologies
- Rails ActiveRecord — Audited is a Rails ORM extension; ActiveRecord is the standard persistence abstraction that all models use
- Ruby Callbacks (before/after) — Hooks into Rails model lifecycle to capture state changes before and after persistence without intrusive code
- RSpec Matchers — Provides a first-class testing API that integrates with Rails test suites and follows RSpec conventions
- Rails Generators — Reduces setup friction and version migration complexity via idiomatic
rails generatecommands
⚖️Trade-offs already made
-
Single
auditstable stores all model changes across entire application- Why: Simplifies schema and reduces migration burden compared to per-model audit tables
- Consequence: Queries can become complex at scale; relies on polymorphic associations and indexing for performance
-
Changes stored as serialized JSON/JSONB in
audited_changescolumn- Why: Allows schema-less storage of any model attribute without predefined columns
- Consequence: Limited queryability of nested changes; database-specific (PostgreSQL JSONB faster than JSON)
-
Supports multiple Rails versions (5.2–8.0) via Appraisals and gemfiles
- Why: Maximizes adoption and eases upgrade paths for gem consumers
- Consequence: Increased maintenance burden and testing matrix; some features only work on newer Rails
-
Optional sweeper pattern for legacy Rails support
- Why: Maintains backward compatibility with pre-Rails 5 callback patterns
- Consequence: Deprecated code adds complexity; newer Rails versions use Railtie hooks exclusively
🚫Non-goals (don't propose these)
- Does not provide real-time audit streaming or event sourcing
- Does not support sharding or distributed audit logs
- Does not include audit UI or visualization dashboard (separate concern)
- Does not enforce audit immutability or tamper detection
- Does not provide fine-grained permission control over which audits can be read
- Does not support non-relational databases (e.g., MongoDB, Elasticsearch)
🪤Traps & gotchas
- Schema must exist first: The audits table must be created via migrations before audited models can write records; missing migration causes silent failures or runtime errors. 2. STI and polymorphism complexity: Audited uses
auditable_type/auditable_idfor polymorphic associations; Single Table Inheritance can cause confusing audit records if not understood. 3. YAML serialization default: YAML format can produce large records and has security implications on deserialization; PostgreSQL JSONB option exists but requires explicit flag. 4. User context not magic: Sweeper requires Audited.current_user to be set (typically in controller); omitting it logsuser_id=nil. 5. Version constraints matter: Each Rails version has a specific Appraisal gemfile; bundling without Appraisals may mask incompatibilities.
🏗️Architecture
🔗Related repos
paper_trail/paper_trail— Direct competitor offering similar versioning and audit trail functionality; compare approach to Audited's designwestonganger/rails_db_comments— Complementary gem for recording database-level column comments, often paired with Audited for schema documentationrails/rails— Core dependency; Audited targets specific Rails versions via Appraisals for version-specific hook and API compatibilityrspec/rspec-rails— Testing framework used throughout spec/ and via rspec matchers; understanding RSpec is prerequisite for contributing testscollectiveidea/acts-as-taggable-on— Same maintainer organization; similar pattern of Ruby on Rails model extension gems
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive integration tests for Rails 8.0 compatibility
The gemfiles directory shows support for Rails 5.2 through 7.2, and rails_main.gemfile likely tests against the Rails main branch. However, there's no explicit rails80.gemfile despite the README mentioning Rails 7.2 support. Rails 8.0 was recently released and there's no dedicated appraisal file or CI coverage documented. This would ensure the gem works with the latest major Rails version and catch any breaking changes early.
- [ ] Create gemfiles/rails80.gemfile with Rails 8.0 dependencies following the pattern of existing gemfiles (e.g., gemfiles/rails72.gemfile)
- [ ] Add a corresponding appraisal entry in Appraisals file
- [ ] Update .github/workflows/ci.yml to include Rails 8.0 in the test matrix
- [ ] Run full test suite against Rails 8.0 and fix any compatibility issues in lib/audited/auditor.rb or lib/audited/audit.rb
Add missing unit tests for Audited::Sweeper class
The sweeper.rb file exists in lib/audited/sweeper.rb but spec/audited/sweeper_spec.rb appears to be very minimal based on the file structure. The Sweeper is a critical component for managing audit state across requests. Comprehensive tests would cover edge cases around user tracking, request UUIDs, and remote address logging that are mentioned in the migration templates.
- [ ] Review lib/audited/sweeper.rb to understand all public methods and state management
- [ ] Expand spec/audited/sweeper_spec.rb with tests for: user assignment/clearing across requests, remote address capture, request UUID generation, and integration with ActionController::Base.append_after_action
- [ ] Add tests for thread-safety of sweeper state variables
- [ ] Test interaction between sweeper and auditor when enabled/disabled
Add end-to-end tests for audit trail reconstruction and versioning
The lib/audited/audit.rb and lib/audited/auditor.rb are core to the gem's functionality, but spec/audited/auditor_spec.rb likely focuses on unit tests. There's a migration template for add_version_to_auditable_index.rb suggesting version tracking is important, but no dedicated spec file tests the complete audit reconstruction workflow. This would validate the gem's core promise of reliable change logging.
- [ ] Create spec/audited/audit_reconstruction_spec.rb to test reconstructing model state from audit trail
- [ ] Add tests for version numbering accuracy when multiple audits exist for the same model
- [ ] Test audit trail completeness for complex scenarios: nested associations (see add_association_to_audits.rb template), concurrent updates, and rollback scenarios
- [ ] Verify associated_audits and polymorphic audit relationships work correctly across these scenarios
🌿Good first issues
- Add RSpec matcher tests for the new
--audited-user-id-column-type uuidinstall option (spec/audited/rspec_matchers_spec.rb is incomplete for UUID scenarios); verify matchers work with non-integer PKs - Document the Sweeper integration in a concrete example showing how to set Audited.current_user in a Devise-based app; README mentions it but provides no sample controller code
- Add migration template for Rails 8.0 compatibility (gemfiles/rails80.gemfile exists but no corresponding migration template update); test against new Rails 8 schema definitions
⭐Top contributors
Click to expand
Top contributors
- @danielmorrison — 52 commits
- @mattbrictson — 14 commits
- [@Jeremy Anderson](https://github.com/Jeremy Anderson) — 7 commits
- @tiagocassio — 5 commits
- @mohammednasser-32 — 3 commits
📝Recent commits
Click to expand
Recent commits
dbf8432— Merge pull request #761 from mlarraz/main (danielmorrison)ab4f020— Add back support for running without Rails (mlarraz)f935285— Bump version (danielmorrison)05b7aad— Merge pull request #739 from collectiveidea/rails8 (danielmorrison)e64b4e3— Add Rails 8.0 to build matrix (danielmorrison)a1847f6— Merge pull request #734 from mohammednasser-32/allow_calling_audited_multiple_times (danielmorrison)b658e95— Merge pull request #738 from BranLiang/main (danielmorrison)f2c9d7d— Relax gemspec to allow Rails 8.1 (BranLiang)882d1cb— remove log message (mohammednasser-32)d1c1b68— return if options did not change (mohammednasser-32)
🔒Security observations
The audited gem is a well-maintained Rails auditing library with moderate security posture. Primary concerns are: (1) potential SQL injection risks if not used carefully with user input, (2) hardcoded secrets in test configuration, and (3) lack of built-in access controls for sensitive audit data. The codebase follows Ruby/Rails conventions with standard tooling (RSpec, Standard linter). No critical vulnerabilities detected in the library itself, but security depends heavily on proper implementation by users. Recommendations include reviewing SQL construction patterns, securing test configuration secrets, and providing stronger documentation on RBAC and XSS prevention when displaying audit information.
- Medium · Potential SQL Injection in Audit Logging —
lib/audited/audit.rb, lib/audited/auditor.rb. The audited gem logs changes to Rails models. If user input is not properly sanitized before being passed to audited, there could be SQL injection risks when raw SQL queries are constructed in audit trails or when filtering audits. Fix: Review all database queries in audit.rb and auditor.rb to ensure parameterized queries are used. Use ActiveRecord query methods instead of string interpolation for dynamic SQL construction. - Medium · Hardcoded Secret Token in Test Configuration —
spec/rails_app/config/initializers/secret_token.rb. The file spec/rails_app/config/initializers/secret_token.rb suggests hardcoded secret configuration in test environment, which could be exposed if accidentally deployed to production. Fix: Ensure secret_token.rb uses environment variables for sensitive values. Never commit actual secrets. Use secrets management tools like Rails credentials or environment variables. - Low · Missing Security Headers Documentation —
spec/rails_app/config/. No evidence of security header configuration (CSP, X-Frame-Options, etc.) in the provided file structure for the test Rails application. Fix: Add security headers middleware configuration in the test application. Document security best practices for users implementing audited in production. - Low · Test Database Credentials May Be Visible —
spec/rails_app/config/database.yml. spec/rails_app/config/database.yml is included in the repository structure, which may contain database credentials for the test environment. Fix: Ensure database.yml for test environments does not contain sensitive credentials. Use .gitignore to exclude environment-specific configs. Document database setup without exposing credentials. - Low · No Input Validation Documentation for Audit Comments —
lib/audited/auditor.rb, lib/audited/audit.rb. The audited gem allows saving comments with audits. There is no explicit documentation visible about sanitizing user-provided comments to prevent XSS attacks when displaying audit comments. Fix: Document that audit comments should be sanitized when displayed in views. Consider adding input validation helpers. Use Rails XSS protection (html_safe only when necessary). - Low · Missing RBAC Implementation Guidance —
lib/audited/audit.rb. No visible access control mechanisms to restrict who can view or modify audit records. The gem appears to audit everything without built-in permission checks. Fix: Document that implementers should add authorization checks (using gems like Pundit or CanCanCan) to control access to audit records. Implement scoping for sensitive data.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.