warning: what follows is a draft of a draft
slug: “3416”
authors: a a@trwnh.com
status: DRAFT
dateReceived: 2024-04-03
FEP-3416: Relay Actors
Summary
This FEP aims to document different types of relay actors across the fediverse, as well as the mechanisms that power them. Current behavior of existing relay software can be very fragile; as a result, this FEP will primarily aim to define standard behaviors for how relay actors ought to operate, rather than detailing the intricate idiosyncracies of each existing implementation.
Introduction
(This section is non-normative.)
[Mastodon] added support for “federation relays” in 2018, where a “federation relay” was defined as an actor to which you can send public posts, and from which you receive other public posts. This was done to address the rise of “follow-bots”, which were unmonitored accounts that followed other accounts solely for the purpose of populating Mastodon’s “federated timeline” feature. [Pleroma] added support for “message relays” in 2018 as well, with largely similar logic, except that Mastodon asks for the inbox endpoint’s IRI, and Pleroma asks for the actor document’s IRI (and then derives the inbox from there).
Current implementations of the relay actor are as follows:
- pub-relay
- ActivityRelay
- aode-relay
- Pleroma; every instance of Pleroma can optionally serve as a relay for all local public posts, if the admin enables a particular setting
Current implementation notes
(This section is non-normative.)
pub-relay
JSON-LD terms
In general, pub-relay does not process JSON-LD on consumption. It expects the following terms verbatim, taken from the Security Vocabulary (https://web-payments.org/vocabs/security#
at the time of implementation, later mostly superseded by https://w3id.org/security#
):
Key
publicKeyPem
owner
publicKey
signature
It also normatively uses the following terms from the ActivityStreams context document:
endpoints
inbox
type
preferredUsername
name
In other words, it implicitly expects compaction against the following context or equivalent (e.g. using the older Web Payments namespace):
{
"@context": [
"https://www.w3.org/ns/activitystreams",
{
"Key": "https://w3id.org/security#Key",
"publicKeyPem": "https://w3id.org/security#publicKeyPem",
"signature": "https://w3id.org/security#signature",
"owner": {
"@id": "https://w3id.org/security#owner",
"@type": "@id"
},
"publicKey": {
"@id": "https://w3id.org/security#publicKey",
"@type": "@id"
}
}
]
}
When producing activities, pub-relay will use the standard normative https://www.w3.org/ns/activitystreams
context document, as well as the https://w3id.org/security/v1
context document in order to properly namespace the publicKey
, owner
, and publicKeyPem
properties. (Key
is unused during production of AS2 documents.)
HTTP Signatures
pub-relay requires and will verify HTTP Signatures according to draft-cavage-06. It checks for the following conditions:
- The
keyId
is present
- The
signature
parameter is present
- An actor can be extracted from
keyId
, either by resolving it directly, or if it resolves to a Key
, by resolving the owner
The actor
of the activity will be ignored completely, in favor of the actor extracted from the HTTP Signature’s keyId
. The resolved actor will be cached for 2 days.
The signature verification method supports the following key parameters:
- SHA256 digests, base64-encoded
- RSA public keys
Subscribing to the pub-relay actor
pub-relay considers the following activities valid for subscribing to the relay actor:
- The
type
array includes Follow
Upon receiving a valid subscription activity,
pub-relay will check for the following conditions:
- The
inbox
of the Follow actor (extracted from the HTTP Signature’s keyId
, ignoring any explicitly defined actor
of the activity) is a valid URI
- The
object.id
exactly matches https://www.w3.org/ns/activitystreams#Public
Note that pub-relay will NOT handle follows for any other object, including for any of the following:
as:Public
Public
- the relay actor’s
id
Pub-relay will then save the subscription along with the actor’s domain, the actor’s inbox
, the Follow activity’s id
, and the actor’s id
. An Accept
activity will be generated by the relay actor and wrapping a reconstructed Follow
activity, containing the actor.id
, Follow.id
, and with the object
set to the relay actor. Finally, pub-relay will respond with an HTTP 202 Accepted, and the text “OK”.
Unsubscribing to the pub-relay actor
pub-relay considers the following activities valid for unsubscribing from the relay actor:
- The
type
array includes Undo
and the object
is an embedded object whose type
array includes Follow
; alternatively, the type
array includes Reject
Upon receiving a valid unsubscription activity, pub-relay will unsubscribe the actor’s domain. Finally, pub-relay will respond with an HTTP 202 Accepted, and the text “OK”.
Forwarding rebroadcastable activities
pub-relay considers the following activities valid for rebroadcast (inbox forwarding):
- The
type
arrays do not match any of the following patterns:
Follow
Undo Follow
or Reject
Accept
- The activity was
published
within the last 30 minutes (otherwise, pub-relay will skip the “old” activity with an HTTP 200)
- The activity does not have an
id
that was already previously processed (otherwise, pub-relay will skip the “already seen” activity with an HTTP 200)
to
or cc
includes https://www.w3.org/ns/activitystreams
(pub-relay will not recognize as:Public
or Public
)
- The
type
array includes any of the following:
Update
Delete
Undo
Move
Like
Add
Remove
Create
(if signature
is present)
Announce
(if signature
is present)
Upon receiving an activity that is valid for rebroadcast, pub-relay will deliver the request body as-is to all relay subscribers. Finally, pub-relay will respond with an HTTP 202 Accepted, and the text “OK”.
Relaying relayable objects
pub-relay considers the following activities valid for relay (Announcing an object):
- The
type
arrays do not match any of the following patterns:
Follow
Undo Follow
or Reject
Accept
- The activity was
published
within the last 30 minutes (otherwise, pub-relay will skip the “old” activity with an HTTP 200)
- The activity does not have an
id
that was already previously processed (otherwise, pub-relay will skip the “already seen” activity with an HTTP 200)
- The activity is not valid for rebroadcast
- The
type
array includes any of the following:
Upon receiving an activity that is valid for relay, pub-relay will construct an Announce
activity wrapping the activity’s object.id
. Finally, pub-relay will respond with an HTTP 202 Accepted, and the text “OK”.
ActivityRelay
aode-relay
Pleroma
Standardization
Subscribing to a relay
Subscribing to a relay is done with the standard Follow → Accept Follow flow described in [ActivityPub]. Use of https://www.w3.org/ns/activitystreams#Public
as the object
of a Follow
SHOULD be deprecated. The actor
of the activity SHOULD be used instead of extracting the actor from the HTTP Signature, subject to a same-origin policy check.
Extending the relay model
Alternative approaches
(This section is non-normative.)
[FEP-1b12] works similarly in that it wraps received messages in Announce, but differs from the classical relay actor in certain ways:
- imposing additional restrictions, such as mandating a type of
Group
and the use of inReplyTo
- leaving moderation as optional instead of required
- wrapping the activities with an
Announce
as-is, rather than Announcing the object
of the Create/Announce
Guppe also works similarly in that it Announces anything sent to it, except that it operates at a user level instead of a service level.
References
Copyright
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.