about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS.md269
-rw-r--r--CHANGELOG.md73
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock4
-rw-r--r--app/javascript/flavours/glitch/actions/search.js1
-rw-r--r--app/javascript/flavours/glitch/styles/_mixins.scss1
-rw-r--r--app/javascript/flavours/glitch/styles/components/accounts.scss1
-rw-r--r--app/javascript/flavours/glitch/styles/widgets.scss1
-rw-r--r--app/javascript/mastodon/actions/search.js1
-rw-r--r--app/javascript/mastodon/features/account/components/header.js10
-rw-r--r--app/javascript/mastodon/features/account_timeline/index.js22
-rw-r--r--app/javascript/mastodon/features/direct_timeline/components/column_settings.js35
-rw-r--r--app/javascript/mastodon/features/direct_timeline/containers/column_settings_container.js17
-rw-r--r--app/javascript/mastodon/features/followers/index.js8
-rw-r--r--app/javascript/mastodon/features/following/index.js8
-rw-r--r--app/javascript/mastodon/locales/co.json6
-rw-r--r--app/javascript/mastodon/locales/cs.json2
-rw-r--r--app/javascript/mastodon/locales/fa.json2
-rw-r--r--app/javascript/mastodon/locales/ko.json2
-rw-r--r--app/javascript/styles/mastodon/components.scss1
-rw-r--r--app/javascript/styles/mastodon/stream_entries.scss6
-rw-r--r--app/javascript/styles/mastodon/widgets.scss1
-rw-r--r--app/lib/activitypub/adapter.rb1
-rw-r--r--app/lib/proof_provider/keybase.rb3
-rw-r--r--app/serializers/activitypub/actor_serializer.rb24
-rw-r--r--app/services/activitypub/process_account_service.rb28
-rw-r--r--config/locales/activerecord.co.yml5
-rw-r--r--config/locales/co.yml28
-rw-r--r--config/locales/cs.yml9
-rw-r--r--config/locales/ko.yml7
-rw-r--r--dist/nginx.conf1
-rw-r--r--lib/mastodon/version.rb6
-rw-r--r--spec/services/activitypub/process_account_service_spec.rb45
33 files changed, 454 insertions, 176 deletions
diff --git a/AUTHORS.md b/AUTHORS.md
index 3171214e0..8d3aaf480 100644
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -6,8 +6,8 @@ and provided thanks to the work of the following contributors:
 
 * [Gargron](https://github.com/Gargron)
 * [ykzts](https://github.com/ykzts)
-* [akihikodaki](https://github.com/akihikodaki)
 * [ThibG](https://github.com/ThibG)
+* [akihikodaki](https://github.com/akihikodaki)
 * [mjankowski](https://github.com/mjankowski)
 * [dependabot[bot]](https://github.com/apps/dependabot)
 * [unarist](https://github.com/unarist)
@@ -27,14 +27,14 @@ and provided thanks to the work of the following contributors:
 * [blackle](https://github.com/blackle)
 * [Quent-in](https://github.com/Quent-in)
 * [JantsoP](https://github.com/JantsoP)
-* [mabkenar](https://github.com/mabkenar)
 * [Kjwon15](https://github.com/Kjwon15)
+* [mabkenar](https://github.com/mabkenar)
 * [nullkal](https://github.com/nullkal)
 * [yookoala](https://github.com/yookoala)
 * [shuheiktgw](https://github.com/shuheiktgw)
 * [ashfurrow](https://github.com/ashfurrow)
-* [Quenty31](https://github.com/Quenty31)
 * [zunda](https://github.com/zunda)
+* [Quenty31](https://github.com/Quenty31)
 * [eramdam](https://github.com/eramdam)
 * [takayamaki](https://github.com/takayamaki)
 * [masarakki](https://github.com/masarakki)
@@ -45,8 +45,8 @@ and provided thanks to the work of the following contributors:
 * [stephenburgess8](https://github.com/stephenburgess8)
 * [Wonderfall](https://github.com/Wonderfall)
 * [matteoaquila](https://github.com/matteoaquila)
-* [rkarabut](https://github.com/rkarabut)
 * [yukimochi](https://github.com/yukimochi)
+* [rkarabut](https://github.com/rkarabut)
 * [Artoria2e5](https://github.com/Artoria2e5)
 * [nightpool](https://github.com/nightpool)
 * [marrus-sh](https://github.com/marrus-sh)
@@ -64,11 +64,14 @@ and provided thanks to the work of the following contributors:
 * [MaciekBaron](https://github.com/MaciekBaron)
 * [MitarashiDango](mailto:mitarashidango@users.noreply.github.com)
 * [beatrix-bitrot](https://github.com/beatrix-bitrot)
+* [Aditoo17](https://github.com/Aditoo17)
 * [adbelle](https://github.com/adbelle)
 * [evanminto](https://github.com/evanminto)
 * [MightyPork](https://github.com/MightyPork)
 * [yhirano55](https://github.com/yhirano55)
+* [rinsuki](https://github.com/rinsuki)
 * [camponez](https://github.com/camponez)
+* [hinaloe](https://github.com/hinaloe)
 * [SerCom-KC](https://github.com/SerCom-KC)
 * [aschmitz](https://github.com/aschmitz)
 * [devkral](https://github.com/devkral)
@@ -81,10 +84,8 @@ and provided thanks to the work of the following contributors:
 * [lindwurm](https://github.com/lindwurm)
 * [victorhck](mailto:victorhck@geeko.site)
 * [voidsatisfaction](https://github.com/voidsatisfaction)
-* [rinsuki](https://github.com/rinsuki)
 * [hikari-no-yume](https://github.com/hikari-no-yume)
 * [angristan](https://github.com/angristan)
-* [hinaloe](https://github.com/hinaloe)
 * [seefood](https://github.com/seefood)
 * [jackjennings](https://github.com/jackjennings)
 * [spla](mailto:spla@mastodont.cat)
@@ -102,9 +103,10 @@ and provided thanks to the work of the following contributors:
 * [victorhck](https://github.com/victorhck)
 * [kedamaDQ](https://github.com/kedamaDQ)
 * [puckipedia](https://github.com/puckipedia)
+* [trwnh](https://github.com/trwnh)
 * [fvh-P](https://github.com/fvh-P)
-* [contraexemplo](https://github.com/contraexemplo)
-* [Aditoo17](https://github.com/Aditoo17)
+* [Anna e só](mailto:contraexemplos@gmail.com)
+* [BenLubar](https://github.com/BenLubar)
 * [kazu9su](https://github.com/kazu9su)
 * [Komic](https://github.com/Komic)
 * [lmorchard](https://github.com/lmorchard)
@@ -117,7 +119,6 @@ and provided thanks to the work of the following contributors:
 * [goofy-bz](mailto:goofy@babelzilla.org)
 * [kadiix](https://github.com/kadiix)
 * [kodacs](https://github.com/kodacs)
-* [trwnh](https://github.com/trwnh)
 * [JMendyk](https://github.com/JMendyk)
 * [KScl](https://github.com/KScl)
 * [sterdev](https://github.com/sterdev)
@@ -133,6 +134,7 @@ and provided thanks to the work of the following contributors:
 * [Reverite](https://github.com/Reverite)
 * [JohnD28](https://github.com/JohnD28)
 * [znz](https://github.com/znz)
+* [marek-lach](https://github.com/marek-lach)
 * [Naouak](https://github.com/Naouak)
 * [pawelngei](https://github.com/pawelngei)
 * [rtucker](https://github.com/rtucker)
@@ -150,7 +152,6 @@ and provided thanks to the work of the following contributors:
 * [178inaba](https://github.com/178inaba)
 * [alyssais](https://github.com/alyssais)
 * [hiphref](https://github.com/hiphref)
-* [BenLubar](https://github.com/BenLubar)
 * [stalker314314](https://github.com/stalker314314)
 * [huertanix](https://github.com/huertanix)
 * [genesixx](https://github.com/genesixx)
@@ -161,16 +162,16 @@ and provided thanks to the work of the following contributors:
 * [kmichl](https://github.com/kmichl)
 * [Kurtis Rainbolt-Greene](mailto:me@kurtisrainboltgreene.name)
 * [saper](https://github.com/saper)
-* [marek-lach](https://github.com/marek-lach)
 * [nevillepark](https://github.com/nevillepark)
 * [ornithocoder](https://github.com/ornithocoder)
 * [pierreozoux](https://github.com/pierreozoux)
 * [qguv](https://github.com/qguv)
 * [Ram Lmn](mailto:ramlmn@users.noreply.github.com)
+* [sascha-sl](https://github.com/sascha-sl)
 * [harukasan](https://github.com/harukasan)
 * [stamak](https://github.com/stamak)
 * [Technowix](mailto:technowix@users.noreply.github.com)
-* [Eychics](https://github.com/Eychics)
+* [Zoeille](https://github.com/Zoeille)
 * [Thor Harald Johansen](mailto:thj@thj.no)
 * [0x70b1a5](https://github.com/0x70b1a5)
 * [gled-rs](https://github.com/gled-rs)
@@ -244,9 +245,9 @@ and provided thanks to the work of the following contributors:
 * [raymestalez](https://github.com/raymestalez)
 * [remram44](https://github.com/remram44)
 * [sts10](https://github.com/sts10)
-* [sascha-sl](https://github.com/sascha-sl)
 * [u1-liquid](https://github.com/u1-liquid)
 * [sim6](https://github.com/sim6)
+* [Sir-Boops](https://github.com/Sir-Boops)
 * [stemid](https://github.com/stemid)
 * [sumdog](https://github.com/sumdog)
 * [ThomasLeister](https://github.com/ThomasLeister)
@@ -316,8 +317,11 @@ and provided thanks to the work of the following contributors:
 * [Andreas Drop](mailto:andy@remline.de)
 * [andi1984](https://github.com/andi1984)
 * [schas002](https://github.com/schas002)
+* [contraexemplo](https://github.com/contraexemplo)
 * [abackstrom](https://github.com/abackstrom)
+* [armandfardeau](https://github.com/armandfardeau)
 * [jumbosushi](https://github.com/jumbosushi)
+* [aurelien-reeves](https://github.com/aurelien-reeves)
 * [ayumin](https://github.com/ayumin)
 * [BaptisteGelez](https://github.com/BaptisteGelez)
 * [bzg](https://github.com/bzg)
@@ -335,7 +339,7 @@ and provided thanks to the work of the following contributors:
 * [Motoma](https://github.com/Motoma)
 * [chriswk](https://github.com/chriswk)
 * [csu](https://github.com/csu)
-* [clarcharr](https://github.com/clarcharr)
+* [clarfon](https://github.com/clarfon)
 * [kklleemm](https://github.com/kklleemm)
 * [colindean](https://github.com/colindean)
 * [dachinat](https://github.com/dachinat)
@@ -358,6 +362,7 @@ and provided thanks to the work of the following contributors:
 * [eai04191](https://github.com/eai04191)
 * [d3vgru](https://github.com/d3vgru)
 * [Elizafox](https://github.com/Elizafox)
+* [enewhuis](https://github.com/enewhuis)
 * [ericblade](https://github.com/ericblade)
 * [mikoim](https://github.com/mikoim)
 * [espenronnevik](https://github.com/espenronnevik)
@@ -446,6 +451,7 @@ and provided thanks to the work of the following contributors:
 * [mouse-reeve](https://github.com/mouse-reeve)
 * [Mozinet-fr](https://github.com/Mozinet-fr)
 * [lae](https://github.com/lae)
+* [nosada](https://github.com/nosada)
 * [Nanamachi](https://github.com/Nanamachi)
 * [orinthe](https://github.com/orinthe)
 * [NecroTechno](https://github.com/NecroTechno)
@@ -462,10 +468,11 @@ and provided thanks to the work of the following contributors:
 * [noppa](https://github.com/noppa)
 * [Otakan951](https://github.com/Otakan951)
 * [fahy](https://github.com/fahy)
-* [PatrickRWells](https://github.com/PatrickRWells)
-* [Pangoraw](https://github.com/Pangoraw)
-* [peterkeen](https://github.com/peterkeen)
-* [pgate](https://github.com/pgate)
+* [PatrickRWells](mailto:32802366+patrickrwells@users.noreply.github.com)
+* [Paul](mailto:naydex.mc+github@gmail.com)
+* [Pete Keen](mailto:pete@petekeen.net)
+* [Pierre-Morgan Gate](mailto:pgate@users.noreply.github.com)
+* [Ratmir Karabut](mailto:rkarabut@sfmodern.ru)
 * [Reto Kromer](mailto:retokromer@users.noreply.github.com)
 * [Rey Tucker](mailto:git@reytucker.us)
 * [Rob Watson](mailto:rfwatson@users.noreply.github.com)
@@ -488,7 +495,6 @@ and provided thanks to the work of the following contributors:
 * [Sho Kusano](mailto:rosylilly@aduca.org)
 * [Shouko Yu](mailto:imshouko@gmail.com)
 * [Sina Mashek](mailto:sina@mashek.xyz)
-* [Sir-Boops](mailto:admin@boops.me)
 * [Soshi Kato](mailto:mail@sossii.com)
 * [Spanky](mailto:2788886+spankyworks@users.noreply.github.com)
 * [Stanislas](mailto:angristan@pm.me)
@@ -555,12 +561,14 @@ and provided thanks to the work of the following contributors:
 * [karlyeurl](mailto:karl.yeurl@gmail.com)
 * [kedama](mailto:32974885+kedamadq@users.noreply.github.com)
 * [kodai](mailto:shirafuta.kodai@gmail.com)
+* [koyu](mailto:me@koyu.space)
 * [kuro5hin](mailto:rusty@kuro5hin.org)
 * [luzpaz](mailto:luzpaz@users.noreply.github.com)
 * [maxypy](mailto:maxime@mpigou.fr)
 * [mhe](mailto:mail@marcus-herrmann.com)
 * [mike castleman](mailto:m@mlcastle.net)
 * [mimikun](mailto:dzdzble_effort_311@outlook.jp)
+* [mohemohe](mailto:mohemohe@users.noreply.github.com)
 * [mshrtkch](mailto:mshrtkch@users.noreply.github.com)
 * [muan](mailto:muan@github.com)
 * [namelessGonbai](mailto:43787036+namelessgonbai@users.noreply.github.com)
@@ -599,243 +607,338 @@ This document is provided for informational purposes only. Since it is only upda
 
 Following people have contributed to translation of Mastodon:
 
+- **Albanian**
+  - Besnik Bleta
+  - Aditoo
 - **Arabic**
   - ButterflyOfFire
+  - Aditoo
+  - Amrz0
 - **Asturian**
   - ButterflyOfFire
   - Enol P.
+  - Aditoo
 - **Basque**
+  - Osoitz
+  - Aditoo
   - Aitzol
   - ButterflyOfFire
-  - Gorka Azkarate
-  - Osoitz
   - Peru Iparragirre
+  - Gorka Azkarate
+- **Bengali**
+  - dxwc
 - **Bulgarian**
   - ButterflyOfFire
+  - Aditoo
 - **Catalan**
+  - spla
+  - Aditoo
   - ButterflyOfFire
   - Joan Montané
   - Jose Luis
-  - spla
 - **Chinese (Hong Kong)**
   - ButterflyOfFire
   - Luzi Leung
+  - Aditoo
 - **Chinese (Simplified)**
   - Allen Zhong
   - ButterflyOfFire
   - SerCom_KC
+  - martialarts
+  - Kaitian Xie
+  - Aditoo
+  - pan93412
 - **Chinese (Traditional)**
+  - Aditoo
   - ButterflyOfFire
   - James58899
-  - Jeff Huang
+  - pan93412
   - S1ttidoe477
   - SHA265
+  - Jeff Huang
 - **Corsican**
   - Alix D. R.
+  - Aditoo
   - ButterflyOfFire
 - **Croatian**
   - ButterflyOfFire
+  - Aditoo
 - **Czech**
-  - ButterflyOfFire
-  - Lorem Ipsum
+  - Aditoo
   - Marek Ľach
-- **Danish**
   - ButterflyOfFire
+- **Danish**
+  - Einhjeriar
   - Rasmus Sæderup
+  - Aditoo
+  - ButterflyOfFire
 - **Dutch**
+  - Albakham
   - ButterflyOfFire
-  - Jelv
   - jeroenpraat
   - rscmbbng
+  - Aditoo
+  - Jelv
 - **English**
   - ButterflyOfFire
   - Renato "Lond" Cerqueira
+- **English (United Kingdom)**
+  - Albakham
 - **Esperanto**
+  - Aditoo
   - ButterflyOfFire
+  - Becci Cat
   - Jeong Arm
-  - Martin Bodin
   - Mélanie Chauvel
   - Vanege
+  - Martin Bodin
   - tuxayo/Victor Grousset
 - **Finnish**
   - ButterflyOfFire
-  - Jonne Arjoranta
-  - S Heija
+  - Mikko Poussu
   - Taru Luojola
+  - S Heija
+  - Aditoo
+  - Jonne Arjoranta
 - **French**
-  - Alda Marteau-Hardi
+  - Albakham
   - Alix D. R.
-  - Baptiste Jonglez
   - ButterflyOfFire
-  - Franck Paul
-  - Jean-Baptiste Holcroft
-  - Jonathan Chan
-  - Letiteuf55
-  - Martin Bodin
+  - codl
+  - Leia
+  - Alda Marteau-Hardi
   - Mélanie Chauvel
-  - Olivier Humbert
   - Paul Marques Mota
-  - Sylvhem
+  - azenet
+  - Olivier Humbert
+  - Aditoo
+  - Jonathan Chan
+  - Letiteuf55
+  - Baptiste Jonglez
+  - goofy-mdn
+  - Jean-Baptiste Holcroft
   - Technowix
-  - Thibaut Girka
+  - Martin Bodin
   - Théodore
-  - azenet
-  - codl
+  - Thibaut Girka
+  - Franck Paul
+  - Sylvhem
 - **Galician**
   - ButterflyOfFire
   - Xose M.
+  - Aditoo
   - manequim
 - **Georgian**
   - ButterflyOfFire
+  - Aditoo
 - **German**
-  - Benedikt Geißler
+  - Aditoo
   - ButterflyOfFire
   - Daniel
-  - Eugen Rochko
-  - Koyu Berteon
-  - Patrick Figel
-  - Weblate Admin
   - averageunicorn
-  - ePirat
-  - koyu
+  - Koyu Berteon
   - larsreineke
+  - koyu
+  - Austin Jones
   - lilo
+  - Benedikt Geißler
+  - ePirat
+  - Eugen Rochko
+  - Weblate Admin
+  - Patrick Figel
 - **Greek**
+  - Dimitris Maroulidis
   - Antonis
+  - Aditoo
   - ButterflyOfFire
-  - Dimitris Maroulidis
   - Konstantinos Grevenitis
 - **Hebrew**
   - ButterflyOfFire
+  - Aditoo
   - Ira
   - Yaron Shahrabani
 - **Hungarian**
-  - Adam Paszternak
   - ButterflyOfFire
+  - Adam Paszternak
+  - Aditoo
   - Tibike Miklós
 - **Ido**
   - ButterflyOfFire
+  - Aditoo
 - **Indonesian**
-  - Alfiana Sibuea
+  - afachri
   - ButterflyOfFire
   - Dito Kurnia Pratama
   - Eirworks
-  - afachri
+  - Aditoo
+  - Alfiana Sibuea
   - se7entime
+- **Irish**
+  - Albakham
+  - Kevin Houlihan
 - **Italian**
   - Alessandro Levati
+  - Albakham
   - ButterflyOfFire
+  - Marcin Mikołajczak
+  - Aditoo
   - Giuseppe Pignataro
   - Stefano
 - **Japanese**
-  - ButterflyOfFire
-  - Kumasun Morino
-  - Yamagishi Kazutoshi
+  - Hinaloe
+  - 小鳥遊まりあ
   - mayaeh
   - osapon
-  - unarist
-  - 小鳥遊まりあ
   - 森の子リスのミーコの大冒険
-- **Korean**
+  - Kumasun Morino
+  - Yamagishi Kazutoshi
+  - Aditoo
   - ButterflyOfFire
   - Jeong Arm
+  - unarist
+- **Kazakh**
+  - arshat
+  - Aditoo
+- **Korean**
+  - Aditoo
+  - Jeong Arm
+  - ButterflyOfFire
   - Minori Hiraoka
   - Yamagishi Kazutoshi
+- **Lithuanian**
+  - Sarunas Medeikis
 - **Malay**
-  - ButterflyOfFire
   - Muhammad Nur Hidayat (MNH48)
+  - Aditoo
+  - ButterflyOfFire
 - **Norwegian (old code)**
   - ButterflyOfFire
   - Espen Rønnevik
+  - Aditoo
   - Tale
 - **Occitan**
+  - Aditoo
   - ButterflyOfFire
-  - Maxenç
   - Quenti2
   - Quentí
+  - Maxenç
 - **Persian**
-  - ButterflyOfFire
   - Masoud Abkenar
+  - Aditoo
+  - ButterflyOfFire
 - **Polish**
+  - Aditoo
+  - Albakham
   - ButterflyOfFire
-  - Jakub Mendyk
+  - Stasiek Michalski
   - Marcin Mikołajczak
+  - Jakub Mendyk
   - Marek Ľach
-  - Stasiek Michalski
   - krkk
 - **Portuguese**
+  - Albakham
+  - João Pinheiro
+  - manequim
+  - Aditoo
   - ButterflyOfFire
   - Hugo Gameiro
-  - manequim
 - **Portuguese (Brazil)**
-  - André Andrade
+  - Aditoo
+  - Albakham
   - Anna e só
-  - ButterflyOfFire
   - Renato "Lond" Cerqueira
-- **Romanian**
+  - André Andrade
   - ButterflyOfFire
+- **Romanian**
   - adrianbblk
+  - ButterflyOfFire
+  - Aditoo
 - **Russian**
-  - Andrew Zyabin
+  - Albakham
   - ButterflyOfFire
   - Evgeny Petrov
+  - Aditoo
+  - Павел Гастелло
+  - Andrew Zyabin
   - Yaron Shahrabani
 - **Serbian**
   - Branko Kokanovic
   - Burekz Finezt
+  - Aditoo
   - ButterflyOfFire
 - **Serbian (latin)**
   - ButterflyOfFire
+  - Aditoo
 - **Slovak**
+  - Aditoo
   - ButterflyOfFire
   - Ivan Pleva
-  - Lorem Ipsum
   - Marek Ľach
   - Peter
 - **Slovenian**
-  - ButterflyOfFire
   - Kristijan Tkalec
+  - Aditoo
+  - ButterflyOfFire
 - **Spanish**
-  - Angeles Broullón
-  - Antón López
+  - Albakham
   - ButterflyOfFire
   - Carlos Mondragon
+  - Antón López
+  - Max Winkler
+  - Pablo de la Concepción Sanz
+  - Sergio Soriano
+  - Angeles Broullón
+  - Lothar Wolf
+  - Aditoo
   - David Charte
   - Emmanuel
-  - Lothar Wolf
-  - Pablo de la Concepción Sanz
 - **Swedish**
   - ButterflyOfFire
-  - Elias Mårtenson
   - Isak Holmström
   - Shellkr
+  - Aditoo
+  - Elias Mårtenson
   - Stefan Midjich
   - Tim Stahel
+  - Jonas Hultén
 - **Telugu**
+  - avndp
+  - Ranjith Tellakula
+  - Aditoo
   - ButterflyOfFire
   - Joseph Nuthalapati
-  - Ranjith Tellakula
-  - avndp
 - **Thai**
   - ButterflyOfFire
+  - parnikkapore
+  - Thai Localization
+  - Aditoo
 - **Turkish**
+  - Ali Demirtas
   - ButterflyOfFire
+  - Aditoo
 - **Ukrainian**
+  - alexcleac
   - ButterflyOfFire
+  - Aditoo
   - Ivan Verchenko
-  - alexcleac
 - **Welsh**
-  - ButterflyOfFire
+  - carl morris
   - Jaz-Michael King
-  - Kevin Beynon
   - Owain Rhys Lewis
-  - Renato "Lond" Cerqueira
   - Rhoslyn Prys
-  - carl morris
+  - Aditoo
+  - ButterflyOfFire
+  - Renato "Lond" Cerqueira
+  - Albakham
+  - Kevin Beynon
 - **Armenian**
+  - Aditoo
   - ButterflyOfFire
 - **Latvian**
+  - Aditoo
   - ButterflyOfFire
+  - Maigonis
 - **Tamil**
+  - Aditoo
   - ButterflyOfFire
   - Prasanna Venkadesh
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7b10adbbf..91e66c400 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,79 @@ Changelog
 
 All notable changes to this project will be documented in this file.
 
+## [Unreleased]
+### Added
+
+- Add polls ([Gargron](https://github.com/tootsuite/mastodon/pull/10111), [ThibG](https://github.com/tootsuite/mastodon/pull/10155), [Gargron](https://github.com/tootsuite/mastodon/pull/10184), [ThibG](https://github.com/tootsuite/mastodon/pull/10196), [Gargron](https://github.com/tootsuite/mastodon/pull/10248), [ThibG](https://github.com/tootsuite/mastodon/pull/10255), [ThibG](https://github.com/tootsuite/mastodon/pull/10322), [Gargron](https://github.com/tootsuite/mastodon/pull/10138), [Gargron](https://github.com/tootsuite/mastodon/pull/10139), [Gargron](https://github.com/tootsuite/mastodon/pull/10144), [Gargron](https://github.com/tootsuite/mastodon/pull/10145),[Gargron](https://github.com/tootsuite/mastodon/pull/10146), [Gargron](https://github.com/tootsuite/mastodon/pull/10148), [Gargron](https://github.com/tootsuite/mastodon/pull/10151), [ThibG](https://github.com/tootsuite/mastodon/pull/10150), [Gargron](https://github.com/tootsuite/mastodon/pull/10168), [Gargron](https://github.com/tootsuite/mastodon/pull/10165), [Gargron](https://github.com/tootsuite/mastodon/pull/10172), [Gargron](https://github.com/tootsuite/mastodon/pull/10170), [Gargron](https://github.com/tootsuite/mastodon/pull/10171), [Gargron](https://github.com/tootsuite/mastodon/pull/10186), [Gargron](https://github.com/tootsuite/mastodon/pull/10189), [ThibG](https://github.com/tootsuite/mastodon/pull/10200), [rinsuki](https://github.com/tootsuite/mastodon/pull/10203), [Gargron](https://github.com/tootsuite/mastodon/pull/10213), [Gargron](https://github.com/tootsuite/mastodon/pull/10246), [Gargron](https://github.com/tootsuite/mastodon/pull/10265), [Gargron](https://github.com/tootsuite/mastodon/pull/10261), [ThibG](https://github.com/tootsuite/mastodon/pull/10333), [Gargron](https://github.com/tootsuite/mastodon/pull/10352), [ThibG](https://github.com/tootsuite/mastodon/pull/10140), [ThibG](https://github.com/tootsuite/mastodon/pull/10142), [ThibG](https://github.com/tootsuite/mastodon/pull/10141), [ThibG](https://github.com/tootsuite/mastodon/pull/10162), [ThibG](https://github.com/tootsuite/mastodon/pull/10161), [ThibG](https://github.com/tootsuite/mastodon/pull/10158), [ThibG](https://github.com/tootsuite/mastodon/pull/10156), [ThibG](https://github.com/tootsuite/mastodon/pull/10160), [Gargron](https://github.com/tootsuite/mastodon/pull/10185), [Gargron](https://github.com/tootsuite/mastodon/pull/10188), [ThibG](https://github.com/tootsuite/mastodon/pull/10195), [ThibG](https://github.com/tootsuite/mastodon/pull/10208), [Gargron](https://github.com/tootsuite/mastodon/pull/10187), [ThibG](https://github.com/tootsuite/mastodon/pull/10214), [ThibG](https://github.com/tootsuite/mastodon/pull/10209))
+- Add follows & followers managing UI ([Gargron](https://github.com/tootsuite/mastodon/pull/10268), [Gargron](https://github.com/tootsuite/mastodon/pull/10308), [Gargron](https://github.com/tootsuite/mastodon/pull/10404), [Gargron](https://github.com/tootsuite/mastodon/pull/10293))
+- Add identity proof integration with Keybase ([Gargron](https://github.com/tootsuite/mastodon/pull/10297), [xgess](https://github.com/tootsuite/mastodon/pull/10375), [Gargron](https://github.com/tootsuite/mastodon/pull/10338), [Gargron](https://github.com/tootsuite/mastodon/pull/10350), [Gargron](https://github.com/tootsuite/mastodon/pull/10414))
+- Add option to overwrite imported data instead of merging ([Gargron](https://github.com/tootsuite/mastodon/pull/9962))
+- Add featured hashtags to profiles ([Gargron](https://github.com/tootsuite/mastodon/pull/9755), [Gargron](https://github.com/tootsuite/mastodon/pull/10167), [Gargron](https://github.com/tootsuite/mastodon/pull/10249), [ThibG](https://github.com/tootsuite/mastodon/pull/10034))
+- Add admission-based registrations mode ([Gargron](https://github.com/tootsuite/mastodon/pull/10250), [ThibG](https://github.com/tootsuite/mastodon/pull/10269), [Gargron](https://github.com/tootsuite/mastodon/pull/10264), [ThibG](https://github.com/tootsuite/mastodon/pull/10321), [Gargron](https://github.com/tootsuite/mastodon/pull/10349))
+- Add support for WebP uploads ([acid-chicken](https://github.com/tootsuite/mastodon/pull/9879))
+- Add "copy link" item to status action bars in web UI ([Gargron](https://github.com/tootsuite/mastodon/pull/9983))
+- Add list title editing in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/9748))
+- Add a "Block & Report" button to the block confirmation dialog in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/10360))
+- Add disappointed elephant when the page crashes in web UI ([Gargron](https://github.com/tootsuite/mastodon/pull/10275))
+- Add ability to upload multiple files at once in web UI ([tmm576](https://github.com/tootsuite/mastodon/pull/9856))
+- Add indication that you have been blocked when viewing profiles in web UI ([Gargron](https://github.com/tootsuite/mastodon/pull/10420))
+- Add validations to admin settings to catch common mistakes ([Gargron](https://github.com/tootsuite/mastodon/pull/10348), [ThibG](https://github.com/tootsuite/mastodon/pull/10354))
+- Add `type`, `limit`, `offset`, `min_id`, `max_id`, `account_id` to search API ([Gargron](https://github.com/tootsuite/mastodon/pull/10091))
+- Add a preferences API so apps can share basic behaviours ([Gargron](https://github.com/tootsuite/mastodon/pull/10109))
+- Add `visibility` param to reblog REST API ([Gargron](https://github.com/tootsuite/mastodon/pull/9851), [ThibG](https://github.com/tootsuite/mastodon/pull/10302))
+- Add `allowfullscreen` attribute to OEmbed iframe ([rinsuki](https://github.com/tootsuite/mastodon/pull/10370))
+- Add `blocked_by` relationship to the REST API ([Gargron](https://github.com/tootsuite/mastodon/pull/10373))
+- Add `tootctl statuses remove` to sweep unreferenced statuses ([Gargron](https://github.com/tootsuite/mastodon/pull/10063))
+- Add `tootctl search deploy` to avoid ugly rake task syntax ([Gargron](https://github.com/tootsuite/mastodon/pull/10403))
+- Add `tootctl self-destruct` to shut down server gracefully ([Gargron](https://github.com/tootsuite/mastodon/pull/10367))
+- Add option to hide application used to toot ([ThibG](https://github.com/tootsuite/mastodon/pull/9897), [rinsuki](https://github.com/tootsuite/mastodon/pull/9994), [hinaloe](https://github.com/tootsuite/mastodon/pull/10086))
+- Add `DB_SSLMODE` configuration variable ([sascha-sl](https://github.com/tootsuite/mastodon/pull/10210))
+- Add click-to-copy UI to invites page ([Gargron](https://github.com/tootsuite/mastodon/pull/10259))
+- Add self-replies fetching ([ThibG](https://github.com/tootsuite/mastodon/pull/10106), [ThibG](https://github.com/tootsuite/mastodon/pull/10128), [ThibG](https://github.com/tootsuite/mastodon/pull/10175), [ThibG](https://github.com/tootsuite/mastodon/pull/10201))
+
+### Changed
+
+- Change design of landing page ([Gargron](https://github.com/tootsuite/mastodon/pull/10232), [Gargron](https://github.com/tootsuite/mastodon/pull/10260), [ThibG](https://github.com/tootsuite/mastodon/pull/10284), [ThibG](https://github.com/tootsuite/mastodon/pull/10291), [koyuawsmbrtn](https://github.com/tootsuite/mastodon/pull/10356), [Gargron](https://github.com/tootsuite/mastodon/pull/10245))
+- Change design of profile column in web UI ([Gargron](https://github.com/tootsuite/mastodon/pull/10337), [Aditoo17](https://github.com/tootsuite/mastodon/pull/10387), [ThibG](https://github.com/tootsuite/mastodon/pull/10390), [mayaeh](https://github.com/tootsuite/mastodon/pull/10379), [ThibG](https://github.com/tootsuite/mastodon/pull/10411))
+- Change language detector threshold from 140 characters to 4 words ([Gargron](https://github.com/tootsuite/mastodon/pull/10376))
+- Change language detector to always kick in for non-latin alphabets ([Gargron](https://github.com/tootsuite/mastodon/pull/10276))
+- Change icons of features on admin dashboard ([Gargron](https://github.com/tootsuite/mastodon/pull/10366))
+- Change DNS timeouts from 1s to 5s ([ThibG](https://github.com/tootsuite/mastodon/pull/10238))
+- Change Docker image to use Ubuntu with jemalloc ([Sir-Boops](https://github.com/tootsuite/mastodon/pull/10100), [BenLubar](https://github.com/tootsuite/mastodon/pull/10212))
+- Change public pages to be cacheable by proxies ([BenLubar](https://github.com/tootsuite/mastodon/pull/9059))
+- Change the 410 gone response for suspended accounts to be cacheable by proxies ([ThibG](https://github.com/tootsuite/mastodon/pull/10339))
+- Change web UI to not not empty timeline of blocked users on block ([ThibG](https://github.com/tootsuite/mastodon/pull/10359))
+- Change JSON serializer to remove unused `@context` values ([Gargron](https://github.com/tootsuite/mastodon/pull/10378))
+- Change GIFV file size limit to be the same as for other videos ([rinsuki](https://github.com/tootsuite/mastodon/pull/9924))
+- Change Webpack to not use @babel/preset-env to compile node_modules ([ykzts](https://github.com/tootsuite/mastodon/pull/10289))
+- Change web UI to use new Web Share Target API ([gol-cha](https://github.com/tootsuite/mastodon/pull/9963))
+- Change ActivityPub reports to have persistent URIs ([ThibG](https://github.com/tootsuite/mastodon/pull/10303))
+
+### Removed
+
+- Remove zopfli compression to speed up Webpack from 6min to 1min ([nolanlawson](https://github.com/tootsuite/mastodon/pull/10288))
+- Remove stats.json generation to speed up Webpack ([nolanlawson](https://github.com/tootsuite/mastodon/pull/10290))
+
+### Fixed
+
+- Fix public timelines being broken by new toots when they are not mounted in web UI ([Gargron](https://github.com/tootsuite/mastodon/pull/10131))
+- Fix quick filter settings not being saved when selecting a different filter in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/10296))
+- Fix remote interaction dialogs being indexed by search engines ([Gargron](https://github.com/tootsuite/mastodon/pull/10240))
+- Fix maxed-out invites not showing up as expired in UI ([Gargron](https://github.com/tootsuite/mastodon/pull/10274))
+- Fix scrollbar styles on compose textarea ([Gargron](https://github.com/tootsuite/mastodon/pull/10292))
+- Fix timeline merge workers being queued for remote users ([Gargron](https://github.com/tootsuite/mastodon/pull/10355))
+- Fix alternative relay support regression ([Gargron](https://github.com/tootsuite/mastodon/pull/10398))
+- Fix trying to fetch keys of unknown accounts on a self-delete from them ([ThibG](https://github.com/tootsuite/mastodon/pull/10326))
+- Fix CAS `:service_validate_url` option ([enewhuis](https://github.com/tootsuite/mastodon/pull/10328))
+- Fix race conditions when creating backups ([ThibG](https://github.com/tootsuite/mastodon/pull/10234))
+- Fix whitespace not being stripped out of username before validation ([aurelien-reeves](https://github.com/tootsuite/mastodon/pull/10239))
+- Fix n+1 query when deleting status ([Gargron](https://github.com/tootsuite/mastodon/pull/10247))
+- Fix exiting follows not being rejected when suspending a remote account ([ThibG](https://github.com/tootsuite/mastodon/pull/10230))
+- Fix the underlying button element in a disabled icon button not being disabled ([ThibG](https://github.com/tootsuite/mastodon/pull/10194))
+- Fix race condition when streaming out deleted statuses ([ThibG](https://github.com/tootsuite/mastodon/pull/10280))
+- Fix performance of admin federation UI by caching account counts ([Gargron](https://github.com/tootsuite/mastodon/pull/10374))
+- Fix JS error on pages that don't define a CSRF token ([hinaloe](https://github.com/tootsuite/mastodon/pull/10383))
+
 ## [2.7.4] - 2019-03-05
 ### Fixed
 
diff --git a/Gemfile b/Gemfile
index ccabbd2e5..5f0e3ab2c 100644
--- a/Gemfile
+++ b/Gemfile
@@ -108,7 +108,7 @@ group :production, :test do
 end
 
 group :test do
-  gem 'capybara', '~> 3.15'
+  gem 'capybara', '~> 3.16'
   gem 'climate_control', '~> 0.2'
   gem 'faker', '~> 1.9'
   gem 'microformats', '~> 4.1'
diff --git a/Gemfile.lock b/Gemfile.lock
index bf41ea656..620651983 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -127,7 +127,7 @@ GEM
       sshkit (~> 1.3)
     capistrano-yarn (2.0.2)
       capistrano (~> 3.0)
-    capybara (3.15.0)
+    capybara (3.16.0)
       addressable
       mini_mime (>= 0.1.3)
       nokogiri (~> 1.8)
@@ -672,7 +672,7 @@ DEPENDENCIES
   capistrano-rails (~> 1.4)
   capistrano-rbenv (~> 2.1)
   capistrano-yarn (~> 2.0)
-  capybara (~> 3.15)
+  capybara (~> 3.16)
   charlock_holmes (~> 0.7.6)
   chewy (~> 5.0)
   cld3 (~> 3.2.3)
diff --git a/app/javascript/flavours/glitch/actions/search.js b/app/javascript/flavours/glitch/actions/search.js
index bc094eed5..b2d24e10b 100644
--- a/app/javascript/flavours/glitch/actions/search.js
+++ b/app/javascript/flavours/glitch/actions/search.js
@@ -37,6 +37,7 @@ export function submitSearch() {
       params: {
         q: value,
         resolve: true,
+        limit: 10,
       },
     }).then(response => {
       if (response.data.accounts) {
diff --git a/app/javascript/flavours/glitch/styles/_mixins.scss b/app/javascript/flavours/glitch/styles/_mixins.scss
index 586802185..d542b1083 100644
--- a/app/javascript/flavours/glitch/styles/_mixins.scss
+++ b/app/javascript/flavours/glitch/styles/_mixins.scss
@@ -1,6 +1,5 @@
 @mixin avatar-radius() {
   border-radius: $ui-avatar-border-size;
-  background: transparent no-repeat;
   background-position: 50%;
   background-clip: padding-box;
 }
diff --git a/app/javascript/flavours/glitch/styles/components/accounts.scss b/app/javascript/flavours/glitch/styles/components/accounts.scss
index 0daef4d35..00380c575 100644
--- a/app/javascript/flavours/glitch/styles/components/accounts.scss
+++ b/app/javascript/flavours/glitch/styles/components/accounts.scss
@@ -550,6 +550,7 @@
       margin-left: -2px;
 
       .account__avatar {
+        background: darken($ui-base-color, 8%);
         border: 2px solid lighten($ui-base-color, 4%);
       }
     }
diff --git a/app/javascript/flavours/glitch/styles/widgets.scss b/app/javascript/flavours/glitch/styles/widgets.scss
index 645192ea4..307e509d5 100644
--- a/app/javascript/flavours/glitch/styles/widgets.scss
+++ b/app/javascript/flavours/glitch/styles/widgets.scss
@@ -352,6 +352,7 @@
     border-radius: 50%;
     position: relative;
     margin-left: -10px;
+    background: darken($ui-base-color, 8%);
     border: 2px solid $ui-base-color;
 
     &:nth-child(1) {
diff --git a/app/javascript/mastodon/actions/search.js b/app/javascript/mastodon/actions/search.js
index b670d25c3..7c06670eb 100644
--- a/app/javascript/mastodon/actions/search.js
+++ b/app/javascript/mastodon/actions/search.js
@@ -37,6 +37,7 @@ export function submitSearch() {
       params: {
         q: value,
         resolve: true,
+        limit: 5,
       },
     }).then(response => {
       if (response.data.accounts) {
diff --git a/app/javascript/mastodon/features/account/components/header.js b/app/javascript/mastodon/features/account/components/header.js
index 76f50a5a4..f21ba8a9c 100644
--- a/app/javascript/mastodon/features/account/components/header.js
+++ b/app/javascript/mastodon/features/account/components/header.js
@@ -94,15 +94,15 @@ class Header extends ImmutablePureComponent {
     let menu        = [];
 
     if (me !== account.get('id') && account.getIn(['relationship', 'followed_by'])) {
-      info.push(<span className='relationship-tag'><FormattedMessage id='account.follows_you' defaultMessage='Follows you' /></span>);
+      info.push(<span key='followed_by' className='relationship-tag'><FormattedMessage id='account.follows_you' defaultMessage='Follows you' /></span>);
     } else if (me !== account.get('id') && account.getIn(['relationship', 'blocking'])) {
-      info.push(<span className='relationship-tag'><FormattedMessage id='account.blocked' defaultMessage='Blocked' /></span>);
+      info.push(<span key='blocked' className='relationship-tag'><FormattedMessage id='account.blocked' defaultMessage='Blocked' /></span>);
     }
 
     if (me !== account.get('id') && account.getIn(['relationship', 'muting'])) {
-      info.push(<span className='relationship-tag'><FormattedMessage id='account.muted' defaultMessage='Muted' /></span>);
+      info.push(<span key='muted' className='relationship-tag'><FormattedMessage id='account.muted' defaultMessage='Muted' /></span>);
     } else if (me !== account.get('id') && account.getIn(['relationship', 'domain_blocking'])) {
-      info.push(<span className='relationship-tag'><FormattedMessage id='account.domain_blocked' defaultMessage='Domain hidden' /></span>);
+      info.push(<span key='domain_blocked' className='relationship-tag'><FormattedMessage id='account.domain_blocked' defaultMessage='Domain hidden' /></span>);
     }
 
     if (me !== account.get('id')) {
@@ -111,7 +111,7 @@ class Header extends ImmutablePureComponent {
       } else if (account.getIn(['relationship', 'requested'])) {
         actionBtn = <Button className='logo-button' text={intl.formatMessage(messages.requested)} onClick={this.props.onFollow} />;
       } else if (!account.getIn(['relationship', 'blocking'])) {
-        actionBtn = <Button className={classNames('logo-button', { 'button--destructive': account.getIn(['relationship', 'following']) })} text={intl.formatMessage(account.getIn(['relationship', 'following']) ? messages.unfollow : messages.follow)} onClick={this.props.onFollow} />;
+        actionBtn = <Button disabled={account.getIn(['relationship', 'blocked_by'])} className={classNames('logo-button', { 'button--destructive': account.getIn(['relationship', 'following']) })} text={intl.formatMessage(account.getIn(['relationship', 'following']) ? messages.unfollow : messages.follow)} onClick={this.props.onFollow} />;
       } else if (account.getIn(['relationship', 'blocking'])) {
         actionBtn = <Button className='logo-button' text={intl.formatMessage(messages.unblock, { name: account.get('username') })} onClick={this.props.onBlock} />;
       }
diff --git a/app/javascript/mastodon/features/account_timeline/index.js b/app/javascript/mastodon/features/account_timeline/index.js
index 883f40d77..71341debb 100644
--- a/app/javascript/mastodon/features/account_timeline/index.js
+++ b/app/javascript/mastodon/features/account_timeline/index.js
@@ -14,14 +14,17 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
 import { FormattedMessage } from 'react-intl';
 import { fetchAccountIdentityProofs } from '../../actions/identity_proofs';
 
+const emptyList = ImmutableList();
+
 const mapStateToProps = (state, { params: { accountId }, withReplies = false }) => {
   const path = withReplies ? `${accountId}:with_replies` : accountId;
 
   return {
-    statusIds: state.getIn(['timelines', `account:${path}`, 'items'], ImmutableList()),
-    featuredStatusIds: withReplies ? ImmutableList() : state.getIn(['timelines', `account:${accountId}:pinned`, 'items'], ImmutableList()),
+    statusIds: state.getIn(['timelines', `account:${path}`, 'items'], emptyList),
+    featuredStatusIds: withReplies ? ImmutableList() : state.getIn(['timelines', `account:${accountId}:pinned`, 'items'], emptyList),
     isLoading: state.getIn(['timelines', `account:${path}`, 'isLoading']),
-    hasMore:   state.getIn(['timelines', `account:${path}`, 'hasMore']),
+    hasMore: state.getIn(['timelines', `account:${path}`, 'hasMore']),
+    blockedBy: state.getIn(['relationships', accountId, 'blocked_by'], false),
   };
 };
 
@@ -37,6 +40,7 @@ class AccountTimeline extends ImmutablePureComponent {
     isLoading: PropTypes.bool,
     hasMore: PropTypes.bool,
     withReplies: PropTypes.bool,
+    blockedBy: PropTypes.bool,
   };
 
   componentWillMount () {
@@ -44,9 +48,11 @@ class AccountTimeline extends ImmutablePureComponent {
 
     this.props.dispatch(fetchAccount(accountId));
     this.props.dispatch(fetchAccountIdentityProofs(accountId));
+
     if (!withReplies) {
       this.props.dispatch(expandAccountFeaturedTimeline(accountId));
     }
+
     this.props.dispatch(expandAccountTimeline(accountId, { withReplies }));
   }
 
@@ -54,9 +60,11 @@ class AccountTimeline extends ImmutablePureComponent {
     if ((nextProps.params.accountId !== this.props.params.accountId && nextProps.params.accountId) || nextProps.withReplies !== this.props.withReplies) {
       this.props.dispatch(fetchAccount(nextProps.params.accountId));
       this.props.dispatch(fetchAccountIdentityProofs(nextProps.params.accountId));
+
       if (!nextProps.withReplies) {
         this.props.dispatch(expandAccountFeaturedTimeline(nextProps.params.accountId));
       }
+
       this.props.dispatch(expandAccountTimeline(nextProps.params.accountId, { withReplies: nextProps.params.withReplies }));
     }
   }
@@ -66,7 +74,7 @@ class AccountTimeline extends ImmutablePureComponent {
   }
 
   render () {
-    const { shouldUpdateScroll, statusIds, featuredStatusIds, isLoading, hasMore } = this.props;
+    const { shouldUpdateScroll, statusIds, featuredStatusIds, isLoading, hasMore, blockedBy } = this.props;
 
     if (!statusIds && isLoading) {
       return (
@@ -76,6 +84,8 @@ class AccountTimeline extends ImmutablePureComponent {
       );
     }
 
+    const emptyMessage = blockedBy ? <FormattedMessage id='empty_column.account_timeline_blocked' defaultMessage='You are blocked' /> : <FormattedMessage id='empty_column.account_timeline' defaultMessage='No toots here!' />;
+
     return (
       <Column>
         <ColumnBackButton />
@@ -84,13 +94,13 @@ class AccountTimeline extends ImmutablePureComponent {
           prepend={<HeaderContainer accountId={this.props.params.accountId} />}
           alwaysPrepend
           scrollKey='account_timeline'
-          statusIds={statusIds}
+          statusIds={blockedBy ? emptyList : statusIds}
           featuredStatusIds={featuredStatusIds}
           isLoading={isLoading}
           hasMore={hasMore}
           onLoadMore={this.handleLoadMore}
           shouldUpdateScroll={shouldUpdateScroll}
-          emptyMessage={<FormattedMessage id='empty_column.account_timeline' defaultMessage='No toots here!' />}
+          emptyMessage={emptyMessage}
         />
       </Column>
     );
diff --git a/app/javascript/mastodon/features/direct_timeline/components/column_settings.js b/app/javascript/mastodon/features/direct_timeline/components/column_settings.js
deleted file mode 100644
index b629c128d..000000000
--- a/app/javascript/mastodon/features/direct_timeline/components/column_settings.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import ImmutablePropTypes from 'react-immutable-proptypes';
-import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
-import SettingText from '../../../components/setting_text';
-
-const messages = defineMessages({
-  filter_regex: { id: 'home.column_settings.filter_regex', defaultMessage: 'Filter out by regular expressions' },
-  settings: { id: 'home.settings', defaultMessage: 'Column settings' },
-});
-
-export default @injectIntl
-class ColumnSettings extends React.PureComponent {
-
-  static propTypes = {
-    settings: ImmutablePropTypes.map.isRequired,
-    onChange: PropTypes.func.isRequired,
-    intl: PropTypes.object.isRequired,
-  };
-
-  render () {
-    const { settings, onChange, intl } = this.props;
-
-    return (
-      <div>
-        <span className='column-settings__section'><FormattedMessage id='home.column_settings.advanced' defaultMessage='Advanced' /></span>
-
-        <div className='column-settings__row'>
-          <SettingText settings={settings} settingKey={['regex', 'body']} onChange={onChange} label={intl.formatMessage(messages.filter_regex)} />
-        </div>
-      </div>
-    );
-  }
-
-}
diff --git a/app/javascript/mastodon/features/direct_timeline/containers/column_settings_container.js b/app/javascript/mastodon/features/direct_timeline/containers/column_settings_container.js
deleted file mode 100644
index 38054ce9e..000000000
--- a/app/javascript/mastodon/features/direct_timeline/containers/column_settings_container.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import { connect } from 'react-redux';
-import ColumnSettings from '../components/column_settings';
-import { changeSetting } from '../../../actions/settings';
-
-const mapStateToProps = state => ({
-  settings: state.getIn(['settings', 'direct']),
-});
-
-const mapDispatchToProps = dispatch => ({
-
-  onChange (key, checked) {
-    dispatch(changeSetting(['direct', ...key], checked));
-  },
-
-});
-
-export default connect(mapStateToProps, mapDispatchToProps)(ColumnSettings);
diff --git a/app/javascript/mastodon/features/followers/index.js b/app/javascript/mastodon/features/followers/index.js
index ce56f270c..167f61b31 100644
--- a/app/javascript/mastodon/features/followers/index.js
+++ b/app/javascript/mastodon/features/followers/index.js
@@ -20,6 +20,7 @@ import ScrollableList from '../../components/scrollable_list';
 const mapStateToProps = (state, props) => ({
   accountIds: state.getIn(['user_lists', 'followers', props.params.accountId, 'items']),
   hasMore: !!state.getIn(['user_lists', 'followers', props.params.accountId, 'next']),
+  blockedBy: state.getIn(['relationships', props.params.accountId, 'blocked_by'], false),
 });
 
 export default @connect(mapStateToProps)
@@ -31,6 +32,7 @@ class Followers extends ImmutablePureComponent {
     shouldUpdateScroll: PropTypes.func,
     accountIds: ImmutablePropTypes.list,
     hasMore: PropTypes.bool,
+    blockedBy: PropTypes.bool,
   };
 
   componentWillMount () {
@@ -50,7 +52,7 @@ class Followers extends ImmutablePureComponent {
   }, 300, { leading: true });
 
   render () {
-    const { shouldUpdateScroll, accountIds, hasMore } = this.props;
+    const { shouldUpdateScroll, accountIds, hasMore, blockedBy } = this.props;
 
     if (!accountIds) {
       return (
@@ -60,7 +62,7 @@ class Followers extends ImmutablePureComponent {
       );
     }
 
-    const emptyMessage = <FormattedMessage id='account.followers.empty' defaultMessage='No one follows this user yet.' />;
+    const emptyMessage = blockedBy ? <FormattedMessage id='empty_column.account_timeline_blocked' defaultMessage='You are blocked' /> : <FormattedMessage id='account.followers.empty' defaultMessage='No one follows this user yet.' />;
 
     return (
       <Column>
@@ -75,7 +77,7 @@ class Followers extends ImmutablePureComponent {
           alwaysPrepend
           emptyMessage={emptyMessage}
         >
-          {accountIds.map(id =>
+          {blockedBy ? [] : accountIds.map(id =>
             <AccountContainer key={id} id={id} withNote={false} />
           )}
         </ScrollableList>
diff --git a/app/javascript/mastodon/features/following/index.js b/app/javascript/mastodon/features/following/index.js
index bda0438a0..87638e051 100644
--- a/app/javascript/mastodon/features/following/index.js
+++ b/app/javascript/mastodon/features/following/index.js
@@ -20,6 +20,7 @@ import ScrollableList from '../../components/scrollable_list';
 const mapStateToProps = (state, props) => ({
   accountIds: state.getIn(['user_lists', 'following', props.params.accountId, 'items']),
   hasMore: !!state.getIn(['user_lists', 'following', props.params.accountId, 'next']),
+  blockedBy: state.getIn(['relationships', props.params.accountId, 'blocked_by'], false),
 });
 
 export default @connect(mapStateToProps)
@@ -31,6 +32,7 @@ class Following extends ImmutablePureComponent {
     shouldUpdateScroll: PropTypes.func,
     accountIds: ImmutablePropTypes.list,
     hasMore: PropTypes.bool,
+    blockedBy: PropTypes.bool,
   };
 
   componentWillMount () {
@@ -50,7 +52,7 @@ class Following extends ImmutablePureComponent {
   }, 300, { leading: true });
 
   render () {
-    const { shouldUpdateScroll, accountIds, hasMore } = this.props;
+    const { shouldUpdateScroll, accountIds, hasMore, blockedBy } = this.props;
 
     if (!accountIds) {
       return (
@@ -60,7 +62,7 @@ class Following extends ImmutablePureComponent {
       );
     }
 
-    const emptyMessage = <FormattedMessage id='account.follows.empty' defaultMessage="This user doesn't follow anyone yet." />;
+    const emptyMessage = blockedBy ? <FormattedMessage id='empty_column.account_timeline_blocked' defaultMessage='You are blocked' /> : <FormattedMessage id='account.follows.empty' defaultMessage="This user doesn't follow anyone yet." />;
 
     return (
       <Column>
@@ -75,7 +77,7 @@ class Following extends ImmutablePureComponent {
           alwaysPrepend
           emptyMessage={emptyMessage}
         >
-          {accountIds.map(id =>
+          {blockedBy ? [] : accountIds.map(id =>
             <AccountContainer key={id} id={id} withNote={false} />
           )}
         </ScrollableList>
diff --git a/app/javascript/mastodon/locales/co.json b/app/javascript/mastodon/locales/co.json
index acc680c53..154feab98 100644
--- a/app/javascript/mastodon/locales/co.json
+++ b/app/javascript/mastodon/locales/co.json
@@ -83,7 +83,7 @@
   "compose_form.spoiler.unmarked": "Testu micca piattatu",
   "compose_form.spoiler_placeholder": "Scrive u vostr'avertimentu quì",
   "confirmation_modal.cancel": "Annullà",
-  "confirmations.block.block_and_report": "Block & Report",
+  "confirmations.block.block_and_report": "Bluccà è signalà",
   "confirmations.block.confirm": "Bluccà",
   "confirmations.block.message": "Site sicuru·a che vulete bluccà @{name}?",
   "confirmations.delete.confirm": "Toglie",
@@ -136,7 +136,7 @@
   "follow_request.reject": "Righjittà",
   "getting_started.developers": "Sviluppatori",
   "getting_started.directory": "Annuariu di i prufili",
-  "getting_started.documentation": "Documentation",
+  "getting_started.documentation": "Ducumentazione",
   "getting_started.heading": "Per principià",
   "getting_started.invite": "Invità ghjente",
   "getting_started.open_source_notice": "Mastodon ghjè un lugiziale liberu. Pudete cuntribuisce à u codice o a traduzione, o palisà un bug, nant'à GitHub: {github}.",
@@ -238,7 +238,7 @@
   "navigation_bar.lists": "Liste",
   "navigation_bar.logout": "Scunnettassi",
   "navigation_bar.mutes": "Utilizatori piattati",
-  "navigation_bar.personal": "Personal",
+  "navigation_bar.personal": "Persunale",
   "navigation_bar.pins": "Statuti puntarulati",
   "navigation_bar.preferences": "Preferenze",
   "navigation_bar.public_timeline": "Linea pubblica glubale",
diff --git a/app/javascript/mastodon/locales/cs.json b/app/javascript/mastodon/locales/cs.json
index 9115f5081..e711961e7 100644
--- a/app/javascript/mastodon/locales/cs.json
+++ b/app/javascript/mastodon/locales/cs.json
@@ -26,7 +26,7 @@
   "account.posts": "Tooty",
   "account.posts_with_replies": "Tooty a odpovědi",
   "account.report": "Nahlásit uživatele @{name}",
-  "account.requested": "Požadavek čeká na schválení. Kliknutím zrušíte požadavek o sledování",
+  "account.requested": "Čekám na schválení. Kliknutím zrušíte požadavek o sledování",
   "account.share": "Sdílet profil uživatele @{name}",
   "account.show_reblogs": "Zobrazit boosty od uživatele @{name}",
   "account.unblock": "Odblokovat uživatele @{name}",
diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json
index 0bfafd222..91a27e366 100644
--- a/app/javascript/mastodon/locales/fa.json
+++ b/app/javascript/mastodon/locales/fa.json
@@ -83,7 +83,7 @@
   "compose_form.spoiler.unmarked": "نوشته پنهان نیست",
   "compose_form.spoiler_placeholder": "هشدار محتوا",
   "confirmation_modal.cancel": "بی‌خیال",
-  "confirmations.block.block_and_report": "Block & Report",
+  "confirmations.block.block_and_report": "مسدودسازی و گزارش",
   "confirmations.block.confirm": "مسدود کن",
   "confirmations.block.message": "آیا واقعاً می‌خواهید {name} را مسدود کنید؟",
   "confirmations.delete.confirm": "پاک کن",
diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json
index 568359651..433592ffd 100644
--- a/app/javascript/mastodon/locales/ko.json
+++ b/app/javascript/mastodon/locales/ko.json
@@ -83,7 +83,7 @@
   "compose_form.spoiler.unmarked": "열람주의가 설정 되어 있지 않습니다",
   "compose_form.spoiler_placeholder": "경고",
   "confirmation_modal.cancel": "취소",
-  "confirmations.block.block_and_report": "Block & Report",
+  "confirmations.block.block_and_report": "차단하고 신고하기",
   "confirmations.block.confirm": "차단",
   "confirmations.block.message": "정말로 {name}를 차단하시겠습니까?",
   "confirmations.delete.confirm": "삭제",
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss
index 75a9be045..2ad93c59d 100644
--- a/app/javascript/styles/mastodon/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -5308,6 +5308,7 @@ noscript {
       margin-left: -2px;
 
       .account__avatar {
+        background: darken($ui-base-color, 8%);
         border: 2px solid lighten($ui-base-color, 4%);
       }
     }
diff --git a/app/javascript/styles/mastodon/stream_entries.scss b/app/javascript/styles/mastodon/stream_entries.scss
index d8bd30377..a739c446d 100644
--- a/app/javascript/styles/mastodon/stream_entries.scss
+++ b/app/javascript/styles/mastodon/stream_entries.scss
@@ -99,9 +99,9 @@
     }
   }
 
-  &:active,
-  &:focus,
-  &:hover {
+  &:active:not(:disabled),
+  &:focus:not(:disabled),
+  &:hover:not(:disabled) {
     background: lighten($ui-highlight-color, 10%);
 
     svg path:last-child {
diff --git a/app/javascript/styles/mastodon/widgets.scss b/app/javascript/styles/mastodon/widgets.scss
index 645192ea4..307e509d5 100644
--- a/app/javascript/styles/mastodon/widgets.scss
+++ b/app/javascript/styles/mastodon/widgets.scss
@@ -352,6 +352,7 @@
     border-radius: 50%;
     position: relative;
     margin-left: -10px;
+    background: darken($ui-base-color, 8%);
     border: 2px solid $ui-base-color;
 
     &:nth-child(1) {
diff --git a/app/lib/activitypub/adapter.rb b/app/lib/activitypub/adapter.rb
index 7e0b16c25..94eb2899c 100644
--- a/app/lib/activitypub/adapter.rb
+++ b/app/lib/activitypub/adapter.rb
@@ -18,6 +18,7 @@ class ActivityPub::Adapter < ActiveModelSerializers::Adapter::Base
     atom_uri: { 'ostatus' => 'http://ostatus.org#', 'atomUri' => 'ostatus:atomUri' },
     conversation: { 'ostatus' => 'http://ostatus.org#', 'inReplyToAtomUri' => 'ostatus:inReplyToAtomUri', 'conversation' => 'ostatus:conversation' },
     focal_point: { 'toot' => 'http://joinmastodon.org/ns#', 'focalPoint' => { '@container' => '@list', '@id' => 'toot:focalPoint' } },
+    identity_proof: { 'toot' => 'http://joinmastodon.org/ns#', 'IdentityProof' => 'toot:IdentityProof' },
   }.freeze
 
   def self.default_key_transform
diff --git a/app/lib/proof_provider/keybase.rb b/app/lib/proof_provider/keybase.rb
index 672e1cb4b..628972e9d 100644
--- a/app/lib/proof_provider/keybase.rb
+++ b/app/lib/proof_provider/keybase.rb
@@ -28,7 +28,8 @@ class ProofProvider::Keybase
       return
     end
 
-    return if @proof.provider_username.blank?
+    # Do not perform synchronous validation for remote accounts
+    return if @proof.provider_username.blank? || !@proof.account.local?
 
     if verifier.valid?
       @proof.verified = true
diff --git a/app/serializers/activitypub/actor_serializer.rb b/app/serializers/activitypub/actor_serializer.rb
index 4b982b955..0644219fb 100644
--- a/app/serializers/activitypub/actor_serializer.rb
+++ b/app/serializers/activitypub/actor_serializer.rb
@@ -6,7 +6,7 @@ class ActivityPub::ActorSerializer < ActivityPub::Serializer
   context :security
 
   context_extensions :manually_approves_followers, :featured, :also_known_as,
-                     :moved_to, :property_value, :hashtag, :emoji
+                     :moved_to, :property_value, :hashtag, :emoji, :identity_proof
 
   attributes :id, :type, :following, :followers,
              :inbox, :outbox, :featured,
@@ -115,7 +115,7 @@ class ActivityPub::ActorSerializer < ActivityPub::Serializer
   end
 
   def virtual_attachments
-    object.fields
+    object.fields + object.identity_proofs.active
   end
 
   def moved_to
@@ -158,4 +158,24 @@ class ActivityPub::ActorSerializer < ActivityPub::Serializer
       Formatter.instance.format_field(object.account, object.value)
     end
   end
+
+  class AccountIdentityProofSerializer < ActivityPub::Serializer
+    attributes :type, :name, :signature_algorithm, :signature_value
+
+    def type
+      'IdentityProof'
+    end
+
+    def name
+      object.provider_username
+    end
+
+    def signature_algorithm
+      object.provider
+    end
+
+    def signature_value
+      object.token
+    end
+  end
 end
diff --git a/app/services/activitypub/process_account_service.rb b/app/services/activitypub/process_account_service.rb
index 5e3308428..6d0609ca0 100644
--- a/app/services/activitypub/process_account_service.rb
+++ b/app/services/activitypub/process_account_service.rb
@@ -24,6 +24,7 @@ class ActivityPub::ProcessAccountService < BaseService
         create_account if @account.nil?
         update_account
         process_tags
+        process_attachments
       else
         raise Mastodon::RaceConditionError
       end
@@ -151,7 +152,7 @@ class ActivityPub::ProcessAccountService < BaseService
 
   def property_values
     return unless @json['attachment'].is_a?(Array)
-    @json['attachment'].select { |attachment| attachment['type'] == 'PropertyValue' }.map { |attachment| attachment.slice('name', 'value') }
+    as_array(@json['attachment']).select { |attachment| attachment['type'] == 'PropertyValue' }.map { |attachment| attachment.slice('name', 'value') }
   end
 
   def mismatching_origin?(url)
@@ -231,6 +232,23 @@ class ActivityPub::ProcessAccountService < BaseService
     end
   end
 
+  def process_attachments
+    return if @json['attachment'].blank?
+
+    previous_proofs = @account.identity_proofs.to_a
+    current_proofs  = []
+
+    as_array(@json['attachment']).each do |attachment|
+      next unless equals_or_includes?(attachment['type'], 'IdentityProof')
+      current_proofs << process_identity_proof(attachment)
+    end
+
+    previous_proofs.each do |previous_proof|
+      next if current_proofs.any? { |current_proof| current_proof.id == previous_proof.id }
+      previous_proof.delete
+    end
+  end
+
   def process_emoji(tag)
     return if skip_download?
     return if tag['name'].blank? || tag['icon'].blank? || tag['icon']['url'].blank?
@@ -247,4 +265,12 @@ class ActivityPub::ProcessAccountService < BaseService
     emoji.image_remote_url = image_url
     emoji.save
   end
+
+  def process_identity_proof(attachment)
+    provider          = attachment['signatureAlgorithm']
+    provider_username = attachment['name']
+    token             = attachment['signatureValue']
+
+    @account.identity_proofs.where(provider: provider, provider_username: provider_username).find_or_create_by(provider: provider, provider_username: provider_username, token: token)
+  end
 end
diff --git a/config/locales/activerecord.co.yml b/config/locales/activerecord.co.yml
index 20c35b67f..0a9a936dd 100644
--- a/config/locales/activerecord.co.yml
+++ b/config/locales/activerecord.co.yml
@@ -2,8 +2,9 @@
 co:
   activerecord:
     attributes:
-      status:
-        owned_poll: Scandagliu
+      poll:
+        expires_at: Fine
+        options: Scelte
     errors:
       models:
         account:
diff --git a/config/locales/co.yml b/config/locales/co.yml
index 71882b7cb..90c60e292 100644
--- a/config/locales/co.yml
+++ b/config/locales/co.yml
@@ -245,6 +245,7 @@ co:
       feature_profile_directory: Annuariu di i prufili
       feature_registrations: Arregistramenti
       feature_relay: Ripetitore di federazione
+      feature_timeline_preview: Vista di a linea pubblica
       features: Funziunalità
       hidden_service: Federazione cù servizii piattati
       open_reports: signalamenti aperti
@@ -586,6 +587,9 @@ co:
       content: Scusate, mà c’hè statu un prublemu cù u nostru servore.
       title: Sta pagina ùn hè curretta
     noscript_html: Mastodon nant’à u web hà bisognu di JavaScript per funziunà. Pudete ancu pruvà <a href="%{apps_path}">l’applicazione native</a> per a vostra piattaforma.
+  existing_username_validator:
+    not_found: ùn si pudeva micca truvà un'utilizatore lucale cù stu cugnome
+    not_found_multiple: ùn si pudeva micca truvà %{usernames}
   exports:
     archive_takeout:
       date: Data
@@ -629,10 +633,31 @@ co:
     all: Tuttu
     changes_saved_msg: Cambiamenti salvati!
     copy: Cupià
+    order_by: Urdinà per
     save_changes: Salvà e mudificazione
     validation_errors:
       one: Qualcosa ùn và bè! Verificate u prublemu quì sottu
       other: Qualcosa ùn và bè! Verificate %{count} prublemi quì sottu
+  html_validator:
+    invalid_markup: 'cuntene codice HTML invalidu: %{error}'
+  identity_proofs:
+    active: Attiva
+    authorize: Ié, auturizà
+    authorize_connection_prompt: Auturizà sta cunnessione crittograffica?
+    errors:
+      failed: A cunnessione crittograffica s'hè fiascata. Ripruvate da %{provider}.
+      keybase:
+        invalid_token: E fiscie Keybase sò hash di firme è duvenu fà 66 caratteri esadecimali (0-9 A-F)
+        verification_failed: Keybase ùn ricunosce micca sta fiscia cum'una firma di l'utilizatore Keybase %{kb_username}. Ripruvate da Keybase.
+      wrong_user: Ùn si pò micca creà una prova per %{proving} mentre chì site cunnettatu·a cum'è %{current}. Cunnettatevi cum'è %{proving} è ripruvate.
+    explanation_html: Quì pudete cunnettà crittografficamente e vostre altre identità, cum'è per esempiu un prufile Keybase. Quessu permette à d'altre persone di mandà vi missaghji crittati, è d'affiducià i cuntinuti chì mandate.
+    i_am_html: Sò %{username} nant'à %{service}.
+    identity: Identità
+    inactive: Inattiva
+    publicize_checkbox: 'È mandà stu statutu:'
+    publicize_toot: 'Hè pruvata! Sò %{username} nant’à %{service}: %{url}'
+    status: Statutu di a verificazione
+    view_proof: Vede a prova
   imports:
     modes:
       merge: Unisce
@@ -753,6 +778,8 @@ co:
   relationships:
     activity: Attività di u contu
     dormant: Inattivu
+    last_active: Ultima attività
+    most_recent: Più ricente
     moved: Spiazzatu
     mutual: Mutuale
     primary: Primariu
@@ -835,6 +862,7 @@ co:
     edit_profile: Mudificà u prufile
     export: Spurtazione d’infurmazione
     featured_tags: Hashtag in vista
+    identity_proofs: Prove d'identità
     import: Impurtazione
     migrate: Migrazione di u contu
     notifications: Nutificazione
diff --git a/config/locales/cs.yml b/config/locales/cs.yml
index 2ec3f6790..43d8764ff 100644
--- a/config/locales/cs.yml
+++ b/config/locales/cs.yml
@@ -650,16 +650,19 @@ cs:
   identity_proofs:
     active: Aktivní
     authorize: Ano, autorizovat
-    authorize_connection_prompt: Autorizovat tohle kryptografické spojení?
+    authorize_connection_prompt: Autorizovat toto kryptografické spojení?
     errors:
       failed: Kryptografické spojení selhalo. Prosím zkuste to znovu z %{provider}.
       keybase:
         invalid_token: Tokeny Keybase jsou hashe podpisů a musí být 66 znaků dlouhé
         verification_failed: Keybase nerozpoznává tento token jako podpis uživatele %{kb_username} na Keybase. Prosím zkuste to znovu z Keybase.
+      wrong_user: Nelze vytvořit důkaz pro uživatele %{proving}, zatímco jste přihlášen/a jako %{current}. Přihlaste se jako %{proving} a zkuste to znovu.
     explanation_html: Zde můžete kryptograficky připojit vaše ostatní identity, například profil Keybase. To dovolí jiným lidem vám posílat šifrované zprávy a důvěřovat obsahu, který jim pošlete.
     i_am_html: Na %{service} jsem %{username}.
     identity: Identita
     inactive: Neaktivní
+    publicize_checkbox: 'A tootnout tohle:'
+    publicize_toot: 'Je to dokázáno! Na %{service} jsem %{username}: %{url}'
     status: Stav ověření
     view_proof: Zobrazit důkaz
   imports:
@@ -784,6 +787,8 @@ cs:
   relationships:
     activity: Aktivita účtu
     dormant: Nečinné
+    last_active: Naposledy aktivní
+    most_recent: Nedávno přidaní
     moved: Přesunuté
     mutual: Vzájemné
     primary: Primární
@@ -1026,7 +1031,7 @@ cs:
     recovery_codes_regenerated: Záložní kódy byly úspěšně znovu vygenerované
     recovery_instructions_html: Ztratíte-li někdy přístup k vašemu telefonu, můžete k získání přístupu k účtu použít jeden ze záložních kódů. <strong>Uchovávejte tyto kódy v bezpečí</strong>. Můžete si je například vytisknout a uložit je mezi jiné důležité dokumenty.
     setup: Nastavit
-    wrong_code: Zadaný kód byl neplatný! Je serverový čas a čas na zařízení správný?
+    wrong_code: Zadaný kód byl neplatný! Je čas na serveru a na zařízení správný?
   user_mailer:
     backup_ready:
       explanation: Vyžádal/a jste si úplnou zálohu svého účtu Mastodon. Nyní je připravena ke stažení!
diff --git a/config/locales/ko.yml b/config/locales/ko.yml
index ee5d662bb..fd1470d2d 100644
--- a/config/locales/ko.yml
+++ b/config/locales/ko.yml
@@ -245,6 +245,7 @@ ko:
       feature_profile_directory: 프로필 디렉토리
       feature_registrations: 가입
       feature_relay: 연합 릴레이
+      feature_timeline_preview: 타임라인 미리보기
       features: 기능
       hidden_service: 히든 서비스와의 연합
       open_reports: 미해결 신고
@@ -634,6 +635,7 @@ ko:
     all: 모두
     changes_saved_msg: 정상적으로 변경되었습니다!
     copy: 복사
+    order_by: 순서
     save_changes: 변경 사항을 저장
     validation_errors:
       one: 오류가 발생했습니다. 아래 오류를 확인해 주십시오
@@ -649,10 +651,13 @@ ko:
       keybase:
         invalid_token: 키베이스 토큰은 서명의 해시이며 66자의 16진수 문자여야 합니다
         verification_failed: 키베이스가 이 토큰을 키베이스 유저 %{kb_username}의 서명으로 인식하지 못했습니다. 키베이스에서 다시 시도하세요.
+      wrong_user: "%{current}로 로그인 한 상태에서는 %{proving}에 대한 증명을 할 수 없습니다. %{proving}으로 로그인 한 후 다시 시도하세요."
     explanation_html: 키베이스와 같은 다른 명의에 대한 암호화 연결을 할 수 있습니다. 이것으로 다른 사람들이 당신에게 암호화 된 메시지를 보낼 수 있고 당신의 메시지를 믿을 수 있습니다.
     i_am_html: 나는 %{service}의 %{username} 입니다.
     identity: 신원
     inactive: 비활성
+    publicize_checkbox: '그리고 이것을 툿 하세요:'
+    publicize_toot: '증명되었습니다! 저는 %{service}에 있는 %{username}입니다: %{url}'
     status: 인증 상태
     view_proof: 증명 보기
   imports:
@@ -775,6 +780,8 @@ ko:
   relationships:
     activity: 계정 활동
     dormant: 휴면
+    last_active: 마지막 활동
+    most_recent: 가장 최근
     moved: 이동함
     mutual: 상호 팔로우
     primary: 주 계정
diff --git a/dist/nginx.conf b/dist/nginx.conf
index 3d5741765..7c429bad4 100644
--- a/dist/nginx.conf
+++ b/dist/nginx.conf
@@ -78,6 +78,7 @@ server {
 
     proxy_cache CACHE;
     proxy_cache_valid 200 7d;
+    proxy_cache_valid 410 24h;
     proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
     add_header X-Cached $upstream_cache_status;
     add_header Strict-Transport-Security "max-age=31536000";
diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb
index b35dd0561..c728b3ab2 100644
--- a/lib/mastodon/version.rb
+++ b/lib/mastodon/version.rb
@@ -9,11 +9,11 @@ module Mastodon
     end
 
     def minor
-      7
+      8
     end
 
     def patch
-      4
+      0
     end
 
     def pre
@@ -21,7 +21,7 @@ module Mastodon
     end
 
     def flags
-      ''
+      'rc1'
     end
 
     def to_a
diff --git a/spec/services/activitypub/process_account_service_spec.rb b/spec/services/activitypub/process_account_service_spec.rb
index d3318b2ed..5141e3f16 100644
--- a/spec/services/activitypub/process_account_service_spec.rb
+++ b/spec/services/activitypub/process_account_service_spec.rb
@@ -28,4 +28,49 @@ RSpec.describe ActivityPub::ProcessAccountService, type: :service do
       expect(account.fields[1].value).to eq 'Unit test'
     end
   end
+
+  context 'identity proofs' do
+    let(:payload) do
+      {
+        id: 'https://foo.test',
+        type: 'Actor',
+        inbox: 'https://foo.test/inbox',
+        attachment: [
+          { type: 'IdentityProof', name: 'Alice', signatureAlgorithm: 'keybase', signatureValue: 'a' * 66 },
+        ],
+      }.with_indifferent_access
+    end
+
+    it 'parses out of attachment' do
+      allow(ProofProvider::Keybase::Worker).to receive(:perform_async)
+
+      account = subject.call('alice', 'example.com', payload)
+
+      expect(account.identity_proofs.count).to eq 1
+
+      proof = account.identity_proofs.first
+
+      expect(proof.provider).to eq 'keybase'
+      expect(proof.provider_username).to eq 'Alice'
+      expect(proof.token).to eq 'a' * 66
+    end
+
+    it 'removes no longer present proofs' do
+      allow(ProofProvider::Keybase::Worker).to receive(:perform_async)
+
+      account   = Fabricate(:account, username: 'alice', domain: 'example.com')
+      old_proof = Fabricate(:account_identity_proof, account: account, provider: 'keybase', provider_username: 'Bob', token: 'b' * 66)
+
+      subject.call('alice', 'example.com', payload)
+
+      expect(account.identity_proofs.count).to eq 1
+      expect(account.identity_proofs.find_by(id: old_proof.id)).to be_nil
+    end
+
+    it 'queues a validity check on the proof' do
+      allow(ProofProvider::Keybase::Worker).to receive(:perform_async)
+      account = subject.call('alice', 'example.com', payload)
+      expect(ProofProvider::Keybase::Worker).to have_received(:perform_async)
+    end
+  end
 end