ActivityPub — это открытый распределенный протокол социальной сети, стандартизированный Консорциумом World Wide Web. Его первая версия вышла в 2018 году, поэтому она не нова. Его используют несколько социальных сетей, в том числе Mastodon , популярность которого в последнее время значительно возросла, когда Илон Маск купил Twitter и внес изменения, которые многим не понравились.
Кроме того, Tumblr и альтернатива Twitter от Facebook, Threads, также дали понять, что будут поддерживать протокол в будущем. Несмотря на то, что ActivityPub не является новым протоколом, сейчас он становится все более популярным.
Поскольку Европейский Союз и США уже давно обеспокоены рыночной монополией крупных социальных сетей, я могу себе представить, что в будущем, под давлением правительства, существующие крупнейшие социальные сети, такие как Facebook и Twitter, также поддержат протокол и станут часть Федиверса . (Fediverse — это вселенная социальных сетей, состоящая из провайдеров, поддерживающих ActivityPub.)
Я считаю, что в будущем мы не выберем Твиттер или Фейсбук, потому что они закроются и у нас не будет другого выбора.
Сила каждой платформы будет зависеть от того, у кого лучше искусственный интеллект, который сможет фильтровать входящие огромные объемы данных, просеивать, выбирать и обобщать наиболее важную информацию для пользователей.
Конечно, для этого нужно очень хорошо знать пользователя, что тоже в его интересах. В свою очередь, искусственный интеллект может предоставлять гораздо более релевантную рекламу.
В открытой, доступной системе конкуренция будет уже не среди социальных сетей, а среди алгоритмов на основе искусственного интеллекта.
Давайте посмотрим, как работает ActivityPub. Базовая функциональность хорошо отражена на этой очень простой диаграмме.
Протокол состоит из двух основных компонентов: входящего и исходящего. Это две конечные точки API, доступ к которым можно получить через протокол HTTP. Когда пользователь хочет что-то сообщить внешнему миру (например, опубликовать какой-то контент), он отправляет это в папку «Исходящие». Здесь система добавляет его в соответствующий список, к которому подписчики могут получить доступ, прочитав исходящие сообщения.
Если кто-то из внешнего мира хочет отправить что-то пользователю (например, непубличное сообщение, которое могут видеть только определенные пользователи), он отправляет это во входящие в зашифрованном виде. Папка «Входящие» похожа на почтовый ящик электронной почты, где собирается входящий контент и где пользователь может получить к нему доступ.
Узнать местоположение входящих и исходящих сообщений можно с помощью протокола WebFinger. Это также можно проверить с помощью ActivityPub Explorer , суперинструмента для экспериментов и понимания протокола.
Имя пользователя в ActivityPub похоже на адрес электронной почты. Например, мое имя пользователя Mastodon — @[email protected]. Это означает, что моя пользовательская информация хранится на сервере dm.me под именем thebojda.
При входе в ActivityPub Explorer он запросит следующий URL-адрес в соответствии с протоколом WebFinger для получения данных:
https://me.dm/.well-known/webfinger?resource=acct:thebojda%40me.dm
Ответом является объект JSON, который выглядит следующим образом:
{ "subject":"acct:[email protected]", "aliases":[ "https://me.dm/@thebojda", "https://me.dm/users/thebojda" ], "links":[ { "rel":"http://webfinger.net/rel/profile-page", "type":"text/html", "href":"https://me.dm/@thebojda" }, { "rel":"self", "type":"application/activity+json", "href":"https://me.dm/users/thebojda" }, { "rel":"http://ostatus.org/schema/1.0/subscribe", "template":"https://me.dm/authorize_interaction?uri={uri}" } ] }
Отсюда можно определить, что информация ActivityPub будет доступна по URL-адресу https://me.dm/users/thebojda . Если мы введем это в ActivityPub Explorer, он вернет следующий JSON:
{ "@context": [ "https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1", { "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", "toot": "http://joinmastodon.org/ns#", "featured": { "@id": "toot:featured", "@type": "@id" }, "featuredTags": { "@id": "toot:featuredTags", "@type": "@id" }, "alsoKnownAs": { "@id": "as:alsoKnownAs", "@type": "@id" }, "movedTo": { "@id": "as:movedTo", "@type": "@id" }, "schema": "http://schema.org#", "PropertyValue": "schema:PropertyValue", "value": "schema:value", "discoverable": "toot:discoverable", "Device": "toot:Device", "Ed25519Signature": "toot:Ed25519Signature", "Ed25519Key": "toot:Ed25519Key", "Curve25519Key": "toot:Curve25519Key", "EncryptedMessage": "toot:EncryptedMessage", "publicKeyBase64": "toot:publicKeyBase64", "deviceId": "toot:deviceId", "claim": { "@type": "@id", "@id": "toot:claim" }, "fingerprintKey": { "@type": "@id", "@id": "toot:fingerprintKey" }, "identityKey": { "@type": "@id", "@id": "toot:identityKey" }, "devices": { "@type": "@id", "@id": "toot:devices" }, "messageFranking": "toot:messageFranking", "messageType": "toot:messageType", "cipherText": "toot:cipherText", "suspended": "toot:suspended", "focalPoint": { "@container": "@list", "@id": "toot:focalPoint" } } ], "id": "https://me.dm/users/thebojda", "type": "Person", "following": "https://me.dm/users/thebojda/following", "followers": "https://me.dm/users/thebojda/followers", "inbox": "https://me.dm/users/thebojda/inbox", "outbox": "https://me.dm/users/thebojda/outbox", "featured": "https://me.dm/users/thebojda/collections/featured", "featuredTags": "https://me.dm/users/thebojda/collections/tags", "preferredUsername": "thebojda", "name": "Laszlo Fazekas", "summary": "<p>Software developer, contributing writer</p>", "url": "https://me.dm/@thebojda", "manuallyApprovesFollowers": false, "discoverable": false, "published": "2023-03-02T00:00:00Z", "devices": "https://me.dm/users/thebojda/collections/devices", "publicKey": { "id": "https://me.dm/users/thebojda#main-key", "owner": "https://me.dm/users/thebojda", "publicKeyPem": "-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxlvpgcOxBikiXfm9snZt EB3Y2BSnBW3s8nd1d4Z1wCzaNfa/woB6RDQJoQYEISbMpkEyWhDzI4jRDafpn5/j YiyyGka9U2KZHv1to0Ej9uVwUcQOnsq9iUtJGhOWCP27blKGTLKFEHtPL2Y4hp4Z kYzlh1x0aAyw8YC7/nbS8WDAeZNS7R3ET7Syhp3LKiCMmL1aCLSoOQJ5DdxVikMJ rJ9bzlUjxzCsm1aNBB0i269t4fD1evBO8QDhEAOnAZ6wLEV74j9SCjYMvKRV8z5i PQbhbKntXjn1XhbkIkj1D+yGRYYfnm1XyWTuaM4mDllvuOyqJ8GQVFADLc6KCQYz 7QIDAQAB -----END PUBLIC KEY----- " }, "tag": [], "endpoints": { "sharedInbox": "https://me.dm/inbox" }, "icon": { "type": "Image", "mediaType": "image/jpeg", "url": "https://media.me.dm/accounts/avatars/109/955/144/019/799/820/original/fe8e930e0f1467ac.jpeg" } }
Здесь вы можете найти всю пользовательскую информацию обо мне, но, что самое важное, это URL-адреса конечных точек входящих и исходящих сообщений, а также открытый ключ для шифрования отправленных мне сообщений. При запросе содержимого исходящих сообщений возвращается следующий JSON:
{ "@context": "https://www.w3.org/ns/activitystreams", "id": "https://me.dm/users/thebojda/outbox", "type": "OrderedCollection", "totalItems": 1, "first": "https://me.dm/users/thebojda/outbox?page=true", "last": "https://me.dm/users/thebojda/outbox?min_id=0&page=true" }
Поскольку публикации разделены на страницы, здесь мы видим URL-адреса первой и последней страниц. Получив доступ к URL-адресу первой страницы, мы можем просмотреть мои записи, из которых на данный момент существует только одна.
{ "@context": [ "https://www.w3.org/ns/activitystreams", { "ostatus": "http://ostatus.org#", "atomUri": "ostatus:atomUri", "inReplyToAtomUri": "ostatus:inReplyToAtomUri", "conversation": "ostatus:conversation", "sensitive": "as:sensitive", "toot": "http://joinmastodon.org/ns#", "votersCount": "toot:votersCount" } ], "id": "https://me.dm/users/thebojda/outbox?page=true", "type": "OrderedCollectionPage", "prev": "https://me.dm/users/thebojda/outbox?min_id=109955178005562038&page=true", "partOf": "https://me.dm/users/thebojda/outbox", "orderedItems": [ { "id": "https://me.dm/users/thebojda/statuses/109955178005562038/activity", "type": "Create", "actor": "https://me.dm/users/thebojda", "published": "2023-03-02T18:47:47Z", "to": [ "https://www.w3.org/ns/activitystreams#Public" ], "cc": [ "https://me.dm/users/thebojda/followers" ], "object": { "id": "https://me.dm/users/thebojda/statuses/109955178005562038", "type": "Note", "summary": null, "inReplyTo": null, "published": "2023-03-02T18:47:47Z", "url": "https://me.dm/@thebojda/109955178005562038", "attributedTo": "https://me.dm/users/thebojda", "to": [ "https://www.w3.org/ns/activitystreams#Public" ], "cc": [ "https://me.dm/users/thebojda/followers" ], "sensitive": false, "atomUri": "https://me.dm/users/thebojda/statuses/109955178005562038", "inReplyToAtomUri": null, "conversation": "tag:me.dm,2023-03-02:objectId=1406005:objectType=Conversation", "content": "<p>My "ars poetica": How to Change the World?! Pocket Guide for People With a Messiah Complex <a href=\"https://medium.com/geekculture/how-to-change-the-world-pocket-guide-for-people-with-a-messiah-complex-dd2d16bb92a\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><span class=\"invisible\">https://</span><span class=\"ellipsis\">medium.com/geekculture/how-to-</span><span class=\"invisible\">change-the-world-pocket-guide-for-people-with-a-messiah-complex-dd2d16bb92a</span></a></p>", "contentMap": { "en": "<p>My "ars poetica": How to Change the World?! Pocket Guide for People With a Messiah Complex <a href=\"https://medium.com/geekculture/how-to-change-the-world-pocket-guide-for-people-with-a-messiah-complex-dd2d16bb92a\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><span class=\"invisible\">https://</span><span class=\"ellipsis\">medium.com/geekculture/how-to-</span><span class=\"invisible\">change-the-world-pocket-guide-for-people-with-a-messiah-complex-dd2d16bb92a</span></a></p>" }, "attachment": [], "tag": [], "replies": { "id": "https://me.dm/users/thebojda/statuses/109955178005562038/replies", "type": "Collection", "first": { "type": "CollectionPage", "next": "https://me.dm/users/thebojda/statuses/109955178005562038/replies?only_other_accounts=true&page=true", "partOf": "https://me.dm/users/thebojda/statuses/109955178005562038/replies", "items": [] } } } } ] }
На основе этих примеров легко реализовать минимальный клиент, который может читать общедоступные сообщения других или публиковать общедоступные сообщения для внешнего мира. Я не буду здесь вдаваться в точную структуру отдельных файлов JSON и функционирование почтового ящика.
Их можно найти в документации ActivityPub .
Как можно видеть, ActivityPub — относительно простой стандарт, который легко понять и реализовать. Его единственная слабость заключается в том, что он использует протокол HTTP, для которого требуется центральный сервер. Это привело к появлению альтернативных протоколов, таких как Nostr, любимый проект Джека Дорси (основателя Twitter).
Однако я считаю, что в этом нет необходимости, и это приводит лишь к дальнейшей фрагментации социальных сетей. Вместо этого протокол ActivityPub следует расширить за счет поддержки уже существующих децентрализованных протоколов, что позволит Fediverse развиваться в еще более открытом и децентрализованном направлении. Далее я покажу, как этого можно достичь.
Одним из идеальных решений для децентрализации описательных данных и каналов является использование Swarm Feeds или IPNS (у меня есть полная статья об этих протоколах). В случае Ethereum Swarm идентификатором канала является адрес Swarm, а в случае IPNS — открытый ключ.
Используя их, пользователь ActivityPub будет выглядеть так: {адрес роя}@swarm или {адрес IPNS}@IPNS. Описание пользователя можно запросить отсюда.
Для обратной совместимости также можно использовать серверы-шлюзы, такие как {swarm адрес}@gateway.ethswarm.org, которые будут возвращать описание пользователя, хранящееся в Swarm, через протокол Webfinger, позволяя существующим системам (таким как Mastodon) читать эти данные без каких-либо модификации.
Реализация исходящих сообщений также будет осуществляться через каналы Swarm или IPNS. Для обеспечения обратной совместимости необходимо ввести поле «decentralized_outbox», в котором будет расположен адрес канала Swarm (bzz://...) или IPNS (ipns://...).
Для обеспечения обратной совместимости в исходное поле «Исходящие» можно включить дополнительный адрес шлюза, чтобы существующие клиенты могли читать эти каналы без каких-либо изменений.
Реализация почтового ящика может осуществляться несколькими способами. У Ethereum Swarm есть система обмена сообщениями под названием PSS , но есть и другие альтернативы, такие как Waku . Здесь адрес PSS или Waku будет помещен в поле «decentralized_inbox», а исходное поле «Входящие» будет содержать адрес шлюза.
С помощью этих нескольких небольших расширений ActivityPub можно сделать полностью децентрализованным и «совместимым с Web3» без необходимости внедрения новых протоколов, таких как Nostr.
Согласно репозиторию Nostr на GitHub , необходимость в новом протоколе и системе ретрансляции обусловлена потенциальной цензурой пользователей со стороны серверов ActivityPub и отсутствием системы стимулирования. Однако эта проблема полностью решается вышеуказанным расширением.
И IPNS, и Swarm устойчивы к цензуре, а Swarm также обеспечивает полную анонимность. Кроме того, у Swarm есть собственная система поощрений, а FileCoin доступен для IPNS.
Я считаю, что будущее явно принадлежит ActivityPub, и разработчикам следует сосредоточиться на продвижении и развитии ActivityPub, а не на создании новых протоколов, чтобы наконец создать всеобъемлющую и по-настоящему единую Fediverse.