Standardizing on ActivityPub Groups

Another level of agency where a group take public actions as-a-group, like schedule a meeting or make an agreement to do something with another group.

For example, I am a member of, which hosts its own fediverse instance, for which I pay something like dues, but it also holds meetings and makes agreements as a group, including an agreement with so that members can use online meeting facilities. also has an identity in the fediverse which I follow, but they do not host their own fediverse instance (yet).

Could you explain what the problems are with the “Announce model of group federation”, and what you would suggest instead? We are using Announce for Lemmy federation, and so far its working perfectly (for public groups).

Announce fails when you have privacy and permissions involved. Downstream recipients can’t fetch and may not have permission to comment on the root object so the entire model breaks. I’ve also outlined elsewhere the issues with using OCAP to get around these limitations. You can no longer thread conversations because everybody is reacting to personalised/different id elements than other members of the conversation.

Aside: I guess most of the disconnect here is that I seem to be the only person pushing for privacy and permission to be fundamental properties of the fediverse. Not to mention account cloning/migration in case your instance admin goes rogue.

I do agree, everything is far simpler if you simply discard these concepts - especially on a decentralised platform where they are much harder to implement in the first place. At least to me, a fediverse without these qualities as foundational elements has zero appeal.

In this respect I’m definitely not alone.

1 Like

As I left Facebook a very long time ago, perhaps you could share what kinds of negative things you attribute to private groups on that platform. Looking it up on the interwebz I can only find some posts about Facebook’s recommendation engine recommending inappropriate group content, and some hints that these private spaces might be used by extremist organisations in the same way tools like Tor and cryptocurrencies might be used by some to sell drugs online. The former would appear to be a breach of privacy by Facebook and the latter a matter of people using privacy for its intended purpose; which is to have some direct control over who you share things with. I’m very interested in your perceptions and experiences in any case.

I think that is only a problem if it is possible to create child objects with laxer privacy/permissions than the root object. I know thats a problem on Mastodon, if a discussion is “followers only” and you only follow some of the participants, then you only see half the conversation.

In case of Lemmy, we will probably only provide privacy options on a per-group basis (eg public group or private group), with no privacy options per post or per comment. In that case I dont think it will be a problem.

Welcome @Gargron and thank you for bringing focus to the kind of private group that users in the real world expect. A public group is simulated fairly well with the hashtag modulo spammers but if you want to chat with your buddies and joke around, you don’t want to do it up on stage for the whole world to critique.

Also agree with your point about local-only posts because what follows is a desire to lock down the server and then admins have to stress over choosing between privacy and federation. As I said here I think groups are victim to a federation or nothing mindset so hope we can remove that and any other blockers to giving users such a valuable feature.

This is a similar concern to discussion I’ve seen around e2ee where message franking allows admins/mods to step when their help is required. Private groups are similar and I think as long as moderators exist, there will be ways to keep harmful activity in check.

FB’s problem is that their incentive (and duty to shareholders) to make money means they allow way more activity than is economical to moderate.

In the interests of moving past the current impasse, let me re-iterate that the only reason why one needs to consider private groups is so that we don’t end up with multiple ways of posting to them in the future that will be different. We require a mechanism which works for both. So I’ll propose a simple set of basic requirements and see if we can move forward:

  1. A group MUST provide an actor type of ‘Group’ so we can determine how to address it.
  2. Posting to a group MUST support FEP-400e as a mechanism and MUST use that mechanism whenever posting to a group remotely. Implementations are free to support additional mechanisms (hashtags, mentions, DMs, wall-posting, etc.) as desired.
  3. A message MUST NOT be cross-posted to multiple groups.
  4. Followups to the group MUST be sent to the group actor and SHOULD only be sent to the group actor. They MUST NOT include any external actors (non group members) unless it can be determined in advance that the audience for this particular group conversation is public.
  5. Groups MUST support ‘Join’ for group membership. They MAY support ‘Follow’ or other methods.

This is just a proposal. Feel free to suggest changes. Under the covers, as long as your group implementation abides by this or a similar basic set of conventions it actually doesn’t matter how it works under the hood or whether it is public or private.

  • Reading FEP 400e, it seems to be about collections. How does this translate to use with Group actors?
  • What do you mean by “Followups”? Wouldn’t sending things only to the group actor make them invisible to everyone?

Posting to a group is essentially adding the object to the group outbox rather than to its inbox. This procedure can be accomplished in C2S for your own resources, but not necessarily in S2S. FEP-400e simulates this behavior using a remotely initiated “wall-to-wall” post, which is Facebook terminology for this mechanism; meaning that if somebody posts onto your personal homepage (i.e. your wall), it is delivered to all your followers. This is the mechanism behind how Facebook groups used to be implemented (through a wall-to-wall post to the group homepage) - I don’t know if it is still done that way.

As for followups, please see section 7.1.2 of the ActivityPub spec. This is what we call the “conversational delivery mode” in which privacy is maintained throughout the conversation and thread completion is accomplished by sending comments to the sender (not necessarily the author) of the top-level post; who may have secret knowledge about who is included in the conversation audience (private lists/circles/aspects, bcc and bto recipients, etc.). This actor (e.g. the group in this case) then redistributes the comment to all the original participants. I would go so far as to say that this is the only actor who should ever receive comments if you wish to provide a privacy respecting platform.


I would go so far as to say that this is the only actor who should ever receive comments if you wish to provide a privacy respecting platform.

Poor choice of words for a technical audience. Mea culpa. It should probably read “… the only actor who you should ever send comments to …”. Every member of the group/list/aspect/circle still receives the comments, but the owner (who is not necessarily the author) of the top-level post is solely responsible for distributing them to the intended audience.

With consent from @dansup I moved this topic to #activitypub category. It was formerly titled “Pixelfed Groups”. Delighted to see @Gargron joining as well. Most welcome to SocialHub, Eugen!

We are at 50+ posts now and very near or already past TL;DR threshold to take it all in. Volunteers for summarizing the insights from this thread, so we can work from there?

1 Like

I guess the following actions should be taken to summarize this intense discussion:

  1. Clarify what is meant by the term “group” and the scope of the discussion
  2. Required readings, e.g., FEP 400e
  3. State of implementations across participant software in this discussion
1 Like

The idea of that FEP is to standardize the common, especially for groups, interaction of someone adding something to a collection owned by someone else. It’s intentionally broad. Smithereen uses it to implement walls, both in groups and in user profiles. A wall is a collection where other actors can add posts.

Some more of my thoughts on the current proposal & 400e:

  • Why is target expected to be a full object? This seems lazy compared to just passing the collection’s ID, especially given that the receiving server is the owner of the collection
  • I don’t think Delete makes sense as a power given to the collection owner. Why not just Remove (or Undo{Add})?
  • Move seems concerning since it doesn’t appear to require consent of the content author. There may be some cases where this could be allowed but that goes into the capabilities discussion, I wouldn’t assume foreign actors can modify others’ objects in general.
  • Ideally we would have some way to link an object to the corresponding Add activity. I vaguely remember some discussion about this but not sure where that ended up
  • Immediately switching to use Join will break compatibility with existing implementations that only support Follow. Should there be a field on the Group to indicate support for either?

It does say right there — that’s to make the database design easier on the receiving side. Passing just the ID would mean that 1) you won’t know which column or even table to select on and 2) you would have to add an index to every column that contains a collection ID. Done how I suggest, however, you first fetch the collection owner, and then compare the ID to all their collections to find the right one, or if it’s your local URL you just parse it as is because you know its structure. A much cheaper operation.

Because Remove or Undo{Add} would imply that the object continues to exist afterwards but without the collection. In reality, it does not, it does get actually deleted.

This is by design. As a group admin, you should, for example, be allowed to move photos between albums regardless of who added them. You have absolute power over all content in the group.

Yes, that’s actually a nice idea about providing the proof that the object in question is part of a collection. We should discuss this further. Maybe add a field that links to that activity? You then resolve that link and if that’s successful and the activity matches your expectations and is hosted on the same domain as the collection owner, you can be sure that object is legitimately part of that collection.

There is.

FYI Via Lemmy’s discussion of @dansup’s Pixelfed Groups support I found this open issue on how @bookwyrm is implementing groups support:

And @nutomic commenting:

“Interesting, it seems that every project implements groups in wildly different ways. Both bookwyrm and pleroma are going for private groups primarily, with public groups as an afterthought.”

And in the #software:bookwyrm issue there’s @mouse saying something on compatibility:

“Here’s some conversation about cross-platform compatibility: Standardizing on ActivityPub Groups - #14 by Sebastian. That said, because so much of bookwyrm is tied to book-related content that’s specific to bookwyrm, I’m not terribly concerned with compatibility at this point. Afaik neither mastodon nor pleroma have any implementation at this point, so I’m inclined to just try and write something sensible based on the AP spec.”


So has anyone implemented this yet?

lotide now (on the master branch) should roughly support this. Namely:

  • communities allow Join/Leave in place of Follow
  • posts with a target referencing a community’s outbox will be added to the community
  • posts sent to a remote community will include its outbox as target
  • posts added to a local community will send an Add to all followers, adding the post to the outbox
  • following a remote community will send Join as well as Follow

However, I still maintain that:

  • Adding an object to a collection should not confer any permissions to the collection owner to modify or delete the object itself, only to modify its relationship to the collection.
  • Servers should generally not be sending remote objects, especially without LDsigs since the object would have to be refetched anyway

I also don’t really know if my implementation works since I don’t have anything to test it against

Hi, I’m currently working on groups support for Mastodon.

The definition of what a group exactly is unfortunately differs from project to project, but what we have settled on is:

  • groups have a set of members and administrators/moderators (we’re assuming this is public information, but that may not be a hard requirement)
  • only group members can post in a group (this one isn’t set in stone)
  • posts and replies within a group all have the same audience, set by the group (group members, and potentially publicly-viewable as well): no per-post scopes like we currently have in Mastodon
  • similarly, mentioning non-members, if at all possible, should not extend the audience of a group post
  • a group post is bound to a specific group and cannot be cross-posted
  • posts are viewed in a per-group timeline and not on the home timeline
  • new members may or may not need to be approved (group-specific settings)
  • moderators can kick/ban group members and delete individual posts
  • ideally, users should be able to report group posts not only to server moderators but to group moderators as well, and have a choice in that (e.g. be able to chose not to report to group moderators in case they are wanting to report the group’s behavior as a whole to their server’s moderators)

For implementation complexity, UX and moderation reasons, I have decided on the following restrictions, at least for the initial implementation in Mastodon:

  • no Announce functionality whatsoever within or across groups
  • mentions of non-members won’t be processed at all. This is mostly an implementation detail, though it may have UX implications
  • only groups with publicly-viewable posts will be supported. While this may change in the long run, restricting ourselves to publicly-viewable posts for now avoids some potential technical difficulties and moderation issues.

I have not started writing the ActivityPub side of things, but what I have in mind is roughly:

  • group actors have Group type
  • Join is used to join a group, and Leave to leave it. It follows the same flow than Follow, with Accept or Reject being sent either automatically or after manual review
  • both top-level group posts and replies are sent only to the group, which is responsible for distributing them (they may be publicly dereferenceable, but distribution itself is handled by the group actor)
  • posting within a group (at least for top-level posts) uses FEP-400e or similar

This seems roughly consistent with what has been described here for Smithereen, lotide, and @macgirvin’s projects, so I’m hopeful we’ll manage to have something interoperable.

That being said, there are still quite a few open questions, even with the limitation I listed for Mastodon’s initial implementation:

  • How do we signal the audience of group posts?
  • If we use to/cc/audience for this, how do we ensure non-group-aware implementations do not interact with them?
  • If non-group-aware implementations do interact with them, what do we actually do? Drop the interactions? Handle out-of-group replies to group posts? This is something we would very much like to avoid in Mastodon for UX reasons.
  • Posting by sending to the group only, with the group deciding whether to allow the posts or not, seems reasonable. But what about other activities, like editing a post or deleting one? A group actor preventing someone from deleting their posts does not sound good, especially since the person deleting their post will have no way to know if the information is distributed to group members.
  • how should posts from someone who has left/been kicked out of a group be handled? should the author still be able to access them? how? what about replies?
  • How is group membership kept in sync? Are Join/Leave/Accept forwarded? Signed? Publicly dereferenceable? Is a collection regularly polled?

I also have other issues in mind, although they don’t apply to the reduced scope of Mastodon’s initial implementation:

  • how do we distribute private group posts? One proposal is Smithereen’s “actor tokens” (short-lived tokens issued by the group actor to its members), although I’m not sure how well it would scale
  • how do we handle federated moderation (having moderators from different servers)? This seems more like a vocabulary issue than a design one, but I haven’t given a lot of thought yet.

What address format you’re going to use for groups in Mastodon, @group@server or !group@server, or something else entirely?

Related topic: