This upgrades Chatwoot to Rails 7.2.3.1 while retaining the current
Rails 7.0 framework defaults, so the runtime upgrade can be deployed and
observed independently from default-behavior changes.
## What changed
- Upgrade Rails and the compatible dependency set to Rails 7.2.3.1.
- Keep `config.load_defaults 7.0` for a staged, lower-risk rollout.
- Replace the unmaintained Azure Active Storage fork with the maintained
`azure-blob` adapter while preserving the `microsoft` service name.
- Pin Sidekiq 7.3.10 with `connection_pool` 2.x after validating
scheduled-job execution against Redis.
- Update Rails 7.2 compatibility surfaces in Active Record, strong
parameters, migrations, storage, and tests.
- Add read-only production preflight checks, an opt-in Active Storage
smoke script, a deployment runbook, and the full Rails 7.2/8.0/8.1
assessment.
## How to test
1. Sign in and verify the dashboard and conversation UI load normally.
2. Open the agent-management modal and confirm agent data is rendered.
3. Create an API inbox and wait for the asynchronous deletion flow to
complete.
4. Open Super Admin pages, including instance status and account-user
management.
5. Upload and download an attachment using the configured Active Storage
service.
6. Confirm recurring Sidekiq Cron jobs register and execute after
startup.
## Rollout
Follow `docs/rails_upgrades/7_2.md` for pre-deploy checks, deployment
order, smoke tests, monitoring, and rollback. Run `bundle exec rails
runner script/rails_upgrade/preflight.rb` against a
production-equivalent environment before rollout.
## Tracking
- [CW-5863 — Upgrade Rails to
8+](https://linear.app/chatwoot/issue/CW-5863/upgrade-rails-to-8)
- [Rails 7.2 to 8.1 upgrade and production rollout
plan](https://linear.app/chatwoot/document/chatwoot-rails-72-to-81-upgrade-and-production-rollout-plan-44e9f4964cb2)
---------
Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
Co-authored-by: Sony Mathew <2040199+sony-mathew@users.noreply.github.com>
Co-authored-by: Sony Mathew <sony@chatwoot.com>
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
## Description
Resolved conversations now preserve historical SLA misses without
allowing their displayed duration to keep growing. Applied SLAs record a
stable completion timestamp that is shared through REST and realtime
payloads, and the dashboard freezes FRT, NRT, and RT misses at that
point.
Legacy completed SLAs without a reliable timestamp remain visible as a
static missed state. Terminal SLAs remain frozen when a conversation is
reopened; a reopen before finalization continues the same SLA without
resetting its deadlines.
### Closes
[CW-7597](https://linear.app/chatwoot/issue/CW-7597/freeze-sla-miss-durations-after-conversation-resolution)
## Type of change
- [x] Bug fix (non-breaking change which fixes an issue)
## How to reproduce
1. Apply an SLA with a resolution-time threshold to a conversation.
2. Let the threshold breach, then resolve the conversation.
3. Observe that the recorded miss duration continues increasing every
minute even though the conversation is resolved.
## What changed
- Added nullable `applied_slas.completed_at` and exposed it as
`sla_completed_at` in conversation, report, and websocket payloads.
- Captured completion before broadcasting resolution and preserved it
for terminal applied SLAs.
- Frozen recorded FRT, NRT, and RT durations in classic and
next-generation conversation labels, including a static fallback for
legacy rows.
- Added a dry-run-first, resumable Rails runner for account-scoped or
explicitly global historical repair without enqueuing jobs or touching
`updated_at`.
Account-scoped production rollout starts with:
```sh
ACCOUNT_ID=168154 bundle exec rails runner script/backfill_applied_sla_completed_at.rb
ACCOUNT_ID=168154 APPLY=true bundle exec rails runner script/backfill_applied_sla_completed_at.rb
```
## How Has This Been Tested?
- Verified resolution stamping, nonterminal reopen clearing, and
terminal reopen preservation.
- Verified dry-run, apply, account/global scope, resume, skip,
idempotency, and timestamp-preserving backfill behavior.
- Verified all three miss types freeze and existing conversation-card
behavior remains intact.
- 71 focused RSpec examples and 37 focused Vitest examples pass.
- RuboCop, ESLint, and diff checks pass.
## Checklist:
- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules
---------
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>