From 80743e0e7f091bfaa5b63148751e7842832a5fa0 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Wed, 19 Jun 2024 10:45:40 +0200
Subject: [PATCH 01/35] New Crowdin Translations (automated) (#30762)

Co-authored-by: GitHub Actions <noreply@github.com>
---
 config/locales/sv.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/config/locales/sv.yml b/config/locales/sv.yml
index a3d31547c..91b1720b5 100644
--- a/config/locales/sv.yml
+++ b/config/locales/sv.yml
@@ -293,6 +293,7 @@ sv:
       filter_by_action: Filtrera efter åtgärd
       filter_by_user: Filtrera efter användare
       title: Revisionslogg
+      unavailable_instance: "(domännamn inte tillgängligt)"
     announcements:
       destroyed_msg: Kungörelsen raderades!
       edit:

From a8b3d2e4e4e244f6dd44a2f9fe971279511534ac Mon Sep 17 00:00:00 2001
From: Matt Jankowski <matt@jankowski.online>
Date: Wed, 19 Jun 2024 04:45:47 -0400
Subject: [PATCH 02/35] Consolidate time periods methods into base measure
 (#30757)

---
 app/lib/admin/metrics/measure/active_users_measure.rb     | 8 --------
 app/lib/admin/metrics/measure/base_measure.rb             | 4 ++--
 .../admin/metrics/measure/instance_accounts_measure.rb    | 8 --------
 .../admin/metrics/measure/instance_followers_measure.rb   | 8 --------
 app/lib/admin/metrics/measure/instance_follows_measure.rb | 8 --------
 .../metrics/measure/instance_media_attachments_measure.rb | 8 --------
 app/lib/admin/metrics/measure/instance_reports_measure.rb | 8 --------
 .../admin/metrics/measure/instance_statuses_measure.rb    | 8 --------
 app/lib/admin/metrics/measure/interactions_measure.rb     | 8 --------
 app/lib/admin/metrics/measure/tag_accounts_measure.rb     | 8 --------
 app/lib/admin/metrics/measure/tag_uses_measure.rb         | 8 --------
 11 files changed, 2 insertions(+), 82 deletions(-)

diff --git a/app/lib/admin/metrics/measure/active_users_measure.rb b/app/lib/admin/metrics/measure/active_users_measure.rb
index e6f09d4bc..c085ced62 100644
--- a/app/lib/admin/metrics/measure/active_users_measure.rb
+++ b/app/lib/admin/metrics/measure/active_users_measure.rb
@@ -22,12 +22,4 @@ class Admin::Metrics::Measure::ActiveUsersMeasure < Admin::Metrics::Measure::Bas
   def activity_tracker
     @activity_tracker ||= ActivityTracker.new('activity:logins', :unique)
   end
-
-  def time_period
-    (@start_at.to_date..@end_at.to_date)
-  end
-
-  def previous_time_period
-    ((@start_at.to_date - length_of_period)..(@end_at.to_date - length_of_period))
-  end
 end
diff --git a/app/lib/admin/metrics/measure/base_measure.rb b/app/lib/admin/metrics/measure/base_measure.rb
index e33a6c494..8b7fe39b5 100644
--- a/app/lib/admin/metrics/measure/base_measure.rb
+++ b/app/lib/admin/metrics/measure/base_measure.rb
@@ -86,11 +86,11 @@ class Admin::Metrics::Measure::BaseMeasure
   end
 
   def time_period
-    (@start_at..@end_at)
+    (@start_at.to_date..@end_at.to_date)
   end
 
   def previous_time_period
-    ((@start_at - length_of_period)..(@end_at - length_of_period))
+    ((@start_at.to_date - length_of_period)..(@end_at.to_date - length_of_period))
   end
 
   def length_of_period
diff --git a/app/lib/admin/metrics/measure/instance_accounts_measure.rb b/app/lib/admin/metrics/measure/instance_accounts_measure.rb
index 746780ee7..889a5e6f0 100644
--- a/app/lib/admin/metrics/measure/instance_accounts_measure.rb
+++ b/app/lib/admin/metrics/measure/instance_accounts_measure.rb
@@ -48,14 +48,6 @@ class Admin::Metrics::Measure::InstanceAccountsMeasure < Admin::Metrics::Measure
     SQL
   end
 
-  def time_period
-    (@start_at.to_date..@end_at.to_date)
-  end
-
-  def previous_time_period
-    ((@start_at.to_date - length_of_period)..(@end_at.to_date - length_of_period))
-  end
-
   def params
     @params.permit(:domain, :include_subdomains)
   end
diff --git a/app/lib/admin/metrics/measure/instance_followers_measure.rb b/app/lib/admin/metrics/measure/instance_followers_measure.rb
index 0693d5a64..fa934c6b9 100644
--- a/app/lib/admin/metrics/measure/instance_followers_measure.rb
+++ b/app/lib/admin/metrics/measure/instance_followers_measure.rb
@@ -49,14 +49,6 @@ class Admin::Metrics::Measure::InstanceFollowersMeasure < Admin::Metrics::Measur
     SQL
   end
 
-  def time_period
-    (@start_at.to_date..@end_at.to_date)
-  end
-
-  def previous_time_period
-    ((@start_at.to_date - length_of_period)..(@end_at.to_date - length_of_period))
-  end
-
   def params
     @params.permit(:domain, :include_subdomains)
   end
diff --git a/app/lib/admin/metrics/measure/instance_follows_measure.rb b/app/lib/admin/metrics/measure/instance_follows_measure.rb
index 90d381935..3f3ab73fc 100644
--- a/app/lib/admin/metrics/measure/instance_follows_measure.rb
+++ b/app/lib/admin/metrics/measure/instance_follows_measure.rb
@@ -49,14 +49,6 @@ class Admin::Metrics::Measure::InstanceFollowsMeasure < Admin::Metrics::Measure:
     SQL
   end
 
-  def time_period
-    (@start_at.to_date..@end_at.to_date)
-  end
-
-  def previous_time_period
-    ((@start_at.to_date - length_of_period)..(@end_at.to_date - length_of_period))
-  end
-
   def params
     @params.permit(:domain, :include_subdomains)
   end
diff --git a/app/lib/admin/metrics/measure/instance_media_attachments_measure.rb b/app/lib/admin/metrics/measure/instance_media_attachments_measure.rb
index 89f8b4149..996ca52e0 100644
--- a/app/lib/admin/metrics/measure/instance_media_attachments_measure.rb
+++ b/app/lib/admin/metrics/measure/instance_media_attachments_measure.rb
@@ -58,14 +58,6 @@ class Admin::Metrics::Measure::InstanceMediaAttachmentsMeasure < Admin::Metrics:
     SQL
   end
 
-  def time_period
-    (@start_at.to_date..@end_at.to_date)
-  end
-
-  def previous_time_period
-    ((@start_at.to_date - length_of_period)..(@end_at.to_date - length_of_period))
-  end
-
   def params
     @params.permit(:domain, :include_subdomains)
   end
diff --git a/app/lib/admin/metrics/measure/instance_reports_measure.rb b/app/lib/admin/metrics/measure/instance_reports_measure.rb
index 5f58387a6..ae1bb6e68 100644
--- a/app/lib/admin/metrics/measure/instance_reports_measure.rb
+++ b/app/lib/admin/metrics/measure/instance_reports_measure.rb
@@ -49,14 +49,6 @@ class Admin::Metrics::Measure::InstanceReportsMeasure < Admin::Metrics::Measure:
     SQL
   end
 
-  def time_period
-    (@start_at.to_date..@end_at.to_date)
-  end
-
-  def previous_time_period
-    ((@start_at.to_date - length_of_period)..(@end_at.to_date - length_of_period))
-  end
-
   def params
     @params.permit(:domain, :include_subdomains)
   end
diff --git a/app/lib/admin/metrics/measure/instance_statuses_measure.rb b/app/lib/admin/metrics/measure/instance_statuses_measure.rb
index 5873c6e71..324d427b1 100644
--- a/app/lib/admin/metrics/measure/instance_statuses_measure.rb
+++ b/app/lib/admin/metrics/measure/instance_statuses_measure.rb
@@ -58,14 +58,6 @@ class Admin::Metrics::Measure::InstanceStatusesMeasure < Admin::Metrics::Measure
     Mastodon::Snowflake.id_at(@end_at.end_of_day, with_random: false)
   end
 
-  def time_period
-    (@start_at.to_date..@end_at.to_date)
-  end
-
-  def previous_time_period
-    ((@start_at.to_date - length_of_period)..(@end_at.to_date - length_of_period))
-  end
-
   def params
     @params.permit(:domain, :include_subdomains)
   end
diff --git a/app/lib/admin/metrics/measure/interactions_measure.rb b/app/lib/admin/metrics/measure/interactions_measure.rb
index 7a2b7e0fa..f4b4836b4 100644
--- a/app/lib/admin/metrics/measure/interactions_measure.rb
+++ b/app/lib/admin/metrics/measure/interactions_measure.rb
@@ -22,12 +22,4 @@ class Admin::Metrics::Measure::InteractionsMeasure < Admin::Metrics::Measure::Ba
   def activity_tracker
     @activity_tracker ||= ActivityTracker.new('activity:interactions', :basic)
   end
-
-  def time_period
-    (@start_at.to_date..@end_at.to_date)
-  end
-
-  def previous_time_period
-    ((@start_at.to_date - length_of_period)..(@end_at.to_date - length_of_period))
-  end
 end
diff --git a/app/lib/admin/metrics/measure/tag_accounts_measure.rb b/app/lib/admin/metrics/measure/tag_accounts_measure.rb
index 8f4512efe..906277b7d 100644
--- a/app/lib/admin/metrics/measure/tag_accounts_measure.rb
+++ b/app/lib/admin/metrics/measure/tag_accounts_measure.rb
@@ -27,14 +27,6 @@ class Admin::Metrics::Measure::TagAccountsMeasure < Admin::Metrics::Measure::Bas
     @tag ||= Tag.find(params[:id])
   end
 
-  def time_period
-    (@start_at.to_date..@end_at.to_date)
-  end
-
-  def previous_time_period
-    ((@start_at.to_date - length_of_period)..(@end_at.to_date - length_of_period))
-  end
-
   def params
     @params.permit(:id)
   end
diff --git a/app/lib/admin/metrics/measure/tag_uses_measure.rb b/app/lib/admin/metrics/measure/tag_uses_measure.rb
index bce86b89f..2be96a02b 100644
--- a/app/lib/admin/metrics/measure/tag_uses_measure.rb
+++ b/app/lib/admin/metrics/measure/tag_uses_measure.rb
@@ -27,14 +27,6 @@ class Admin::Metrics::Measure::TagUsesMeasure < Admin::Metrics::Measure::BaseMea
     @tag ||= Tag.find(params[:id])
   end
 
-  def time_period
-    (@start_at.to_date..@end_at.to_date)
-  end
-
-  def previous_time_period
-    ((@start_at.to_date - length_of_period)..(@end_at.to_date - length_of_period))
-  end
-
   def params
     @params.permit(:id)
   end

From 4e7e31538feb329abf1be454121fc5fdb8e16bd3 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Wed, 19 Jun 2024 10:45:51 +0200
Subject: [PATCH 03/35] chore(deps): update opentelemetry-ruby (non-major)
 (#30755)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
 Gemfile.lock | 21 +++++++--------------
 1 file changed, 7 insertions(+), 14 deletions(-)

diff --git a/Gemfile.lock b/Gemfile.lock
index 3a76cc50c..41fc86c8a 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -528,32 +528,27 @@ GEM
     opentelemetry-instrumentation-concurrent_ruby (0.21.3)
       opentelemetry-api (~> 1.0)
       opentelemetry-instrumentation-base (~> 0.22.1)
-    opentelemetry-instrumentation-excon (0.22.1)
+    opentelemetry-instrumentation-excon (0.22.3)
       opentelemetry-api (~> 1.0)
-      opentelemetry-common (~> 0.20.0)
       opentelemetry-instrumentation-base (~> 0.22.1)
-    opentelemetry-instrumentation-faraday (0.24.2)
+    opentelemetry-instrumentation-faraday (0.24.4)
       opentelemetry-api (~> 1.0)
-      opentelemetry-common (~> 0.20.0)
       opentelemetry-instrumentation-base (~> 0.22.1)
     opentelemetry-instrumentation-http (0.23.3)
       opentelemetry-api (~> 1.0)
       opentelemetry-instrumentation-base (~> 0.22.1)
-    opentelemetry-instrumentation-http_client (0.22.4)
+    opentelemetry-instrumentation-http_client (0.22.6)
       opentelemetry-api (~> 1.0)
-      opentelemetry-common (~> 0.20.0)
       opentelemetry-instrumentation-base (~> 0.22.1)
-    opentelemetry-instrumentation-net_http (0.22.4)
+    opentelemetry-instrumentation-net_http (0.22.6)
       opentelemetry-api (~> 1.0)
-      opentelemetry-common (~> 0.20.0)
       opentelemetry-instrumentation-base (~> 0.22.1)
     opentelemetry-instrumentation-pg (0.27.3)
       opentelemetry-api (~> 1.0)
       opentelemetry-helpers-sql-obfuscation
       opentelemetry-instrumentation-base (~> 0.22.1)
-    opentelemetry-instrumentation-rack (0.24.3)
+    opentelemetry-instrumentation-rack (0.24.5)
       opentelemetry-api (~> 1.0)
-      opentelemetry-common (~> 0.20.0)
       opentelemetry-instrumentation-base (~> 0.22.1)
     opentelemetry-instrumentation-rails (0.30.2)
       opentelemetry-api (~> 1.0)
@@ -564,13 +559,11 @@ GEM
       opentelemetry-instrumentation-active_record (~> 0.7.0)
       opentelemetry-instrumentation-active_support (~> 0.5.0)
       opentelemetry-instrumentation-base (~> 0.22.1)
-    opentelemetry-instrumentation-redis (0.25.4)
+    opentelemetry-instrumentation-redis (0.25.6)
       opentelemetry-api (~> 1.0)
-      opentelemetry-common (~> 0.20.0)
       opentelemetry-instrumentation-base (~> 0.22.1)
-    opentelemetry-instrumentation-sidekiq (0.25.3)
+    opentelemetry-instrumentation-sidekiq (0.25.5)
       opentelemetry-api (~> 1.0)
-      opentelemetry-common (~> 0.20.0)
       opentelemetry-instrumentation-base (~> 0.22.1)
     opentelemetry-registry (0.3.1)
       opentelemetry-api (~> 1.1)

From 556d4097804838efed16e4ac6cb57db3b4b50216 Mon Sep 17 00:00:00 2001
From: Matt Jankowski <matt@jankowski.online>
Date: Wed, 19 Jun 2024 05:08:04 -0400
Subject: [PATCH 04/35] Enable renovate `lockFileMaintenance` setting (#30732)

---
 .github/renovate.json5 | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/.github/renovate.json5 b/.github/renovate.json5
index 2cf7bec8e..03787dfac 100644
--- a/.github/renovate.json5
+++ b/.github/renovate.json5
@@ -14,6 +14,9 @@
   // to `null` after any other rule set it to something.
   dependencyDashboardHeader: 'This issue lists Renovate updates and detected dependencies. Read the [Dependency Dashboard](https://docs.renovatebot.com/key-concepts/dashboard/) docs to learn more. Before approving any upgrade: read the description and comments in the [`renovate.json5` file](https://github.com/mastodon/mastodon/blob/main/.github/renovate.json5).',
   postUpdateOptions: ['yarnDedupeHighest'],
+  lockFileMaintenance: {
+    enabled: true,
+  },
   packageRules: [
     {
       // Require Dependency Dashboard Approval for major version bumps of these node packages

From 8098d27f84028c226729c76f1ebdeadec881b1c5 Mon Sep 17 00:00:00 2001
From: Claire <claire.github-309c@sitedethib.com>
Date: Wed, 19 Jun 2024 11:31:30 +0200
Subject: [PATCH 05/35] Stop calling Webpacker in full-stack tests (#30763)

---
 .github/workflows/test-ruby.yml          | 8 ++++++--
 spec/support/streaming_server_manager.rb | 3 ---
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/.github/workflows/test-ruby.yml b/.github/workflows/test-ruby.yml
index 513de2072..dd71fd253 100644
--- a/.github/workflows/test-ruby.yml
+++ b/.github/workflows/test-ruby.yml
@@ -285,9 +285,13 @@ jobs:
 
       - uses: actions/download-artifact@v4
         with:
-          path: './public'
+          path: './'
           name: ${{ github.sha }}
 
+      - name: Expand archived asset artifacts
+        run: |
+          tar xvzf artifacts.tar.gz
+
       - name: Set up Ruby environment
         uses: ./.github/actions/setup-ruby
         with:
@@ -405,7 +409,7 @@ jobs:
 
       - uses: actions/download-artifact@v4
         with:
-          path: './public'
+          path: './'
           name: ${{ github.sha }}
 
       - name: Set up Ruby environment
diff --git a/spec/support/streaming_server_manager.rb b/spec/support/streaming_server_manager.rb
index 3facf16b8..376d6b872 100644
--- a/spec/support/streaming_server_manager.rb
+++ b/spec/support/streaming_server_manager.rb
@@ -80,9 +80,6 @@ end
 RSpec.configure do |config|
   config.before :suite do
     if streaming_examples_present?
-      # Compile assets
-      Webpacker.compile
-
       # Start the node streaming server
       streaming_server_manager.start(port: STREAMING_PORT)
     end

From 49b323c13ddfcaad6c4ad1de74f712f44cfef0bb Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Wed, 19 Jun 2024 11:31:56 +0200
Subject: [PATCH 06/35] fix(deps): update dependency cssnano to v7.0.3 (#30764)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
 yarn.lock | 205 +++++++++++++++++++++++++++---------------------------
 1 file changed, 104 insertions(+), 101 deletions(-)

diff --git a/yarn.lock b/yarn.lock
index 1be5eb422..61a8f420a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5643,17 +5643,17 @@ __metadata:
   languageName: node
   linkType: hard
 
-"browserslist@npm:^4.0.0, browserslist@npm:^4.22.2, browserslist@npm:^4.22.3, browserslist@npm:^4.23.0":
-  version: 4.23.0
-  resolution: "browserslist@npm:4.23.0"
+"browserslist@npm:^4.0.0, browserslist@npm:^4.22.2, browserslist@npm:^4.22.3, browserslist@npm:^4.23.0, browserslist@npm:^4.23.1":
+  version: 4.23.1
+  resolution: "browserslist@npm:4.23.1"
   dependencies:
-    caniuse-lite: "npm:^1.0.30001587"
-    electron-to-chromium: "npm:^1.4.668"
+    caniuse-lite: "npm:^1.0.30001629"
+    electron-to-chromium: "npm:^1.4.796"
     node-releases: "npm:^2.0.14"
-    update-browserslist-db: "npm:^1.0.13"
+    update-browserslist-db: "npm:^1.0.16"
   bin:
     browserslist: cli.js
-  checksum: 10c0/8e9cc154529062128d02a7af4d8adeead83ca1df8cd9ee65a88e2161039f3d68a4d40fea7353cab6bae4c16182dec2fdd9a1cf7dc2a2935498cee1af0e998943
+  checksum: 10c0/eb47c7ab9d60db25ce2faca70efeb278faa7282a2f62b7f2fa2f92e5f5251cf65144244566c86559419ff4f6d78f59ea50e39911321ad91f3b27788901f1f5e9
   languageName: node
   linkType: hard
 
@@ -5855,10 +5855,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001587, caniuse-lite@npm:^1.0.30001599":
-  version: 1.0.30001599
-  resolution: "caniuse-lite@npm:1.0.30001599"
-  checksum: 10c0/8b3b9610b5be88533a3c8d0770d6896f7b1a9fee3dbeb7339e4ee119a514c81e5e07a628a5a289a6541ca291ac78a9402f5a99cf6012139e91f379083488a8eb
+"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001599, caniuse-lite@npm:^1.0.30001629":
+  version: 1.0.30001636
+  resolution: "caniuse-lite@npm:1.0.30001636"
+  checksum: 10c0/e5f965b4da7bae1531fd9f93477d015729ff9e3fa12670ead39a9e6cdc4c43e62c272d47857c5cc332e7b02d697cb3f2f965a1030870ac7476da60c2fc81ee94
   languageName: node
   linkType: hard
 
@@ -6723,43 +6723,43 @@ __metadata:
   languageName: node
   linkType: hard
 
-"cssnano-preset-default@npm:^7.0.2":
-  version: 7.0.2
-  resolution: "cssnano-preset-default@npm:7.0.2"
+"cssnano-preset-default@npm:^7.0.3":
+  version: 7.0.3
+  resolution: "cssnano-preset-default@npm:7.0.3"
   dependencies:
-    browserslist: "npm:^4.23.0"
+    browserslist: "npm:^4.23.1"
     css-declaration-sorter: "npm:^7.2.0"
     cssnano-utils: "npm:^5.0.0"
     postcss-calc: "npm:^10.0.0"
-    postcss-colormin: "npm:^7.0.0"
-    postcss-convert-values: "npm:^7.0.0"
-    postcss-discard-comments: "npm:^7.0.0"
+    postcss-colormin: "npm:^7.0.1"
+    postcss-convert-values: "npm:^7.0.1"
+    postcss-discard-comments: "npm:^7.0.1"
     postcss-discard-duplicates: "npm:^7.0.0"
     postcss-discard-empty: "npm:^7.0.0"
     postcss-discard-overridden: "npm:^7.0.0"
-    postcss-merge-longhand: "npm:^7.0.1"
-    postcss-merge-rules: "npm:^7.0.1"
+    postcss-merge-longhand: "npm:^7.0.2"
+    postcss-merge-rules: "npm:^7.0.2"
     postcss-minify-font-values: "npm:^7.0.0"
     postcss-minify-gradients: "npm:^7.0.0"
-    postcss-minify-params: "npm:^7.0.0"
-    postcss-minify-selectors: "npm:^7.0.1"
+    postcss-minify-params: "npm:^7.0.1"
+    postcss-minify-selectors: "npm:^7.0.2"
     postcss-normalize-charset: "npm:^7.0.0"
     postcss-normalize-display-values: "npm:^7.0.0"
     postcss-normalize-positions: "npm:^7.0.0"
     postcss-normalize-repeat-style: "npm:^7.0.0"
     postcss-normalize-string: "npm:^7.0.0"
     postcss-normalize-timing-functions: "npm:^7.0.0"
-    postcss-normalize-unicode: "npm:^7.0.0"
+    postcss-normalize-unicode: "npm:^7.0.1"
     postcss-normalize-url: "npm:^7.0.0"
     postcss-normalize-whitespace: "npm:^7.0.0"
-    postcss-ordered-values: "npm:^7.0.0"
-    postcss-reduce-initial: "npm:^7.0.0"
+    postcss-ordered-values: "npm:^7.0.1"
+    postcss-reduce-initial: "npm:^7.0.1"
     postcss-reduce-transforms: "npm:^7.0.0"
     postcss-svgo: "npm:^7.0.1"
     postcss-unique-selectors: "npm:^7.0.1"
   peerDependencies:
     postcss: ^8.4.31
-  checksum: 10c0/7c66240594c1d7a0cc761e755236228b17251455aa57abc45be0631f7de0fde070c23b0e41ffa200d39cd8351718514217d8c7a8cc4f06b54289dc1d555dfeb2
+  checksum: 10c0/ab3e51003efed6542a12d43c10ca693ab26138a1d035697b9be8f07e084e37a78617cbb8028b0a7e7841302ec151f4ecf35cbd763efe291846b62c35ea4c0bb4
   languageName: node
   linkType: hard
 
@@ -6773,14 +6773,14 @@ __metadata:
   linkType: hard
 
 "cssnano@npm:^7.0.0":
-  version: 7.0.2
-  resolution: "cssnano@npm:7.0.2"
+  version: 7.0.3
+  resolution: "cssnano@npm:7.0.3"
   dependencies:
-    cssnano-preset-default: "npm:^7.0.2"
-    lilconfig: "npm:^3.1.1"
+    cssnano-preset-default: "npm:^7.0.3"
+    lilconfig: "npm:^3.1.2"
   peerDependencies:
     postcss: ^8.4.31
-  checksum: 10c0/ad43d8c2e96fa1022fc5103064e4f08da3fdc5501a946d455edf0b81981b58cd06ad2d3f0c68d666e2b687c10c02ffbb383252aa34da0ddc3bd4d075f4a922c7
+  checksum: 10c0/4cbcd1e0ebe0bd83196cc5b16b3a60d3ebc98326c79b2f71df597bb73c8e3ee1f42b89159d7a038acc398251184d648d9dd516f4194e46746f3af6fa74b4aec7
   languageName: node
   linkType: hard
 
@@ -7395,10 +7395,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"electron-to-chromium@npm:^1.4.668":
-  version: 1.4.681
-  resolution: "electron-to-chromium@npm:1.4.681"
-  checksum: 10c0/5b2558dfb8bb82c20fb5fa1d9bbe06a3add47431dc3e1e4815e997be6ad387787047d9e534ed96839a9e7012520a5281c865158b09db41d10c029af003f05f94
+"electron-to-chromium@npm:^1.4.796":
+  version: 1.4.806
+  resolution: "electron-to-chromium@npm:1.4.806"
+  checksum: 10c0/44f925ba64bb623d0482cd2f14fcfb27017cec1f11ee642e0d49cb128cd714ba5e074c2cd8756dfc18010aa66d3c64039cdea891905f7c17160a8963db574fab
   languageName: node
   linkType: hard
 
@@ -7714,10 +7714,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"escalade@npm:^3.1.1":
-  version: 3.1.1
-  resolution: "escalade@npm:3.1.1"
-  checksum: 10c0/afd02e6ca91ffa813e1108b5e7756566173d6bc0d1eb951cb44d6b21702ec17c1cf116cfe75d4a2b02e05acb0b808a7a9387d0d1ca5cf9c04ad03a8445c3e46d
+"escalade@npm:^3.1.1, escalade@npm:^3.1.2":
+  version: 3.1.2
+  resolution: "escalade@npm:3.1.2"
+  checksum: 10c0/6b4adafecd0682f3aa1cd1106b8fff30e492c7015b178bc81b2d2f75106dabea6c6d6e8508fc491bd58e597c74abb0e8e2368f943ecb9393d4162e3c2f3cf287
   languageName: node
   linkType: hard
 
@@ -11267,10 +11267,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"lilconfig@npm:^3.1.1, lilconfig@npm:~3.1.1":
-  version: 3.1.1
-  resolution: "lilconfig@npm:3.1.1"
-  checksum: 10c0/311b559794546894e3fe176663427326026c1c644145be9e8041c58e268aa9328799b8dfe7e4dd8c6a4ae305feae95a1c9e007db3569f35b42b6e1bc8274754c
+"lilconfig@npm:^3.1.2, lilconfig@npm:~3.1.1":
+  version: 3.1.2
+  resolution: "lilconfig@npm:3.1.2"
+  checksum: 10c0/f059630b1a9bddaeba83059db00c672b64dc14074e9f232adce32b38ca1b5686ab737eb665c5ba3c32f147f0002b4bee7311ad0386a9b98547b5623e87071fbe
   languageName: node
   linkType: hard
 
@@ -13236,29 +13236,29 @@ __metadata:
   languageName: node
   linkType: hard
 
-"postcss-colormin@npm:^7.0.0":
-  version: 7.0.0
-  resolution: "postcss-colormin@npm:7.0.0"
+"postcss-colormin@npm:^7.0.1":
+  version: 7.0.1
+  resolution: "postcss-colormin@npm:7.0.1"
   dependencies:
-    browserslist: "npm:^4.23.0"
+    browserslist: "npm:^4.23.1"
     caniuse-api: "npm:^3.0.0"
     colord: "npm:^2.9.3"
     postcss-value-parser: "npm:^4.2.0"
   peerDependencies:
     postcss: ^8.4.31
-  checksum: 10c0/d365a5365e0a94748309d32c7208cd06249bc53eb82cc32c771de4073b109fa8552e58d60dbe84d7e69e68081ed8a01fbf645d38a650e90cb2e13b21043cd796
+  checksum: 10c0/e01e9e129ce39320cf10bb09ee2a3ab5b44b77805d3f7827eea07297644838b85c33b78996eeae0a1aba327ffd72a6ab1d24949ebc831523e310e916d5500371
   languageName: node
   linkType: hard
 
-"postcss-convert-values@npm:^7.0.0":
-  version: 7.0.0
-  resolution: "postcss-convert-values@npm:7.0.0"
+"postcss-convert-values@npm:^7.0.1":
+  version: 7.0.1
+  resolution: "postcss-convert-values@npm:7.0.1"
   dependencies:
-    browserslist: "npm:^4.23.0"
+    browserslist: "npm:^4.23.1"
     postcss-value-parser: "npm:^4.2.0"
   peerDependencies:
     postcss: ^8.4.31
-  checksum: 10c0/5d7cfa06f307e024574a1842016f006691e0c1932352f53a99ce8f2f9930c64c3c1ae17518e9e4e5176630b99f1beaab37bc339bc779fb07dc543670ae66bb21
+  checksum: 10c0/612f025f179f0f2ad7365db8c0b423614dcb8e1e4061875a4691a39dede0bca758d1a8f9f5c8b08e12af053e9e884f65ca5626ccc723d5b3f420650d67fe3046
   languageName: node
   linkType: hard
 
@@ -13316,12 +13316,14 @@ __metadata:
   languageName: node
   linkType: hard
 
-"postcss-discard-comments@npm:^7.0.0":
-  version: 7.0.0
-  resolution: "postcss-discard-comments@npm:7.0.0"
+"postcss-discard-comments@npm:^7.0.1":
+  version: 7.0.1
+  resolution: "postcss-discard-comments@npm:7.0.1"
+  dependencies:
+    postcss-selector-parser: "npm:^6.1.0"
   peerDependencies:
     postcss: ^8.4.31
-  checksum: 10c0/7fef7deea85c1e68161f69057be19a3aedd54d23c9b464c9b1531faa7a115f0c96a4f0ee3a560ce300578599dbc8114fe0fb744208b20b9d2fd8df1b4b39c58a
+  checksum: 10c0/64de3fced7e0e49dfea6aede8a5ca495b81dcd01c3c47734a5fbc86a3cb2b1ae39e1958e34e9bea64ecabd5fb4d8c287ec1d6189cf175c2434c6b6582da79948
   languageName: node
   linkType: hard
 
@@ -13466,29 +13468,29 @@ __metadata:
   languageName: node
   linkType: hard
 
-"postcss-merge-longhand@npm:^7.0.1":
-  version: 7.0.1
-  resolution: "postcss-merge-longhand@npm:7.0.1"
+"postcss-merge-longhand@npm:^7.0.2":
+  version: 7.0.2
+  resolution: "postcss-merge-longhand@npm:7.0.2"
   dependencies:
     postcss-value-parser: "npm:^4.2.0"
-    stylehacks: "npm:^7.0.1"
+    stylehacks: "npm:^7.0.2"
   peerDependencies:
     postcss: ^8.4.31
-  checksum: 10c0/e3d20502e65c82c9c4ba2e400bd093ee6b9c1b0019618ccd50eb40ef0e496206dd518c7e655a6986d780d5a52576e32e8f310d00484b15f67c77664a148df6eb
+  checksum: 10c0/71d22418e5850e134bfcf2038acb1c91eeb48d9b6f9e4c0252fee757e11dc4ae351097a855c327fbc38dc7658fa6edc7cc7f458c08bb4044b82c6005dc565fcb
   languageName: node
   linkType: hard
 
-"postcss-merge-rules@npm:^7.0.1":
-  version: 7.0.1
-  resolution: "postcss-merge-rules@npm:7.0.1"
+"postcss-merge-rules@npm:^7.0.2":
+  version: 7.0.2
+  resolution: "postcss-merge-rules@npm:7.0.2"
   dependencies:
-    browserslist: "npm:^4.23.0"
+    browserslist: "npm:^4.23.1"
     caniuse-api: "npm:^3.0.0"
     cssnano-utils: "npm:^5.0.0"
     postcss-selector-parser: "npm:^6.1.0"
   peerDependencies:
     postcss: ^8.4.31
-  checksum: 10c0/d380c162327e7aad59efb55cfddc5ec4e3bf51d18b07b832fdd876505279bac3cb44511ada8e1e1992428dcec4f64c7ec457b6ff9109063c5a61abf4b59b7176
+  checksum: 10c0/fbad20382ca45f1b3b5ff704c075f899cc9ba8418ae6effbdeb9e7c1f9b5c24996d1941ad36cd0936d60cbf127a72f235b2cbb0c44d9239a8a61042406d95b4a
   languageName: node
   linkType: hard
 
@@ -13516,27 +13518,28 @@ __metadata:
   languageName: node
   linkType: hard
 
-"postcss-minify-params@npm:^7.0.0":
-  version: 7.0.0
-  resolution: "postcss-minify-params@npm:7.0.0"
+"postcss-minify-params@npm:^7.0.1":
+  version: 7.0.1
+  resolution: "postcss-minify-params@npm:7.0.1"
   dependencies:
-    browserslist: "npm:^4.23.0"
+    browserslist: "npm:^4.23.1"
     cssnano-utils: "npm:^5.0.0"
     postcss-value-parser: "npm:^4.2.0"
   peerDependencies:
     postcss: ^8.4.31
-  checksum: 10c0/28a7ae313a197aeaff8b3fa1e695a6443b11a74258374a05adee6a1b05f5849ef52037b7a5069d6910614b03b4610acdaf4a76f38b89cb42e813a8cb5ec2fc01
+  checksum: 10c0/84e1c4de5af47178c1f48e10ce16341560f32bb2becf5ec9b014103f6c706174bc70885e2e13ced4de9b4f1959fb970193261cbd4751c8b87d5159e859e8c5ec
   languageName: node
   linkType: hard
 
-"postcss-minify-selectors@npm:^7.0.1":
-  version: 7.0.1
-  resolution: "postcss-minify-selectors@npm:7.0.1"
+"postcss-minify-selectors@npm:^7.0.2":
+  version: 7.0.2
+  resolution: "postcss-minify-selectors@npm:7.0.2"
   dependencies:
+    cssesc: "npm:^3.0.0"
     postcss-selector-parser: "npm:^6.1.0"
   peerDependencies:
     postcss: ^8.4.31
-  checksum: 10c0/a8ff69657fb1808d8f0f105b13a416426902d6f498a4b7ebb3b96b4b9149e97ee2e2ad6cd98108e2f0b8f781701724e6c51e120e215cee3e40c2d7a2afac755a
+  checksum: 10c0/87e0c21a0135b6c61b58d62c4c1e0cbd3cfb516ff8105db714c6a33a5edc477846ae220399d368e4ef6518529c711aa2dee9ff49e9befd93e83d5c939f3084a1
   languageName: node
   linkType: hard
 
@@ -13661,15 +13664,15 @@ __metadata:
   languageName: node
   linkType: hard
 
-"postcss-normalize-unicode@npm:^7.0.0":
-  version: 7.0.0
-  resolution: "postcss-normalize-unicode@npm:7.0.0"
+"postcss-normalize-unicode@npm:^7.0.1":
+  version: 7.0.1
+  resolution: "postcss-normalize-unicode@npm:7.0.1"
   dependencies:
-    browserslist: "npm:^4.23.0"
+    browserslist: "npm:^4.23.1"
     postcss-value-parser: "npm:^4.2.0"
   peerDependencies:
     postcss: ^8.4.31
-  checksum: 10c0/f2d6ab0076c006dcf3ed33ba30686f2d29e81a408c66acced22e2c942df6d613697ea786137833dd258aafab5fda4d3eb27df13a82df830357dbad9b79154881
+  checksum: 10c0/fcabac738765f608cb211ac01a19f9a7d784f99d223ef6f31352f37b9bcf008e0ca7849414c9e77116be8660d78b01dba6fc4a87cee7c9a977d3c2741d6a222d
   languageName: node
   linkType: hard
 
@@ -13704,15 +13707,15 @@ __metadata:
   languageName: node
   linkType: hard
 
-"postcss-ordered-values@npm:^7.0.0":
-  version: 7.0.0
-  resolution: "postcss-ordered-values@npm:7.0.0"
+"postcss-ordered-values@npm:^7.0.1":
+  version: 7.0.1
+  resolution: "postcss-ordered-values@npm:7.0.1"
   dependencies:
     cssnano-utils: "npm:^5.0.0"
     postcss-value-parser: "npm:^4.2.0"
   peerDependencies:
     postcss: ^8.4.31
-  checksum: 10c0/42b14f9518b573318594c2aeb2f13fd1fbe44936d14f1b28a438e7a82644ace9a2946699bebfe7a2d383534dc24e7203c35308d749f3c585a86daa238ad920a4
+  checksum: 10c0/9fc62e9039c7d4fa417d165678b065fc577a7232aa41a94a4e9208ad7db2268e1ce003aaad7c6a569afdf890a43416b0bf21047461505b4e3a16eec311a6eb63
   languageName: node
   linkType: hard
 
@@ -13828,15 +13831,15 @@ __metadata:
   languageName: node
   linkType: hard
 
-"postcss-reduce-initial@npm:^7.0.0":
-  version: 7.0.0
-  resolution: "postcss-reduce-initial@npm:7.0.0"
+"postcss-reduce-initial@npm:^7.0.1":
+  version: 7.0.1
+  resolution: "postcss-reduce-initial@npm:7.0.1"
   dependencies:
-    browserslist: "npm:^4.23.0"
+    browserslist: "npm:^4.23.1"
     caniuse-api: "npm:^3.0.0"
   peerDependencies:
     postcss: ^8.4.31
-  checksum: 10c0/ed50cd680ce258df953b82ce9b3fb52564d08548724577810800e236d017d80430cbccb4b1ad38b0f4d521663598e44ab93136b20064231181ef49e1e113ae10
+  checksum: 10c0/3e7c6c1d0cc4ace38f44971f02d0dd98131af678cf114aa05cfa0c066420019d5329c221ef8507644b8a79d0e76534303f747c97860ac777fe17f57110edefe1
   languageName: node
   linkType: hard
 
@@ -16407,15 +16410,15 @@ __metadata:
   languageName: node
   linkType: hard
 
-"stylehacks@npm:^7.0.1":
-  version: 7.0.1
-  resolution: "stylehacks@npm:7.0.1"
+"stylehacks@npm:^7.0.2":
+  version: 7.0.2
+  resolution: "stylehacks@npm:7.0.2"
   dependencies:
-    browserslist: "npm:^4.23.0"
+    browserslist: "npm:^4.23.1"
     postcss-selector-parser: "npm:^6.1.0"
   peerDependencies:
     postcss: ^8.4.31
-  checksum: 10c0/538d5d9c6d84906efad3706f0873b85b67fa224f17759b122bad3d60f2928c31204fd658dd16ec952bf54858a3aeaef4643e040c04030459285ce1b13c4cae91
+  checksum: 10c0/552299e869ac430e1076c025ace6c80bdfd5b672632435625eb1bd45ff5611aad7f3ee810e72edc04dc0fc3761e08dec40d27b72c50b95690eea2de43238b8d8
   languageName: node
   linkType: hard
 
@@ -17334,17 +17337,17 @@ __metadata:
   languageName: node
   linkType: hard
 
-"update-browserslist-db@npm:^1.0.13":
-  version: 1.0.13
-  resolution: "update-browserslist-db@npm:1.0.13"
+"update-browserslist-db@npm:^1.0.16":
+  version: 1.0.16
+  resolution: "update-browserslist-db@npm:1.0.16"
   dependencies:
-    escalade: "npm:^3.1.1"
-    picocolors: "npm:^1.0.0"
+    escalade: "npm:^3.1.2"
+    picocolors: "npm:^1.0.1"
   peerDependencies:
     browserslist: ">= 4.21.0"
   bin:
     update-browserslist-db: cli.js
-  checksum: 10c0/e52b8b521c78ce1e0c775f356cd16a9c22c70d25f3e01180839c407a5dc787fb05a13f67560cbaf316770d26fa99f78f1acd711b1b54a4f35d4820d4ea7136e6
+  checksum: 10c0/5995399fc202adbb51567e4810e146cdf7af630a92cc969365a099150cb00597e425cc14987ca7080b09a4d0cfd2a3de53fbe72eebff171aed7f9bb81f9bf405
   languageName: node
   linkType: hard
 

From 5f4d231e980665c0946297909df508269fb25dc6 Mon Sep 17 00:00:00 2001
From: Matt Jankowski <matt@jankowski.online>
Date: Wed, 19 Jun 2024 05:34:24 -0400
Subject: [PATCH 07/35] Use rubocop `DisplayCopNames` and `UseCache` defaults
 (true) (#30750)

---
 .rubocop.yml | 2 --
 1 file changed, 2 deletions(-)

diff --git a/.rubocop.yml b/.rubocop.yml
index 6da1dc8cb..965f56f3e 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -1,7 +1,6 @@
 ---
 AllCops:
   CacheRootDirectory: tmp
-  DisplayCopNames: true
   DisplayStyleGuide: true
   Exclude:
     - Vagrantfile
@@ -10,7 +9,6 @@ AllCops:
   ExtraDetails: true
   NewCops: enable
   TargetRubyVersion: 3.1 # Oldest supported ruby version
-  UseCache: true
 
 inherit_from:
   - .rubocop/layout.yml

From 53776cd58f98e93797ebc9fb34f02ccdb6dad01f Mon Sep 17 00:00:00 2001
From: Nick Schonning <nschonni@gmail.com>
Date: Wed, 19 Jun 2024 09:42:36 -0400
Subject: [PATCH 08/35] Enable passing ESLint rules (#30726)

---
 .eslintrc.js | 27 +--------------------------
 1 file changed, 1 insertion(+), 26 deletions(-)

diff --git a/.eslintrc.js b/.eslintrc.js
index e3afb1c9f..d11826282 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -20,10 +20,6 @@ module.exports = defineConfig({
     es6: true,
   },
 
-  globals: {
-    ATTACHMENT_HOST: false,
-  },
-
   parser: '@typescript-eslint/parser',
 
   plugins: [
@@ -79,7 +75,7 @@ module.exports = defineConfig({
         ],
       },
     ],
-    'no-empty': 'off',
+    'no-empty': ['error', { "allowEmptyCatch": true }],
     'no-restricted-properties': [
       'error',
       { property: 'substring', message: 'Use .slice instead of .substring.' },
@@ -94,7 +90,6 @@ module.exports = defineConfig({
         message: "Use '·' (middle dot) instead of '•' (bullet)",
       },
     ],
-    'no-self-assign': 'off',
     'no-unused-expressions': 'error',
     'no-unused-vars': 'off',
     '@typescript-eslint/no-unused-vars': [
@@ -119,12 +114,10 @@ module.exports = defineConfig({
     'react/jsx-tag-spacing': 'error',
     'react/jsx-uses-react': 'off', // not needed with new JSX transform
     'react/jsx-wrap-multilines': 'error',
-    'react/no-deprecated': 'off',
     'react/react-in-jsx-scope': 'off', // not needed with new JSX transform
     'react/self-closing-comp': 'error',
 
     // recommended values found in https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/v6.8.0/src/index.js#L46
-    'jsx-a11y/accessible-emoji': 'warn',
     'jsx-a11y/click-events-have-key-events': 'off',
     'jsx-a11y/label-has-associated-control': 'off',
     'jsx-a11y/media-has-caption': 'off',
@@ -139,23 +132,6 @@ module.exports = defineConfig({
     // ],
     'jsx-a11y/no-interactive-element-to-noninteractive-role': 'off',
     // recommended rule is:
-    // 'jsx-a11y/no-noninteractive-element-interactions': [
-    //   'error',
-    //   {
-    //     body: ['onError', 'onLoad'],
-    //     iframe: ['onError', 'onLoad'],
-    //     img: ['onError', 'onLoad'],
-    //   },
-    // ],
-    'jsx-a11y/no-noninteractive-element-interactions': [
-      'warn',
-      {
-        handlers: [
-          'onClick',
-        ],
-      },
-    ],
-    // recommended rule is:
     // 'jsx-a11y/no-noninteractive-tabindex': [
     //   'error',
     //   {
@@ -165,7 +141,6 @@ module.exports = defineConfig({
     //   },
     // ],
     'jsx-a11y/no-noninteractive-tabindex': 'off',
-    'jsx-a11y/no-onchange': 'off',
     // recommended is full 'error'
     'jsx-a11y/no-static-element-interactions': [
       'warn',

From 84a31319e9900260b54c05fdeec804e182d06573 Mon Sep 17 00:00:00 2001
From: Matt Jankowski <matt@jankowski.online>
Date: Wed, 19 Jun 2024 09:46:52 -0400
Subject: [PATCH 09/35] Add `match_json_values` and use in AP worker specs
 (#30720)

---
 spec/support/matchers/json/match_json_schema.rb      | 11 +++++++++++
 .../distribute_poll_update_worker_spec.rb            |  2 +-
 spec/workers/activitypub/distribution_worker_spec.rb |  6 +++---
 .../activitypub/move_distribution_worker_spec.rb     | 12 ++++++++----
 .../status_update_distribution_worker_spec.rb        |  4 ++--
 .../activitypub/update_distribution_worker_spec.rb   |  2 +-
 6 files changed, 26 insertions(+), 11 deletions(-)

diff --git a/spec/support/matchers/json/match_json_schema.rb b/spec/support/matchers/json/match_json_schema.rb
index 3a275199e..b4ced8add 100644
--- a/spec/support/matchers/json/match_json_schema.rb
+++ b/spec/support/matchers/json/match_json_schema.rb
@@ -6,3 +6,14 @@ RSpec::Matchers.define :match_json_schema do |schema|
     JSON::Validator.validate(schema_path, input_json, validate_schema: true)
   end
 end
+
+RSpec::Matchers.define :match_json_values do |values|
+  match do |string|
+    expect(json_str_to_hash(string))
+      .to include(values)
+  end
+
+  failure_message do |value|
+    "expected that #{value} would have the same values as #{values}."
+  end
+end
diff --git a/spec/workers/activitypub/distribute_poll_update_worker_spec.rb b/spec/workers/activitypub/distribute_poll_update_worker_spec.rb
index afe2b291f..4427cfdf9 100644
--- a/spec/workers/activitypub/distribute_poll_update_worker_spec.rb
+++ b/spec/workers/activitypub/distribute_poll_update_worker_spec.rb
@@ -16,7 +16,7 @@ describe ActivityPub::DistributePollUpdateWorker do
     end
 
     it 'delivers to followers' do
-      expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[kind_of(String), account.id, 'http://example.com']]) do
+      expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[match_json_values(type: 'Update'), account.id, 'http://example.com']]) do
         subject.perform(status.id)
       end
     end
diff --git a/spec/workers/activitypub/distribution_worker_spec.rb b/spec/workers/activitypub/distribution_worker_spec.rb
index 2706967fc..0eb622785 100644
--- a/spec/workers/activitypub/distribution_worker_spec.rb
+++ b/spec/workers/activitypub/distribution_worker_spec.rb
@@ -19,7 +19,7 @@ describe ActivityPub::DistributionWorker do
       end
 
       it 'delivers to followers' do
-        expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[kind_of(String), status.account.id, 'http://example.com', anything]]) do
+        expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[match_json_values(type: 'Create'), status.account.id, 'http://example.com', anything]]) do
           subject.perform(status.id)
         end
       end
@@ -31,7 +31,7 @@ describe ActivityPub::DistributionWorker do
       end
 
       it 'delivers to followers' do
-        expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[kind_of(String), status.account.id, 'http://example.com', anything]]) do
+        expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[match_json_values(type: 'Create'), status.account.id, 'http://example.com', anything]]) do
           subject.perform(status.id)
         end
       end
@@ -46,7 +46,7 @@ describe ActivityPub::DistributionWorker do
       end
 
       it 'delivers to mentioned accounts' do
-        expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[kind_of(String), status.account.id, 'https://foo.bar/inbox', anything]]) do
+        expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[match_json_values(type: 'Create'), status.account.id, 'https://foo.bar/inbox', anything]]) do
           subject.perform(status.id)
         end
       end
diff --git a/spec/workers/activitypub/move_distribution_worker_spec.rb b/spec/workers/activitypub/move_distribution_worker_spec.rb
index 75ca21733..c810b33c2 100644
--- a/spec/workers/activitypub/move_distribution_worker_spec.rb
+++ b/spec/workers/activitypub/move_distribution_worker_spec.rb
@@ -16,12 +16,16 @@ describe ActivityPub::MoveDistributionWorker do
     end
 
     it 'delivers to followers and known blockers' do
-      expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [
-                                  [kind_of(String), migration.account.id, 'http://example.com'],
-                                  [kind_of(String), migration.account.id, 'http://example2.com'],
-                                ]) do
+      expect_push_bulk_to_match(ActivityPub::DeliveryWorker, expected_migration_deliveries) do
         subject.perform(migration.id)
       end
     end
+
+    def expected_migration_deliveries
+      [
+        [match_json_values(type: 'Move'), migration.account.id, 'http://example.com'],
+        [match_json_values(type: 'Move'), migration.account.id, 'http://example2.com'],
+      ]
+    end
   end
 end
diff --git a/spec/workers/activitypub/status_update_distribution_worker_spec.rb b/spec/workers/activitypub/status_update_distribution_worker_spec.rb
index a4fd246e5..66e52c4f2 100644
--- a/spec/workers/activitypub/status_update_distribution_worker_spec.rb
+++ b/spec/workers/activitypub/status_update_distribution_worker_spec.rb
@@ -25,7 +25,7 @@ describe ActivityPub::StatusUpdateDistributionWorker do
       end
 
       it 'delivers to followers' do
-        expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[kind_of(String), status.account.id, 'http://example.com', anything]]) do
+        expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[match_json_values(type: 'Update'), status.account.id, 'http://example.com', anything]]) do
           subject.perform(status.id)
         end
       end
@@ -37,7 +37,7 @@ describe ActivityPub::StatusUpdateDistributionWorker do
       end
 
       it 'delivers to followers' do
-        expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[kind_of(String), status.account.id, 'http://example.com', anything]]) do
+        expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[match_json_values(type: 'Update'), status.account.id, 'http://example.com', anything]]) do
           subject.perform(status.id)
         end
       end
diff --git a/spec/workers/activitypub/update_distribution_worker_spec.rb b/spec/workers/activitypub/update_distribution_worker_spec.rb
index 4a0ed050b..b183a58df 100644
--- a/spec/workers/activitypub/update_distribution_worker_spec.rb
+++ b/spec/workers/activitypub/update_distribution_worker_spec.rb
@@ -14,7 +14,7 @@ describe ActivityPub::UpdateDistributionWorker do
     end
 
     it 'delivers to followers' do
-      expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[kind_of(String), account.id, 'http://example.com', anything]]) do
+      expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[match_json_values(type: 'Update'), account.id, 'http://example.com', anything]]) do
         subject.perform(account.id)
       end
     end

From 2cda1dd542b20a47245cb8d28a4f6f8750c2284c Mon Sep 17 00:00:00 2001
From: Claire <claire.github-309c@sitedethib.com>
Date: Wed, 19 Jun 2024 18:59:37 +0200
Subject: [PATCH 10/35] Fix compatibility with Redis < 6.2 again (#30412)

---
 config/application.rb                        |  1 +
 lib/stoplight/redis_data_store_extensions.rb | 17 +++++++++++++++++
 2 files changed, 18 insertions(+)
 create mode 100644 lib/stoplight/redis_data_store_extensions.rb

diff --git a/config/application.rb b/config/application.rb
index 65407da05..5aca74fd1 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -49,6 +49,7 @@ require_relative '../lib/webpacker/manifest_extensions'
 require_relative '../lib/webpacker/helper_extensions'
 require_relative '../lib/rails/engine_extensions'
 require_relative '../lib/action_dispatch/remote_ip_extensions'
+require_relative '../lib/stoplight/redis_data_store_extensions'
 require_relative '../lib/active_record/database_tasks_extensions'
 require_relative '../lib/active_record/batches'
 require_relative '../lib/active_record/with_recursive'
diff --git a/lib/stoplight/redis_data_store_extensions.rb b/lib/stoplight/redis_data_store_extensions.rb
new file mode 100644
index 000000000..900748784
--- /dev/null
+++ b/lib/stoplight/redis_data_store_extensions.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+# Restore compatibility with Redis < 6.2
+
+module Stoplight
+  module DataStore
+    module RedisExtensions
+      def query_failures(light, transaction: @redis)
+        window_start = Time.now.to_i - light.window_size
+
+        transaction.zrevrangebyscore(failures_key(light), Float::INFINITY, window_start)
+      end
+    end
+  end
+end
+
+Stoplight::DataStore::Redis.prepend(Stoplight::DataStore::RedisExtensions)

From cb7121e5a9ad4f0fa0a2d4a6058b3889570ca76e Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Thu, 20 Jun 2024 09:42:28 +0200
Subject: [PATCH 11/35] chore(deps): update dependency rspec-rails to v6.1.3
 (#30770)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
 Gemfile.lock | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/Gemfile.lock b/Gemfile.lock
index 41fc86c8a..1f8645a59 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -702,7 +702,7 @@ GEM
     rqrcode_core (1.2.0)
     rspec-core (3.13.0)
       rspec-support (~> 3.13.0)
-    rspec-expectations (3.13.0)
+    rspec-expectations (3.13.1)
       diff-lcs (>= 1.2.0, < 2.0)
       rspec-support (~> 3.13.0)
     rspec-github (2.4.0)
@@ -710,7 +710,7 @@ GEM
     rspec-mocks (3.13.1)
       diff-lcs (>= 1.2.0, < 2.0)
       rspec-support (~> 3.13.0)
-    rspec-rails (6.1.2)
+    rspec-rails (6.1.3)
       actionpack (>= 6.1)
       activesupport (>= 6.1)
       railties (>= 6.1)
@@ -891,7 +891,7 @@ GEM
     xorcist (1.1.3)
     xpath (3.2.0)
       nokogiri (~> 1.8)
-    zeitwerk (2.6.15)
+    zeitwerk (2.6.16)
 
 PLATFORMS
   ruby

From a0910cd49ca0f455ed6616deb429b41dc55e2207 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Thu, 20 Jun 2024 11:03:28 +0200
Subject: [PATCH 12/35] New Crowdin Translations (automated) (#30772)

Co-authored-by: GitHub Actions <noreply@github.com>
---
 app/javascript/mastodon/locales/ko.json | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json
index aa05887d6..c4c084d98 100644
--- a/app/javascript/mastodon/locales/ko.json
+++ b/app/javascript/mastodon/locales/ko.json
@@ -32,7 +32,7 @@
   "account.featured_tags.last_status_never": "게시물 없음",
   "account.featured_tags.title": "{name} 님의 추천 해시태그",
   "account.follow": "팔로우",
-  "account.follow_back": "맞팔로우",
+  "account.follow_back": "맞팔로우 하기",
   "account.followers": "팔로워",
   "account.followers.empty": "아직 아무도 이 사용자를 팔로우하고 있지 않습니다.",
   "account.followers_counter": "{counter} 팔로워",
@@ -53,7 +53,7 @@
   "account.mute_notifications_short": "알림 뮤트",
   "account.mute_short": "뮤트",
   "account.muted": "뮤트됨",
-  "account.mutual": "상호 팔로우",
+  "account.mutual": "맞팔로우 중",
   "account.no_bio": "제공된 설명이 없습니다.",
   "account.open_original_page": "원본 페이지 열기",
   "account.posts": "게시물",

From 7889e983fbe7e29f3f91784cfa2117e620514ad7 Mon Sep 17 00:00:00 2001
From: Claire <claire.github-309c@sitedethib.com>
Date: Thu, 20 Jun 2024 13:05:25 +0200
Subject: [PATCH 13/35] Add `group_key` attribute to `NotificationSerializer` 
 (#30776)

Co-authored-by: Renaud Chaput <renchap@gmail.com>
---
 app/serializers/rest/notification_serializer.rb | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/app/serializers/rest/notification_serializer.rb b/app/serializers/rest/notification_serializer.rb
index 417245d19..966819585 100644
--- a/app/serializers/rest/notification_serializer.rb
+++ b/app/serializers/rest/notification_serializer.rb
@@ -1,7 +1,7 @@
 # frozen_string_literal: true
 
 class REST::NotificationSerializer < ActiveModel::Serializer
-  attributes :id, :type, :created_at
+  attributes :id, :type, :created_at, :group_key
 
   belongs_to :from_account, key: :account, serializer: REST::AccountSerializer
   belongs_to :target_status, key: :status, if: :status_type?, serializer: REST::StatusSerializer
@@ -13,6 +13,10 @@ class REST::NotificationSerializer < ActiveModel::Serializer
     object.id.to_s
   end
 
+  def group_key
+    object.group_key || "ungrouped-#{object.id}"
+  end
+
   def status_type?
     [:favourite, :reblog, :status, :mention, :poll, :update].include?(object.type)
   end

From 27529247b289a0e78d2deb97626ddb60baf04d86 Mon Sep 17 00:00:00 2001
From: Renaud Chaput <renchap@gmail.com>
Date: Thu, 20 Jun 2024 13:42:10 +0200
Subject: [PATCH 14/35] Improve `createdataLoadingThunk` (#30778)

---
 .../mastodon/store/typed_functions.ts         | 36 +++++++++++++------
 1 file changed, 25 insertions(+), 11 deletions(-)

diff --git a/app/javascript/mastodon/store/typed_functions.ts b/app/javascript/mastodon/store/typed_functions.ts
index dae37e622..e5820149d 100644
--- a/app/javascript/mastodon/store/typed_functions.ts
+++ b/app/javascript/mastodon/store/typed_functions.ts
@@ -82,13 +82,19 @@ export function createThunk<Arg = void, Returned = void>(
 const discardLoadDataInPayload = Symbol('discardLoadDataInPayload');
 type DiscardLoadData = typeof discardLoadDataInPayload;
 
-type OnData<LoadDataResult, ReturnedData> = (
+type OnData<ActionArg, LoadDataResult, ReturnedData> = (
   data: LoadDataResult,
   api: AppThunkApi & {
+    actionArg: ActionArg;
     discardLoadData: DiscardLoadData;
   },
 ) => ReturnedData | DiscardLoadData | Promise<ReturnedData | DiscardLoadData>;
 
+type LoadData<Args, LoadDataResult> = (
+  args: Args,
+  api: AppThunkApi,
+) => Promise<LoadDataResult>;
+
 type ArgsType = Record<string, unknown> | undefined;
 
 // Overload when there is no `onData` method, the payload is the `onData` result
@@ -101,18 +107,18 @@ export function createDataLoadingThunk<LoadDataResult, Args extends ArgsType>(
 // Overload when the `onData` method returns discardLoadDataInPayload, then the payload is empty
 export function createDataLoadingThunk<LoadDataResult, Args extends ArgsType>(
   name: string,
-  loadData: (args: Args) => Promise<LoadDataResult>,
+  loadData: LoadData<Args, LoadDataResult>,
   onDataOrThunkOptions?:
     | AppThunkOptions
-    | OnData<LoadDataResult, DiscardLoadData>,
+    | OnData<Args, LoadDataResult, DiscardLoadData>,
   thunkOptions?: AppThunkOptions,
 ): ReturnType<typeof createThunk<Args, void>>;
 
 // Overload when the `onData` method returns nothing, then the mayload is the `onData` result
 export function createDataLoadingThunk<LoadDataResult, Args extends ArgsType>(
   name: string,
-  loadData: (args: Args) => Promise<LoadDataResult>,
-  onDataOrThunkOptions?: AppThunkOptions | OnData<LoadDataResult, void>,
+  loadData: LoadData<Args, LoadDataResult>,
+  onDataOrThunkOptions?: AppThunkOptions | OnData<Args, LoadDataResult, void>,
   thunkOptions?: AppThunkOptions,
 ): ReturnType<typeof createThunk<Args, LoadDataResult>>;
 
@@ -123,8 +129,10 @@ export function createDataLoadingThunk<
   Returned,
 >(
   name: string,
-  loadData: (args: Args) => Promise<LoadDataResult>,
-  onDataOrThunkOptions?: AppThunkOptions | OnData<LoadDataResult, Returned>,
+  loadData: LoadData<Args, LoadDataResult>,
+  onDataOrThunkOptions?:
+    | AppThunkOptions
+    | OnData<Args, LoadDataResult, Returned>,
   thunkOptions?: AppThunkOptions,
 ): ReturnType<typeof createThunk<Args, Returned>>;
 
@@ -159,11 +167,13 @@ export function createDataLoadingThunk<
   Returned,
 >(
   name: string,
-  loadData: (args: Args) => Promise<LoadDataResult>,
-  onDataOrThunkOptions?: AppThunkOptions | OnData<LoadDataResult, Returned>,
+  loadData: LoadData<Args, LoadDataResult>,
+  onDataOrThunkOptions?:
+    | AppThunkOptions
+    | OnData<Args, LoadDataResult, Returned>,
   maybeThunkOptions?: AppThunkOptions,
 ) {
-  let onData: OnData<LoadDataResult, Returned> | undefined;
+  let onData: OnData<Args, LoadDataResult, Returned> | undefined;
   let thunkOptions: AppThunkOptions | undefined;
 
   if (typeof onDataOrThunkOptions === 'function') onData = onDataOrThunkOptions;
@@ -177,7 +187,10 @@ export function createDataLoadingThunk<
   return createThunk<Args, Returned>(
     name,
     async (arg, { getState, dispatch }) => {
-      const data = await loadData(arg);
+      const data = await loadData(arg, {
+        dispatch,
+        getState,
+      });
 
       if (!onData) return data as Returned;
 
@@ -185,6 +198,7 @@ export function createDataLoadingThunk<
         dispatch,
         getState,
         discardLoadData: discardLoadDataInPayload,
+        actionArg: arg,
       });
 
       // if there is no return in `onData`, we return the `onData` result

From 1c6593277696c6f4698684860f7c6d6189f9b371 Mon Sep 17 00:00:00 2001
From: Renaud Chaput <renchap@gmail.com>
Date: Thu, 20 Jun 2024 13:56:52 +0200
Subject: [PATCH 15/35] Convert `disconnectTimeline` and `timelineDelete`
 actions to Typescript (#30777)

---
 app/javascript/mastodon/actions/streaming.js  |  2 +-
 app/javascript/mastodon/actions/timelines.js  | 21 +++++--------------
 .../mastodon/actions/timelines_typed.ts       | 20 ++++++++++++++++++
 .../features/account_timeline/index.jsx       |  4 ++--
 app/javascript/mastodon/reducers/compose.js   |  9 ++++----
 app/javascript/mastodon/reducers/contexts.js  |  8 ++++---
 app/javascript/mastodon/reducers/modal.ts     |  7 ++++---
 .../mastodon/reducers/notifications.js        | 13 ++++++------
 .../mastodon/reducers/picture_in_picture.ts   |  8 +++----
 app/javascript/mastodon/reducers/statuses.js  |  7 ++++---
 app/javascript/mastodon/reducers/timelines.js | 15 ++++++-------
 11 files changed, 65 insertions(+), 49 deletions(-)
 create mode 100644 app/javascript/mastodon/actions/timelines_typed.ts

diff --git a/app/javascript/mastodon/actions/streaming.js b/app/javascript/mastodon/actions/streaming.js
index 9daeb3c60..e7fe1c53e 100644
--- a/app/javascript/mastodon/actions/streaming.js
+++ b/app/javascript/mastodon/actions/streaming.js
@@ -77,7 +77,7 @@ export const connectTimelineStream = (timelineId, channelName, params = {}, opti
       },
 
       onDisconnect() {
-        dispatch(disconnectTimeline(timelineId));
+        dispatch(disconnectTimeline({ timeline: timelineId }));
 
         if (options.fallback) {
           // @ts-expect-error
diff --git a/app/javascript/mastodon/actions/timelines.js b/app/javascript/mastodon/actions/timelines.js
index dc37cdf1f..d1851551b 100644
--- a/app/javascript/mastodon/actions/timelines.js
+++ b/app/javascript/mastodon/actions/timelines.js
@@ -6,9 +6,11 @@ import { usePendingItems as preferPendingItems } from 'mastodon/initial_state';
 
 import { importFetchedStatus, importFetchedStatuses } from './importer';
 import { submitMarkers } from './markers';
+import {timelineDelete} from './timelines_typed';
+
+export { disconnectTimeline } from './timelines_typed';
 
 export const TIMELINE_UPDATE  = 'TIMELINE_UPDATE';
-export const TIMELINE_DELETE  = 'TIMELINE_DELETE';
 export const TIMELINE_CLEAR   = 'TIMELINE_CLEAR';
 
 export const TIMELINE_EXPAND_REQUEST = 'TIMELINE_EXPAND_REQUEST';
@@ -17,7 +19,6 @@ export const TIMELINE_EXPAND_FAIL    = 'TIMELINE_EXPAND_FAIL';
 
 export const TIMELINE_SCROLL_TOP   = 'TIMELINE_SCROLL_TOP';
 export const TIMELINE_LOAD_PENDING = 'TIMELINE_LOAD_PENDING';
-export const TIMELINE_DISCONNECT   = 'TIMELINE_DISCONNECT';
 export const TIMELINE_CONNECT      = 'TIMELINE_CONNECT';
 
 export const TIMELINE_MARK_AS_PARTIAL = 'TIMELINE_MARK_AS_PARTIAL';
@@ -62,16 +63,10 @@ export function updateTimeline(timeline, status, accept) {
 export function deleteFromTimelines(id) {
   return (dispatch, getState) => {
     const accountId  = getState().getIn(['statuses', id, 'account']);
-    const references = getState().get('statuses').filter(status => status.get('reblog') === id).map(status => status.get('id'));
+    const references = getState().get('statuses').filter(status => status.get('reblog') === id).map(status => status.get('id')).toJSON();
     const reblogOf   = getState().getIn(['statuses', id, 'reblog'], null);
 
-    dispatch({
-      type: TIMELINE_DELETE,
-      id,
-      accountId,
-      references,
-      reblogOf,
-    });
+    dispatch(timelineDelete(id, accountId, references, reblogOf));
   };
 }
 
@@ -225,12 +220,6 @@ export function connectTimeline(timeline) {
   };
 }
 
-export const disconnectTimeline = timeline => ({
-  type: TIMELINE_DISCONNECT,
-  timeline,
-  usePendingItems: preferPendingItems,
-});
-
 export const markAsPartial = timeline => ({
   type: TIMELINE_MARK_AS_PARTIAL,
   timeline,
diff --git a/app/javascript/mastodon/actions/timelines_typed.ts b/app/javascript/mastodon/actions/timelines_typed.ts
new file mode 100644
index 000000000..07d82b2f0
--- /dev/null
+++ b/app/javascript/mastodon/actions/timelines_typed.ts
@@ -0,0 +1,20 @@
+import { createAction } from '@reduxjs/toolkit';
+
+import { usePendingItems as preferPendingItems } from 'mastodon/initial_state';
+
+export const disconnectTimeline = createAction(
+  'timeline/disconnect',
+  ({ timeline }: { timeline: string }) => ({
+    payload: {
+      timeline,
+      usePendingItems: preferPendingItems,
+    },
+  }),
+);
+
+export const timelineDelete = createAction<{
+  statusId: string;
+  accountId: string;
+  references: string[];
+  reblogOf: string | null;
+}>('timelines/delete');
diff --git a/app/javascript/mastodon/features/account_timeline/index.jsx b/app/javascript/mastodon/features/account_timeline/index.jsx
index 0478f7a1a..dc69f83e7 100644
--- a/app/javascript/mastodon/features/account_timeline/index.jsx
+++ b/app/javascript/mastodon/features/account_timeline/index.jsx
@@ -133,7 +133,7 @@ class AccountTimeline extends ImmutablePureComponent {
     }
 
     if (prevProps.accountId === me && accountId !== me) {
-      dispatch(disconnectTimeline(`account:${me}`));
+      dispatch(disconnectTimeline({ timeline: `account:${me}` }));
     }
   }
 
@@ -141,7 +141,7 @@ class AccountTimeline extends ImmutablePureComponent {
     const { dispatch, accountId } = this.props;
 
     if (accountId === me) {
-      dispatch(disconnectTimeline(`account:${me}`));
+      dispatch(disconnectTimeline({ timeline: `account:${me}` }));
     }
   }
 
diff --git a/app/javascript/mastodon/reducers/compose.js b/app/javascript/mastodon/reducers/compose.js
index 97218e9f7..9f66c0963 100644
--- a/app/javascript/mastodon/reducers/compose.js
+++ b/app/javascript/mastodon/reducers/compose.js
@@ -1,5 +1,7 @@
 import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable';
 
+import { timelineDelete } from 'mastodon/actions/timelines_typed';
+
 import {
   COMPOSE_MOUNT,
   COMPOSE_UNMOUNT,
@@ -51,7 +53,6 @@ import {
 } from '../actions/compose';
 import { REDRAFT } from '../actions/statuses';
 import { STORE_HYDRATE } from '../actions/store';
-import { TIMELINE_DELETE } from '../actions/timelines';
 import { me } from '../initial_state';
 import { unescapeHTML } from '../utils/html';
 import { uuid } from '../uuid';
@@ -446,10 +447,10 @@ export default function compose(state = initialState, action) {
     return updateSuggestionTags(state, action.token);
   case COMPOSE_TAG_HISTORY_UPDATE:
     return state.set('tagHistory', fromJS(action.tags));
-  case TIMELINE_DELETE:
-    if (action.id === state.get('in_reply_to')) {
+  case timelineDelete.type:
+    if (action.payload.statusId === state.get('in_reply_to')) {
       return state.set('in_reply_to', null);
-    } else if (action.id === state.get('id')) {
+    } else if (action.payload.statusId === state.get('id')) {
       return state.set('id', null);
     } else {
       return state;
diff --git a/app/javascript/mastodon/reducers/contexts.js b/app/javascript/mastodon/reducers/contexts.js
index f7d7419a4..b2c6f3f1a 100644
--- a/app/javascript/mastodon/reducers/contexts.js
+++ b/app/javascript/mastodon/reducers/contexts.js
@@ -1,11 +1,13 @@
 import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
 
+import { timelineDelete } from 'mastodon/actions/timelines_typed';
+
 import {
   blockAccountSuccess,
   muteAccountSuccess,
 } from '../actions/accounts';
 import { CONTEXT_FETCH_SUCCESS } from '../actions/statuses';
-import { TIMELINE_DELETE, TIMELINE_UPDATE } from '../actions/timelines';
+import { TIMELINE_UPDATE } from '../actions/timelines';
 import { compareId } from '../compare_id';
 
 const initialState = ImmutableMap({
@@ -97,8 +99,8 @@ export default function replies(state = initialState, action) {
     return filterContexts(state, action.payload.relationship, action.payload.statuses);
   case CONTEXT_FETCH_SUCCESS:
     return normalizeContext(state, action.id, action.ancestors, action.descendants);
-  case TIMELINE_DELETE:
-    return deleteFromContexts(state, [action.id]);
+  case timelineDelete.type:
+    return deleteFromContexts(state, [action.payload.statusId]);
   case TIMELINE_UPDATE:
     return updateContext(state, action.status);
   default:
diff --git a/app/javascript/mastodon/reducers/modal.ts b/app/javascript/mastodon/reducers/modal.ts
index 368f26542..ca85eb8c7 100644
--- a/app/javascript/mastodon/reducers/modal.ts
+++ b/app/javascript/mastodon/reducers/modal.ts
@@ -1,10 +1,11 @@
 import type { Reducer } from '@reduxjs/toolkit';
 import { Record as ImmutableRecord, Stack } from 'immutable';
 
+import { timelineDelete } from 'mastodon/actions/timelines_typed';
+
 import { COMPOSE_UPLOAD_CHANGE_SUCCESS } from '../actions/compose';
 import type { ModalType } from '../actions/modal';
 import { openModal, closeModal } from '../actions/modal';
-import { TIMELINE_DELETE } from '../actions/timelines';
 
 export type ModalProps = Record<string, unknown>;
 interface Modal {
@@ -72,10 +73,10 @@ export const modalReducer: Reducer<State> = (state = initialState, action) => {
   // TODO: type those actions
   else if (action.type === COMPOSE_UPLOAD_CHANGE_SUCCESS)
     return popModal(state, { modalType: 'FOCAL_POINT', ignoreFocus: false });
-  else if (action.type === TIMELINE_DELETE)
+  else if (timelineDelete.match(action))
     return state.update('stack', (stack) =>
       stack.filterNot(
-        (modal) => modal.get('modalProps').statusId === action.id,
+        (modal) => modal.get('modalProps').statusId === action.payload.statusId,
       ),
     );
   else return state;
diff --git a/app/javascript/mastodon/reducers/notifications.js b/app/javascript/mastodon/reducers/notifications.js
index 64cddcb66..79aa5651f 100644
--- a/app/javascript/mastodon/reducers/notifications.js
+++ b/app/javascript/mastodon/reducers/notifications.js
@@ -1,6 +1,7 @@
 import { fromJS, Map as ImmutableMap, List as ImmutableList } from 'immutable';
 
 import { blockDomainSuccess } from 'mastodon/actions/domain_blocks';
+import { timelineDelete } from 'mastodon/actions/timelines_typed';
 
 import {
   authorizeFollowRequestSuccess,
@@ -30,7 +31,7 @@ import {
   NOTIFICATIONS_SET_BROWSER_SUPPORT,
   NOTIFICATIONS_SET_BROWSER_PERMISSION,
 } from '../actions/notifications';
-import { TIMELINE_DELETE, TIMELINE_DISCONNECT } from '../actions/timelines';
+import { disconnectTimeline } from '../actions/timelines';
 import { compareId } from '../compare_id';
 
 const initialState = ImmutableMap({
@@ -291,11 +292,11 @@ export default function notifications(state = initialState, action) {
     return filterNotifications(state, [action.payload.id], 'follow_request');
   case NOTIFICATIONS_CLEAR:
     return state.set('items', ImmutableList()).set('pendingItems', ImmutableList()).set('hasMore', false);
-  case TIMELINE_DELETE:
-    return deleteByStatus(state, action.id);
-  case TIMELINE_DISCONNECT:
-    return action.timeline === 'home' ?
-      state.update(action.usePendingItems ? 'pendingItems' : 'items', items => items.first() ? items.unshift(null) : items) :
+  case timelineDelete.type:
+    return deleteByStatus(state, action.payload.statusId);
+  case disconnectTimeline.type:
+    return action.payload.timeline === 'home' ?
+      state.update(action.payload.usePendingItems ? 'pendingItems' : 'items', items => items.first() ? items.unshift(null) : items) :
       state;
   case NOTIFICATIONS_MARK_AS_READ:
     const lastNotification = state.get('items').find(item => item !== null);
diff --git a/app/javascript/mastodon/reducers/picture_in_picture.ts b/app/javascript/mastodon/reducers/picture_in_picture.ts
index 0feddcb70..10d4f1fae 100644
--- a/app/javascript/mastodon/reducers/picture_in_picture.ts
+++ b/app/javascript/mastodon/reducers/picture_in_picture.ts
@@ -4,8 +4,7 @@ import {
   deployPictureInPictureAction,
   removePictureInPicture,
 } from 'mastodon/actions/picture_in_picture';
-
-import { TIMELINE_DELETE } from '../actions/timelines';
+import { timelineDelete } from 'mastodon/actions/timelines_typed';
 
 export interface PIPMediaProps {
   src: string;
@@ -49,8 +48,9 @@ export const pictureInPictureReducer: Reducer<PIPState> = (
       ...action.payload.props,
     };
   else if (removePictureInPicture.match(action)) return initialState;
-  else if (action.type === TIMELINE_DELETE)
-    if (state.type && state.statusId === action.id) return initialState;
+  else if (timelineDelete.match(action))
+    if (state.type && state.statusId === action.payload.statusId)
+      return initialState;
 
   return state;
 };
diff --git a/app/javascript/mastodon/reducers/statuses.js b/app/javascript/mastodon/reducers/statuses.js
index ca766f73a..d92174f80 100644
--- a/app/javascript/mastodon/reducers/statuses.js
+++ b/app/javascript/mastodon/reducers/statuses.js
@@ -1,5 +1,7 @@
 import { Map as ImmutableMap, fromJS } from 'immutable';
 
+import { timelineDelete } from 'mastodon/actions/timelines_typed';
+
 import { STATUS_IMPORT, STATUSES_IMPORT } from '../actions/importer';
 import { normalizeStatusTranslation } from '../actions/importer/normalizer';
 import {
@@ -27,7 +29,6 @@ import {
   STATUS_FETCH_REQUEST,
   STATUS_FETCH_FAIL,
 } from '../actions/statuses';
-import { TIMELINE_DELETE } from '../actions/timelines';
 
 const importStatus = (state, status) => state.set(status.id, fromJS(status));
 
@@ -114,8 +115,8 @@ export default function statuses(state = initialState, action) {
     });
   case STATUS_COLLAPSE:
     return state.setIn([action.id, 'collapsed'], action.isCollapsed);
-  case TIMELINE_DELETE:
-    return deleteStatus(state, action.id, action.references);
+  case timelineDelete.type:
+    return deleteStatus(state, action.payload.statusId, action.payload.references);
   case STATUS_TRANSLATE_SUCCESS:
     return statusTranslateSuccess(state, action.id, action.translation);
   case STATUS_TRANSLATE_UNDO:
diff --git a/app/javascript/mastodon/reducers/timelines.js b/app/javascript/mastodon/reducers/timelines.js
index 4c9ab98a8..786d20b30 100644
--- a/app/javascript/mastodon/reducers/timelines.js
+++ b/app/javascript/mastodon/reducers/timelines.js
@@ -1,5 +1,7 @@
 import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable';
 
+import { timelineDelete } from 'mastodon/actions/timelines_typed';
+
 import {
   blockAccountSuccess,
   muteAccountSuccess,
@@ -7,19 +9,18 @@ import {
 } from '../actions/accounts';
 import {
   TIMELINE_UPDATE,
-  TIMELINE_DELETE,
   TIMELINE_CLEAR,
   TIMELINE_EXPAND_SUCCESS,
   TIMELINE_EXPAND_REQUEST,
   TIMELINE_EXPAND_FAIL,
   TIMELINE_SCROLL_TOP,
   TIMELINE_CONNECT,
-  TIMELINE_DISCONNECT,
   TIMELINE_LOAD_PENDING,
   TIMELINE_MARK_AS_PARTIAL,
   TIMELINE_INSERT,
   TIMELINE_GAP,
   TIMELINE_SUGGESTIONS,
+  disconnectTimeline,
 } from '../actions/timelines';
 import { compareId } from '../compare_id';
 
@@ -201,8 +202,8 @@ export default function timelines(state = initialState, action) {
     return expandNormalizedTimeline(state, action.timeline, fromJS(action.statuses), action.next, action.partial, action.isLoadingRecent, action.usePendingItems);
   case TIMELINE_UPDATE:
     return updateTimeline(state, action.timeline, fromJS(action.status), action.usePendingItems);
-  case TIMELINE_DELETE:
-    return deleteStatus(state, action.id, action.references, action.reblogOf);
+  case timelineDelete.type:
+    return deleteStatus(state, action.payload.statusId, action.payload.references, action.payload.reblogOf);
   case TIMELINE_CLEAR:
     return clearTimeline(state, action.timeline);
   case blockAccountSuccess.type:
@@ -214,11 +215,11 @@ export default function timelines(state = initialState, action) {
     return updateTop(state, action.timeline, action.top);
   case TIMELINE_CONNECT:
     return state.update(action.timeline, initialTimeline, map => reconnectTimeline(map, action.usePendingItems));
-  case TIMELINE_DISCONNECT:
+  case disconnectTimeline.type:
     return state.update(
-      action.timeline,
+      action.payload.timeline,
       initialTimeline,
-      map => map.set('online', false).update(action.usePendingItems ? 'pendingItems' : 'items', items => items.first() ? items.unshift(TIMELINE_GAP) : items),
+      map => map.set('online', false).update(action.payload.usePendingItems ? 'pendingItems' : 'items', items => items.first() ? items.unshift(TIMELINE_GAP) : items),
     );
   case TIMELINE_MARK_AS_PARTIAL:
     return state.update(

From f723370c6982d914695378ef70949b22a8bb235d Mon Sep 17 00:00:00 2001
From: Claire <claire.github-309c@sitedethib.com>
Date: Thu, 20 Jun 2024 15:44:49 +0200
Subject: [PATCH 16/35] Fix missing `account_warning` delegation in
 `NotificationGroup` (#30779)

---
 app/models/notification_group.rb | 1 +
 1 file changed, 1 insertion(+)

diff --git a/app/models/notification_group.rb b/app/models/notification_group.rb
index 43612d49b..093fdbe33 100644
--- a/app/models/notification_group.rb
+++ b/app/models/notification_group.rb
@@ -29,5 +29,6 @@ class NotificationGroup < ActiveModelSerializers::Model
            :target_status,
            :report,
            :account_relationship_severance_event,
+           :account_warning,
            to: :notification, prefix: false
 end

From 6ab6146c0be04271d9da1dc57b842e8998fbbfb9 Mon Sep 17 00:00:00 2001
From: Nick Schonning <nschonni@gmail.com>
Date: Thu, 20 Jun 2024 11:30:49 -0400
Subject: [PATCH 17/35] Remove --no-exclude-limit for RuboCop ToDo (#30427)

---
 .rubocop_todo.yml | 50 +++--------------------------------------------
 1 file changed, 3 insertions(+), 47 deletions(-)

diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index 8a4e59803..fb3a928d3 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -1,6 +1,6 @@
 # This configuration was generated by
-# `rubocop --auto-gen-config --auto-gen-only-exclude --no-exclude-limit --no-offense-counts --no-auto-gen-timestamp`
-# using RuboCop version 1.63.5.
+# `rubocop --auto-gen-config --auto-gen-only-exclude --no-offense-counts --no-auto-gen-timestamp`
+# using RuboCop version 1.64.1.
 # The point is for the user to remove these configuration records
 # one by one as the offenses are removed from the code base.
 # Note that changes in the inspected code, or installation of new
@@ -55,7 +55,6 @@ Style/FetchEnvVar:
     - 'config/initializers/vapid.rb'
     - 'lib/mastodon/redis_config.rb'
     - 'lib/tasks/repo.rake'
-    - 'spec/system/profile_spec.rb'
 
 # This cop supports safe autocorrection (--autocorrect).
 # Configuration parameters: EnforcedStyle, MaxUnannotatedPlaceholdersAllowed, AllowedMethods, AllowedPatterns.
@@ -66,40 +65,10 @@ Style/FormatStringToken:
     - 'config/initializers/devise.rb'
     - 'lib/paperclip/color_extractor.rb'
 
-# This cop supports unsafe autocorrection (--autocorrect-all).
-Style/GlobalStdStream:
-  Exclude:
-    - 'config/environments/development.rb'
-    - 'config/environments/production.rb'
-
 # This cop supports safe autocorrection (--autocorrect).
 # Configuration parameters: MinBodyLength, AllowConsecutiveConditionals.
 Style/GuardClause:
-  Exclude:
-    - 'app/lib/activitypub/activity/block.rb'
-    - 'app/lib/request.rb'
-    - 'app/lib/request_pool.rb'
-    - 'app/lib/webfinger.rb'
-    - 'app/lib/webfinger_resource.rb'
-    - 'app/models/concerns/account/counters.rb'
-    - 'app/models/concerns/user/ldap_authenticable.rb'
-    - 'app/models/tag.rb'
-    - 'app/models/user.rb'
-    - 'app/services/fan_out_on_write_service.rb'
-    - 'app/services/post_status_service.rb'
-    - 'app/services/process_hashtags_service.rb'
-    - 'app/workers/move_worker.rb'
-    - 'app/workers/redownload_avatar_worker.rb'
-    - 'app/workers/redownload_header_worker.rb'
-    - 'app/workers/redownload_media_worker.rb'
-    - 'app/workers/remote_account_refresh_worker.rb'
-    - 'config/initializers/devise.rb'
-    - 'lib/devise/strategies/two_factor_ldap_authenticatable.rb'
-    - 'lib/devise/strategies/two_factor_pam_authenticatable.rb'
-    - 'lib/mastodon/cli/accounts.rb'
-    - 'lib/mastodon/cli/maintenance.rb'
-    - 'lib/mastodon/cli/media.rb'
-    - 'lib/tasks/repo.rake'
+  Enabled: false
 
 # This cop supports unsafe autocorrection (--autocorrect-all).
 Style/HashTransformValues:
@@ -121,16 +90,10 @@ Style/MutableConstant:
     - 'app/services/delete_account_service.rb'
     - 'lib/mastodon/migration_warning.rb'
 
-# This cop supports safe autocorrection (--autocorrect).
-Style/NilLambda:
-  Exclude:
-    - 'config/initializers/paperclip.rb'
-
 # Configuration parameters: AllowedMethods.
 # AllowedMethods: respond_to_missing?
 Style/OptionalBooleanParameter:
   Exclude:
-    - 'app/helpers/admin/account_moderation_notes_helper.rb'
     - 'app/helpers/jsonld_helper.rb'
     - 'app/lib/admin/system_check/message.rb'
     - 'app/lib/request.rb'
@@ -154,13 +117,6 @@ Style/RedundantConstantBase:
     - 'config/environments/production.rb'
     - 'config/initializers/sidekiq.rb'
 
-# This cop supports unsafe autocorrection (--autocorrect-all).
-# Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods, MaxChainLength.
-# AllowedMethods: present?, blank?, presence, try, try!
-Style/SafeNavigation:
-  Exclude:
-    - 'app/models/concerns/account/finder_concern.rb'
-
 # This cop supports safe autocorrection (--autocorrect).
 # Configuration parameters: WordRegex.
 # SupportedStyles: percent, brackets

From bb2d77b4a07e95e7d96df080f2d6994c1422b0c0 Mon Sep 17 00:00:00 2001
From: Claire <claire.github-309c@sitedethib.com>
Date: Thu, 20 Jun 2024 17:54:50 +0200
Subject: [PATCH 18/35] Change `/api/v2_alpha/notifications` to only return
 historical data in pages (#30781)

---
 app/controllers/api/v2_alpha/notifications_controller.rb | 2 +-
 app/models/notification_group.rb                         | 9 ++++++---
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/app/controllers/api/v2_alpha/notifications_controller.rb b/app/controllers/api/v2_alpha/notifications_controller.rb
index 19d3ac901..edba23ab4 100644
--- a/app/controllers/api/v2_alpha/notifications_controller.rb
+++ b/app/controllers/api/v2_alpha/notifications_controller.rb
@@ -15,7 +15,7 @@ class Api::V2Alpha::NotificationsController < Api::BaseController
       @relationships = StatusRelationshipsPresenter.new(target_statuses_from_notifications, current_user&.account_id)
     end
 
-    render json: @notifications.map { |notification| NotificationGroup.from_notification(notification) }, each_serializer: REST::NotificationGroupSerializer, relationships: @relationships, group_metadata: @group_metadata
+    render json: @notifications.map { |notification| NotificationGroup.from_notification(notification, max_id: @group_metadata.dig(notification.group_key, :max_id)) }, each_serializer: REST::NotificationGroupSerializer, relationships: @relationships, group_metadata: @group_metadata
   end
 
   def show
diff --git a/app/models/notification_group.rb b/app/models/notification_group.rb
index 093fdbe33..b1cbd7c19 100644
--- a/app/models/notification_group.rb
+++ b/app/models/notification_group.rb
@@ -3,13 +3,16 @@
 class NotificationGroup < ActiveModelSerializers::Model
   attributes :group_key, :sample_accounts, :notifications_count, :notification, :most_recent_notification_id
 
-  def self.from_notification(notification)
+  def self.from_notification(notification, max_id: nil)
     if notification.group_key.present?
       # TODO: caching and preloading
-      most_recent_notifications = notification.account.notifications.where(group_key: notification.group_key).order(id: :desc).take(3)
+      scope = notification.account.notifications.where(group_key: notification.group_key)
+      scope = scope.where(id: ..max_id) if max_id.present?
+
+      most_recent_notifications = scope.order(id: :desc).take(3)
       most_recent_id = most_recent_notifications.first.id
       sample_accounts = most_recent_notifications.map(&:from_account)
-      notifications_count = notification.account.notifications.where(group_key: notification.group_key).count
+      notifications_count = scope.count
     else
       most_recent_id = notification.id
       sample_accounts = [notification.from_account]

From 7d12522ed71193decc2a9aeacc8cf921b09d3654 Mon Sep 17 00:00:00 2001
From: Renaud Chaput <renchap@gmail.com>
Date: Fri, 21 Jun 2024 00:39:06 +0200
Subject: [PATCH 19/35] Fix error when deleting a status (#30784)

---
 app/javascript/mastodon/actions/timelines.js  | 4 ++--
 app/javascript/mastodon/reducers/timelines.js | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/app/javascript/mastodon/actions/timelines.js b/app/javascript/mastodon/actions/timelines.js
index d1851551b..4ca3c3a15 100644
--- a/app/javascript/mastodon/actions/timelines.js
+++ b/app/javascript/mastodon/actions/timelines.js
@@ -63,10 +63,10 @@ export function updateTimeline(timeline, status, accept) {
 export function deleteFromTimelines(id) {
   return (dispatch, getState) => {
     const accountId  = getState().getIn(['statuses', id, 'account']);
-    const references = getState().get('statuses').filter(status => status.get('reblog') === id).map(status => status.get('id')).toJSON();
+    const references = getState().get('statuses').filter(status => status.get('reblog') === id).map(status => status.get('id')).valueSeq().toJSON();
     const reblogOf   = getState().getIn(['statuses', id, 'reblog'], null);
 
-    dispatch(timelineDelete(id, accountId, references, reblogOf));
+    dispatch(timelineDelete({ statusId: id, accountId, references, reblogOf }));
   };
 }
 
diff --git a/app/javascript/mastodon/reducers/timelines.js b/app/javascript/mastodon/reducers/timelines.js
index 786d20b30..b07281ab8 100644
--- a/app/javascript/mastodon/reducers/timelines.js
+++ b/app/javascript/mastodon/reducers/timelines.js
@@ -159,7 +159,7 @@ const filterTimelines = (state, relationship, statuses) => {
       return;
     }
 
-    references = statuses.filter(item => item.get('reblog') === status.get('id')).map(item => item.get('id'));
+    references = statuses.filter(item => item.get('reblog') === status.get('id')).map(item => item.get('id')).valueSeq().toJSON();
     state      = deleteStatus(state, status.get('id'), references, relationship.id);
   });
 

From 9e932fa1ddaea569ca52fe663eb4bb13a5a43e0a Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Fri, 21 Jun 2024 11:14:44 +0200
Subject: [PATCH 20/35] New Crowdin Translations (automated) (#30789)

Co-authored-by: GitHub Actions <noreply@github.com>
---
 app/javascript/mastodon/locales/hi.json | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/app/javascript/mastodon/locales/hi.json b/app/javascript/mastodon/locales/hi.json
index 5dc99dd76..a2da55da8 100644
--- a/app/javascript/mastodon/locales/hi.json
+++ b/app/javascript/mastodon/locales/hi.json
@@ -80,6 +80,7 @@
   "admin.dashboard.retention.cohort_size": "नये उपयोगकर्ता",
   "admin.impact_report.instance_accounts": "ये अकाउंट प्रोफाइल मिटा देगा",
   "admin.impact_report.instance_followers": "हमारे यूजर्स इन फॉलोअर्स को खो देंगे",
+  "admin.impact_report.instance_follows": "उनके उपयोगकर्ता इतने फ़ॉलोअर खो देंगे",
   "admin.impact_report.title": "प्रभावकां सारांश",
   "alert.rate_limited.message": "कृप्या {retry_time, time, medium} के बाद दुबारा कोशिश करें",
   "alert.rate_limited.title": "सीमित दर",
@@ -88,6 +89,7 @@
   "announcement.announcement": "घोषणा",
   "attachments_list.unprocessed": "(असंसाधित)",
   "audio.hide": "हाईड ऑडियो",
+  "block_modal.remote_users_caveat": "हम {domain} को आपके निर्णय का सम्मान करने को कहेंगे।हालाकि इसकी आपूर्ति कि प्रत्याभूति नहीं हे। क्योंकि कुछ सर्वर ब्लॉक को अलग तरह से निभा सकते हे। अभी भी सार्वजानिक पोस्ट लोग- इन बगैर के उपयोगकर्ताओं को दिख सकती हैं।",
   "block_modal.show_less": "कम दिखाएं",
   "block_modal.show_more": "और दिखाएँ",
   "block_modal.they_cant_mention": "वे आपको मेंशन या फॉलो नहीं कर सकते",
@@ -205,7 +207,12 @@
   "dismissable_banner.dismiss": "डिसमिस",
   "dismissable_banner.explore_links": "इन समाचारों के बारे में लोगों द्वारा इस पर और डेसेंट्रलीसेड नेटवर्क के अन्य सर्वरों पर अभी बात की जा रही है।",
   "dismissable_banner.explore_tags": "ये हैशटैग अभी इस पर और डेसेंट्रलीसेड नेटवर्क के अन्य सर्वरों पर लोगों के बीच कर्षण प्राप्त कर रहे हैं।",
+  "dismissable_banner.public_timeline": "यह ताजा सार्वजनिक पोस्ट है जिसका सामाजिक वेब {domain} के लोगो द्वारा अनुसरण हो रहा हैं।",
   "domain_block_modal.block": "सर्वर ब्लॉक करें",
+  "domain_block_modal.block_account_instead": "इसकी जगह यह @{name} रखें",
+  "domain_block_modal.they_can_interact_with_old_posts": "इस सर्वर की लोग आपकी पूरानी पोस्ट्स का अनुसरण किया जा sakta है।",
+  "domain_block_modal.they_cant_follow": "इस सर्वर मेसे कोई भी आपका अनुसरण नहीं कर सकता।",
+  "domain_block_modal.they_wont_know": "उनको पता नहीं चलेगा कि वे अवरोधित किए गए है।",
   "domain_block_modal.title": "डोमेन ब्लॉक करें",
   "domain_pill.server": "सर्वर",
   "domain_pill.username": "यूज़रनेम",

From 5b938e6e20ce9956812834031c6fd8c7dfa5b184 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 21 Jun 2024 13:37:15 +0200
Subject: [PATCH 21/35] chore(deps): update dependency @types/uuid to v10
 (#30787)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
 streaming/package.json |  2 +-
 yarn.lock              | 10 +++++-----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/streaming/package.json b/streaming/package.json
index ba024fe7a..deaa760d9 100644
--- a/streaming/package.json
+++ b/streaming/package.json
@@ -34,7 +34,7 @@
     "@types/cors": "^2.8.16",
     "@types/express": "^4.17.17",
     "@types/pg": "^8.6.6",
-    "@types/uuid": "^9.0.0",
+    "@types/uuid": "^10.0.0",
     "@types/ws": "^8.5.9",
     "eslint-define-config": "^2.0.0",
     "pino-pretty": "^11.0.0",
diff --git a/yarn.lock b/yarn.lock
index 61a8f420a..948670e2c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2925,7 +2925,7 @@ __metadata:
     "@types/cors": "npm:^2.8.16"
     "@types/express": "npm:^4.17.17"
     "@types/pg": "npm:^8.6.6"
-    "@types/uuid": "npm:^9.0.0"
+    "@types/uuid": "npm:^10.0.0"
     "@types/ws": "npm:^8.5.9"
     bufferutil: "npm:^4.0.7"
     cors: "npm:^2.8.5"
@@ -4045,10 +4045,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@types/uuid@npm:^9.0.0":
-  version: 9.0.8
-  resolution: "@types/uuid@npm:9.0.8"
-  checksum: 10c0/b411b93054cb1d4361919579ef3508a1f12bf15b5fdd97337d3d351bece6c921b52b6daeef89b62340fd73fd60da407878432a1af777f40648cbe53a01723489
+"@types/uuid@npm:^10.0.0":
+  version: 10.0.0
+  resolution: "@types/uuid@npm:10.0.0"
+  checksum: 10c0/9a1404bf287164481cb9b97f6bb638f78f955be57c40c6513b7655160beb29df6f84c915aaf4089a1559c216557dc4d2f79b48d978742d3ae10b937420ddac60
   languageName: node
   linkType: hard
 

From 2c65a1b0e58ef4aa0fddd1b1cb1fa0d51237b189 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 21 Jun 2024 13:37:47 +0200
Subject: [PATCH 22/35] chore(deps): update dependency selenium-webdriver to
 v4.22.0 (#30786)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
 Gemfile.lock | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Gemfile.lock b/Gemfile.lock
index 1f8645a59..cb796409d 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -398,6 +398,7 @@ GEM
     llhttp-ffi (0.5.0)
       ffi-compiler (~> 1.0)
       rake (~> 13.0)
+    logger (1.6.0)
     lograge (0.14.0)
       actionpack (>= 4)
       activesupport (>= 4)
@@ -771,8 +772,9 @@ GEM
     scenic (1.8.0)
       activerecord (>= 4.0.0)
       railties (>= 4.0.0)
-    selenium-webdriver (4.21.1)
+    selenium-webdriver (4.22.0)
       base64 (~> 0.2)
+      logger (~> 1.4)
       rexml (~> 3.2, >= 3.2.5)
       rubyzip (>= 1.2.2, < 3.0)
       websocket (~> 1.0)

From 4e6db5e284988e77b9c2bec5c100b302f2294b74 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 21 Jun 2024 11:38:26 +0000
Subject: [PATCH 23/35] chore(deps): update yarn to v4.3.1 (#30790)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
 package.json           | 2 +-
 streaming/package.json | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index d52f0ea1c..729482f85 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "@mastodon/mastodon",
   "license": "AGPL-3.0-or-later",
-  "packageManager": "yarn@4.3.0",
+  "packageManager": "yarn@4.3.1",
   "engines": {
     "node": ">=18"
   },
diff --git a/streaming/package.json b/streaming/package.json
index deaa760d9..1ee738c33 100644
--- a/streaming/package.json
+++ b/streaming/package.json
@@ -1,7 +1,7 @@
 {
   "name": "@mastodon/streaming",
   "license": "AGPL-3.0-or-later",
-  "packageManager": "yarn@4.3.0",
+  "packageManager": "yarn@4.3.1",
   "engines": {
     "node": ">=18"
   },

From 2cab1c7b09f64cae8128fa33645137fe55daf075 Mon Sep 17 00:00:00 2001
From: David Roetzel <david@roetzel.de>
Date: Fri, 21 Jun 2024 14:51:10 +0200
Subject: [PATCH 24/35] Improve encoding detection for link cards (#30780)

---
 app/lib/link_details_extractor.rb               | 15 ++++++++++-----
 .../fixtures/requests/low_confidence_latin1.txt | 17 +++++++++++++++++
 spec/services/fetch_link_card_service_spec.rb   |  9 +++++++++
 3 files changed, 36 insertions(+), 5 deletions(-)
 create mode 100644 spec/fixtures/requests/low_confidence_latin1.txt

diff --git a/app/lib/link_details_extractor.rb b/app/lib/link_details_extractor.rb
index 2e49d3fb4..dbfdd33fc 100644
--- a/app/lib/link_details_extractor.rb
+++ b/app/lib/link_details_extractor.rb
@@ -269,16 +269,21 @@ class LinkDetailsExtractor
   end
 
   def document
-    @document ||= Nokogiri::HTML(@html, nil, encoding)
+    @document ||= detect_encoding_and_parse_document
   end
 
-  def encoding
-    @encoding ||= begin
-      guess = detector.detect(@html, @html_charset)
-      guess&.fetch(:confidence, 0).to_i > 60 ? guess&.fetch(:encoding, nil) : nil
+  def detect_encoding_and_parse_document
+    [detect_encoding, nil, @html_charset, 'UTF-8'].uniq.each do |encoding|
+      document = Nokogiri::HTML(@html, nil, encoding)
+      return document if document.to_s.valid_encoding?
     end
   end
 
+  def detect_encoding
+    guess = detector.detect(@html, @html_charset)
+    guess&.fetch(:confidence, 0).to_i > 60 ? guess&.fetch(:encoding, nil) : nil
+  end
+
   def detector
     @detector ||= CharlockHolmes::EncodingDetector.new.tap do |detector|
       detector.strip_tags = true
diff --git a/spec/fixtures/requests/low_confidence_latin1.txt b/spec/fixtures/requests/low_confidence_latin1.txt
new file mode 100644
index 000000000..39c3e23d6
--- /dev/null
+++ b/spec/fixtures/requests/low_confidence_latin1.txt
@@ -0,0 +1,17 @@
+HTTP/1.1 200 OK
+server: nginx
+date: Thu, 13 Jun 2024 14:33:13 GMT
+content-type: text/html; charset=ISO-8859-1
+content-length: 158
+accept-ranges: bytes
+
+<!doctype html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+  <title>Tofu � l'orange</title>
+</head>
+<body>
+  <h2>Tofu � l'orange</h2>
+</body>
+</html>
diff --git a/spec/services/fetch_link_card_service_spec.rb b/spec/services/fetch_link_card_service_spec.rb
index 63ebc3b97..239f84fde 100644
--- a/spec/services/fetch_link_card_service_spec.rb
+++ b/spec/services/fetch_link_card_service_spec.rb
@@ -26,6 +26,7 @@ RSpec.describe FetchLinkCardService do
     stub_request(:get, 'http://example.com/sjis_with_wrong_charset').to_return(request_fixture('sjis_with_wrong_charset.txt'))
     stub_request(:get, 'http://example.com/koi8-r').to_return(request_fixture('koi8-r.txt'))
     stub_request(:get, 'http://example.com/windows-1251').to_return(request_fixture('windows-1251.txt'))
+    stub_request(:get, 'http://example.com/low_confidence_latin1').to_return(request_fixture('low_confidence_latin1.txt'))
 
     Rails.cache.write('oembed_endpoint:example.com', oembed_cache) if oembed_cache
 
@@ -148,6 +149,14 @@ RSpec.describe FetchLinkCardService do
       end
     end
 
+    context 'with a URL of a page in ISO-8859-1 encoding, that charlock_holmes cannot detect' do
+      let(:status) { Fabricate(:status, text: 'Check out http://example.com/low_confidence_latin1') }
+
+      it 'decodes the HTML' do
+        expect(status.preview_card.title).to eq("Tofu á l'orange")
+      end
+    end
+
     context 'with a Japanese path URL' do
       let(:status) { Fabricate(:status, text: 'テストhttp://example.com/日本語') }
 

From 4651c0cb39c1a1e4feb6d8fc2b53de622eeb7373 Mon Sep 17 00:00:00 2001
From: Matt Jankowski <matt@jankowski.online>
Date: Fri, 21 Jun 2024 10:43:12 -0400
Subject: [PATCH 25/35] Fix `Rails/ReversibleMigrationMethodDefinition` cop
 (#30794)

---
 .../20160227230233_add_attachment_avatar_to_accounts.rb       | 4 ++--
 db/migrate/20160305115639_add_devise_to_users.rb              | 4 ++--
 .../20160312193225_add_attachment_header_to_accounts.rb       | 4 ++--
 db/migrate/20161006213403_rails_settings_migration.rb         | 4 ++--
 db/migrate/20170330164118_add_attachment_data_to_imports.rb   | 4 ++--
 5 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/db/migrate/20160227230233_add_attachment_avatar_to_accounts.rb b/db/migrate/20160227230233_add_attachment_avatar_to_accounts.rb
index 534df25ee..cfe4c23de 100644
--- a/db/migrate/20160227230233_add_attachment_avatar_to_accounts.rb
+++ b/db/migrate/20160227230233_add_attachment_avatar_to_accounts.rb
@@ -1,7 +1,7 @@
 # frozen_string_literal: true
 
 class AddAttachmentAvatarToAccounts < ActiveRecord::Migration[4.2]
-  def self.up
+  def up
     change_table :accounts do |t|
       # The following corresponds to `t.attachment :avatar` in an older version of Paperclip
       t.string :avatar_file_name
@@ -11,7 +11,7 @@ class AddAttachmentAvatarToAccounts < ActiveRecord::Migration[4.2]
     end
   end
 
-  def self.down
+  def down
     remove_attachment :accounts, :avatar
   end
 end
diff --git a/db/migrate/20160305115639_add_devise_to_users.rb b/db/migrate/20160305115639_add_devise_to_users.rb
index 64ad78dbc..22697b238 100644
--- a/db/migrate/20160305115639_add_devise_to_users.rb
+++ b/db/migrate/20160305115639_add_devise_to_users.rb
@@ -1,7 +1,7 @@
 # frozen_string_literal: true
 
 class AddDeviseToUsers < ActiveRecord::Migration[4.2]
-  def self.up
+  def up
     change_table(:users, bulk: true) do |t|
       ## Database authenticatable
       t.string :encrypted_password, null: false, default: ''
@@ -24,7 +24,7 @@ class AddDeviseToUsers < ActiveRecord::Migration[4.2]
     add_index :users, :reset_password_token, unique: true
   end
 
-  def self.down
+  def down
     remove_index :users, :reset_password_token
 
     remove_column :users, :encrypted_password
diff --git a/db/migrate/20160312193225_add_attachment_header_to_accounts.rb b/db/migrate/20160312193225_add_attachment_header_to_accounts.rb
index b481fc529..45dc65236 100644
--- a/db/migrate/20160312193225_add_attachment_header_to_accounts.rb
+++ b/db/migrate/20160312193225_add_attachment_header_to_accounts.rb
@@ -1,7 +1,7 @@
 # frozen_string_literal: true
 
 class AddAttachmentHeaderToAccounts < ActiveRecord::Migration[4.2]
-  def self.up
+  def up
     change_table :accounts do |t|
       # The following corresponds to `t.attachment :header` in an older version of Paperclip
       t.string :header_file_name
@@ -11,7 +11,7 @@ class AddAttachmentHeaderToAccounts < ActiveRecord::Migration[4.2]
     end
   end
 
-  def self.down
+  def down
     remove_attachment :accounts, :header
   end
 end
diff --git a/db/migrate/20161006213403_rails_settings_migration.rb b/db/migrate/20161006213403_rails_settings_migration.rb
index 9764196fa..d08ad2efd 100644
--- a/db/migrate/20161006213403_rails_settings_migration.rb
+++ b/db/migrate/20161006213403_rails_settings_migration.rb
@@ -1,7 +1,7 @@
 # frozen_string_literal: true
 
 class RailsSettingsMigration < ActiveRecord::Migration[5.0]
-  def self.up
+  def up
     create_table :settings do |t|
       t.string     :var, null: false
       t.text       :value
@@ -11,7 +11,7 @@ class RailsSettingsMigration < ActiveRecord::Migration[5.0]
     add_index :settings, [:target_type, :target_id, :var], unique: true
   end
 
-  def self.down
+  def down
     drop_table :settings
   end
 end
diff --git a/db/migrate/20170330164118_add_attachment_data_to_imports.rb b/db/migrate/20170330164118_add_attachment_data_to_imports.rb
index 0daaa9d02..afacfa86d 100644
--- a/db/migrate/20170330164118_add_attachment_data_to_imports.rb
+++ b/db/migrate/20170330164118_add_attachment_data_to_imports.rb
@@ -1,7 +1,7 @@
 # frozen_string_literal: true
 
 class AddAttachmentDataToImports < ActiveRecord::Migration[4.2]
-  def self.up
+  def up
     change_table :imports do |t|
       # The following corresponds to `t.attachment :data` in an older version of Paperclip
       t.string :data_file_name
@@ -11,7 +11,7 @@ class AddAttachmentDataToImports < ActiveRecord::Migration[4.2]
     end
   end
 
-  def self.down
+  def down
     remove_attachment :imports, :data
   end
 end

From 72484a194fb5f52cf2512a95045fc6bd2d3e2ef4 Mon Sep 17 00:00:00 2001
From: Matt Jankowski <matt@jankowski.online>
Date: Fri, 21 Jun 2024 11:32:49 -0400
Subject: [PATCH 26/35] Remove `CacheBuster` default options (#30718)

---
 app/lib/cache_buster.rb       | 9 ++-------
 spec/lib/cache_buster_spec.rb | 8 --------
 2 files changed, 2 insertions(+), 15 deletions(-)

diff --git a/app/lib/cache_buster.rb b/app/lib/cache_buster.rb
index 554f2ba95..d3395f8f0 100644
--- a/app/lib/cache_buster.rb
+++ b/app/lib/cache_buster.rb
@@ -2,13 +2,8 @@
 
 class CacheBuster
   def initialize(options = {})
-    Rails.application.deprecators[:mastodon].warn('Default values for the cache buster secret header name and values will be removed in Mastodon 4.3. Please set them explicitely if you rely on those.') unless options[:http_method] || (options[:secret] && options[:secret_header])
-
-    @secret_header = options[:secret_header] ||
-                     (options[:http_method] ? nil : 'Secret-Header')
-    @secret = options[:secret] ||
-              (options[:http_method] ? nil : 'True')
-
+    @secret_header = options[:secret_header]
+    @secret = options[:secret]
     @http_method = options[:http_method] || 'GET'
   end
 
diff --git a/spec/lib/cache_buster_spec.rb b/spec/lib/cache_buster_spec.rb
index 78ca18349..84085608e 100644
--- a/spec/lib/cache_buster_spec.rb
+++ b/spec/lib/cache_buster_spec.rb
@@ -28,14 +28,6 @@ describe CacheBuster do
     end
 
     context 'when using default options' do
-      around do |example|
-        # Disables the CacheBuster.new deprecation warning about default arguments.
-        # Remove this `silence` block when default arg support is removed from CacheBuster
-        Rails.application.deprecators[:mastodon].silence do
-          example.run
-        end
-      end
-
       include_examples 'makes_request'
     end
 

From 348ccf206ee245309d8e44855667f92c4fc06b7d Mon Sep 17 00:00:00 2001
From: Matt Jankowski <matt@jankowski.online>
Date: Fri, 21 Jun 2024 11:33:55 -0400
Subject: [PATCH 27/35] Fix `Style/ClassEqualityComparison` cop (#30058)

---
 .rubocop_todo.yml                                | 8 --------
 app/helpers/jsonld_helper.rb                     | 2 +-
 app/serializers/activitypub/outbox_serializer.rb | 2 +-
 3 files changed, 2 insertions(+), 10 deletions(-)

diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index fb3a928d3..b05d1bc6b 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -31,14 +31,6 @@ Rails/OutputSafety:
   Exclude:
     - 'config/initializers/simple_form.rb'
 
-# This cop supports unsafe autocorrection (--autocorrect-all).
-# Configuration parameters: AllowedMethods, AllowedPatterns.
-# AllowedMethods: ==, equal?, eql?
-Style/ClassEqualityComparison:
-  Exclude:
-    - 'app/helpers/jsonld_helper.rb'
-    - 'app/serializers/activitypub/outbox_serializer.rb'
-
 # This cop supports safe autocorrection (--autocorrect).
 # Configuration parameters: AllowedVars.
 Style/FetchEnvVar:
diff --git a/app/helpers/jsonld_helper.rb b/app/helpers/jsonld_helper.rb
index b0f2077db..932a3420d 100644
--- a/app/helpers/jsonld_helper.rb
+++ b/app/helpers/jsonld_helper.rb
@@ -141,7 +141,7 @@ module JsonLdHelper
   def safe_for_forwarding?(original, compacted)
     original.without('@context', 'signature').all? do |key, value|
       compacted_value = compacted[key]
-      return false unless value.class == compacted_value.class
+      return false unless value.instance_of?(compacted_value.class)
 
       if value.is_a?(Hash)
         safe_for_forwarding?(value, compacted_value)
diff --git a/app/serializers/activitypub/outbox_serializer.rb b/app/serializers/activitypub/outbox_serializer.rb
index 4f4f950a5..4d3d9706d 100644
--- a/app/serializers/activitypub/outbox_serializer.rb
+++ b/app/serializers/activitypub/outbox_serializer.rb
@@ -2,7 +2,7 @@
 
 class ActivityPub::OutboxSerializer < ActivityPub::CollectionSerializer
   def self.serializer_for(model, options)
-    if model.class.name == 'ActivityPub::ActivityPresenter'
+    if model.instance_of?(::ActivityPub::ActivityPresenter)
       ActivityPub::ActivitySerializer
     else
       super

From 929b9fdaff1e6d4223efd8f00bd0b53fae1c7ce1 Mon Sep 17 00:00:00 2001
From: Matt Jankowski <matt@jankowski.online>
Date: Fri, 21 Jun 2024 11:34:13 -0400
Subject: [PATCH 28/35] Remove exclusion for
 `Rails/LexicallyScopedActionFilter` cop (#30697)

---
 .rubocop/rails.yml                               | 4 ----
 app/controllers/auth/registrations_controller.rb | 8 ++++++++
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/.rubocop/rails.yml b/.rubocop/rails.yml
index b83928dee..4e08f1ab9 100644
--- a/.rubocop/rails.yml
+++ b/.rubocop/rails.yml
@@ -5,10 +5,6 @@ Rails/FilePath:
 Rails/HttpStatus:
   EnforcedStyle: numeric
 
-Rails/LexicallyScopedActionFilter:
-  Exclude:
-    - app/controllers/auth/* # Conflicts with `Lint/UselessMethodDefinition` for inherited controller actions
-
 Rails/NegateInclude:
   Enabled: false
 
diff --git a/app/controllers/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb
index f858c0ad9..e5a2ac027 100644
--- a/app/controllers/auth/registrations_controller.rb
+++ b/app/controllers/auth/registrations_controller.rb
@@ -25,6 +25,14 @@ class Auth::RegistrationsController < Devise::RegistrationsController
     super(&:build_invite_request)
   end
 
+  def edit # rubocop:disable Lint/UselessMethodDefinition
+    super
+  end
+
+  def create # rubocop:disable Lint/UselessMethodDefinition
+    super
+  end
+
   def update
     super do |resource|
       resource.clear_other_sessions(current_session.session_id) if resource.saved_change_to_encrypted_password?

From 253a9f766aca839804d231c7988aede71d667893 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 21 Jun 2024 18:13:53 +0200
Subject: [PATCH 29/35] chore(deps): update dependency addressable to v2.8.7
 (#30791)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
 Gemfile.lock | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Gemfile.lock b/Gemfile.lock
index cb796409d..98a1b0e1a 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -89,8 +89,8 @@ GEM
       minitest (>= 5.1)
       mutex_m
       tzinfo (~> 2.0)
-    addressable (2.8.6)
-      public_suffix (>= 2.0.2, < 6.0)
+    addressable (2.8.7)
+      public_suffix (>= 2.0.2, < 7.0)
     aes_key_wrap (1.1.0)
     android_key_attestation (0.3.0)
     annotate (3.2.0)

From abbda3dc26713d7b510a86dd2dac5ed2d20424cb Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 21 Jun 2024 18:14:20 +0200
Subject: [PATCH 30/35] chore(deps): update dependency node to 20.15 (#30782)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
 .nvmrc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.nvmrc b/.nvmrc
index c61a3d77e..cecb93628 100644
--- a/.nvmrc
+++ b/.nvmrc
@@ -1 +1 @@
-20.14
+20.15

From f898214dea0b855a7b47de7fd6a151146f8efad4 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 21 Jun 2024 18:14:41 +0200
Subject: [PATCH 31/35] chore(deps): update opentelemetry-ruby (non-major)
 (#30771)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
 Gemfile      | 2 +-
 Gemfile.lock | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/Gemfile b/Gemfile
index ecd9088d3..c2693a3cd 100644
--- a/Gemfile
+++ b/Gemfile
@@ -105,7 +105,7 @@ gem 'private_address_check', '~> 0.5'
 gem 'opentelemetry-api', '~> 1.2.5'
 
 group :opentelemetry do
-  gem 'opentelemetry-exporter-otlp', '~> 0.27.0', require: false
+  gem 'opentelemetry-exporter-otlp', '~> 0.28.0', require: false
   gem 'opentelemetry-instrumentation-active_job', '~> 0.7.1', require: false
   gem 'opentelemetry-instrumentation-active_model_serializers', '~> 0.20.1', require: false
   gem 'opentelemetry-instrumentation-concurrent_ruby', '~> 0.21.2', require: false
diff --git a/Gemfile.lock b/Gemfile.lock
index 98a1b0e1a..aedc5718a 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -490,8 +490,8 @@ GEM
     opentelemetry-api (1.2.5)
     opentelemetry-common (0.20.1)
       opentelemetry-api (~> 1.0)
-    opentelemetry-exporter-otlp (0.27.0)
-      google-protobuf (~> 3.14)
+    opentelemetry-exporter-otlp (0.28.0)
+      google-protobuf (>= 3.18)
       googleapis-common-protos-types (~> 1.3)
       opentelemetry-api (~> 1.1)
       opentelemetry-common (~> 0.20)
@@ -974,7 +974,7 @@ DEPENDENCIES
   omniauth-saml (~> 2.0)
   omniauth_openid_connect (~> 0.6.1)
   opentelemetry-api (~> 1.2.5)
-  opentelemetry-exporter-otlp (~> 0.27.0)
+  opentelemetry-exporter-otlp (~> 0.28.0)
   opentelemetry-instrumentation-active_job (~> 0.7.1)
   opentelemetry-instrumentation-active_model_serializers (~> 0.20.1)
   opentelemetry-instrumentation-concurrent_ruby (~> 0.21.2)

From 8fd5b59f8ff74d08514a0b8f563c9e23ad278814 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 21 Jun 2024 16:15:09 +0000
Subject: [PATCH 32/35] chore(deps): update dependency devise-two-factor to
 v5.1.0 (#30760)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
 Gemfile.lock | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/Gemfile.lock b/Gemfile.lock
index aedc5718a..15b4e41aa 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -143,7 +143,7 @@ GEM
     brpoplpush-redis_script (0.1.3)
       concurrent-ruby (~> 1.0, >= 1.0.5)
       redis (>= 1.0, < 6)
-    builder (3.2.4)
+    builder (3.3.0)
     bundler-audit (0.9.1)
       bundler (>= 1.2.0, < 3)
       thor (~> 1.0)
@@ -195,7 +195,7 @@ GEM
       railties (>= 4.1.0)
       responders
       warden (~> 1.2.3)
-    devise-two-factor (5.0.0)
+    devise-two-factor (5.1.0)
       activesupport (~> 7.0)
       devise (~> 4.0)
       railties (~> 7.0)
@@ -226,7 +226,7 @@ GEM
       htmlentities (~> 4.3.3)
       launchy (~> 2.1)
       mail (~> 2.7)
-    erubi (1.12.0)
+    erubi (1.13.0)
     et-orbi (1.2.11)
       tzinfo
     excon (0.110.0)
@@ -676,7 +676,7 @@ GEM
       link_header (~> 0.0, >= 0.0.8)
     rdf-normalize (0.7.0)
       rdf (~> 3.3)
-    rdoc (6.6.3.1)
+    rdoc (6.7.0)
       psych (>= 4.0.0)
     redcarpet (3.6.0)
     redis (4.8.1)

From 93741f6a707329fb3f4c1b46bfc979fa99dd16d7 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 21 Jun 2024 18:15:33 +0200
Subject: [PATCH 33/35] fix(deps): update dependency glob to v10.4.2 (#30761)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
 yarn.lock | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/yarn.lock b/yarn.lock
index 948670e2c..ff4e1110d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -8924,17 +8924,18 @@ __metadata:
   linkType: hard
 
 "glob@npm:^10.2.2, glob@npm:^10.2.6, glob@npm:^10.3.10":
-  version: 10.4.1
-  resolution: "glob@npm:10.4.1"
+  version: 10.4.2
+  resolution: "glob@npm:10.4.2"
   dependencies:
     foreground-child: "npm:^3.1.0"
     jackspeak: "npm:^3.1.2"
     minimatch: "npm:^9.0.4"
     minipass: "npm:^7.1.2"
+    package-json-from-dist: "npm:^1.0.0"
     path-scurry: "npm:^1.11.1"
   bin:
     glob: dist/esm/bin.mjs
-  checksum: 10c0/77f2900ed98b9cc2a0e1901ee5e476d664dae3cd0f1b662b8bfd4ccf00d0edc31a11595807706a274ca10e1e251411bbf2e8e976c82bed0d879a9b89343ed379
+  checksum: 10c0/2c7296695fa75a935f3ad17dc62e4e170a8bb8752cf64d328be8992dd6ad40777939003754e10e9741ff8fbe43aa52fba32d6930d0ffa0e3b74bc3fb5eebaa2f
   languageName: node
   linkType: hard
 
@@ -12668,6 +12669,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"package-json-from-dist@npm:^1.0.0":
+  version: 1.0.0
+  resolution: "package-json-from-dist@npm:1.0.0"
+  checksum: 10c0/e3ffaf6ac1040ab6082a658230c041ad14e72fabe99076a2081bb1d5d41210f11872403fc09082daf4387fc0baa6577f96c9c0e94c90c394fd57794b66aa4033
+  languageName: node
+  linkType: hard
+
 "pako@npm:~1.0.5":
   version: 1.0.11
   resolution: "pako@npm:1.0.11"

From 637de635054d42a0ae43035c2658c6941498f918 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 21 Jun 2024 21:37:22 +0200
Subject: [PATCH 34/35] chore(deps): update dependency public_suffix to v6
 (#30738)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
 Gemfile      | 2 +-
 Gemfile.lock | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/Gemfile b/Gemfile
index c2693a3cd..f2d7d098d 100644
--- a/Gemfile
+++ b/Gemfile
@@ -69,7 +69,7 @@ gem 'oj', '~> 3.14'
 gem 'ox', '~> 2.14'
 gem 'parslet'
 gem 'premailer-rails'
-gem 'public_suffix', '~> 5.0'
+gem 'public_suffix', '~> 6.0'
 gem 'pundit', '~> 2.3'
 gem 'rack-attack', '~> 6.6'
 gem 'rack-cors', '~> 2.0', require: 'rack/cors'
diff --git a/Gemfile.lock b/Gemfile.lock
index 15b4e41aa..0fe1c03b2 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -603,7 +603,7 @@ GEM
       railties (>= 7.0.0)
     psych (5.1.2)
       stringio
-    public_suffix (5.1.1)
+    public_suffix (6.0.0)
     puma (6.4.2)
       nio4r (~> 2.0)
     pundit (2.3.2)
@@ -996,7 +996,7 @@ DEPENDENCIES
   premailer-rails
   private_address_check (~> 0.5)
   propshaft
-  public_suffix (~> 5.0)
+  public_suffix (~> 6.0)
   puma (~> 6.3)
   pundit (~> 2.3)
   rack (~> 2.2.7)

From 4743657ba24e83c376e9f477fbf49114e6f09a57 Mon Sep 17 00:00:00 2001
From: Michael Stanclift <mx@vmstan.com>
Date: Fri, 21 Jun 2024 15:26:39 -0500
Subject: [PATCH 35/35] Fix Docker buildx warnings about casing and undefined
 variables (#30798)

---
 Dockerfile           | 18 +++++++++---------
 streaming/Dockerfile |  9 ++++++++-
 2 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/Dockerfile b/Dockerfile
index c3e43dac8..7f7eca06d 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -19,9 +19,9 @@ ARG NODE_MAJOR_VERSION="20"
 # Debian image to use for base image, change with [--build-arg DEBIAN_VERSION="bookworm"]
 ARG DEBIAN_VERSION="bookworm"
 # Node image to use for base image based on combined variables (ex: 20-bookworm-slim)
-FROM docker.io/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim as node
+FROM docker.io/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim AS node
 # Ruby image to use for base image based on combined variables (ex: 3.3.x-slim-bookworm)
-FROM docker.io/ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} as ruby
+FROM docker.io/ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} AS ruby
 
 # Resulting version string is vX.X.X-MASTODON_VERSION_PRERELEASE+MASTODON_VERSION_METADATA
 # Example: v4.3.0-nightly.2023.11.09+pr-123456
@@ -117,7 +117,7 @@ RUN \
   ;
 
 # Create temporary build layer from base image
-FROM ruby as build
+FROM ruby AS build
 
 # Copy Node package configuration files into working directory
 COPY package.json yarn.lock .yarnrc.yml /opt/mastodon/
@@ -185,7 +185,7 @@ RUN \
   corepack prepare --activate;
 
 # Create temporary libvips specific build layer from build layer
-FROM build as libvips
+FROM build AS libvips
 
 # libvips version to compile, change with [--build-arg VIPS_VERSION="8.15.2"]
 # renovate: datasource=github-releases depName=libvips packageName=libvips/libvips
@@ -205,7 +205,7 @@ RUN \
   ninja install;
 
 # Create temporary ffmpeg specific build layer from build layer
-FROM build as ffmpeg
+FROM build AS ffmpeg
 
 # ffmpeg version to compile, change with [--build-arg FFMPEG_VERSION="7.0.x"]
 # renovate: datasource=repology depName=ffmpeg packageName=openpkg_current/ffmpeg
@@ -247,7 +247,7 @@ RUN \
   make install;
 
 # Create temporary bundler specific build layer from build layer
-FROM build as bundler
+FROM build AS bundler
 
 ARG TARGETPLATFORM
 
@@ -269,7 +269,7 @@ RUN \
   bundle install -j"$(nproc)";
 
 # Create temporary node specific build layer from build layer
-FROM build as yarn
+FROM build AS yarn
 
 ARG TARGETPLATFORM
 
@@ -286,7 +286,7 @@ RUN \
   yarn workspaces focus --production @mastodon/mastodon;
 
 # Create temporary assets build layer from build layer
-FROM build as precompiler
+FROM build AS precompiler
 
 # Copy Mastodon sources into precompiler layer
 COPY . /opt/mastodon/
@@ -310,7 +310,7 @@ RUN \
   rm -fr /opt/mastodon/tmp;
 
 # Prep final Mastodon Ruby layer
-FROM ruby as mastodon
+FROM ruby AS mastodon
 
 ARG TARGETPLATFORM
 
diff --git a/streaming/Dockerfile b/streaming/Dockerfile
index aee1f76ad..319d5b7fd 100644
--- a/streaming/Dockerfile
+++ b/streaming/Dockerfile
@@ -13,7 +13,14 @@ ARG NODE_MAJOR_VERSION="20"
 # Debian image to use for base image, change with [--build-arg DEBIAN_VERSION="bookworm"]
 ARG DEBIAN_VERSION="bookworm"
 # Node image to use for base image based on combined variables (ex: 20-bookworm-slim)
-FROM docker.io/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim as streaming
+FROM docker.io/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim AS streaming
+
+# Resulting version string is vX.X.X-MASTODON_VERSION_PRERELEASE+MASTODON_VERSION_METADATA
+# Example: v4.3.0-nightly.2023.11.09+pr-123456
+# Overwrite existence of 'alpha.X' in version.rb [--build-arg MASTODON_VERSION_PRERELEASE="nightly.2023.11.09"]
+ARG MASTODON_VERSION_PRERELEASE=""
+# Append build metadata or fork information to version.rb [--build-arg MASTODON_VERSION_METADATA="pr-123456"]
+ARG MASTODON_VERSION_METADATA=""
 
 # Timezone used by the Docker container and runtime, change with [--build-arg TZ=Europe/Berlin]
 ARG TZ="Etc/UTC"