ActivityPub es un protocolo de red social distribuido y abierto estandarizado por el World Wide Web Consortium. Su primera versión fue lanzada en 2018, por lo que no es nueva. Es utilizado por varias redes sociales, incluida Mastodon , que recientemente ha experimentado un aumento significativo en popularidad cuando Elon Musk compró Twitter e hizo cambios que no agradaron a muchos.
Además, Tumblr y la alternativa de Facebook a Twitter, Threads, también han señalado que apoyarán el protocolo en el futuro. A pesar de no ser un protocolo nuevo, ActivityPub se está volviendo cada vez más popular.
Como la Unión Europea y los Estados Unidos llevan mucho tiempo preocupados por el monopolio de mercado de las grandes redes sociales, me imagino que en el futuro, bajo presión gubernamental, las redes sociales más grandes existentes, como Facebook y Twitter, también apoyarán el protocolo y se convertirán en parte del Fediverso . (Fediverse es un universo de redes sociales formado por proveedores que respaldan ActivityPub).
Creo que en el futuro no elegiremos Twitter ni Facebook porque estarán cerrados y no nos quedará otra opción.
La fortaleza de cada plataforma vendrá de quién tenga mejor inteligencia artificial para filtrar la enorme cantidad de datos entrantes, examinar, seleccionar y resumir la información más importante para los usuarios.
Por supuesto, para ello es necesario conocer muy bien al usuario, lo que también redunda en su interés. A cambio, la inteligencia artificial puede ofrecer anuncios mucho más relevantes.
En un sistema abierto y accesible, la competencia ya no será entre redes sociales, sino entre algoritmos basados en inteligencia artificial.
Veamos cómo funciona ActivityPub. La funcionalidad básica se resume muy bien en este diagrama muy simple.
El protocolo tiene dos componentes principales: la bandeja de entrada y la bandeja de salida. Estos son dos puntos finales de API a los que se puede acceder a través del protocolo HTTP. Cuando un usuario quiere comunicar algo con el mundo exterior (por ejemplo, publicar algún contenido), lo envía a la bandeja de salida. Aquí, el sistema lo agrega a una lista adecuada, a la que los seguidores pueden acceder leyendo la bandeja de salida.
Si alguien del mundo exterior quiere enviar algo al usuario (por ejemplo, una publicación no pública que sólo pueden ver ciertos usuarios), lo envía a la bandeja de entrada en forma cifrada. La bandeja de entrada es como una bandeja de entrada de correo electrónico, donde se recopila el contenido entrante y donde el usuario puede acceder a él.
Se puede recuperar la ubicación de la bandeja de entrada y de salida utilizando el protocolo WebFinger. Esto también se puede probar con la ayuda de ActivityPub Explorer , una súper herramienta para experimentar y comprender el protocolo.
Un nombre de usuario en ActivityPub es similar a una dirección de correo electrónico. Por ejemplo, mi nombre de usuario de Mastodon es @[email protected]. Esto significa que mi información de usuario se almacena en el servidor dm.me con el nombre thebojda.
Cuando ingrese a ActivityPub Explorer, consultará la siguiente URL de acuerdo con el protocolo WebFinger para recuperar los datos:
https://me.dm/.well-known/webfinger?resource=acct:thebojda%40me.dm
La respuesta es un objeto JSON similar a este:
{ "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}" } ] }
Desde aquí se puede determinar que se podrá acceder a la información de ActivityPub en la URL https://me.dm/users/thebojda . Si ingresamos esto en ActivityPub Explorer, devolverá el siguiente 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" } }
Aquí puede encontrar toda la información específica del usuario sobre mí, pero lo más importante es que aquí están las URL de los puntos finales de la bandeja de entrada y de la bandeja de salida, así como la clave pública para cifrar los mensajes que me envían. Al consultar el contenido de la bandeja de salida, se devuelve el siguiente 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" }
Como las publicaciones están divididas en páginas, aquí podemos ver las URL de la primera y la última página. Accediendo a la URL de la primera página, podemos ver mis entradas, de las que actualmente sólo hay una.
{ "@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": [] } } } } ] }
Con base en estos ejemplos, es fácil implementar un cliente mínimo que pueda leer las publicaciones públicas de otros o publicar publicaciones públicas en el mundo exterior. No entraré aquí en la estructura exacta de los archivos JSON individuales ni en el funcionamiento de la bandeja de entrada.
Estos se pueden encontrar en la documentación de ActivityPub .
Como puede verse, ActivityPub es un estándar relativamente simple y fácil de entender e implementar. Su único punto débil es que utiliza el protocolo HTTP, que requiere un servidor central. Esto dio lugar a protocolos alternativos como Nostr, que es el proyecto favorito de Jack Dorsey (el fundador de Twitter).
Sin embargo, creo que esto no es necesario y sólo provoca una mayor fragmentación de las redes sociales. En cambio, el protocolo ActivityPub debería ampliarse con soporte para protocolos descentralizados ya existentes, lo que permitiría que Fediverse se desarrolle hacia una dirección aún más abierta y descentralizada. A continuación demostraré cómo se puede lograr esto.
Una solución perfecta para descentralizar datos descriptivos y feeds es utilizar Swarm Feeds o IPNS (tengo un artículo completo sobre estos protocolos). En el caso de Ethereum Swarm, el identificador del feed es una dirección de Swarm, mientras que en el caso de IPNS, es una clave pública.
Al usarlos, un usuario de ActivityPub se vería así: {dirección de enjambre}@swarm o {dirección IPNS}@IPNS. La descripción del usuario se puede consultar desde aquí.
Para compatibilidad con versiones anteriores, también se podrían utilizar servidores de puerta de enlace como {dirección de swarm}@gateway.ethswarm.org, que devolverían la descripción del usuario almacenada en Swarm a través del protocolo Webfinger, permitiendo a los sistemas existentes (como Mastodon) leer estos datos sin ningún modificaciones.
La implementación de la bandeja de salida también se realizaría a través de feeds Swarm o IPNS. Para mantener la compatibilidad con versiones anteriores, sería necesario introducir un campo "decentralized_outbox", donde se ubicaría una dirección Swarm feed (bzz://...) o IPNS (ipns://...).
Para mantener la compatibilidad con versiones anteriores, se podría incluir una dirección de puerta de enlace adicional en el campo "bandeja de salida" original para que los clientes existentes puedan leer estos feeds sin ningún cambio.
La implementación de una bandeja de entrada se puede realizar de varias maneras. Ethereum Swarm tiene un sistema de mensajería llamado PSS , pero también existen otras alternativas, como Waku . Aquí, la dirección de PSS o Waku se colocaría en un campo "decentralized_inbox", mientras que el campo de la bandeja de entrada original contendría una dirección de puerta de enlace.
Con estas pequeñas extensiones, ActivityPub puede volverse completamente descentralizado y "compatible con web3", sin la necesidad de introducir nuevos protocolos como Nostr.
Según el repositorio GitHub de Nostr, la necesidad del nuevo protocolo y sistema de retransmisión se debe a la posible censura de los usuarios por parte de los servidores ActivityPub y la falta de un sistema de incentivos. Sin embargo, este problema se resuelve completamente con la extensión anterior.
Tanto IPNS como Swarm son resistentes a la censura y Swarm también proporciona un anonimato total. Además, Swarm tiene su propio sistema de incentivos, mientras que FileCoin está disponible para IPNS.
Creo que el futuro claramente pertenece a ActivityPub, y los desarrolladores deberían centrarse en hacer avanzar y evolucionar ActivityPub en lugar de crear nuevos protocolos, para finalmente establecer un Fediverse completo y verdaderamente unificado.