FEP-5624: Per-object reply control policies

amazing thanks for the walkthrough, that helps a lot

@Claire is there a reason to use a new type for approval/rejection, instead of just Accept and Reject?

Problem: Accept/Reject is too general.
Proposed solution: Use unambiguous extension types for approving replies.
Proposed alternative: Use Add/Remove targeting the replies collection. Or any other collection, like a context collection representing the conversation. Heck, just distribute the Add instead of the Create, save yourself a logistical step – the processing is mostly the same in either case, just take object and convert it to a Mastodon-flavoured status, you can ignore target if you don’t understand it.

1 Like

Add/Remove was going to be my other suggestion!

Another alternative is to use a new property that makes activity unambiguous. For example objectType: Reply.

This way we can define it once and not worry about the proliferation of AcceptX activity types.

This technique was used by authors of VC Data Integrity spec to solve a similar problem with proof types. They provide the following justification:

One of the design patterns seen in Data Integrity cryptosuites from 2012 to 2020 was use of the type property to establish a specific type for a cryptographic suite. …
This led to a greater burden on cryptographic suite implementations, where every new cryptographic suite required a new JSON-LD Context to be specified, resulting in a sub-optimal developer experience. …
Authors creating new Data Integrity cryptographic suite specifications SHOULD use the modern pattern — where the type is set to DataIntegrityProof; the cryptosuite property carries the identifier for the cryptosuite

1 Like

One thing I really like about Add is that it’s very clear what’s happening; the object is being added to the replies collection.

The other thing I like is that it succinctly encapsulates changes to replies for all addressees, so it would help a lot with conversation fragmentation.

The one issue: who is the actor? Is it the original poster, or the creator of the reply? Or, more descriptive, the OP’s server, which usually adds to replies automatically.

In any event, Add/Remove is the right way to do this.

For myself, I really like the proposal to send Add/Remove for an object that targets a collection. I can see arguments either way for whether that should be the Context or Replies collection. I think using Context is a little more robust, particularly because then reply objects could link their Context to that same id, to propagate that context relationship. That makes it quick and reliable to know where to send the Add for replies-to-replies.

My one question with this scheme: is there a way that a 3rd party server could identify the root or creator of that collection from just that link? That is, if I receive an object with a Context that is a link to a collection, how would I know it represents a set of responses, as opposed to any other purpose? And how would I know what they are in response to? Would I still have to build up an object tree based on all of the InReplyTos?

1 Like

The actor responsible for the context collection would be the attributedTo actor. (Tangentially, FEP-7888 proposes that, when context resolves and has attributedTo, you can send your Create to just those actors.)

One could define an extension type such as Conversation if this was a concern. The sum type would be type: [OrderedCollection, ex:Conversation] in keeping with the recommendation for extensibility in AS2.

You could render the conversation in chronological order as a flat list, with replies being metadata… or you could attempt to construct a reply tree if you wished. With membership in the context collection being the primary way to group objects, the use of inReplyTo becomes optional for constructing a conversation (but probably recommended if you wish to preserve some level of back-compatibility). And authors/producers can of course still use inReplyTo as a clarification on what they are responding to.

1 Like

Setting AttributedTo on the collection makes complete sense. I think that on its own answers like 99% of the question I had.

This was basically described up-thread, but the gist is: we use a special ativity for the same reason we use the Follow, Like, EmojiReact, … special activities to manipulate those special collections.

If you use Add, then implementations end up having to deal with the fact that the target of an Add might be a reply collection, (a followers collection, a following collection, a liked collection, an emoji reactions collection, …) or some general collection, and in practice this means implementations end up having to just search through multiple database tables (and then deciding what to do if somehow the collection has appeared in multiple!)

There are a few areas of the spec where implementations end up doing this, and its inefficient and its a pain (e.g. there are some complexities around processing the Undo activity which are annoying)

As a general principle, we shoud avoid reusing the generic activities for special purposes, because as appealing as it is in theory, in practice it is false orthogonality that hurts implementers.

1 Like

@Claire One thing I noticed, which I think I missed in the original post:

When processing a reply from a remote actor to a remote authority, a recipient SHOULD discard any reply that does not match any of the following conditions:

  • the object it is in reply to has a canReply containing the as:Public collection

I don’t think we should special-case the as:Public collection. I think we should say that the presence of any value in the canReply property enables FEP-5624 approvals. Once adoption is sufficiently widespread, it then becomes possible for a person to moderate the replies to all of their posts

1 Like

I’m looking at implementing non-replyable (or rather, approved-reply-only posts) into GoToSocial, as part of our NLnet work for this year.

The main use case we’re interested in is allowing users to write (micro)blog posts without the comments section. In other words, we want to let users write posts to which only their own replies will show up on the web view (so they can still write threads).

As usual with ActivityPub things, we have very little control over what other servers do (or think they can do) with GoToSocial posts, so preventing other non-GtS servers from showing replies to non-replyable posts is more of a “nice-to-have” and a “we may try to implement this later” sort of thing. So for now I think it’s fine if we leave that out of it.

Judging from the most recent activity in this thread, it seems like canReply is probably the way to go to signal between GtS instances that a post has limited replyability. For “normal” posts, including the public collection seems fine here. For a post that only oneself will ever be able to reply to, having a single canReply entry with just the ID of the post author seems to make sense to me.

Based on the limited scale in which I’d like to implement this to begin with, does anyone foresee any “gotchas”?

ps. I quite like the idea of approving replies by sending out an Add to the post’s Replies collection. To me that makes sense, though I’m sure there’s gonna be some issues there. Seems like something that can be decided a little bit later.

2 Likes

What is the status of this proposal? I see that it has been about 8 months since this last got updated, but in the meantime, the need for reply controls have gotten all the more sharp across the fediverse, and i’m unsure where work is being done on this.

(And, if this proposal failed, if it is continued elsewhere)

I think this particular one got stalled, but it did spawn some other discussions and approaches:

  • fep/fep/7888/fep-7888.md at main - fediverse/fep - Codeberg.org (discussion) uses the context property to specify a resolvable collection that represents the “thread” or “conversation”. It expects the owner of the collection (currently denoted by attributedTo) to Add objects to that collection. This approach allows for a thread/conversation/topic/etc to be moderated separately from just “direct replies/descendants”.

    • One of the big problems discussed several posts up is that you can “trojan horse” your way into a conversation by replying to someone with less restrictive reply policies, if they reply to one of your posts. Using a context collection solves that.
  • fep/fep/7458/fep-7458.md at main - fediverse/fep - Codeberg.org (discussion) proposes always checking the replies collection instead of implicitly reconstructing one based on all posts you are aware of that contain inReplyTo. Under this proposal, if a replies collection is not specified or doesn’t exist, this maps to the state of “not accepting replies” or “replies closed”. If it does exist and is specified, then you can load the replies to an object on-demand from either your local cache or the canonical origin.

    • Really, the cause of this entire issue of not being able to control what gets shown below your post is entirely social and conventional, not technological. Right now, most implementations simply do not care and do not check any replies collection. If we want to allow any sort of “control” over what gets shown, we NEED to define an “authority” who gets to exercise that control. This is the other big reason that is mentioned upthread for why 5624 got stalled – it is unclear who the “authority” is, whether that is the author of the immediate parent or the author of the “root” of the reply tree.

The astute among you may have figured out an issue with both of these above points: regardless of whether you check a context collection for the thread, or if you check one or several replies collections, you still have to check the collection… there is no “proof” that any given object is contained in a given collection. inReplyTo is not enough to know that it has been added. context is not enough to know that it has been added. Luckily, there is also:

  • fep/fep/0391/fep-0391.md at main - fediverse/fep - Codeberg.org (discussion) is the latest ongoing work being done to develop the concept of a “stamp”, which is an activity that “proves” that some object is included in some special collection. Basically, if you encounter an object with inReplyTo or context, there should be some way to:
    • navigate up to the Create activity that created the object, which should have the result pointing to an Add activity that was caused by the Create
    • alternatively, take an inReplyToProof or contextProof property pointing to an Add activity where the target is inReplyTo.replies or context

I would appreciate any feedback and advise anyone who wants to move forward on the general concept of “reply controls” to participate in any of these discussions, and also call for implementers to change the way that they handle these things. I repeat that it is a matter of convention, not technology, that is causing the issue. Put another way, the issue is not so much of “reply control” as much as it “reply canonicity”. Ditto for any other form of interaction – we have special collections such as likes and shares that share the same logic expressed in this post. In order to be able to decide which interactions get shown, we need our software to first care for and check these collections explicitly instead of relying on implicit reconstruction.

1 Like

Additionally, two non-FEP-5624 implementations of reply controls have emerged recently: