Install the published add_auth package through your Rails app’s Gemfile, then rehearse these changes in an isolated copy of the app. Enable only the capabilities you need. Review the release status and upgrade procedure first.
Preserve a supported legacy verifier until the account has a valid current Rails password.
Check the effective verifier
Start with the source inventory. The bounded adapter covers the tested Devise bcrypt profile, including an explicitly supplied legacy pepper. A custom verifier, unknown digest, multiple scopes or missing identifier remains a blocker until its own conversion is proved. Never copy peppers or hashes into logs, reports or support tickets.
Prepare and backfill
The reviewed add_auth:devise_accounts migration preserves encrypted_password and adds canonical password/identifier fields. The bounded converter works in primary-key order, locks each account, rechecks source state and keeps Devise authoritative. It does not send mail or create sessions.
For contributor rehearsals, the source repository includes examples/devise_backfill.rb and executable interruption/conflict coverage in spec/migration/backfill_checkpoint.rb. These are version-specific contributor tools, not a production deployment command. The operator supplies a reviewed manifest and a private checkpoint directory. Resume with the same source, configuration and target; reconcile a blocked batch before advancing.
Select exactly one verifier
In the reviewed destination User model, include AddAuth::Rails::PasswordAdoption after has_secure_password. Configure the tested legacy verifier explicitly:
require "add_auth/core/passwords/legacy_bcrypt"
AddAuth.configure do |config|
config.legacy_password_verifier = AddAuth::Core::Passwords::LegacyBcrypt.new
endFor a verified peppered source, supply pepper: -> { Rails.application.credentials.fetch(:legacy_devise_pepper) } to that adapter. Keep the secret only while the retained legacy cohort needs it.
The credential profile chooses its verifier. A failed Rails password never falls back to an old Devise digest. A successful compatible login can rehash under the account lock; historically valid passwords outside Rails’ new-assignment byte contract remain on their explicit verifier until reset. New-password policy does not invalidate an otherwise valid historical password at login.
Fence old writers
The opt-in AddAuth::Rails::Migration::SourceBridge belongs after Devise in a reviewed source model. It projects source credential writes while Devise is authoritative and rejects security writes or Devise admission after that account switches. It cannot inventory or fix arbitrary host workers and bulk SQL; drain incompatible writers and map their behavior before activation.
Verify replacement and interruption
Use real source-generated hashes. Prove current password acceptance, wrong-password denial, normalization conflicts, concurrent password changes, restart after a committed batch and zero migration mail. Then reset a password: the new password must work and the old password, sessions and spent reset links must remain invalid after a fresh compatibility boot.
If the verifier is unsupported, preserve the account and require an independently authorized enrollment/recovery path. Never invent confirmation provenance. Continue with migration recovery.