Feature set inconsistency and Feature Discoverability
The Sales pitch
Different platforms on the fediverse have a different feature set, which can lead to problems. For example, when someone from mastodon makes a post, I can emoji-react to it, but they wont see it. This is one example, but there are many. This leads to a bad UX because people can't easily be sure whether their actions will me noticed by the relevant people. This problem also leads to an incentive for implementations to implement an ever growing feature set, which is not sustainable in the long run.
One solution I see to this, is feature discoverability. Let's take the Emoji-react example again; We could imagine instances somehow advertising what features they do or don't support. That way Pleroma could let their clients know about what features are supported and the clients could present that information in a user-friendly way. (E.g. by giving the emoji-react icon a "dissabled" state when the target doesn't support this feature.)
Known ways in the wild
There are two examples of how features are advertised that I know of
- On the individual object (both examples are actors)
- Pleroma has this for
capabilities.acceptsChatMessages
(but we don't actually use it) - Smithereen has this for
FriendRequests
- Pleroma has this for
- Instance wide we have Nodeinfo's
metadata.features
I added some examples below[1]. See also https://socialhub.activitypub.rocks/t/service-capability-discovery/630.
Practical
For Object specific things, advertising should be done by adding the relevant info as part of the object. Maybe the feature set should be a collection? (Y'know, since it's AP and all.)
A first idea if we want to keep track of instance wide features: We already have a table instances
. We could add a new json column there with relevant nodeinfo. To keep it up to date we could fetch the Nodeinfo from newly discovered instances and then at regular intervals.
When a front-end fetches a post or account, we could make the supported feature list part of the json-object we return. This list is first loaded from the list on the instance level and then overloaded with the list of the object.
Maybe there are cases where a certain feature is relevant to e.g. a Note, but should be defined on the Actor level? In that case the overloading of the features list could be instance-actor-object.
We could wonder if such a layered way is needed. A Note whose instance can't handle emoji reactions now, may be able to handle them in the future. If we only pass the list in objects over AP and ignore the whole Nodeinfo part, then the older objects will show an outdated feature list. This may lead to some unexpected cases when someone interacts with an older object, but may be worth the trade-off to reduce complexity?
If a certain feature isn't advertised, we have to make our own assumptions. We can also let the front-end decide how to deal with missing information.
When doing this, we should share it in https://socialhub.activitypub.rocks/t/service-capability-discovery/630 so that other implementers know about it and can provide feedback.
Beyond
Even though this solves the problem of knowing what interactions can be done with other people, there is still a problem of how you want people to be able to interact with you. For example, they may want to invite you to a party, and you may want them to have that ability, but your instances software doesn't understand events. A work-around is to make an account on a different instance and tell people to invite that account, but that's not really a good UX either. This problem also leads to an incentive for implementations to implement an ever growing feature set (which is a problem we wanted to address here as well).
A solution to that problem could be nomadic identities, where one person can have multiple actors spread over multiple instances. The actor(s) who does have the needed feature, will receive the invitation. That problem is somewhat related, but otherwise completely out of scope for this feature/discussion.
References
[1]
# Pleroma
curl -s 'https://ilja.space/users/ilja' -H 'Content-Type: application/json; charset=utf-8' -H 'Accept: application/ld+json; profile="https://www.w3.org/ns/activitystreams"' | python3 -m json.tool
{
"capabilities": {
"acceptsChatMessages": true
},
...
}
# Smithereen
curl -s 'https://friends.grishka.me/grishka' -H 'Content-Type: application/json; charset=utf-8' -H 'Accept: application/ld+json; profile="https://www.w3.org/ns/activitystreams"' | python3 -m json.tool
{
"supportsFriendRequests": true,
...
}
# Nodeinfo
curl -s 'https://ilja.space/nodeinfo/2.1.json' | python3 -m json.tool
{
"metadata": {
"features": [
"pleroma_api",
"mastodon_api",
"mastodon_api_streaming",
"polls",
"pleroma_explicit_addressing",
"shareable_emoji_packs",
"multifetch",
"pleroma:api/v1/notifications:include_types_filter",
"chat",
"shout",
"relay",
"pleroma_emoji_reactions",
"pleroma_chat_messages"
],
...
},
...
}