w3c / activitypub

http://w3c.github.io/activitypub/
Other
1.22k stars 78 forks source link

Disable replies #319

Open nclm opened 6 years ago

nclm commented 6 years ago

Almost all blogging platforms and a few social networks (for instance Dribbble) allow the author to disable replies on their post. So that ActivityPub-enabled platforms are up to usage on that, I think it’s necessary to have the possibility to send posts with a standardised “replies disabled” tag added to them.

(Not knowing the standard, I’m using the “tag”, “post”, etc. without the proper terminology.)

ActivityPub clients must at least:

Clients probably should:

Clients can if they wish, or if it makes sense, do one or a few or all among these:

For platforms that have no sort of interface for displaying comments or replies, it could also make sense for them to enable this feature by default (unless they are fine with people commenting the posts on other platforms even if the discussion does not federate back).

gobengo commented 6 years ago

ActivityPub clients must at least: Respect the “replies disabled” added to posts by either hiding, greying out, or crossing any “reply” icon or other interface used for replying or commenting.

If you mean "MUST" and not "must", then this may be philosophically contentious.

I am familiar with many reasons why someone might not want replies to a post. And they shouldn't have to host those replies on their server or even look at them.

But I personally don't think it's reasonable for anyone in a federated context to say "no one is allowed to reply to me". It's stepping a bit further then is fair in terms of free speech, which is any individuals' prerogative. But I don't think it should be baked in at the protocol level.

What's cool about federation is that this reply policy can be enforced not just at time of authoring replies, but at the OP's original server when replies are federated to it. If 'no replies' is indicated, the original author's server can just reject all replies coming into the inbox (or all replies with profanity or images or whatever).

With that said: Sure, why not have something like:

nclm commented 6 years ago

Oh sorry I edited my message while you were replying. For reference, I added: Clients probably should: Hide any replies to posts with “replies disabled” enabled, if ever some got through the net. At least to the author.

If this one becomes a must, then the first one can become a should or may. What is important is that an author never see a reply to something they posted with “no replies” checked on.

kizu commented 6 years ago

Disallowing replies does not ever impede the “free speech”. Anyone would be able to use their platform to post replies, but the link between the replies and the original document shouldn't be enforced. Replies without a consent to replies would be basically violence and could be used as a harassment channel.

So I'm all for the MUST wording.

nightpool commented 6 years ago

we already have a couple special cased "can I do this?" properties in various forms of standardization, so I wonder if people have any thoughts on how to unify "can I follow you", "can I Announce this post" and "can I inReplyTo you" from a technical perspective

@cwebber probably would like to say something about capabilities here?

On Mon, Sep 3, 2018, 2:35 PM Roman Komarov notifications@github.com wrote:

Disallowing replies does not ever impede the “free speech”. Anyone would be able to use their platform to post replies, but the link between the replies and the original document shouldn't be enforced. Replies without a consent to replies would be basically violence and could be used as a harassment channel.

So I'm all for the MUST wording.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/w3c/activitypub/issues/319#issuecomment-418174789, or mute the thread https://github.com/notifications/unsubscribe-auth/AAORVxvzFeYcMHqUsZ8e0b52J29tYDy3ks5uXXaJgaJpZM4WX4_z .

cwebber commented 6 years ago

So we have to be careful about "request policy" / "advisory policy" things that ask a good participant to behave correctly. That can still be useful, but it's important to remember what will happen if either a bad or negligent participant ignores the behavior. If we don't consider that, we might accidentally allow bad / negligent participants to be more abusive than they were before we implemented the protocol, because we will violate the expectations of good participants when what they suddenly see that intent is violated.

So let's consider what we can do. There's what we can do within current reply conventions (not very powerful, but advisory) and what we could do much better if we changed things more dramatically with a capabilities approach. I'll focus on the former, but if people are interested in the more capability-centric approach which can more powerfully restrict these things I could write it up as a separate post.

Anyway, that's all to say that this is trickier than it appears, and writing the code to "enforce" whether or not the client MUST show the reply button or not does not actually enforce itself the behavior in the system, and there are complex decisions and state management problems we must consider if this feature is introduced.

Anyway, @nightpool is right, there's absolutely a couple of ways to do this from a capabilities perspective that get the behavior that people want to be able to more carefully control what are and aren't considered legitimate replies, but that's work-in-progress research on my end and may end up requiring that servers rethink how they do things.

trwnh commented 6 years ago

A proposal in follow-up to @cwebber: instead of a replyPreference, could this be done instead by changing the way replies work to refer to some secret replyID instead? Fundamentally, the problem is that you can refer to anything with an address; therefore, it logically follows that to disallow references to something, it's necessary to keep the address private. If the URI is used as the replyID, then you can reply to any post that you know exists. This replyID would be requested by a server on behalf of an Actor, and can be changed to null to disable replies at any time; it would be the responsibility of the Server to verify that the replyID is valid.

That might be closer to what you refer to as "capability perspective"; if creating an entirely separate replyID is too complicated right now, then perhaps it might suffice to generate a one-time secret replyProof of some sort, and this could be used for validation by other participants' clients.

Alternatively, clients should stop querying their own servers for replies to a post, and should instead query the authoring server for replies -- this would be less efficient since it cannot be fully cached, but would make the authoring server also the authoritative one; this would open the door to allowing each Actor to disallow or de-list specific replies, similarly to how you can delete other people's comments on Facebook or Instagram.

cwebber commented 6 years ago

@trwnh That is indeed similar to the capability perspective. The important idea here is that the actor you receive may not actually be the full most powerful reference to the actor (and its inbox), it may be a "facade" which has more limited powers and instead forwards some messages to the full-powered actor but filters others. So in this case, the facade lets you view the object read-only but does not give you access to replying by default. (Alternately, the actor for viewing and the actor for replying are just two entirely separate actors which coordinate behind the scenes.) We must also provide a way for the object to demonstrate which replies are valid.

I will work on a full writeup of how to do this "the right way" via capabilities. I had intended to hold off on this until later because I think it introduces several new concepts. However, it's probably time to put out a first draft so people can understand some of the powers possible when we introduce ocaps into the fediverse.

Expect a reply within the next several hours.

nightpool commented 6 years ago

just to preempt the already-disclaimed-to-be-theoretical post with a more practical solution: we should allow objects to require that their actor Accepts an activity relating to them (announce, reply, etc) before other servers process it, in the same way we currently require Accepts for following

nightpool commented 6 years ago

this seems similar to @kaniini's proposal but i'm not sure that there's even a need for a specific interaction inbox. Here's an example of how I think this could work in practice:

Alice posts a status they only want certain people to be able to reply to:

{
  "type": "Create",
  "to": "https://alice.com/followers",
  "actor": "https://alice.com/user",
  "object": {
    "id": "https://alice.com/my_private_status",
    "type": "Note",
    "requireAcceptedInteractions": true,
    "content": "Just got out of a bad meeting with my boss. Don't want to talk about it"
  }
}

Bella sends a tentative reply just to alice's inbox:

{
  "type": "Create",
  "to": "https://alice.com/user",
  "cc": ["https://alice.com/followers", "https://bella.com/followers"],
  "actor": "https://bella.com/user",
  "object": {
    "id": "https://bella.com/my_reply",
    "type": "Note",
    "content": "that sucks! hope you're feeling better",
    "inReplyTo": "https://alice.com/my_private_status"
  }
}

Alice either Accepts or Rejects this reply. if alice Accepts it, then she sends an Accept activity back to Bella, and then either of them can forward the Accept activity on to whoever they would have originally:

{
  "type": "Accept",
  "actor": "https://alice.com/user",
  "object": {
    "type": "Create",
    "to": "https://alice.com/user",
    "cc": ["https://alice.com/followers", "https://bella.com/followers"],
    "actor": "https://bella.com/user",
    "object": {
      "id": "https://bella.com/my_reply",
      "type": "Note",
      "content": "that sucks! hope you're feeling better",
      "inReplyTo": "https://alice.com/my_private_status"
    }
  }
}

So this boils down to a couple of rules:

This relies on the definition of a couple iffy terms:

but i think that in practice it would work pretty well.

trwnh commented 6 years ago

Hmm, Accept and Reject semantics sound like "approved" or "unapproved" comments -- not necessarily the same as preventing replies due to requiring oversight, but functionally similar enough in many cases. Although, I'm worried that asking a user to approve/disapprove replies is still forcing the user to at least view the replies, and thus receive them. Outside of a simple "Accept all replies" or "Reject all replies" boolean, this would necessitate a holding area for all tentative/unanswered inReplyTo activities, similar to follow requests.

nightpool commented 6 years ago

@trwnh i don't think the idea that you're sending an Accept or Reject activity necessarily implies that you're requiring the user to look at each individual one. There are plenty of other procedures a server could run automatically for determining if a reply is valid ("only allow replies from mutuals", like tumblr has, for example)

kaniini commented 6 years ago

how do you prevent spoofing with Accept in this case?

nightpool commented 6 years ago

wym?

kaniini commented 6 years ago
  1. who sends the Accept messages?

  2. if anyone can send the Accept messages how does forgery prevention work? since Pleroma use capability URIs extensively for forgery protection (and Mastodon use LDS), how can we ensure things are safe?

nightpool commented 6 years ago

@kaniini my proposal for now was that the actor who created the object/who the object is attributed to is the only person who can send accept messages, although I admit that this is limited in The General Case. auth&auth is currently outside of the scope of the spec, but i would assume any method of ensuring the activity content is genuine would work, the proposal is agnostic, it just assumes you have some way of preventing forgery (like all of activitypub)

nightpool commented 6 years ago

I'm not sure what you mean by pleroma using capability URIs extensively for forgery protection—this is the first i'm hearing about it. My understanding is that pleroma uses HTTP signatures for validating incoming federated activities and domain-based checks for imported activities.

kaniini commented 6 years ago

so say Elaine sends a Create that AliceAccepts.

it is addressed to Alice herself and Elaine's followers collection.

how does Alice forward those messages to Elaine's followers collection without walking it?

I think we need it to work this way:

  1. Alice sends the Accept back to Elaine.
  2. Elaine forwards the Accept to her followers, by referencing the Accept by IRI.
  3. Capability enforcement is achieved by fetching the Accept.
  4. If the Accept is fetchable, then the grant is valid, and the underlying referenced object is processed.

This could be optionally supplemented by LDS to avoid the fetch step if wanted.

kaniini commented 6 years ago

Pleroma always refetches any URI that is not local, to protect against forgery and enforce object integrity. It is one of the reasons we are opposed to inline signature schemes such as LDS. But that's beside the point right now, let's stick to the topic at hand :)

nightpool commented 6 years ago

i don't think any of that is inconsistent with what I said, it just hardcodes two forms of authentication. (fetching the Accept and using LDS)

nightpool commented 6 years ago

I don't think it's appropriate to refer to these Accept activities as "capabilities", since they're only judgements about single objects, not permissions to do things in the future

kaniini commented 6 years ago

That is precisely what object capability enforcement is.

nightpool commented 6 years ago

I'm very sure that's incorrect (since it doesn't involve different permissions based on different references you hand to different people) but i don't want to get off topic on this discussion

cjslep commented 6 years ago

Re: @nightpool comment w/ concrete Accept / Reject proposal:

This proposal as I understand it is not backwards compatible with the delivery model outlined in the original ActivityPub spec. If a vanilla ActivityPub server is sending:

{
  "type": "Create",
  "to": "https://alice.com/user",
  "cc": ["https://alice.com/followers", "https://bella.com/followers", "https://example.com/arbitrary_onlookers"],
  "actor": "https://bella.com/user",
  "object": {
    "id": "https://bella.com/my_reply",
    "type": "Note",
    "content": "that sucks! hope you're feeling better",
    "inReplyTo": "https://alice.com/my_private_status"
  }
}

It will forward the response to the other ActivityPub servers, despite Alice's wish against it.

This is tangential to the problem you point out:

If you're a third-party server, and you see a post with requireAcceptedInteractions, don't process activities that aren't embedded in an Accept from the author of the post

Which in my mind is a huge limitation: all vanilla ActivityPub implementations are essentially spreading around replies unwanted to be received and shown by the original person. This is similar to the second bullet by @cwebber and remains unsolved by the proposal.

I think this is really the crux of the issue: vanilla AP implementations already violate the proposed concrete rules above. If this can't be solved, ActivityPub clients might as well provide a "don't show replies" UI checkbox when posting to achieve the same thing: not letting the recipient see the unwanted content, but still allowing the rest of the AP servers to spread information as allowed by the original AP protocol (w/o mucking up the original protocol).

nightpool commented 6 years ago

@cjslep yes, I agree that this proposal doesn't do anything for servers that don't support it. Unfortunately, we have to make a choice here—either we extend activitypub is such a way that it breaks replies for all servers that don't respect disabling replies, or we do so in a way that is backwards compatible. I chose the latter option, but i guess there are also arguments for the former.

cwebber commented 6 years ago

There's a way we can do things that isn't backwards incompatible involving proofs/signatures with a certain proofPurpose. It's been a long day for me but I'll write this up tomorrow.

nightpool commented 6 years ago

@cwebber you're telling me there's a backwards compatible way to prevent non-extended ActivityPub servers from passing around inReplyTo properties that reference the original post, to other non-extended servers? that seems impossible given that it's strictly a restriction on existing behavior.

or are you saying there's a backwards-incompatible-but-less-so way?

cwebber commented 6 years ago

The right approach which degrades gracefully is to add a new proof node with a proofPurpose that says whether or not a post is signed off on as a valid reply. So:

{"type": "Note",
 "content": "bla bla",
 "inReplyTo": ...,
 ...
 "signature": [
   {"proofPurpose": "acceptedReply",
    ... sig of person being replied to ...}]}

proofPurpose is a new field in ld-sigs/proofs to avoid confused deputy problems... signing an object because you made it vs because you are accepting the reply, etc, are different things.

Prior implementations of ActivityPub before this extension will still show all replies. New applications will know to only show the replies with the appropriate signature.

How to get your object signed by the original author? That's another post for me to write.

nightpool commented 6 years ago

@cwebber i don't see how that's significantly different then passing around a signed/dereferenced Accept object, from a backwards compatibility perspective

kaniini commented 6 years ago

keep in mind that use of ld-sigs is untenable in Pleroma

trwnh commented 6 years ago

Revisiting an earlier comment I made:

Alternatively, clients should stop querying their own servers for replies to a post, and should instead query the authoring server for replies -- this would be less efficient since it cannot be fully cached, but would make the authoring server also the authoritative one; this would open the door to allowing each Actor to disallow or de-list specific replies, similarly to how you can delete other people's comments on Facebook or Instagram.

With the recent hubbub about Google+'s death and renewed interest in Diaspora*, I came across this article again (https://schub.io/blog/2018/02/01/activitypub-one-protocol-to-rule-them-all.html) and specifically this bit (minorly edited for typos and clarity):

Let us have a look at the implementation in the diaspora* protocol first. We have a pretty easy rule: Whenever Bob interacts to something Alice shared, that interaction will be sent to Alice’s host and Alice’s host alone. Since interactions are designed to be relayable without losing the option to validate them, Alice’s host can forward these interactions to everyone who received the post in the first place. Alice’s host is the one who delivered the post, so it feels somewhat natural to also ask Alice’s host to distribute the interactions. That is, however, not the case with ActivityPub [...] Bob has to address individual recipients in his interaction. We have seen this implementation before and it is built to fail [...] a more sensible, reliable, and even more ActivityStreams-y way of handling replies would probably be adding the interaction to the replies collection and sending an Update.

Would this perhaps be simpler and less backwards-incompatible than mandating an Accept {Create {Note.inReplyTo}} response? Or is that functionally the same thing?

kaniini commented 5 years ago

I wrote up a specification draft over on the litepub side of things building on discussions here: https://litepub.social/litepub/lice.html

ap-socialhub commented 1 year ago

This issue has been mentioned on SocialHub. There might be relevant details there:

https://socialhub.activitypub.rocks/t/fep-5624-per-object-reply-control-policies/2666/4

evanp commented 3 months ago

This is an important topic, and there's a lot of exploration of the area. There are a number of FEPs working on this problem. FEP 5624 uses a tag mechanism as recommended here. FEP 7458 is also about managing the replies collection.

This is a frequently requested feature. I think the best solution is to see this feature developed in the FEP process, but I also think we should keep it on the radar for the next version of AP. It's important enough that we should strongly consider it for an upgrade.