diff --git a/CHANGELOG.md b/CHANGELOG.md
index e1604ab3a..b70302bbf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - **Breaking:** Changed `mix pleroma.user toggle_confirmed` to `mix pleroma.user confirm`
 - Search: When using Postgres 11+, Pleroma will use the `websearch_to_tsvector` function to parse search queries.
 - Emoji: Support the full Unicode 13.1 set of Emoji for reactions, plus regional indicators.
+- Admin API: Reports now ordered by newest
 
 ### Added
 
@@ -29,6 +30,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - Mix tasks to help with displaying and removing ConfigDB entries. See `mix pleroma.config`.
 - OAuth form improvements: users are remembered by their cookie, the CSS is overridable by the admin, and the style has been improved.
 - OAuth improvements and fixes: more secure session-based authentication (by token that could be revoked anytime), ability to revoke belonging OAuth token from any client etc.
+- Ability to set ActivityPub aliases for follower migration.
 
 <details>
   <summary>API Changes</summary>
diff --git a/config/test.exs b/config/test.exs
index a85881592..7fc457463 100644
--- a/config/test.exs
+++ b/config/test.exs
@@ -134,6 +134,10 @@
 
 config :pleroma, :cachex, provider: Pleroma.CachexMock
 
+config :pleroma, :side_effects,
+  ap_streamer: Pleroma.Web.ActivityPub.ActivityPubMock,
+  logger: Pleroma.LoggerMock
+
 if File.exists?("./config/test.secret.exs") do
   import_config "test.secret.exs"
 else
diff --git a/docs/API/admin_api.md b/docs/API/admin_api.md
index 266f8cef8..5253dc668 100644
--- a/docs/API/admin_api.md
+++ b/docs/API/admin_api.md
@@ -1123,6 +1123,7 @@ Loads json generated from `config/descriptions.exs`.
 ```json
 [
   {
+    "id": 1234,
     "data": {
       "actor": {
         "id": 1,
diff --git a/docs/API/differences_in_mastoapi_responses.md b/docs/API/differences_in_mastoapi_responses.md
index 1b197e073..84430408b 100644
--- a/docs/API/differences_in_mastoapi_responses.md
+++ b/docs/API/differences_in_mastoapi_responses.md
@@ -206,6 +206,7 @@ Additional parameters can be added to the JSON body/Form data:
 - `pleroma_settings_store` - Opaque user settings to be saved on the backend.
 - `skip_thread_containment` - if true, skip filtering out broken threads
 - `allow_following_move` - if true, allows automatically follow moved following accounts
+- `also_known_as` - array of ActivityPub IDs, needed for following move
 - `pleroma_background_image` - sets the background image of the user. Can be set to "" (an empty string) to reset.
 - `discoverable` - if true, external services (search bots) etc. are allowed to index / list the account (regardless of this setting, user will still appear in regular search results).
 - `actor_type` - the type of this account.
diff --git a/lib/pleroma/logging.ex b/lib/pleroma/logging.ex
new file mode 100644
index 000000000..37b201c29
--- /dev/null
+++ b/lib/pleroma/logging.ex
@@ -0,0 +1,7 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Logging do
+  @callback error(String.t()) :: any()
+end
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index bd4801058..52730fd8d 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -142,7 +142,7 @@ defmodule Pleroma.User do
     field(:allow_following_move, :boolean, default: true)
     field(:skip_thread_containment, :boolean, default: false)
     field(:actor_type, :string, default: "Person")
-    field(:also_known_as, {:array, :string}, default: [])
+    field(:also_known_as, {:array, ObjectValidators.ObjectID}, default: [])
     field(:inbox, :string)
     field(:shared_inbox, :string)
     field(:accepts_chat_messages, :boolean, default: nil)
@@ -515,6 +515,7 @@ def update_changeset(struct, params \\ %{}) do
         :hide_follows_count,
         :hide_favorites,
         :allow_following_move,
+        :also_known_as,
         :background,
         :show_role,
         :skip_thread_containment,
@@ -523,7 +524,6 @@ def update_changeset(struct, params \\ %{}) do
         :pleroma_settings_store,
         :is_discoverable,
         :actor_type,
-        :also_known_as,
         :accepts_chat_messages
       ]
     )
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index 15f298bb8..3e346d49a 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -33,6 +33,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
   require Pleroma.Constants
 
   @behaviour Pleroma.Web.ActivityPub.ActivityPub.Persisting
+  @behaviour Pleroma.Web.ActivityPub.ActivityPub.Streaming
 
   defp get_recipients(%{"type" => "Create"} = data) do
     to = Map.get(data, "to", [])
@@ -224,6 +225,7 @@ def stream_out_participations(participations) do
     Streamer.stream("participation", participations)
   end
 
+  @impl true
   def stream_out_participations(%Object{data: %{"context" => context}}, user) do
     with %Conversation{} = conversation <- Conversation.get_for_ap_id(context) do
       conversation = Repo.preload(conversation, :participations)
@@ -240,8 +242,10 @@ def stream_out_participations(%Object{data: %{"context" => context}}, user) do
     end
   end
 
+  @impl true
   def stream_out_participations(_, _), do: :noop
 
+  @impl true
   def stream_out(%Activity{data: %{"type" => data_type}} = activity)
       when data_type in ["Create", "Announce", "Delete"] do
     activity
@@ -249,6 +253,7 @@ def stream_out(%Activity{data: %{"type" => data_type}} = activity)
     |> Streamer.stream(activity)
   end
 
+  @impl true
   def stream_out(_activity) do
     :noop
   end
diff --git a/lib/pleroma/web/activity_pub/activity_pub/streaming.ex b/lib/pleroma/web/activity_pub/activity_pub/streaming.ex
new file mode 100644
index 000000000..30009f2fb
--- /dev/null
+++ b/lib/pleroma/web/activity_pub/activity_pub/streaming.ex
@@ -0,0 +1,12 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.ActivityPub.Streaming do
+  alias Pleroma.Activity
+  alias Pleroma.Object
+  alias Pleroma.User
+
+  @callback stream_out(Activity.t()) :: any()
+  @callback stream_out_participations(Object.t(), User.t()) :: any()
+end
diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex
index 55c99ad0c..e37caf6a0 100644
--- a/lib/pleroma/web/activity_pub/side_effects.ex
+++ b/lib/pleroma/web/activity_pub/side_effects.ex
@@ -28,6 +28,8 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
   require Logger
 
   @cachex Pleroma.Config.get([:cachex, :provider], Cachex)
+  @ap_streamer Pleroma.Config.get([:side_effects, :ap_streamer], ActivityPub)
+  @logger Pleroma.Config.get([:side_effects, :logger], Logger)
 
   @behaviour Pleroma.Web.ActivityPub.SideEffects.Handling
 
@@ -287,12 +289,12 @@ def handle(%{data: %{"type" => "Delete", "object" => deleted_object}} = object,
 
             MessageReference.delete_for_object(deleted_object)
 
-            ActivityPub.stream_out(object)
-            ActivityPub.stream_out_participations(deleted_object, user)
+            @ap_streamer.stream_out(object)
+            @ap_streamer.stream_out_participations(deleted_object, user)
             :ok
           else
             {:actor, _} ->
-              Logger.error("The object doesn't have an actor: #{inspect(deleted_object)}")
+              @logger.error("The object doesn't have an actor: #{inspect(deleted_object)}")
               :no_object_actor
           end
 
diff --git a/lib/pleroma/web/activity_pub/views/user_view.ex b/lib/pleroma/web/activity_pub/views/user_view.ex
index 93c9f436c..241224b57 100644
--- a/lib/pleroma/web/activity_pub/views/user_view.ex
+++ b/lib/pleroma/web/activity_pub/views/user_view.ex
@@ -112,7 +112,8 @@ def render("user.json", %{user: user}) do
       "tag" => emoji_tags,
       # Note: key name is indeed "discoverable" (not an error)
       "discoverable" => user.is_discoverable,
-      "capabilities" => capabilities
+      "capabilities" => capabilities,
+      "alsoKnownAs" => user.also_known_as
     }
     |> Map.merge(maybe_make_image(&User.avatar_url/2, "icon", user))
     |> Map.merge(maybe_make_image(&User.banner_url/2, "image", user))
diff --git a/lib/pleroma/web/admin_api/views/moderation_log_view.ex b/lib/pleroma/web/admin_api/views/moderation_log_view.ex
index 112f9e0e1..3fa778b0a 100644
--- a/lib/pleroma/web/admin_api/views/moderation_log_view.ex
+++ b/lib/pleroma/web/admin_api/views/moderation_log_view.ex
@@ -21,6 +21,7 @@ def render("show.json", %{log_entry: log_entry}) do
       |> DateTime.to_unix()
 
     %{
+      id: log_entry.id,
       data: log_entry.data,
       time: time,
       message: ModerationLog.get_log_entry_message(log_entry)
diff --git a/lib/pleroma/web/admin_api/views/report_view.ex b/lib/pleroma/web/admin_api/views/report_view.ex
index 535556370..da949e306 100644
--- a/lib/pleroma/web/admin_api/views/report_view.ex
+++ b/lib/pleroma/web/admin_api/views/report_view.ex
@@ -19,8 +19,7 @@ def render("index.json", %{reports: reports}) do
       reports:
         reports[:items]
         |> Enum.map(&Report.extract_report_info/1)
-        |> Enum.map(&render(__MODULE__, "show.json", &1))
-        |> Enum.reverse(),
+        |> Enum.map(&render(__MODULE__, "show.json", &1)),
       total: reports[:total]
     }
   end
diff --git a/lib/pleroma/web/api_spec/operations/account_operation.ex b/lib/pleroma/web/api_spec/operations/account_operation.ex
index 280100c3d..bd3a73c11 100644
--- a/lib/pleroma/web/api_spec/operations/account_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/account_operation.ex
@@ -614,6 +614,12 @@ defp update_credentials_request do
           nullable: true,
           description: "Allows automatically follow moved following accounts"
         },
+        also_known_as: %Schema{
+          type: :array,
+          items: %Schema{type: :string},
+          nullable: true,
+          description: "List of alternate ActivityPub IDs"
+        },
         pleroma_background_image: %Schema{
           type: :string,
           nullable: true,
@@ -644,6 +650,7 @@ defp update_credentials_request do
         pleroma_settings_store: %{"pleroma-fe" => %{"key" => "val"}},
         skip_thread_containment: false,
         allow_following_move: false,
+        also_known_as: ["https://foo.bar/users/foo"],
         discoverable: false,
         actor_type: "Person"
       }
diff --git a/lib/pleroma/web/api_spec/schemas/account.ex b/lib/pleroma/web/api_spec/schemas/account.ex
index 684f6fc92..70437003c 100644
--- a/lib/pleroma/web/api_spec/schemas/account.ex
+++ b/lib/pleroma/web/api_spec/schemas/account.ex
@@ -40,6 +40,8 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do
       pleroma: %Schema{
         type: :object,
         properties: %{
+          ap_id: %Schema{type: :string},
+          also_known_as: %Schema{type: :array, items: %Schema{type: :string}},
           allow_following_move: %Schema{
             type: :boolean,
             description: "whether the user allows automatically follow moved following accounts"
diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
index b4375872b..3951d10ac 100644
--- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
@@ -184,6 +184,7 @@ def update_credentials(%{assigns: %{user: user}, body_params: params} = conn, _p
         :show_role,
         :skip_thread_containment,
         :allow_following_move,
+        :also_known_as,
         :accepts_chat_messages
       ]
       |> Enum.reduce(%{}, fn key, acc ->
@@ -207,6 +208,7 @@ def update_credentials(%{assigns: %{user: user}, body_params: params} = conn, _p
         if bot, do: {:ok, "Service"}, else: {:ok, "Person"}
       end)
       |> Maps.put_if_present(:actor_type, params[:actor_type])
+      |> Maps.put_if_present(:also_known_as, params[:also_known_as])
       # Note: param name is indeed :locked (not an error)
       |> Maps.put_if_present(:is_locked, params[:locked])
       # Note: param name is indeed :discoverable (not an error)
diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex
index 026ae9458..948a05a6d 100644
--- a/lib/pleroma/web/mastodon_api/views/account_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/account_view.ex
@@ -265,6 +265,7 @@ defp do_render("show.json", %{user: user} = opts) do
       # Pleroma extension
       pleroma: %{
         ap_id: user.ap_id,
+        also_known_as: user.also_known_as,
         confirmation_pending: user.confirmation_pending,
         tags: user.tags,
         hide_followers_count: user.hide_followers_count,
diff --git a/lib/pleroma/web/web_finger.ex b/lib/pleroma/web/web_finger.ex
index 2e39ae048..a109e1acc 100644
--- a/lib/pleroma/web/web_finger.ex
+++ b/lib/pleroma/web/web_finger.ex
@@ -58,12 +58,16 @@ defp gather_links(%User{} = user) do
     ] ++ Publisher.gather_webfinger_links(user)
   end
 
+  defp gather_aliases(%User{} = user) do
+    [user.ap_id | user.also_known_as]
+  end
+
   def represent_user(user, "JSON") do
     {:ok, user} = User.ensure_keys_present(user)
 
     %{
       "subject" => "acct:#{user.nickname}@#{Pleroma.Web.Endpoint.host()}",
-      "aliases" => [user.ap_id],
+      "aliases" => gather_aliases(user),
       "links" => gather_links(user)
     }
   end
@@ -71,6 +75,11 @@ def represent_user(user, "JSON") do
   def represent_user(user, "XML") do
     {:ok, user} = User.ensure_keys_present(user)
 
+    aliases =
+      user
+      |> gather_aliases()
+      |> Enum.map(&{:Alias, &1})
+
     links =
       gather_links(user)
       |> Enum.map(fn link -> {:Link, link} end)
@@ -79,9 +88,8 @@ def represent_user(user, "XML") do
       :XRD,
       %{xmlns: "http://docs.oasis-open.org/ns/xri/xrd-1.0"},
       [
-        {:Subject, "acct:#{user.nickname}@#{Pleroma.Web.Endpoint.host()}"},
-        {:Alias, user.ap_id}
-      ] ++ links
+        {:Subject, "acct:#{user.nickname}@#{Pleroma.Web.Endpoint.host()}"}
+      ] ++ aliases ++ links
     }
     |> XmlBuilder.to_doc()
   end
diff --git a/test/pleroma/web/activity_pub/side_effects/delete_test.exs b/test/pleroma/web/activity_pub/side_effects/delete_test.exs
new file mode 100644
index 000000000..e4ad606a9
--- /dev/null
+++ b/test/pleroma/web/activity_pub/side_effects/delete_test.exs
@@ -0,0 +1,147 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.SideEffects.DeleteTest do
+  use Oban.Testing, repo: Pleroma.Repo
+  use Pleroma.DataCase, async: true
+
+  alias Pleroma.Activity
+  alias Pleroma.Object
+  alias Pleroma.Repo
+  alias Pleroma.Tests.ObanHelpers
+  alias Pleroma.User
+  alias Pleroma.Web.ActivityPub.ActivityPub
+  alias Pleroma.Web.ActivityPub.Builder
+  alias Pleroma.Web.ActivityPub.SideEffects
+  alias Pleroma.Web.CommonAPI
+
+  alias Pleroma.LoggerMock
+  alias Pleroma.Web.ActivityPub.ActivityPubMock
+
+  import Mox
+  import Pleroma.Factory
+
+  describe "user deletion" do
+    setup do
+      user = insert(:user)
+
+      {:ok, delete_user_data, _meta} = Builder.delete(user, user.ap_id)
+      {:ok, delete_user, _meta} = ActivityPub.persist(delete_user_data, local: true)
+
+      %{
+        user: user,
+        delete_user: delete_user
+      }
+    end
+
+    test "it handles user deletions", %{delete_user: delete, user: user} do
+      {:ok, _delete, _} = SideEffects.handle(delete)
+      ObanHelpers.perform_all()
+
+      assert User.get_cached_by_ap_id(user.ap_id).deactivated
+    end
+  end
+
+  describe "object deletion" do
+    setup do
+      user = insert(:user)
+      other_user = insert(:user)
+
+      {:ok, op} = CommonAPI.post(other_user, %{status: "big oof"})
+      {:ok, post} = CommonAPI.post(user, %{status: "hey", in_reply_to_id: op})
+      {:ok, favorite} = CommonAPI.favorite(user, post.id)
+      object = Object.normalize(post)
+      {:ok, delete_data, _meta} = Builder.delete(user, object.data["id"])
+      {:ok, delete, _meta} = ActivityPub.persist(delete_data, local: true)
+
+      %{
+        user: user,
+        delete: delete,
+        post: post,
+        object: object,
+        op: op,
+        favorite: favorite
+      }
+    end
+
+    test "it handles object deletions", %{
+      delete: delete,
+      post: post,
+      object: object,
+      user: user,
+      op: op,
+      favorite: favorite
+    } do
+      object_id = object.id
+      user_id = user.id
+
+      ActivityPubMock
+      |> expect(:stream_out, fn ^delete -> nil end)
+      |> expect(:stream_out_participations, fn %Object{id: ^object_id}, %User{id: ^user_id} ->
+        nil
+      end)
+
+      {:ok, _delete, _} = SideEffects.handle(delete)
+      user = User.get_cached_by_ap_id(object.data["actor"])
+
+      object = Object.get_by_id(object.id)
+      assert object.data["type"] == "Tombstone"
+      refute Activity.get_by_id(post.id)
+      refute Activity.get_by_id(favorite.id)
+
+      user = User.get_by_id(user.id)
+      assert user.note_count == 0
+
+      object = Object.normalize(op.data["object"], false)
+
+      assert object.data["repliesCount"] == 0
+    end
+
+    test "it handles object deletions when the object itself has been pruned", %{
+      delete: delete,
+      post: post,
+      object: object,
+      user: user,
+      op: op
+    } do
+      object_id = object.id
+      user_id = user.id
+
+      ActivityPubMock
+      |> expect(:stream_out, fn ^delete -> nil end)
+      |> expect(:stream_out_participations, fn %Object{id: ^object_id}, %User{id: ^user_id} ->
+        nil
+      end)
+
+      {:ok, _delete, _} = SideEffects.handle(delete)
+      user = User.get_cached_by_ap_id(object.data["actor"])
+
+      object = Object.get_by_id(object.id)
+      assert object.data["type"] == "Tombstone"
+      refute Activity.get_by_id(post.id)
+
+      user = User.get_by_id(user.id)
+      assert user.note_count == 0
+
+      object = Object.normalize(op.data["object"], false)
+
+      assert object.data["repliesCount"] == 0
+    end
+
+    test "it logs issues with objects deletion", %{
+      delete: delete,
+      object: object
+    } do
+      {:ok, _object} =
+        object
+        |> Object.change(%{data: Map.delete(object.data, "actor")})
+        |> Repo.update()
+
+      LoggerMock
+      |> expect(:error, fn str -> assert str =~ "The object doesn't have an actor" end)
+
+      {:error, :no_object_actor} = SideEffects.handle(delete)
+    end
+  end
+end
diff --git a/test/pleroma/web/activity_pub/side_effects_test.exs b/test/pleroma/web/activity_pub/side_effects_test.exs
index 297fc0b84..50af7a507 100644
--- a/test/pleroma/web/activity_pub/side_effects_test.exs
+++ b/test/pleroma/web/activity_pub/side_effects_test.exs
@@ -19,7 +19,6 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
   alias Pleroma.Web.ActivityPub.SideEffects
   alias Pleroma.Web.CommonAPI
 
-  import ExUnit.CaptureLog
   import Mock
   import Pleroma.Factory
 
@@ -131,115 +130,6 @@ test "it uses a given changeset to update", %{user: user, update: update} do
     end
   end
 
-  describe "delete objects" do
-    setup do
-      user = insert(:user)
-      other_user = insert(:user)
-
-      {:ok, op} = CommonAPI.post(other_user, %{status: "big oof"})
-      {:ok, post} = CommonAPI.post(user, %{status: "hey", in_reply_to_id: op})
-      {:ok, favorite} = CommonAPI.favorite(user, post.id)
-      object = Object.normalize(post)
-      {:ok, delete_data, _meta} = Builder.delete(user, object.data["id"])
-      {:ok, delete_user_data, _meta} = Builder.delete(user, user.ap_id)
-      {:ok, delete, _meta} = ActivityPub.persist(delete_data, local: true)
-      {:ok, delete_user, _meta} = ActivityPub.persist(delete_user_data, local: true)
-
-      %{
-        user: user,
-        delete: delete,
-        post: post,
-        object: object,
-        delete_user: delete_user,
-        op: op,
-        favorite: favorite
-      }
-    end
-
-    test "it handles object deletions", %{
-      delete: delete,
-      post: post,
-      object: object,
-      user: user,
-      op: op,
-      favorite: favorite
-    } do
-      with_mock Pleroma.Web.ActivityPub.ActivityPub, [:passthrough],
-        stream_out: fn _ -> nil end,
-        stream_out_participations: fn _, _ -> nil end do
-        {:ok, delete, _} = SideEffects.handle(delete)
-        user = User.get_cached_by_ap_id(object.data["actor"])
-
-        assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out(delete))
-        assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out_participations(object, user))
-      end
-
-      object = Object.get_by_id(object.id)
-      assert object.data["type"] == "Tombstone"
-      refute Activity.get_by_id(post.id)
-      refute Activity.get_by_id(favorite.id)
-
-      user = User.get_by_id(user.id)
-      assert user.note_count == 0
-
-      object = Object.normalize(op.data["object"], false)
-
-      assert object.data["repliesCount"] == 0
-    end
-
-    test "it handles object deletions when the object itself has been pruned", %{
-      delete: delete,
-      post: post,
-      object: object,
-      user: user,
-      op: op
-    } do
-      with_mock Pleroma.Web.ActivityPub.ActivityPub, [:passthrough],
-        stream_out: fn _ -> nil end,
-        stream_out_participations: fn _, _ -> nil end do
-        {:ok, delete, _} = SideEffects.handle(delete)
-        user = User.get_cached_by_ap_id(object.data["actor"])
-
-        assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out(delete))
-        assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out_participations(object, user))
-      end
-
-      object = Object.get_by_id(object.id)
-      assert object.data["type"] == "Tombstone"
-      refute Activity.get_by_id(post.id)
-
-      user = User.get_by_id(user.id)
-      assert user.note_count == 0
-
-      object = Object.normalize(op.data["object"], false)
-
-      assert object.data["repliesCount"] == 0
-    end
-
-    test "it handles user deletions", %{delete_user: delete, user: user} do
-      {:ok, _delete, _} = SideEffects.handle(delete)
-      ObanHelpers.perform_all()
-
-      assert User.get_cached_by_ap_id(user.ap_id).deactivated
-    end
-
-    test "it logs issues with objects deletion", %{
-      delete: delete,
-      object: object
-    } do
-      {:ok, object} =
-        object
-        |> Object.change(%{data: Map.delete(object.data, "actor")})
-        |> Repo.update()
-
-      Object.invalid_object_cache(object)
-
-      assert capture_log(fn ->
-               {:error, :no_object_actor} = SideEffects.handle(delete)
-             end) =~ "object doesn't have an actor"
-    end
-  end
-
   describe "EmojiReact objects" do
     setup do
       poster = insert(:user)
diff --git a/test/pleroma/web/activity_pub/views/user_view_test.exs b/test/pleroma/web/activity_pub/views/user_view_test.exs
index fe6ddf0d6..5702c1b6f 100644
--- a/test/pleroma/web/activity_pub/views/user_view_test.exs
+++ b/test/pleroma/web/activity_pub/views/user_view_test.exs
@@ -80,6 +80,12 @@ test "renders an invisible user with the invisible property set to true" do
     assert %{"invisible" => true} = UserView.render("service.json", %{user: user})
   end
 
+  test "renders AKAs" do
+    akas = ["https://i.tusooa.xyz/users/test-pleroma"]
+    user = insert(:user, also_known_as: akas)
+    assert %{"alsoKnownAs" => ^akas} = UserView.render("user.json", %{user: user})
+  end
+
   describe "endpoints" do
     test "local users have a usable endpoints structure" do
       user = insert(:user)
diff --git a/test/pleroma/web/admin_api/views/moderation_log_view_test.exs b/test/pleroma/web/admin_api/views/moderation_log_view_test.exs
index 390d7bbeb..a4748990e 100644
--- a/test/pleroma/web/admin_api/views/moderation_log_view_test.exs
+++ b/test/pleroma/web/admin_api/views/moderation_log_view_test.exs
@@ -9,6 +9,7 @@ defmodule Pleroma.Web.AdminAPI.ModerationLogViewTest do
   describe "renders `report_note_delete` log messages" do
     setup do
       log1 = %Pleroma.ModerationLog{
+        id: 1,
         data: %{
           "action" => "report_note_delete",
           "actor" => %{"id" => "A1I7G8", "nickname" => "admin", "type" => "user"},
@@ -21,6 +22,7 @@ defmodule Pleroma.Web.AdminAPI.ModerationLogViewTest do
       }
 
       log2 = %Pleroma.ModerationLog{
+        id: 2,
         data: %{
           "action" => "report_note_delete",
           "actor" => %{"id" => "A1I7G8", "nickname" => "admin", "type" => "user"},
@@ -42,6 +44,7 @@ test "renders `report_note_delete` log messages", %{log1: log1, log2: log2} do
              ) == %{
                items: [
                  %{
+                   id: 1,
                    data: %{
                      "action" => "report_note_delete",
                      "actor" => %{"id" => "A1I7G8", "nickname" => "admin", "type" => "user"},
@@ -59,6 +62,7 @@ test "renders `report_note_delete` log messages", %{log1: log1, log2: log2} do
                    time: 1_605_622_400
                  },
                  %{
+                   id: 2,
                    data: %{
                      "action" => "report_note_delete",
                      "actor" => %{"id" => "A1I7G8", "nickname" => "admin", "type" => "user"},
@@ -82,6 +86,7 @@ test "renders `report_note_delete` log messages", %{log1: log1, log2: log2} do
 
     test "renders `report_note_delete` log message", %{log1: log} do
       assert ModerationLogView.render("show.json", %{log_entry: log}) == %{
+               id: 1,
                data: %{
                  "action" => "report_note_delete",
                  "actor" => %{"id" => "A1I7G8", "nickname" => "admin", "type" => "user"},
diff --git a/test/pleroma/web/admin_api/views/report_view_test.exs b/test/pleroma/web/admin_api/views/report_view_test.exs
index ff3453208..3914751b5 100644
--- a/test/pleroma/web/admin_api/views/report_view_test.exs
+++ b/test/pleroma/web/admin_api/views/report_view_test.exs
@@ -143,4 +143,29 @@ test "doesn't error out when the user doesn't exists" do
 
     assert %{} = ReportView.render("show.json", Report.extract_report_info(activity))
   end
+
+  test "reports are ordered newest first" do
+    user = insert(:user)
+    other_user = insert(:user)
+
+    {:ok, report1} =
+      CommonAPI.report(user, %{
+        account_id: other_user.id,
+        comment: "first report"
+      })
+
+    {:ok, report2} =
+      CommonAPI.report(user, %{
+        account_id: other_user.id,
+        comment: "second report"
+      })
+
+    %{reports: rendered} =
+      ReportView.render("index.json",
+        reports: Pleroma.Web.ActivityPub.Utils.get_reports(%{}, 1, 50)
+      )
+
+    assert report2.id == rendered |> Enum.at(0) |> Map.get(:id)
+    assert report1.id == rendered |> Enum.at(1) |> Map.get(:id)
+  end
 end
diff --git a/test/pleroma/web/mastodon_api/update_credentials_test.exs b/test/pleroma/web/mastodon_api/update_credentials_test.exs
index 023726468..e3e437a19 100644
--- a/test/pleroma/web/mastodon_api/update_credentials_test.exs
+++ b/test/pleroma/web/mastodon_api/update_credentials_test.exs
@@ -218,6 +218,25 @@ test "updates the user's name", %{conn: conn} do
       assert update_activity.data["object"]["name"] == "markorepairs"
     end
 
+    test "updates the user's AKAs", %{conn: conn} do
+      conn =
+        patch(conn, "/api/v1/accounts/update_credentials", %{
+          "also_known_as" => ["https://mushroom.kingdom/users/mario"]
+        })
+
+      assert user_data = json_response_and_validate_schema(conn, 200)
+      assert user_data["pleroma"]["also_known_as"] == ["https://mushroom.kingdom/users/mario"]
+    end
+
+    test "doesn't update non-url akas", %{conn: conn} do
+      conn =
+        patch(conn, "/api/v1/accounts/update_credentials", %{
+          "also_known_as" => ["aReallyCoolGuy"]
+        })
+
+      assert json_response_and_validate_schema(conn, 403)
+    end
+
     test "updates the user's avatar", %{user: user, conn: conn} do
       new_avatar = %Plug.Upload{
         content_type: "image/jpeg",
diff --git a/test/pleroma/web/mastodon_api/views/account_view_test.exs b/test/pleroma/web/mastodon_api/views/account_view_test.exs
index 8c77f14d4..f9afd0afc 100644
--- a/test/pleroma/web/mastodon_api/views/account_view_test.exs
+++ b/test/pleroma/web/mastodon_api/views/account_view_test.exs
@@ -35,7 +35,8 @@ test "Represent a user account" do
           "<script src=\"invalid-html\"></script><span>valid html</span>. a<br>b<br/>c<br >d<br />f '&<>\"",
         inserted_at: ~N[2017-08-15 15:47:06.597036],
         emoji: %{"karjalanpiirakka" => "/file.png"},
-        raw_bio: "valid html. a\nb\nc\nd\nf '&<>\""
+        raw_bio: "valid html. a\nb\nc\nd\nf '&<>\"",
+        also_known_as: ["https://shitposter.zone/users/shp"]
       })
 
     expected = %{
@@ -75,6 +76,7 @@ test "Represent a user account" do
       },
       pleroma: %{
         ap_id: user.ap_id,
+        also_known_as: ["https://shitposter.zone/users/shp"],
         background_image: "https://example.com/images/asuka_hospital.png",
         favicon: nil,
         confirmation_pending: false,
@@ -173,6 +175,7 @@ test "Represent a Service(bot) account" do
       },
       pleroma: %{
         ap_id: user.ap_id,
+        also_known_as: [],
         background_image: nil,
         favicon: nil,
         confirmation_pending: false,
diff --git a/test/pleroma/web/web_finger/web_finger_controller_test.exs b/test/pleroma/web/web_finger/web_finger_controller_test.exs
index 0023f1e81..ce9eb0650 100644
--- a/test/pleroma/web/web_finger/web_finger_controller_test.exs
+++ b/test/pleroma/web/web_finger/web_finger_controller_test.exs
@@ -30,14 +30,24 @@ test "GET host-meta" do
   end
 
   test "Webfinger JRD" do
-    user = insert(:user)
+    user =
+      insert(:user,
+        ap_id: "https://hyrule.world/users/zelda",
+        also_known_as: ["https://mushroom.kingdom/users/toad"]
+      )
 
     response =
       build_conn()
       |> put_req_header("accept", "application/jrd+json")
       |> get("/.well-known/webfinger?resource=acct:#{user.nickname}@localhost")
+      |> json_response(200)
 
-    assert json_response(response, 200)["subject"] == "acct:#{user.nickname}@localhost"
+    assert response["subject"] == "acct:#{user.nickname}@localhost"
+
+    assert response["aliases"] == [
+             "https://hyrule.world/users/zelda",
+             "https://mushroom.kingdom/users/toad"
+           ]
   end
 
   test "it returns 404 when user isn't found (JSON)" do
@@ -51,14 +61,20 @@ test "it returns 404 when user isn't found (JSON)" do
   end
 
   test "Webfinger XML" do
-    user = insert(:user)
+    user =
+      insert(:user,
+        ap_id: "https://hyrule.world/users/zelda",
+        also_known_as: ["https://mushroom.kingdom/users/toad"]
+      )
 
     response =
       build_conn()
       |> put_req_header("accept", "application/xrd+xml")
       |> get("/.well-known/webfinger?resource=acct:#{user.nickname}@localhost")
+      |> response(200)
 
-    assert response(response, 200)
+    assert response =~ "<Alias>https://hyrule.world/users/zelda</Alias>"
+    assert response =~ "<Alias>https://mushroom.kingdom/users/toad</Alias>"
   end
 
   test "it returns 404 when user isn't found (XML)" do
diff --git a/test/support/conn_case.ex b/test/support/conn_case.ex
index 02f49c590..f20e3d955 100644
--- a/test/support/conn_case.ex
+++ b/test/support/conn_case.ex
@@ -138,6 +138,8 @@ defp json_response_and_validate_schema(conn, _status) do
 
     Pleroma.DataCase.stub_pipeline()
 
+    Mox.verify_on_exit!()
+
     {:ok, conn: Phoenix.ConnTest.build_conn()}
   end
 end
diff --git a/test/support/data_case.ex b/test/support/data_case.ex
index 5c657c1d9..0b41f0f63 100644
--- a/test/support/data_case.ex
+++ b/test/support/data_case.ex
@@ -85,6 +85,8 @@ def clear_cachex do
 
     stub_pipeline()
 
+    Mox.verify_on_exit!()
+
     :ok
   end
 
diff --git a/test/support/mocks.ex b/test/support/mocks.ex
index a600a6458..442ff5b71 100644
--- a/test/support/mocks.ex
+++ b/test/support/mocks.ex
@@ -13,7 +13,10 @@
 )
 
 Mox.defmock(Pleroma.Web.ActivityPub.ActivityPubMock,
-  for: Pleroma.Web.ActivityPub.ActivityPub.Persisting
+  for: [
+    Pleroma.Web.ActivityPub.ActivityPub.Persisting,
+    Pleroma.Web.ActivityPub.ActivityPub.Streaming
+  ]
 )
 
 Mox.defmock(Pleroma.Web.ActivityPub.SideEffectsMock,
@@ -23,3 +26,5 @@
 Mox.defmock(Pleroma.Web.FederatorMock, for: Pleroma.Web.Federator.Publishing)
 
 Mox.defmock(Pleroma.ConfigMock, for: Pleroma.Config.Getting)
+
+Mox.defmock(Pleroma.LoggerMock, for: Pleroma.Logging)