Groups implementation

How we’re doing groups in lemmy, is that a user sends messages to a group, then the group announces (acting as a forward) to all other members of that group, on all the various other instances. Their shared inbox then receives the announce.

What if the owner leaved the group?

Could the group still survive?

Hi, just to share some thoughts, at GNU social, for v3, we’re planning on adding a logic layer of umbrella groups that we’ve elaborated a bit here: https://notabug.org/diogo/gnu-social/issues/186 . We haven’t got to a lot of implementation details yet as we’ve been busy with other priorities. But it seems that the rest of the world is already having fun with implementing Groups in ActivityPub and, since we really aren’t available enough to get into these implementation discussions at the moment, just wanted to share this here so that the others could start deliberating a bit about it as well. TL;DR: GNU social may need a property in the group actor indicating whether it is meant to be under an umbrella (as described in the linked issue) or not. Thanks. If someone else has already thought about this or came up with a better solution, sorry for bothering, we will eventually read about it when with time to implement this.

Seems there are a lot of conflicting implementations. Zap has a conflicting implementation as well which grew from the way we initially tried to do groups across multiple protocols such as ActivityPub and OStatus and Diaspora - none of which gave much thought how to implement groups in their initial specs . These earlier efforts are still visible in Friendica and Hubzilla and have issues with privacy conflicts.

A group in Zap looks just like any other actor except the type is ‘Group’. You can join a group with either a normal follow/group or use a join/group activity if you prefer. Groups, like Actors - can have either public, restricted, or private scope.

Posting to a group is done either via a wall-to-wall post or a direct message to the group. These are re-written as normal posts from the group containing an embedded reshare activity (embedded as html, with some care taken to work around Mastodon’s aggressive HTML filtering). We couldn’t use Announce because of privacy conflicts (*) and resultant complex delivery chains; as well as the fact that projects like Pleroma can’t handle LD-signatures on relayed posts and I’ve yet to see another project that correctly handles attribution on federated wall-to-wall posts correctly without embedding them - though I haven’t yet had an opportunity to test Smithereen. If the original post is edited or deleted, the embedded share is updated accordingly and re-pushed.

Comments behave no different from any other activity.

(*) Privacy conflicts arise when the posting actor has a different privacy and permission profile from the group. For instance if the actor only accepts comments from connections, they won’t see replies to the group post. Likewise if an actor with a public profile posts to a private group, all the replies to the private group would end up being shared publicly. A privacy conflict also arises in Pleroma because of their inability to use LD-sigs. The object must be fetched from the original actor site and will be blocked if the actor has restrictive permissions. You can’t easily use OCAP methods to allow this because if the group is public, your private access key is now fully public.

I don’t claim the solution I’ve come up with is elegant, only that it works and is fully compatible with existing ActivityPub implementations and works correctly even when there are privacy conflicts between the posting actor and the group. This behaviour has been honed and refined as a result what we’ve learned in ten years of supporting this feature across protocols that are hostile to or ignorant of privacy and permissions. Maybe if we all share what we’re doing we might find a combination that is both elegant and works for everybody, though I am willing to live with “works for everybody” and go it alone if the end result is elegant but only works with fully public groups or actors.

1 Like

I don’t think groups copying the user’s content is a good solution, since that loses the connection with the original object/actor. If a user wants to post to a group, they need to send the object with enough permissions to be viewed by all group members (or public if the group is public), otherwise the post should be rejected by the group host.

In Friendica the group is an actor with the type “group”. The users then are following the group account. To publish a note (or article) a user simply writes a (public) message and is mentioning the group account. The group then automatically shares this post via announce.

1 Like

@heluecht Public posts to public groups and wide-open comment permissions work fine with that model. See gup.pe groups. However, if your software supports both public and private groups and restrictive comment permissions (and/or aspects), the same mechanisms are fatally flawed so that approach won’t work. How would you suggest supporting both behaviours? A completely different UX for each, or (as I’ve done) finding a method which works well for the private case as well as across all platforms and protocols; which can then be used for all situations and policy variants - wherever you need to post to a group? There’s method to my madness…

Private groups won’t work quite as seamlessly with other software, but it’s still a viable option with similar mechanics. The Group would need to have manually approved followers, then mark all the Announces as to its followers and not public. For any posts to the group, they should also be sent to the group’s followers. Implementations that don’t know about groups probably wouldn’t do this, but they could technically still post to the group with a public post

Restricting comments is a separate discussion that is still ongoing

That won’t actually work in our environment (where restricted comments are a fact, as well as permission to examine/enumerate the followers list). This ultimately implies a different implementation for every platform just like we do with protocols and signature requirements and mention formats and “obligatory mentions” to trigger notifications and markup support and differing comment policies.

No big deal.

The followers don’t need to be enumerable to target them, the collection can be specified as a target

I don’t think membership in a group should be implicit through following. A group should have two collections, one of followers and one of members. You become a member of a group by Joining, not by Following. Restricted messages are addressed to both the group and the members and get Announced to the members. Public messages are addressed to the group and the public and get Announced to the followers.

1 Like

How should an implementation know whether they need to Join vs Follow? For some groups I guess they would need to offer both, but for the groups I’ve implemented so far there would be no difference

For everybody attending the conference :

This thread got very long and is very active.
A Birds of Feather session would be nice !
But I am currently writing 2 proposals for “topics” and “ui things”, so:

Does any attendee maybe want to write a very short proposal “groups”, linking to this post ?
Just create a topic in this category …

1 Like

@Sebastian that APConf sub-category does not yet exist (or is restricted).

Hm, I can see six proposals by different people and other posts in the category.
So, @how : Is the category maybe restricted to a group?

Bumping… this discussion has unfinished biz   :slight_smile:

2 Likes

Re-using this topic as it is still open. I’m currently implementing FEP-400e from @grishka, in order to provide a complete project-agnostic groups implementation covering every known groups implementation and quirk (there are a fair number of these and I suspect we’ll have even more before all is said and done). Some questions came up.

If an actor has publicly-appendable collections, its server MAY include them as additional fields in its ActivityPub representation. For example, user actors may specify the link to their walls, or groups may specify the link to the collection of their photo albums.

Implementations MAY use the presence or absence of specific collection to determine whether the actor’s server supports features that depend on that collection and alter their UIs accordingly.

What is the proposal for indicating these writable collections in the actor record? It’s OK if this is just a hack. I just need to know what it is so we can use it and alter our behaviour accordingly. I’m more concerned at the moment with the “wall” than photo albums, but if there’s an example actor record that shows what is planned for both it would be sweet.

The next question is about using Create/Note/Collection (type, object,target). In the original AP/AS specifications, it was suggested that such activities should be Add/Note/Collection (not explicitly, but more or less inferred in the description of ‘Add’ and also the text in section 5.8.2 “Collection Management”). I intend to provide this as a general collection management interface and as recommended in the spec. Is there any chance that Smithereen could also do this, or should we also support Create/Note/Collection purely for Smithereen compatibility?

Third question. Regardless of the answer to the second question, there are different behaviours depending on the audience of the activity. If the activity is public, we don’t intend to add the Note to the wall (technically the outbox). This is more a published report of an activity that already happened - “Joe added a note to the Foobar group’s outbox”. Whereas if there is a single recipient (the owner of the wall) it can be taken as a directive to actually perform the activity rather than just report that it happened. Not sure how best to clarify this difference other than by looking at the audience and seeing if the collection belongs to the single recipient and ignore it if the activity is addressed more widely.

Fourth question (slightly related to the third): If the collection operation fails (lack of permission), is it even appropriate to notify anybody else besides the wall owner of the collection operation? I would say no, but I know there are a lot of people in this forum that would disagree and say the actor should be able to tell anybody anything at all, and the success or failure of the operation isn’t relevant. Because free speech. But if the activity is “Joe added a note to foobar group’s outbox” and it didn’t actually get added to foobar group’s outbox because Joe isn’t a member, such an activity is a lie and should not be sent.

I’m merely suggesting that any kind of activity with a collection target might require a bit of extra care to define the activity audience; which would let receivers know for certain whether this was a request to perform the operation or an activity reporting that it happened. Without looking at the activity audience, the desired action on receipt of the activity is ambiguous.

That’s a good question! Currently it’s up to the implementation. I suppose it’s best to take care of this particular thing as part of the capability negotiation/“compliance profiles”/privacy settings effort. Because, for example, an actor might have a wall, but whether you can post on it depends on who you are.

The problem I see with the approach in the spec is that the collection ID is only contained in the Add activity. It’s fine for straightforward cases like when your server hosts the collection and receives such an activity, but there are cases when this breaks down. For example, if you fetch the object using its ID (aka copy a link to a post and paste it into the search field on your instance), your instance has no way of knowing which collection the object belongs to because it doesn’t have its enclosing activity. So, it’s not self-contained. This would lead to buggy behavior like misrepresenting wall posts as something posted to one’s followers.

Example of an already existing similar behavior is replies. Each reply has a link to its parent in its inReplyTo, and each post that has replies lists them in its replies collection. This way you can traverse the thread in both directions, even when you start off with just a single post from the middle of it.

It depends. For wall posts, it doesn’t make much sense imo — you can’t move a post between walls. There’s also the question of semantics: Add implies that you add an existing object to a collection, so there should have been a Create at some point before it.

Right now I rely on LD-signed activity forwarding for this (the Create is sent to the collection owner only, and nothing is forwarded if it wasn’t added), but yes, I agree that it might use some improvement. There is currently no protection against some bad person sending a wall post to group members directly despite the group itself not allowing that post. You got me thinking about how there needs to be some (simple) way to prove that the collection owner approved someone adding an object to their collection. Maybe it should actually be an Add activity after all. So the flow would go like that:

  • Someone sends a Create{Note}, as in my FEP, to the instance that hosts the group.
  • If this is isn’t allowed, it returns a 403 or sends a Reject{Create{Note}} to that person.
  • If it is allowed, it adds the post to its wall, and then sends all group members an Add{Note}, as per spec, with the post as a link.

This way there will be a proof that the group has accepted the post, because there was an activity explicitly mentioning this post, signed by the group actor.

The one small problem that then remains is that if you fetch that post using a direct URL, it would still be considered to be on the group’s wall even though it’s actually not. This could be abused by making such a post and then a comment (reply) to it mentioning someone. Their instance would receive the post with the mention, and will fetch the thread to show its context, and would thus end up with that fake post on a group wall.

The problem then becomes: given an object that claims to belong to a collection on another instance, how do I prove that this instance that owns the collection has sanctioned the addition of this object to its collection? Since I’m treating ActivityPub like an API, I want something resembling an API call that would accept a collection ID and an object ID and return a yes/no answer whether the object is in the collection. I’m open to suggestions on this one.

Thanks. I’ve got something that may work with what you have today (needs testing but shouldn’t be too far off). If you do change anything just say something so we can adjust and re-test if necessary.

I’m not ignoring the other points raised, but they aren’t really issues in our implementation – for various reasons; so I wouldn’t be the best person to offer any advice on them or debate their merit.