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

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?

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.