Open nclm opened 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:
"replyPreferences": "http://your-vocabulary.com/replyPreferences/NONE"
. There could even be specific pre-baked policy URLs somewhere for "don't reply to me" or "don't reply with curse words" or "don't reply with images" or "don't reply with r-rated images"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.
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.
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 .
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.
So, initially Alice makes a post about her cat with no explicit replyPreference
, which defaults to "replies are ok". Her friend Bob replies, and Alice favorites his reply. This is the simplest case.
Alice makes a post about her recent dancing performance but marks it as replyPreference
to NoReplies
or some such value.
inReplyTo
Alice's post. We must remember that the protocol cannot prevent an inReplyTo
another person's id that is already known, so instead we should ask, how do Alice and Bob's clients render the reply thread? If they were expecting that clients MUST not render the reply button or send replies, perhaps their clients would be lazy and expect that any inReplyTo objects must be fine because all clients are behaving correctly. But clearly this would be upset and hurtful to Alice. So we might say, their clients should actually expect that other clients might behave badly, in which case maybe they check the replyPreference
to decide whether to allow any further replies. At any rate, there is nothing we can do to prevent bad or negligent actors to continue commenting on the post and to continue seeing those replies, even if nobody else does.Alice makes a post about some food that she cooked and initially gets a reply from Bob that she likes, but then people start dogpiling and she decides to change her replyPreference
, and well behaving clients respect this but Mallet still sends replies. This is the hardest case because a new problem appears: should we render the messages that happen before Alice updates her replyPreference?
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.
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.
@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.
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
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.
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.
@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)
how do you prevent spoofing with Accept
in this case?
wym?
who sends the Accept
messages?
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?
@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)
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.
so say Elaine sends a Create
that AliceAccept
s.
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:
Accept
back to Elaine.Accept
to her followers, by referencing the Accept
by IRI.Accept
.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.
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 :)
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)
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
That is precisely what object capability enforcement is.
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
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).
@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.
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.
@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?
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.
@cwebber i don't see how that's significantly different then passing around a signed/dereferenced Accept object, from a backwards compatibility perspective
keep in mind that use of ld-sigs is untenable in Pleroma
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?
I wrote up a specification draft over on the litepub side of things building on discussions here: https://litepub.social/litepub/lice.html
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
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.
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).