RepoPilotOpen in app →

collectiveidea/audited

Audited (formerly acts_as_audited) is an ORM extension that logs all changes to your Rails models.

Healthy

Healthy across all four use cases

Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 6mo ago
  • 20 active contributors
  • MIT licensed
Show 4 more →
  • 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.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/collectiveidea/audited)](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:

  1. 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.
  2. 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.
  3. 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 |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>collectiveidea/audited</code></summary>
#!/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).

</details>

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 the audited DSL 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

  1. In your Rails model (e.g., app/models/user.rb), add the audited declaration to enable change tracking (spec/support/active_record/models.rb (see class User example))
  2. Configure audit options: audited only: [:email], except: [:password], comment_required: true (lib/audited/auditor.rb (see Auditor::ClassMethods#audited method))
  3. Ensure the audits table exists by running rails generate audited:install or rails db:migrate (lib/generators/audited/install_generator.rb)
  4. Access audit history via user.audits association; query changes with user.audits.map(&:audited_changes) (lib/audited/audit.rb (see Audit model and associations))

Add a Custom Audit Field or Column

  1. Generate and run a migration using the upgrade generator: rails generate audited:upgrade --add-<field> (lib/generators/audited/upgrade_generator.rb)
  2. Choose a template matching your field (e.g., add_comment_to_audits.rb for comment support) (lib/generators/audited/templates/ (e.g., add_comment_to_audits.rb, add_remote_address_to_audits.rb))
  3. In your models, populate the new field via audited user_id: current_user.id or callbacks (lib/audited/auditor.rb (see #write_audit method and options handling))

Write Tests Using Audited RSpec Matchers

  1. Require the RSpec matchers in your spec_helper.rb or spec file: require 'audited-rspec' (lib/audited-rspec.rb)
  2. Use matchers in your specs: expect(user).to have_audited(:email, :name) or expect { user.update }.to change { user.audits.count } (lib/audited/rspec_matchers.rb (see HaveAudited matcher definition))
  3. Verify audit content in callbacks: user.audits.last.audited_changes returns { 'email' => [old, new] } (spec/audited/rspec_matchers_spec.rb (see test examples))

Migrate or Upgrade Audited Between Versions

  1. Run the upgrade generator to detect schema version: rails generate audited:upgrade (lib/generators/audited/upgrade_generator.rb)
  2. Review and apply generated migration files from templates (rename_changes_to_audited_changes.rb, etc.) (lib/generators/audited/templates/ (version-specific migrations))
  3. 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 generate commands

⚖️Trade-offs already made

  • Single audits table 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_changes column

    • 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

  1. 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_id for 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 logs user_id=nil. 5. Version constraints matter: Each Rails version has a specific Appraisal gemfile; bundling without Appraisals may mask incompatibilities.

🏗️Architecture

  • paper_trail/paper_trail — Direct competitor offering similar versioning and audit trail functionality; compare approach to Audited's design
  • westonganger/rails_db_comments — Complementary gem for recording database-level column comments, often paired with Audited for schema documentation
  • rails/rails — Core dependency; Audited targets specific Rails versions via Appraisals for version-specific hook and API compatibility
  • rspec/rspec-rails — Testing framework used throughout spec/ and via rspec matchers; understanding RSpec is prerequisite for contributing tests
  • collectiveidea/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 uuid install 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

📝Recent commits

Click to expand
  • 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.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · collectiveidea/audited — RepoPilot