Branching out of FEP-2677: Identifying the Application Actor
@stevebate brings up good points that deserve some effort at clarification and definition. in this topic, i will explore some of them.
prior art
xmpp
takeaway 1: activitypub servers communicate with an inbox endpoint, but xmpp communicate directly with other servers
xmpp doesn’t have a similar concept besides the use of “IQ stanzas” to query for information directly from the other server’s connection. this is used for XEPs such as XEP-0030: Service Discovery or XEP-0157: Contact Addresses for XMPP Services which look something like this:
<iq from='juliet@capulet.com/chamber'
to='shakespeare.lit'
id='disco1'
type='get'>
<query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
note that to
is just the fqdn of the xmpp server, so there is no real discovery needed to get to this point. the server is always represented by its own fqdn. this is similar to the proposal to just always put the instance actor at the root url of the instance. but more saliently, xmpp establishes streams for c2s and s2s in such a way that it is somewhat analogous to having all communication happen between servers or “server actors”.
from rfc 6120 section 2.5 “distributed network of clients and servers”:
end-to-end communication in XMPP is logically peer-to-
peer but physically client-to-server-to-server-to-client, as
illustrated in the following diagram.
example.net <--------------> im.example.com
^ ^
| |
v v
romeo@example.net juliet@im.example.com
from 4.3.6 “determination of addresses”:
For server-to-server communication, the initiating server’s bare JID (
<domainpart>
) MUST be the authorization identity
4.7.1 “from” / 4.7.2 “to”
For initial stream headers in server-to-server communication, the
'from' attribute is one of the configured FQDNs of the server, i.e.,
a JID of the form <domainpart>. The initiating server might have
more than one XMPP identity, e.g., in the case of a server that
provides virtual hosting, so it will need to choose an identity that
is associated with this output stream (e.g., based on the 'to'
attribute of the stanza that triggered the stream negotiation
attempt). Because a server is a "public entity" on the XMPP network,
it MUST include the 'from' attribute after the confidentiality and
integrity of the stream are protected via TLS or an equivalent
security layer.
I: <?xml version='1.0'?>
<stream:stream
from='example.net'
to='im.example.com'
version='1.0'
xml:lang='en'
xmlns='jabber:server'
xmlns:stream='http://etherx.jabber.org/streams'>
For response stream headers in server-to-server communication, the
receiving entity MUST include a 'to' attribute in the response stream
header and MUST set its value to the domainpart specified in the
'from' attribute of the initial stream header.
R: <?xml version='1.0'?>
<stream:stream
from='im.example.com'
id='g4qSvGvBxJ+xeAd7QKezOQJFFlw='
to='example.net'
version='1.0'
xml:lang='en'
xmlns='jabber:server'
xmlns:stream='http://etherx.jabber.org/streams'>
so we see a very clear pattern here where servers communicate directly with each other and address each other directly. activitypub works a bit differently in that each actor has their own inbox
endpoint. the addressing within activitypub is more-or-less purely informational, because the real delivery happens via that POST to inbox. if you receive the activity, it doesn’t matter whether or not you are actually addressed in the activity. (this allows bto/bcc to work, also.)
so clearly, we need to rethink this for activitypub. let’s start by trying to define which communications should happen directly.
mastodon
takeaway 2: we mostly want something to receive reports and maybe blocks
mastodon in particular made the decision to start federating out Flag
and Block
activities, which are used to represent reports and blocks. however, the addressing is a bit wonky because of sharedInbox
. mastodon just blindly assumes that it should POST to the sharedInbox if found… and otherwise it just POSTs directly to the reported or blocked user! this is generally undesirable and not-useful behavior. what is expected is that there is some separation between a “user” and their “instance”, although the server is implicitly expected to not differentiate significantly between a personal inbox and a shared inbox.
takeaway 3: maybe sharedInbox is enough, maybe it isn’t
so, is the sharedInbox “enough” to determine that the user is on an “instance”? well, if you just want to receive activities, then “maybe”. if you want to do anything else involving actors, then maybe not! maybe we need the concept of an “instance actor” to be more explicit and to allow for communications like any other actor.
takeaway 4: what happens if we make/encounter an “instance actor”? we can follow it.
having an actor implies we can send it activities and we can receive activities from it, and most importantly we can follow it. now that we have a reference to an actor and not just an inbox endpoint (via sharedInbox), this actor can be the object
of a Follow
.
theorycrafting
we established that:
- other protocols like xmpp make s2s communication happen directly, without inboxes
- the most likely use for an instance actor is to send and receive service-related activities like Flag or Block
- the way this is currently done is sort of through sharedInbox
- having an explicit instance actor most importantly allows us to Follow it
so here’s some possible use cases of what we can do with such an instance actor
- sending Flag and Block to the instance actor via an explicit inbox instead of via sharedInbox may not be too different, but it is at least a more pure model for interaction
- the instance actor may be followed to receive whatever the instance actor deems interesting enough to send out
- perhaps it sends out notifications of local actions taken
- perhaps it allows for admins to post regular statuses or notes or messages or whatever
- this could be used for announcements
- this could also be used for messaging other admin/mod teams directly as a sort of inter-instance mail system
- perhaps it relays or Announces public posts from that instance
now we see we’re mostly missing a way for a follower to signal interest in arbitrary subsets of activities, which i have talked about previously in the form of followable Collections that you make into actors and then expose via streams
. of course it could be some other mechanism, but eh.
some other concerns: can users follow instance actors? if so, aren’t they opting in to inter-instance communication on behalf of their admins? this implies that it would be best practice to not deliver administrative actions to the instance actor’s followers, at least.
discovering such an instance actor
if this is to be done, then it makes the most sense to use endpoints
for this. endpoints are typically server-wide, and the mere presence of an endpoint like endpoints.instanceActor
(name pending) should be enough to at least semantically guarantee that the server you are communicating with a) is an instance, b) can be communicated with directly / without involving users
{
"@context": {
"instanceActor": {
"@id": "https://...",
"@type": "@id"
}
}
}
conclusion
i left this open-ended because i’m not fully sure what the boundaries are for this “instance actor” concept. personally i don’t even like the idea of “instances” at all or that much, but i recognize that it’s a popular model for the sake of convenience
we might minimally say something like this for the normative requirements:
- if
endpoints.instanceActor
is present on an actor, you SHOULD send related Flag and Block to it- you MAY send them to
endpoints.sharedInbox
if present (?) - you SHOULD NOT send Flag and Block directly to the actor (?? i am unsure of this one because the semantics of Flag and Block are implementation-specific)
- you MAY send them to