Fediverse Enhancement Proposals
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

9.1 KiB

authors status dateReceived
Diogo Peralta Cordeiro <mail@diogo.site> DRAFT 2022-12-30

FEP-8485: Unbound Actor

This FEP wasn't a result of my individual work but rather of the joint effort in this SocialHub discussion and, prior to that, the discussion in GNU social's IRC/XMPP with rozzin (Joshua Judson Rosen) and someonewithpc (Hugo Sales).


Historically, after the sudden death of a popular instance, one could neither target groups hosted at it anymore nor contact the whole followers collection to let them know of the new instance housing a certain group. If we always have absolute knowledge of the complete followers collection (or good enough), we can automate based on which instance has more local followers which server would become the new house. Another alternative would be to automatically archive the old group and start again from scratch.

This FEP, on the other hand, discusses something very different of automatically moving an actor from one server to a different one. It is about collaboration between different group or organization actors to promote an unified experience between the participants of the linked group actors. We think this may be easier, more flexible, and promote a better UX than only notifying the actor that the house of a certain group has moved, but both solutions would probably achieve similar results in the above use case.

This proposal introduces both an interpretation of a Group following another Group and gs:unbound's link augmentation mechanism. The first makes two groups or organization "act as one" (not exactly, but elaborated afterwards), the second triggers a mechanism that attempts to augment a collection of gs:linksToGroups in an opportunistic manner.

This primarily aims at effectively removing a central point of authority for groups, but offers more than that. With this, @alice@undefinedhackers.net can mention a group named hackers (!hackers) or even address an activity To !hackers@instance.gnusocial.test (C2S) and let her instance's !hackers announce to other instances' !hackers.

Finally, this proposal is general enough to allow a server to simultaneously have !lug@server (without links), !lug-unbound@server (with the greatest links collection it can grow), and !lug-with-some-links@server (with only some links). It doesn't require linked groups to have the same preferredUsername.

If gs:unbound attribute is present, then the aim of the augmentation mechanism described in this document will be to have an ActivityStreams Actor (of type Group) that is independent of the instance(s) that host it.

Notation and Definitions

To keep things simple, sometimes you will see things formatted like Activity{Object}. For example, Create{Note} would be a Create activity containing a Note in the object field. Also, we will focus in Actor of type Group, but nothing should stop from using this for Organization.

  • @nickname@server will be used to refer Actors of type Person or Application.
  • !nickname@server will be used to refer Actors of type Group or Organization.
  • @#!group@server#collection will be used to refer collection collection of !group@server.

The key words MAY, MUST, MUST NOT, SHOULD, and SHOULD NOT are to be interpreted as described in [RFC2119].

ActivityStreams 2.0 requirements for this mechanism

Example Group Actor in this FEP

  "type": "Group",
  "streams": [],
  "@context": [
      "gs": "https://www.gnu.org/software/social/ns#"
      "unbound": {
        "@id": "gs:unbound",
        "@type": "@id"
      "linksToGroups": {
        "@id": "gs:linksToGroups",
        "@type": "@id"
  "id": "https://instance.gnusocial.test/group/hackers",
  "unbound": true,
  "preferredUsername": "hackers",
  "linksToGroups": "https://instance.gnusocial.test/group/hackers/followers/_of_type_group",
  "endpoints": {
    "sharedInbox": "https://instance.gnusocial.test/inbox.json"
  "inbox": "https://instance.gnusocial.test/group/hackers/inbox.json",
  "outbox": "https://instance.gnusocial.test/group/hackers/outbox.json",
  "following": "https://instance.gnusocial.test/group/hackers/subscriptions",
  "followers": "https://instance.gnusocial.test/group/hackers/subscribers",

The linksToGroups attribute points to an OrderedCollection of URIs of actors of type Group that follow this Group. This collection is a subset of the followers collection.

This attribute MUST be present in the actor if it wants to take advantage of the augmentation mechanism described in this document.

  "@context": ["https://www.w3.org/ns/activitystreams"],
  "type": "OrderedCollection",
  "id": "https://instance.gnusocial.test/group/hackers/followers/_of_type_group",
  "orderedItems": [

The collection is ordered lexicographically, making it faster to compare and run set operations with other collections.

Creating a directed link between two group actors is just a regular Follow request between any two actors.

Assume that !hackers@instance.gnusocial.test sends a Follow request to !lug@gnusocial.net.

If gs:unbound: false or not present, then if !lug@gnusocial.net accepts the Follow request, it will Announce{*} entering its inbox to !hackers@instance.gnusocial.test.

If gs:unbound: true, then !lug@gnusocial.net will both accept the Follow request and submit a Follow request of its own to !hackers@instance.gnusocial.test.

If both !hackers@instance.gnusocial.test and !lug@gnusocial.net have added each other to their linksTo, they will act as if they were the same group. If they have equivalent groupLinks collections, then they are essentially fully mirrored groups.

Note that the "Link negotiation" happens between two Group actors (S2S).

Opportunistic linksToGroups Augmentation Mechanism (when gs:unbound is true)

Let's suppose that an Announce from !hackers@instance.gnusocial.test has just been delivered to https://gnusocial.net/inbox.json.

And let's assume the following items in @#!hackers@gnusocial.net#linksToGroups:

  "orderedItems": [

gnusocial.net must send a Follow request the unknown items from @#!hackers@instance.gnusocial.test#linksToGroups actors (excluding itself), so that it may become:

  "orderedItems": [

Obs.: This only happened because !hackers@gnusocial.net had the gs:unbound attribute set to true and !hackers@instance.gnusocial.test a linksToGroups collection.


Please note that the following examples are not independent, each continuously builds on the previous one.

  • !hackers@A: Create{Group}

@#!hackers@A#linksToGroups = []

  • !hackers@B: Create{Group} (S2S)
  • !hackers@B: Follow{!hackers@A} (S2S)

!hackers@A#linksToGroups = [B]

  • !hackers@A: Follow{!hackers@B} (S2S)

!hackers@B#linksToGroups = [A]

  • @alice@B: Create{Note} TO !hackers@B (C2S)
  • !hackers@B: Announce{Note} TO !hackers@[A] (S2S)

2. Opportunistic linksToGroups Augmentation Mechanism

  • !hackers@C: Create{Group}
  • !hackers@C: Follow {!hackers@B}

@#!hackers@B#linksToGroups = [A, C]

  • !hackers@C: Follow{!hackers@A}

  • !hackers@B: Follow{!hackers@C}

  • !hackers@A: Follow{!hackers@C}

@#!hackers@A#linksToGroups = [B, C]

@#!hackers@C#linksToGroups = [A, B]

3. Forwarding from Inbox

  • !hackers@C: Announce{Note} TO !hackers@[B] (S2S)
  • B MUST NOT forward this to other groups. If other groups expect to receive this activity, then they must follow !hackers@C as well.


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.