ActivityPub’s federated model allows for flexibility in referencing data between different instances. However it requires that these instances be always online and do not allow for non-internet or locally published identities outside of the HTTPS/DNS based web.
This document describes how implementors can extend ActivityPub to link to objects hosted on Peer to Peer protocols and how compatible clients should detect this support and load each others’ content.
ActivityPub’s federated model allows for flexibility in referencing data between different instances. However it requires that these instances be always online and do not allow for non-internet or locally published identities outside of the HTTPS/DNS based web. By linking to P2P versions of documents from HTTPS versions, we can enable interoperability with existing AP implementations while opening the way to P2P-only networks.
There are existing specifications in place for linking to “alternate” URLs for content. These are already used by implementations to resolve ActivityPub identities from web pages, to link to web pages from ActivityPub objects like an Actor or a Note, or to discover the ActivityPub account of a user referenced with @username@domain
syntax with Webfinger.
Our approach builds on these methods by adding extra URLs pointing to P2P versions of resources along side the expected HTTP links.
Compliant clients should attempt to prioritize loading P2P versions of AP data when possible / enabled by users.
One of the easiest ways is to sit beside the content negotiation support with links to HTML pages. Statically published AP sites which cannot do content negotiation via Accept headers have the option to point to the ActivityStreams version of a site using a link
header pointing to the JSON-LD file for the AP object associated with the page. P2P sites should add extra links after this to the P2P URLs of the site which also use the rel=alternate
attribute.
When loading a link to an HTML page, clients should attempt to detect the Link
element with the preferred url scheme and resume from there.
Similar to the HTML links, published sites should add the P2P URLs of their AP Actors after the HTTP version within the links
section of their JRD document. These links must use "type": "application/activity+json"
and "rel": "self"
along with their P2P URL under href
. Make sure to place these P2P links after the HTTP versions to avoid bugs in implementations that check the first Link without looking at the URL scheme.
When attempting to resolve a user from a webfinger style mention like @username@domain.com
, clients should first resolve the Webfinger data using standard methods over HTTP. Clients should then loop through the links
field and search for "type": "application/activity+json"
and "rel": "self"
objects with an href
pointing to a P2P URL.
FEP-fffd set the foundation for linking to alternate versions of content. P2P clients should expand on this by adding links to p2p versions of all AP objecs served via HTTP. Note that the P2P objects should have their id
set to their P2P URL and Must link to the HTTP version of the data. Due to how most AP implementations resolve these links, make sure any HTTP links come first in your URL list so that they don’t accidentally cause loading errors in implementations lacking support for P2P resolving.
When loading a JSON-LD file associated with an Activitypub object (Actor, Note, Collection, etc), clients should check the url
field for objects with type: Link
and rel: Alternate
with the href
property pointing to a URL with the supported P2P protocol.
For accounts that don’t want to set up their own HTTP server, an HTTP gateway may be used. In this case, have your P2P site loadable on a gateway on its own subdomain. For example on ipfs.io
. From there use this domain as your root for all the URLs for HTTP versions of your data. Have your P2P objects link to the HTTP URLs and vise versa.
Actor HTTP version
{
"@context": ["https://www.w3.org/ns/activitystreams", { "@language": "en- CA" }],
"type": "Person",
"id": "https://staticpub.mauve.moe/about.html",
"url": [{
"type": "Link",
"rel": "alternate",
"mediaType": "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"",
"href": "ipns://staticpub.mauve.moe/about-ipns.jsonld"
}],
"outbox": "https://staticpub.mauve.moe/outbox.jsonld",
"inbox": "https://social.distributed.press/v1/@mauve@staticpub.mauve.moe/inbox",
"following": "https://staticpub.mauve.moe/following.jsonld",
"followers": "https://staticpub.mauve.moe/followers.jsonld",
"preferredUsername": "mauve",
"name": "Mauve 👁️",
"summary": "This is an example static site profile. You can find the source code at https://github.com/RangerMauve/staticpub.mauve.moe/",
"icon": [{
"type": "Image",
"mediaType": "image/png",
"name": "Distributed Press logo",
"url": "https://staticpub.mauve.moe/profile.png"
}]
}
Actor IPNS version:
{
"@context": ["https://www.w3.org/ns/activitystreams", { "@language": "en- CA" }],
"type": "Person",
"id": "ipns://staticpub.mauve.moe/about-ipns.jsonld",
"url": [{
"type": "Link",
"rel": "alternate",
"mediaType": "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"",
"href": "https://staticpub.mauve.moe/about.jsonld"
}],
"outbox": "ipns://staticpub.mauve.moe/outbox-ipns.jsonld",
"inbox": "https://social.distributed.press/v1/@mauve@staticpub.mauve.moe/inbox",
"following": "ipns://staticpub.mauve.moe/following-ipns.jsonld",
"followers": "ipns://staticpub.mauve.moe/followers-ipns.jsonld",
"preferredUsername": "mauve",
"name": "Mauve 👁️",
"summary": "This is an example static site profile. You can find the source code at https://github.com/RangerMauve/staticpub.mauve.moe/",
"icon": [{
"type": "Image",
"mediaType": "image/png",
"name": "Distributed Press logo",
"url": "ipns://staticpub.mauve.moe/profile.png"
}]
}
Webfinger doc
{
"subject": "acct:mauve@staticpub.mauve.moe",
"aliases": [
],
"links": [
{
"rel": "http://webfinger.net/rel/profile-page",
"type": "text/html",
"href": "https://staticpub.mauve.moe/about.html"
},
{
"rel": "self",
"type": "application/activity+json",
"href": "https://staticpub.mauve.moe/about.jsonld"
},
{
"rel": "self",
"type": "application/activity+json",
"href": "ipns://staticpub.mauve.moe/about-ipns.jsonld"
}
]
}
CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
To the extent possible under law, the authors of this Fediverse Enhancement Proposal have waived all copyright and related or neighboring rights to this work.