blog.erincandescent.net

Tag: activitypub

Right of Reply

Who's allowed to reply to your posts?

Truthfully, anyone who can see it (and nothing can prevent someone who wants to from seeing something you make public). If they have to, they can link, copy and paste or screenshot it, and fundamentally there's no way of stopping them.

But that's not really what we're talking about when we talk about replies on social network's. What we're really talking about is who's replies get to show up under your post; or, in other words, who gets to borrow your audience.

The centralised networks have chosen to give the post's author control of this; and for good reason: it's not good to let harassers, stalkers and spammers borrow your audience.

In general, the centralised networks will prevent blocked users from replying, and will (often) also reduce visibility of posts by users who were blocked after said post was created. Occasionally they will even grant the post author the ability to "hide" specific replies (generally behind a "Show hidden replies" button or similar)

Defining Replies

In ActivityPub, like the pump.io protocol and OStatus before them, replies are identified by having an inReplyTo field containing the ID of the parent post.

If you send a post inReplyTo one of mine to my instance and I block you, then your reply won't show up on my instance. However, if you send it to a third instance, that instance won't be aware of the block that exists between us (and it shouldn't be: federating blocks even to the blocked user's instance is already a harassment vector!)

This means that, today, blocks only work to stop people borrowing your audience if the blocked user is on a server which honours your blocks (or is universally defederated). This, of course, means it's not reliable; it is relatively trivial to patch out incoming block handling from any piece of software (or just delete the block from the database).

(It's also possible for the occasional block to just go missing - as with any message; and if you're on a Pleroma or Akkoma instance, then your blocks probably aren't federated outwards: they disable this by defult, because as mentioned before it is a harassment vector)

Worse, it grants a false sense of security: their posts will disappear for you, but not for people on other instances you federate with.

An argument could be made that this could be fixed with better moderation, but there are always going to be edge cases, disagreements, and new hives of scum and villainy that aren't blocked yet.

It's hard for me to tell, but it appears that BlueSky is making the same mistake (it is possible that their approach will involve more widely federating blocks, but it's hard to tell; and federating blocks more widely comes with its' own harassment concerns)

Solutions

There is no 100% solution to this problem; even if the protocol did not include replies, people would find a way to make them. The corner of the network that hates you always has the option of reinventing Google Sidewiki or similar systems in which replies exist outside of the network itself.

But that's, on the whole, fine: what we care about is the replies that our friends on "good" servers see. And the fix is fundamentally simple: We change the rule for which replies are displayed from "anything inReplyTo this post" to "anything inReplyTo this post which was approved by the author of the parent post" (and then we introduce an ApproveReply activity to federate those approvals).

Approval can then be done automatically by your instance, simply by following your block/mute list or according to whichever rules you choose.

Some might raise issues of censorship here, and they're not completely invalid. Giving absolute control over replies to someone comes with risks; but I think there are two important ways to mitigate this:

  1. The approval only shows what replies show up under a post; it doesn't prevent the backlink from appearing when viewing a reply.
  2. Unapproved replies need not be removed completely; the can simply be hidden behind a "Show hidden replies" button (similar to the one which Twitter has, and which often hides a bunch of cryptocurrency scams). This is, fundamentally, an implementation decision.

For migration purposes, we can add a repliesRequireApproval (or similar) flag to posts to indicate that they are opting in to the new mode; over time, more and more instances will upgrade, and more and more posts will be in approved reply mode.

A better moderation system is possible for the social web

The Fediverse has a bit of a moderation problem. In fact, it's had one for quite a while.

When I wrote the first draft of the ActivityPump spec back in 2014, it had an Authorization section which began like this:

Authorization

This is a stub, to be expanded. OAuth 2.0 is an open question.

ActivityPump uses authorization for two purposes; first, to authenticate clients to servers, and secondly in federated implementations to authenticate servers to each other. These methods are based upon the OAuth 2.0 authorization framework as specified in RFC6749.

It continued on, but it was broadly a sketch. I was hoping we'd elaborate some more on this as a working group; instead, we spent 4 years going around in circles arguing with each other about minor details. The SocialWG was a working group divided; if you ever wondered why it produced two families of incompatible social networking protocols, this is why! (and also one of the most perfect examples of the failure modes of standardization bodies)

At the end of the process, I'm pretty sure that everyone involved was exhausted. Four years is a long time to spend working on one thing, never mind a thing which such a tumultuous development cycle.

So if there's something that's obviously missing from ActivityPub that you think should be there, here's your rationale.

An aside on working groups and standard bodies

From this you might conclude that the standards process is fundamentally broken; I think I'd say it can be, but it doesn't have to be. The biggest problem we had is that we effectively had two factions within the working group, each looking for the legitimization of their preferred solution in the form of being adopted as a W3C standard, and with some fundamental and irreconcilable differences of opinion with regards to approach

Despite all of this, I'd be happy to dive back into a working group chartered specifically to make a specific set of improvements to, or more generally maintain, ActivityPub. Having that more defined scope vastly reduces the risk of the kinds of fracturing we had before.

Anyway, back to moderation

This hell we're in

The basics of ActivityPub are that, to send you something, a person POSTs a message to your Inbox.

This raises the obvious question: Who can do that? And, well, the default answer is anybody. You might think "Wait, isn't that a bit like E-Mail? Why on earth don't we have an enormous spam problem?" and my answer to that is: you know, I just don't know. I guess implementing AP has been too much effort for spammers up until now? Perhaps it has just been easier to sign up for accounts on open Mastodon installs?

Anway, this means that we're dealing with things now with the crude tools of instance blocks or allow list based federation; and these are tools which are necesssary, but not sufficient

The hell of shared blocklists

Shared blocklists are the most commonly suggested solution; there are even crude tools for implementing them today.

They can help, but they can also cause enoromous harm. Back in 2014/15, during the Gamergate harassment campaign, there was a fairly popular Twitter blocklist, widely used by the gaming media, pupporting to block the perpetrators of said campaign. It also blocked a bunch of random people - particularly trans women - who the creator had previously gotten into arguments with; because it was based upon their personal block list. Those caught in the cross fire found their ability to reach out to journalists and e.g. promote games that they were developing substantially curtailed.

I don't mean to cast aspersions on the creator here; I don't think this was done with ill intent, and I'm especially willing to give benefit of the doubt with regards to personal blocks made by someone under continual attack. However, the collateral damage was sizable.

The trust one must place in the creator of a blocklist is enormous, because the most dangerous failure mode isn't that it doesn't block who it says it does, but that it blocks who it says it doesn't and they just disappear.

I'm not going to say that you should not implement shared blocklist functionality, but I would say that you should be very careful when doing so. Features I'd consider vitally important to mitigate harms:

  • The implementation should track the source of any blocks; and any published reason should also be copied
  • Blocklists should be subscription based - i.e. you should be subscribing to a feed of blocks, not doing a onetime import
  • They should handle unblocking too - its vitally important for a healthy environment that people can correct their mistakes
  • Ideally, there would be an option to queue up blocks for manual review before applying them

That said, shared blocklists will always be a whack-a-mole scenario

Use our superpower

Why are we allowing random people to send us messages, anyway?

The answer, of course, is discovery - we want to meet new people - but perhaps letting any random person send us a message is not ideal.

In real life, we normally meet people either through introduction by mutual friends, or in community spaces that we both inhabit. It's an inherently social discovery method.

And - hang on - we're building a social network here! This feels perfect for us!

So here's a really simple idea: We let trusted friends hand out "Letters of introduction" to people they trust, and we make these letters carry information about who handed them out, so when someone turns up who we really don't like, we can tell our friend "dude, not cool".

Now we just need to decide who we trust to introduce new people to us, and who we are willing vouch for (these are probably but not necessarily the same lists). This is going to come down to policy, at the end of the day, but some possible options include:

  • Just an allow-list of people we trust, or
  • Any instance that someone on our instance has been following someone from for more than N days, or
  • Anything you can imagine

(We probably even have multiple levels of trust, and probably even pass those along inside our letters of recommendation, so people can make decisions)

This is effectively an allow list system, but it's an anarchic one which allows discovery. It's not a foolproof way of stopping bad actors from getting into our feeds, but it should be a fairly effective one; they need to find somebody that we trust to introduce them. And, well, if someone keeps introducing their racist friends to you, you're probably not going to stay friends with them for long (or are at very least you're hopefully going to ban them from introducing new people to you)

Note that in this system we don't share blocks; blocks become something which flows naturally from the fact that neither we nor any of our friends want to talk to someone. Manual moderation is still required when there isn't unanimous agreement about someone; but these are the sorts of complicated cases which should be left to human judgement anyway

For the curious, the technical underpinnings I'd go with for this system are Macaroons


Closing notes

  • I am intentionally biasing systems towards inclusivity here; I'm willing to tolerate some degree of potentially avoidable harassment in order to avoid excluding people unintentionally.

    Other people may wish to draw the line somewhere else; these are my biases from having seen ostracism used as both an intentional and unintentional weapon.

  • This is not the be-all and end-all of protocol evolution discussions we can or should be having around abuse. There are other issues (around e.g. reply threading) which we can and should close independently.

    A lot of those are simultaneously more straightforward and more technical, however (that is to say: they're less about social dynamics and more about addressing specific aspects of the protocol)

  • Are you an ActivityPub implementer who'd like to implement something along the lines of what's in this document? Please, let's talk and flesh this out!