FEP-8485: Unbound Actor

Before anything, I want to honestly thank you for the time, dedication and attention you’re putting into this. The discussion threads you’re referring to are long and full of different concepts. And you pointing at various of their aspects while explaining truly helps :slight_smile:

I think I ended involving too many different assumptions and concepts in a single proposal, when what I wanted, and wasn’t fully making that step, was to focus in this one aspect that you have just emphasized.

To fill the gap between otherwise disperse groups and provide an experience equivalent to that of only having one group everywhere that is not bounded to any single server.
And this mode of operation should always be optional. It should be possible to only do that with three groups instead of every group, as well as stop or start doing it when wanted.
While always leaving federated administration and/or moderation be its completely separate and not necessarily related thing.

I had that intention but I was implying that a Group ideally would always maintain a relationships collection with as many collaboratesWith as possible.
And that this wouldn’t be possible for an Organization.

But it’s much better to let any actor hold a relationships collection and this proposal should instead focus on how, and probably while using FEP-400e, can we “unbound” a group or an organisation from a single server, when that is indeed desired.

The http://purl.org/vocab/relationship/collaboratesWith I ended selecting is not ideal, as it can be needed to express other things more accurately. The same is true, for the same reason, towards using http://xmlns.com/foaf/0.1/knows.

Maybe then use https://w3id.org/#AgentRelationship instead and thus have the roles specified in the subjects:

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "summary": "!lug@social.undefinedhackers.net is linked with !lug@gnusocial.net",
  "type": "Relationship",
  "subject": {
    "type": "Group",
    "id": "https://social.undefinedhackers.net/group/lug",
    "role": "link"
  },
  "relationship": "https://w3id.org/#AgentRelationship",
  "object": {
    "type": "Group",
    "id": "https://gnusocial.net/group/lug",
    "role": "link"
  }
}

If the relationships collection is going to allow a group to express relationships with other groups (such as part_of), and both let a person follow its feed vs be a member of it, then it may be better to always be
explicit with what relationship is being expressed…

Indeed in the “augumentation mechanism” proposed here, for each new remote group discovered, if they have the gs:unbound attribute set to true, it could:

  • Send a request to be added to their relationships as described in FEP-400e;
  • If authorised, then add the remote !hackers to its own relationships collection.

I think the issue we had with GNU social’s OStatus groups is clear. And, in the Groups implementation discussion, we had vaguely commented about this umbrella method as a possible solution to this issue.

I started a new discussion because I felt that maybe the proposed “Connections augmentation mechanism” was a bit tangent to these discussions. As this is mostly specific to removing the dependency on a single server for a group and not so much about what a Group is and how to interact with it (although both things are necessarily related, as you have just shown).

Anyway, I’m definitely not looking forward to implement an AP extension or convention that only GNU social will understand and, as hopefully is clear, I want to discuss this and end with a good specification (which definitely doesn’t have to be one originally proposed by GS) in hands to implement.

To follow up on this, do you think I should:

  • Move this proposal to one of the ongoing discussions and close this discussion (to avoid duplication);
  • Rename the current discussion to Unbounded Group (to make it more clear and specific);
  • Submit this as a FEP with the corrections you’ve pointed me for further discussion (such as using relationships, and use FEP-400e between groups to update the collections).

Or, if this is not a new concept, or not much different of something already proposed, could you point me to it so we can start implementing it on GNU social? You mentioned that #software:bonfire already has an implementation that uses Vlueflows, is there a spec of how their groups work?

Happy new year! :smiley:

2 Likes

You mentioned that #software:bonfire already has an implementation that uses Vlueflows, is there a spec of how their groups work?

@mayel @ivan would know better about the plans, but afaik Bonfire hasn’t yet implemented Valueflows agent model (although several other parts of VF are implemented). We have talked about it several times, but it isn’t actually simple, because it involves mapping the agent and the actor models, and there’s a bunch of discussion that could happen there, with both short term (less discussion) and longer term (more discussion) possible solutions. (I can say more if you like, but don’t want to hijack this either. :slight_smile: )

2 Likes

We have implemented VF agents but agent relationships are still on the to do list.

Currently in Bonfire we map Person Agents (in the API) to User (in the database) and Organization to SharedUser (which is simply a user identity that multiple accounts can identify as, such as an Organisation or Team where all members are equally admins). Groups and more flexible forms of organisations are on the backlog (both will use our existing implementation of circles and boundaries to manage membership, roles, and permissions, which will then be mapped to VF agent relationships).

For federation, we simply map Person Agents to AS:Person and Organization to AS:Organization.

1 Like

Hi @mayel, thank you for joining this discussion :slight_smile:

What happens when two #software:bonfire servers want to share the same organization?

What happens when two #software:bonfire servers want to share the same organization?

Currently all admin-members of the organisation need to use the same instance.

The question about how to enable cross-instance use of shared actors in a complex one which I brainstormed a while back (during my time working on MoodleNet) regarding groups and shared collections, here are a few of those ideas (which I haven’t revisited since then):

3 Likes

So, I tried to rewrite the original proposal so it is more focused on unbounded groups. Let me hear your thoughts :slight_smile: . In the meantime, recent discussion in GNU social IRC has rewind the idea of automated group move to the one with more local followers when the previous one becomes unreachable for a certain period of time. I still prefer the one presented below as I don’t think it has as many corner cases and shortcomes, but included this concept in the summary and think it is very worthy of raising in discussion.

FEP-b615: Unbounded Actor

Summary

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 actors to promote an unified experience between the participants of the linked group actors. We think this may be easier, flexible, and promotes 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 two concepts: Group Link Relationship, and gs:unbound. The first makes two groups “act as one”, the second triggers a mechanism that attempts to augment that collection of linkedGroups in an opportunistic manner.

This aims at effectively removing a central point of authority for groups, which is a probably useful functionality. With this, @alice@undefinedhackers.net can mention a group named hackers (!hackers) or even address an activity To !hackers@social.undefinedhackers.net (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-unbounded@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.

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.

  • @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.

Other FEP Dependencies

ActivityStreams 2.0 requirements for this mechanism

Example Group Actor in this FEP

{
  "id": "https://social.undefinedhackers.net/group/hackers",
  "type": "Group",
  "gs:unbound": true,
  "preferredUsername": "hackers",
  "linkedGroups": "https://social.undefinedhackers.net/group/hackers/relationships",
  "endpoints": {
    "sharedInbox": "https://social.undefinedhackers.net/inbox.json"
  },
  "inbox": "https://social.undefinedhackers.net/group/hackers/inbox.json",
  "outbox": "https://social.undefinedhackers.net/group/hackers/outbox.json",
  "publicKey": {
    "id": "https://social.undefinedhackers.net/group/hackers#public-key",
    "owner": "https://social.undefinedhackers.net/group/hackers",
    "publicKeyPem": "..."
  }
}

The linkedGroups attribute points to an OrderedCollection of URIs of actors of type Group in other servers that this group has established a “link” agent relationship with.

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

{
  "type": "OrderedCollection",
  "id": "https://social.undefinedhackers.net/group/hackers/relationships/links",
  "orderedItems": [
    "https://gnusocial.net/group/hackers",
    "https://social.diogo.site/group/hackers",
    "https://social.eliseuama.ro/group/hackers",
    "https://social.hsal.es/group/hackers",
    "https://status.hackerposse.com/group/hackers"
  ]
}

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

Example of a Group Link relationship

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "https://social.undefinedhackers.net/group/lug/relationships/links/1",
  "summary": "!lug@social.undefinedhackers.net is linked with !lug@gnusocial.net",
  "type": "Relationship",
  "subject": {
    "type": "Group",
    "id": "https://social.undefinedhackers.net/group/lug",
    "role": "link"
  },
  "relationship": "https://w3id.org/#AgentRelationship",
  "object": {
    "type": "Group",
    "id": "https://gnusocial.net/group/lug",
    "role": "link"
  },
  "target": {
    "type": "Collection",
    "id": "https://social.undefinedhackers.net/group/lug/relationships/links",
    "attributedTo": "https://social.undefinedhackers.net/group/lug"
  }
}

Link request using FEP-400e

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "summary": "!lug@social.undefinedhackers.net wants to link with !lug@gnusocial.net",
  "actor": "https://social.undefinedhackers.net/group/hackers",
  "id": "https://social.undefinedhackers.net/activity/1337",
  "to": "https://www.w3.org/ns/activitystreams#Public",
  "type": "Create",
  "object": "https://social.undefinedhackers.net/group/lug/relationships/links/1",
  "target": "https://gnusocial.net/group/hackers/relationships"
}

The handling of the above activity happens as described in [FEP-400e], Section “Adding an object of a colection”.

Assuming that !hackers@social.undefinedhackers.net and !lug@gnusocial.net have mutually agreeded in adding each other to their links, that will result in !hackers@social.undefinedhackers.net Announcing{*} entering its inbox to !lug@social.gnusocial.net and vice versa. Allowing them to act as if they were the same group. If they have equivalent groupLinks collections, then they are essentially fully mirrored groups.

Note that the “Linking negotiation” happens between two Group actors (S2S).

Example Announce{Note} from a Group and targeted at another Group (S2S)

{
    "@context": [
        "https://www.w3.org/ns/activitystreams"
    ],
    "id": "https://social.undefinedhackers.net/activity/1337",
    "type": "Announce",
    "actor": "https://social.undefinedhackers.net/group/hackers",
    "published": "2021-12-29T13:37:42Z",
    "to": "https://social.undefinedhackers.net/group/hackers/relationships/links",
    "cc": [
        "https://www.w3.org/ns/activitystreams#Public"
    ],
    "object": {
        "id": "https://social.hackersatporto.com/object/note/31337",
        "type": "Note",
        "published": "2021-12-29T13:37:42Z",
        "attributedTo": "https://social.undefinedhackers.net/person/1",
        "to": [
            "https://www.w3.org/ns/activitystreams#Public"
        ],
        "cc": [
            "https://social.hackersatporto.com/index.php/user/1"
        ],
        "content": "<p>hello, <span class=\"h-card\"><a href=\"https://social.undefinedhackers.net/!hackers\" class=\"u-url mention\">!<span>hackers</span></a></span></p>",
        "tag": [
            {
                "type": "Group",
                "name": "!hackers",
                "href": "https://social.undefinedhackers.net/!hackers"
            }
        ]
    },
    "signature": {
        "type": "RsaSignature2017",
        "creator": "https://social.undefinedhackers.net/group/hackers#public-key",
        "created": "2021-12-29T13:37:42Z",
        "signatureValue": "..."
    }
  }
}

The local persons interested in interacting with an unbounded group MAY mention it using !group without the @server bit, the local server in that situation can assume !group@server. !group@server will then reproduce the above Announce activity.

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

Let’s suppose that the Announce above has just been delivered to https://gnusocial.net/inbox.json.

And let’s assume the following items in !hackers@gnusocial.net's linkedGroups collection:

  "orderedItems": [
    "https://loadaverage.org/group/hackers",
    "https://social.diogo.site/group/hackers",
    "https://social.undefinedhackers.net/group/hackers"
  ]

gnusocial.net must include the unknown addressed to actors in its own linkedGroups collection (excluding itself), so that it becomes:

  "orderedItems": [
    "https://loadaverage.org/group/hackers",
    "https://social.diogo.site/group/hackers",
    "https://social.eliseuama.ro/group/hackers",
    "https://social.hsal.es/group/hackers",
    "https://social.undefinedhackers.net/group/hackers",
    "https://status.hackerposse.com/group/hackers"
  ]

For that it should use the described in section [Link request using FEP-400e] for each new group.

Obs.: If in the addressed to groups there’s one that gnusocial.net knows to be dead, the dead actor should be in a temporary list for sufficient time to avoid re-adding it to the connections.

Obs.: This only happened because the actor had the gs:unbound attribute set to true.

Obs.: gnusocial.net should record groups that have previously rejected a Link request.

Examples

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

1. Creating a group with a link

  • !hackers@A: Create{Group}

@#!hackers@A#linkedGroups = []

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

!hackers@B#linkedGroups = [A]

  • !hackers@A: Create{Relationship} TO !hackers@B (S2S)

!hackers@A#linkedGroups = [B]

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

@#!hackers@A#linkedGroups is unchanged as he was the only in TO

2. Opportunistic linkedGroups Augmentation Mechanism

  • !hackers@C: Create{Group}
  • !hackers@C: Create{Relationship} TO !hackers@B

@#!hackers@C#linkedGroups = [B]

  • !hackers@B: Create{Relationship} TO !hackers@C

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

  • @bob@C: Create{Note} TO [@tux@D (S2S), !hackers@C (C2S)]

Let’s assume that D either doesn’t have the group !hackers or has the group but @#!hackers@D#linkedGroups = []

  • D fetches !hackers@C and merges the existing linkedGroups (none) with !hackers@C’s linkedGroups

  • !hackers@D: Create{Relationship} TO !hackers@B (S2S)

@#!hackers@D#linkedGroups = [B]

  • !hackers@B: Create{Relationship} TO !hackers@D (S2S)

@#!hackers@B#linkedGroups = [A, C, D]

3. Forwarding from Inbox

  • !hackers@C: Announce{Note} TO !hackers@[B] (S2S)
  • B will be kind enough to inboxForward this activity TO A
  • A fetches !hackers@C and merges the existing linkedGroups with !hackers@C’s linkedGroups
  • !hackers@A: Create{Relationship} TO !hackers@C (S2S)

@#!hackers@A#linkedGroups = [B, C], was updated due to the proposed augumentation mechanism

  • !hackers@C: Create{Relationship} TO !hackers@A (S2S)

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

This is not the same as the defined in [ActivityPub], Section 7.1.2. As it does not respect bullet points 2 and 3. It instead acts on the premise that there are values in to that the sender doesn’t yet know about but would like to, this is a safe premise when the gs:unbound attribute is set to true.

N.B.: Unless the linkedGroups in the To are exactly the same as the ones the receiving instance already has, a diff will always have to be made. Therefore, noticing that some of ours linkedGroups aren’t going to be notified is a free by-product of augumenting our current linkedGroups.

6 Likes

@diogo wow! It will take me a while to get deep enough into where you are going to be maybe helpful. In the meantime, a couple thoughts. And apologies if I don’t get it yet.

I think the concept of “unbounded actor” is super interesting. You probably don’t want to go there, but the way I’ve thought about it is to also include Person, Group, Organization in other technology ecosystems, besides different installations within the fediverse. But even just considering the fediverse, you are hitting on one reason mapping agent and actor is complex. Conceptually, one actual agent can be represented by many actors, and your Group !hackers is a perfect example. Let’s say theoretically that “one agent” is a foaf:agent. And in addition to social activity, that agent engages in economic activity with other agents. So, it becomes more important that the agent is identified more generally than an actor on one fediverse installation supporting social activity. Even besides the issue of servers going away. At least I think; I could be wrong. But I’m also thinking about your more flat P2P kind of structure, which I need to go through in more detail to make sure I understand how flat it is.

Re. using vf:AgentRelationship for your link relationships, snippet from your comment:

  "subject": {
    "type": "Group",
    "id": "https://social.undefinedhackers.net/group/lug",
    "role": "link"
  },
  "relationship": "https://w3id.org/#AgentRelationship",
  "object": {
    "type": "Group",
    "id": "https://gnusocial.net/group/lug",
    "role": "link"
  },

vf:AgentRelationship works a lot like as:Relationship. The vf:AgentRelationship includes the subject, relationship, object, just like as:Relationship. Like one as:Relationship could be “http://purl.org/vocab/relationship/link” if that existed.

So using the vf role, I think it would look more like this, unless I’m missing something, which is possible!

  "subject": {
    "type": "Group",
    "id": "https://social.undefinedhackers.net/group/lug"
  },
  "relationship":{
    "type": "vf:AgentRelationshipRole",
    "id": "https://example.org/role/link"
  },
  "object": {
    "type": "Group",
    "id": "https://gnusocial.net/group/lug"
  },

Thinking about it, maybe using as:Relationship would be cleaner for you, since it avoids the issue of is agent:actor 1:M or 1:1 ? Except it goes just one direction, if I understand correctly? But that’s solvable.

  "subject": {
    "type": "Group",
    "id": "https://social.undefinedhackers.net/group/lug"
  },
  "relationship":"https://example.org/relationship/link",
  "object": {
    "type": "Group",
    "id": "https://gnusocial.net/group/lug"
  },

(I’m thinking you can’t really put the role inside the subject and object, which are actors.)

2 Likes

Here’s some thoughts, just brainstorming, on this latest version…

Update: I didn’t post this yesterday as I was uncertain on my AP/LD/VF knowledge and asked on fedi, and am delighted to see @lynnfoster’s update, as I was thinking in a similar direction with the relationship property having the range of as:Object. And also defining relationships at Actor level. Adjusting my text to Lynn’s suggestion…


Unbound Groups

Definition (I’d use singular instead of plural):

Unbound Actor: An ActivityStreams Actor that is independent of the instance(s) that host it.

With that name I think the scope of this FEP should relate to any actor-type, not just Group. That also makes it more compatible to Valueflows, which defines relationships between ‘Agents’ on the same level.

The challenge to overcome is that the ActivityPub Object ID ties any object to a domain via an URL, and hence ties to an instance. The Unbound Actor FEP provides a workaround until the time that a better ID mechanism (content addressing, DID’s, … ?) is specified.

In this Group Link Relationship is a specialization of Actor Relationships, and gs:unbound an indicator of the Unbound Actor workaround being used. So I wonder if all this couldn’t be generalised to define these actor relationships.

Valueflows

Valueflows writes the following on Agent Relationships (see also: example):

click to expand Valueflows Agent Relationships documentation and ontology diagram ...

Agent relationships have many nuances, thus VF provides the ability to define one’s own kinds of relationships. For example people might “participate” with an organization by means of agreeing to terms and conditions. Or people might have more active “membership” in a group or organization. Or people might consider themselves members but want a more independently flavored term such as “affiliates”.

A relationship can be direct, like “steward”, or more like a role, for example “grower” or “harvester” for a food network.

Relationships can also include roles like “sub-organization” or “trading partner”.

There are a number of useful Properties in existing vocabularies that can be used. Or people can create their own as needed.

Relationships have direction: For example, in “Michael is a member of Enspiral”, Michael is the subject and Enspiral is the object. In this case the inverse is also valid, “Enspiral has member Michael”. In VF, we consider this to be one relationship. One directional relationships like “follows” are also supported.

Relationships can be in a scope (or not): For example, “Kathy is mentor of Sam, in the scope of Enspiral.”

@lynnfoster here on SocialHub provided the following diagram of the ontology that Valueflows uses for that:

Valueflows Agent Relationships ontology

  • An actor can have zero or more relationships
  • Some relationship types are commonly understood (standardized)
  • Other relationship types can be custom defined (app-specific)

One thing I wonder about in the Valueflows specification of AgentRelationship… it looks like, by using roleLabel and inverseRoleLabel in AgentRelationshipRole, you lose the ability to define standardized Linked Data relationships. The only supported relationship is a Valueflows relationship. If you consider for instance the FOAF, Relationship, GoodRelations or Schema.org or many other ontologies, you want to standardize from widely adopted semantics defined there.

Actor Relationships

Though it is a bit vaguely defined in ActivityPub the streams property can contain “A list of supplementary Collections which may be of interest.”. And in @mayel’s doc for #software:bonfire this is also used. Then the Group may be:

{
  "id": "https://social.undefinedhackers.net/group/hackers",
  "type": "Group",
  "preferredUsername": "hackers",
  "streams": {
    "relationships": "https://social.undefinedhackers.net/group/hackers/relationships"
  },
  "endpoints": {
    "sharedInbox": "https://social.undefinedhackers.net/inbox.json"
  },
  "inbox": "https://social.undefinedhackers.net/group/hackers/inbox.json",
  "outbox": "https://social.undefinedhackers.net/group/hackers/outbox.json",
  "publicKey": {
    "id": "https://social.undefinedhackers.net/group/hackers#public-key",
    "owner": "https://social.undefinedhackers.net/group/hackers",
    "publicKeyPem": "..."
  }
}

(Note: If I look at the ActivityStreams definition of Relationship, then isn’t Example 47 invalid? The value of relationship property cannot be "http://purl.org/vocab/relationship/acquaintanceOf" as the range is as:Object. But that may be my limited LD understanding shining through.)

Here I follow up from @lynnfoster. But relationship should be an as:Object first. Idk, but maybe to express the relationship type the url property can be used. And maybe to express RoleBehavior (grouping of relationships into categories) the context property may be used. The spec says about “context”:

The notion of “context” used is intentionally vague. The intended function is to serve as a means of grouping objects and activities that share a common originating context or purpose. An example could be all activities relating to a common project or event.

With that, when dereferencing the relationships collection, something like this is returned:

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "https://social.undefinedhackers.net/group/hackers/relationships",
  "type": "Collection",
  "items": [
    {
      "id": "https://social.undefinedhackers.net/group/hackers/relationships/1",
      "summary": "!lhackers@social.undefinedhackers.net and !lug@gnusocial.net are the same",
      "type": "Relationship",
      "subject": {
        "type": "Group",
        "id": "https://social.undefinedhackers.net/group/hackers"
      },
      "relationship": {
        "type": ["Object", "vf:AgentRelationshipRole"],
        "id": "https://social.undefinedhackers.net/groups/role/sameAs",
        "url": "https://schema.org/sameAs",
        "context": "https://social.undefinedhackers.net/nodeinfo/capability/UnboundGroups"
      },
      "object": {
        "type": "Group",
        "id": "https://gnusocial.net/group/lug"
      }
    }
  ]
}

In other words the Unbound Group that is hosted across 2 instances is indicated with a “sameAs” relationship, and the “context” makes clear how we should interpret the relationship’s meaning (UnboundGroup capability).

I left out the target here, because I’d need to learn more about this before doing so. In ActivityStreams 5.2.1 Modeling friends requests is an interesting flow to look at, I think.

This way an arbitrary number of different relationships could be defined between actors. The “context” as RoleBehavior might serve as a filter to only retrieve the ones that are interesting.

In the regular Groups implementations we have right now the “member_of” relationship is expressed via the followers collection I think. This may continue to be so, but only for a single relationship type i.e. “follows”. The Follow activity is defined in ActivityStreams as:

Indicates that the actor is “following” the object . Following is defined in the sense typically used within Social systems in which the actor is interested in any activity performed by or on the object. The target and origin typically have no defined meaning.

That also indicates a single type of relationship (though to me it seems to be different in meaning than a “member of” relationship. Someone can follow a Group without being a member. But it is as it is).

Standardized relationship types

In the example above there would be a need to standardize a set of relationship types and maybe contexts to be universally understood across the Fediverse. Just brainstorming, but e.g.

context (capability) relationship types
Unbound Groups https://schema.org/sameAs
Organization Structure http://purl.org/vocab/relationship/childOf
http://purl.org/vocab/relationship/parentOf
http://purl.org/vocab/relationship/siblingOf
Offering http://purl.org/goodrelations/v1#offers
http://purl.org/goodrelations/v1#seeks

Etcetera…

Minor remarks

In @mayel’s document there is some terminology that seems to indicate a specialization of Groups, in other words app/implementation-specific. Probably perfectly fine, because it was created in that context, I think. But want to mention anyway…

  • “User creates Group” → “Person creates Group” (I personally try to avoid “user” altogether)
  • “Moderator” → yes, if you have moderators, but the notion of that is app-specific
  • “The context field contains the parent Group’s id/uri” → a parent relationship?

I did not look into SharedCollections. I know too little about the low-level stuff needed still. But may spend more time on this :hugs:

2 Likes

Yes, good point, and I really like the direction you’re going in general.

Although I can’t just speak for VF, I would personally be happy to use a more universal agent model instead of the one we have, which is partly foaf, partly org, but all vf in the relationship area because we couldn’t find what we needed, and weren’t thinking outside of the vf economic model at that time. Now that we’ve been working with Bonfire and others, seeing the necessary integration of social and economic, etc., I picture this whole area (people, orgs, groups, relationships) being its own vocabulary, which could be used by other vocabularies, instead of each one having their own version. And maybe just some more flexible range definitions or some cross-vocab owl:sameAs kind of things would do a lot, but I don’t have enough rdf coding experience to know what that means for devs. But is that more in the spirit of the web?

2 Likes

Hi Everyone,

I wanted to add to this discussion because I’m starting work on a project that’s focused on communities, and have been looking at the implementation of distributed communities with ActivityPub. So I’m finding everything in this thread very interesting :slight_smile:

I like to consider a distributed community as being something ephemeral and requiring minimal management or intervention - it should be easy to connect to in the same way that (originally) public Internet exchange points are - you specify where you need to go and you’re connected. And you should be able to connect to wherever and whatever you want to. It shouldn’t be necessary to have to manage peering with other services.

So when I started looking at it this way and in the context of the ActivityPub specification, isn’t this what the context field is for? For example, something like this:

{
  "type": "Note",
  "to": "https://www.w3.org/ns/activitystreams#Public",
  "name": "My post to a community",
  "content": "Hi world!",
  "context": [
    "https://yuforia.com/topic/anything",
    {
      "type": "Topic",
      "name": "anything"
    }
  ]
}

Anyway, just throwing my $0.02 in, mostly just want to get involved and figure this out. I’m fairly new to ActivityPub, but not forums and communities.

Yes, I think you’re correct.

Yes, I was trying to generalize to any actor. But then focused on groups throughout the rest of the document because it becomes easier of understanding the aim of the proposal. For Persons I don’t think it makes a lot of sense to have the proposed relationship, I guess it is essentially for either Groups and Organizations. I’m not considering Service as I don’t know much about it yet.

The example link isn’t available :confused:

I was considering this Link relationship as something Directed. I.e., Group A asks whether Group B wants it to Announce everything in its inbox to it, and vice versa.
To try and give an example where this could be useful: Group B could be a closed debating group that receives activities from other groups and debates it internally without polluting the other groups. People could still Follow Group B.

For that reason, I’m not sure https://schema.org/sameAs expresses exactly what we want. Also because, even if Group A and Group B are linked, they still are different actors that can have a different collection of relationships and most definitely a different one of followers.

I like that idea of using the context.
When I suggested using NodeInfo I wasn’t thinking on it like this… Just as a way of querying whether a server supported something or not. I’m not sure if you can use it like this.

For communities, if you haven’t already, it may be helpful to have a look at #software:lemmy’s implementation and the ongoing discussion in standardizing on a common community extension.

With regards to your use of context, I think that would be semantically correct. But I think that what is usually done is to have the topic post being a “root note/page” and the follow ups being replies (inReplyTo). In OStatus there is the conversation URI, which expresses the same that I think you are trying to.

I don’t know enough about rdf to come with something here either, but was searching for alternatives that can potentially model this or at the very least bring new ideas/perspectives. And have found AgRelOn, an Agent Relationship Ontology and the Agreements ontology . They are tangent as their usage domain is fairly different of ours.

I was unable to find a LOV that models this directed collaboration/knowledge relationship/agreement between actors/agents.

@lynnfoster and @aschrijver: I don’t really like AgentRelationshipRole requires an ID… I was playing in JSON-LD Playground and came up with this:

{
	"@context": {
		"@vocab": "https://www.w3.org/ns/activitystreams",
		"vf": "https://w3id.org/valueflows#"
	},
	"summary": "!hackers@social.undefinedhackers.net links to !lug@gnusocial.net",
	"id": "https://social.undefinedhackers.net/group/hackers/relationships/123",
	"type": "Relationship",
	"subject": "https://social.undefinedhackers.net/group/hackers",
	"relationship": "vf:AgentRelationshipRole",
	"object": "https://gnusocial.net/group/lug",
	"context": {
		"vf:roleLabel": "has a link to",
		"vf:inverseRoleLabel": "has a link from"
	}
}

The id of this AgentRelationshipRole would thus expressed by the Relationship Activity’s id… Would this work instead or is it too much of a stretch?

Experimenting with that:

{
	"@context": "https://www.w3.org/ns/activitystreams",
	"id": "https://social.undefinedhackers.net/activity/1337",
	"summary": "!hackers@social.undefinedhackers.net offered to link to !lug@gnusocial.net",
	"type": "Offer",
	"actor": "https://social.undefinedhackers.net/group/hackers",
	"object": "https://social.undefinedhackers.net/group/hackers/relationships/123",
	"target": "https://gnusocial.net/group/lug/relationships"
}

Hi Diogo,

Thanks, I’ll definitely check out Lemmy’s implementation.

Using the word topic might be confusing terminology since it’s used by popular forum systems to denote a thread. I’d like to use topic to refer to the subject matter that’s being discussed and not an individual forum thread.

The reason that I was thinking context might be the right field is based on what I read in ActivityStreams:

The notion of “context” used is intentionally vague. The intended function is to serve as a means of grouping objects and activities that share a common originating context or purpose. An example could be all activities relating to a common project or event.

In the case of communities and forums, I would consider topic to be subject matter:

{
  "type": "Topic",
  "id": "https://activitypub-server.com/topic/programming",
  "name": "Programming",
  "summary": "All discussions centered on programming"
}

And individual services (ones residing on a server) would then specify that they may accept content based on that topic:

{
  "type": "Service",
  "id": "https://yuforia.com/forum/programming",
  "name": "Talk about programming and system architecture",
  "context": [
    "https://activitypub-server.com/topic/programming",
    "https://activitypub-server.com/topic/system-architecture"
  ]
}

As I’m working on my implementation, I’m trying to stick as closely as possible to what ActivityPub already provides since the way a social profile works is very similar to how a forum works. However it may be completely unavoidable (or even advisable) to give community discussions their own AP terminology.

Oh, well, in the spirit of Activity Vocabulary, I think I would instead use a “TopicTag” for that.

Note that Groups are fundamentally different from tags tho (or lists/collections, for that matter). Rozzin explains very clearly the differences in this #software:andstatus Groups issue: Add Group support · Issue #248 · andstatus/andstatus · GitHub

This proposal doesn’t want to change this “mailing list nature” of Groups. #software:gnu-social groups in v3 will be the same as they were in GS version 2. We are first bringing it to ActivityPub federation (Announcing what arrives its inbox to its followers collection), and only after adding this optional extra functionality.

The proposed functionality serves two distinct purposes:

  • Allow a Group Actor A to state that would like announcing to a different Group Actor B (it’s resembles A telling B: would you like to follow me? (Offer{Follow}), but different of that) - either because the group owner did it or because a setting such as gs:unbound is enabled;
  • gs:unbound: Opportunistically maximize these relationships.

With gs:unbound, an aim would then be to have this more resilient Group that despite a server going offline, still federates properly because it is announcing to all known concerned group actors (which then announce their inbox news to its person followers).

Such topic tag could look like this:

{
  "@context": "https://www.w3.org/ns/activitystreams",
 "actor":"http://example.org/actor/sally",
 "to": ["https://chatty.example/ben/"],
  "type": "Note",
  "content": "hello, world.",
  "tag": [
    {
      "type":"TopicTag",
      "id": "http://example.org/topics/gnu",
      "name": "GNU"
    }
  ]
}

If the receiver doesn’t accept a certain TopicTag, it could then identify the forbidden tag from its name property and reject (or only accept a specific set of tags instead).

Tags (as well as your suggestion of using context) is already dissociated from a specific server, which I think is part of what you want. I wouldn’t use context for topics due to two reasons:

  • It states “…grouping objects or activities that share a common…” - I don’t think you’re grouping anything here?;
  • I think a tag expresses this better.

With tags you can also scale it with tags collections where an actor could add a tag to your note (an ideia GNU social has in its backlog to think and maybe implement), etc. :slight_smile:

Oh I didn’t think of the tags field - that makes a lot of sense and you are correct in that I’m looking for something that can represent a community that is dissociated from a specific server. I was thinking that Topic would be an Actor as well and thus have followers - which would be a method of discovery between servers. This is still a centralized model, but eventually (once enough participants in the network reach a critical mass) discovery could be untethered from the centralized Topic authority.

I think that the context field is underutilized and is a good fit for distributing content across servers. One of things I am struggling with is whether Topic is a good representation of a distributed community or if there should be something like a Community resource for such a thing.

Initially I thought Topic was better just because it’s a more ephemeral concept, so when it comes to distributed content, that just seems like a natural fit.

A lot of it comes down to semantics but a Community can represent a number of individual subject topics so it seems like an inversion of the Topics model. That may work well with topic tags representing subject matter and a Community resource representing a distributed model across servers.

There’s no reason that TopicTags couldn’t be an Actor and that could have the associated followers along with it. I do get the impression that AP may need a resource type that represents subject matter.

4 posts were split to a new topic: Actor Mentions

So, we rewrote this FEP a little until it became FEP-2100: Unbound Group and Organization.

It was implemented onto GNU social with a plugin.

A relevant aspect concerning activities delivered by groups is that a Follow from a Group is not wrapped inside an Announce activity.

3 Likes

Hi @diogo,

Recent automation uncovered that this never got a tracking issue and we never finalized it. Here’s the tracking issue: #36 - [TRACKING] FEP-2100: Unbound Group and Organization - fep - Codeberg.org

My questions for you are, do you feel there’s any need for renewed discussion and would you like it to be finalized? I put dates from today as a default since four months from March was July. It became eligible for FINAL in May. I’m happy to share out the thread once more if you want to give it a couple weeks for reexamination by interested parties.

1 Like

A post was merged into an existing topic: FEP-2100: Unbound Group and Organization