ʕ•ᴥ•ʔ River's Blog

Private accounts don't work on Bluesky or Mastadon

Over the past few weeks, many people who were previously unaware of anything to do with federated or decentralized social networks became aware, as Bluesky Social has risen to prominence following a mass exodus of the Twitter platform. Prior to this sudden burst of energy, Mastadon also got a short boost in attention, as did a number of more standard social media platforms, such as Tumblr.

Bluesky, of course, implements the AT Protocol, and Mastadon implements the ActivityPub Protocol. What both of these protocols lack is what I will call an ideal model for allowing users to create private/hidden accounts and posts. That is, even if the bare minimum functionality for hidden accounts exists, it is implemented in a non-ideal way that denies users the right to access-controls for their own content after hitting post.

This blog post discusses the issues with existing privacy features on the two popular decentralized social media networks, and discusses what features would help fix this. I propose that these networks are unsuitable for private accounts, and develop the beginnings of a plan for how we could go about creating a protocol with private accounts in mind.

Privacy Models

Instagram

Let's talk first about what an ideal model is for private accounts and posts. Think for a moment about Instagram. Most people that I follow on Instagram have private accounts, where you need to request to follow them, and only once approved can you view their posts. In addition, Instagram has a "close friends" list, which allows users to post exclusive content which can be viewed only by a select number of their friends they've identified as being within their inner circle (or whoever they want to add to that list, the choice is theirs). If at any point, the owner of a private account wants to remove a follower, they can do so. That follower will no longer be allowed to view any of the posts by that user. Even if they made copies of some of those posts (screenshots, downloads, etc), they will be entirely incapable of receiving any of that old content from the server. They will be entirely dependent on their own prior archives from before they were removed. And let's be honest here, very few people save posts from everyone they follow.

Mastadon (ActivityPub)

On the other hand, let's examine how one might try to implement a private account on an ActivityPub platform like Mastadon. The user would configure their client to save a whitelist of "trusted users", who are authorized to view their posts. This would be analogous to the Instagram user's approved follower list. When the Mastadon user creates a post, the client would create an ActivityStream object, and specify the "to" field to only include that whitelist of users, so that it would be hidden to everyone else. The object would NOT be listed as publicly viewable (good!).

We've done the first half of what we want -- allowing users to post only to their trusted whitelist of followers. The hard part comes in giving them the ability to remove users from that whitelist, specifically for posts that were created using the old whitelist.

The standard way to do this would be to delete the old post, and re-create it again, just with modified values for who is allowed to view it. Unfortunately, because of the way that federation works, other servers will have stored copies of your post, so you'll also need to tell them to delete it too. And there's no way to guarantee that those other servers will respect your request. This means that a user who's been removed from the whitelist of trusted followers might still be able to view your old posts if their own homeserver doesn't want to respect the request to delete/edit their copy of the post.

Bluesky (AT Protocol)

As for the AT Protocol, they specify "Non-Public Content" within the "Future Work" header of their protocol. In other words, AT hasn't even described the protocol for how private content would be handled, let alone has Bluesky implemented it. Given how much they have on their plate right now, with how many new users they have to handle right now, and how many other features they're still working on implementing, I wouldn't rely on them getting around to private accounts anytime soon.

Where does that leave us?

With all this in mind, it seems to me that good account privacy lies outside the realm of what these protocols deem important. And to their credit, I don't think that's such a bad thing. The ambitions of these federation projects were incredibly high from the start, and with no real guarantee that any of it would take of like it did. These developers didn't need to throw on top of that the logistical difficulties of creating good functionality for private accounts as well.

In my opinion, we shouldn't attempt to hack together a solution using ActivityPub in order to somehow force good account privacy to work. Instead, I think those of us developers who would like to see a decentralized network that is catered towards small social dynamics for friends only (private accounts) should develop a new protocol that doesn't turn this into a logistical nightmare. This protocol would be centered around helping create a network more analogous to Facebook or Instagram, as opposed to the way that the existing decentralized networks mimic the functionality of the massively parasocial Twitter and Tumblr platforms.

Goals and Solutions

Goals

To start, we should identify our goals, before outlining any kind of plan or protocol.

I'd say that the big point for many people who would be attracted to ActivityPub in the first place would be the fact that they're trying to escape the control of Big Tech. Put more succinctly, we're tired of what Cory Doctorow calls "Enshittification", or platform decay -- the constant, intentional destruction of the usefulness and functionality of a platform, while at the same time making it as difficult as possible for the frustrated user to switch away to a better alternative.

As an example, we don't like it when Instagram starts making it harder to control your own feed, while at the same time removing public APIs that would empower you to use external clients that would put the control back in your hands.

What we're trying to do is create a platform that is both good for the user, and also allows the user to leave at any time without being trapped. For a social platform, that means allowing room for other servers to exist which can communicate on the same network, and allow you to talk to the same set of friends you had when using the old server that you switched away from. Again borrowing vocabulary from Cory Doctorow, we want the protocol to keep the "switching costs" of transferring from one server to another low, so that disgruntled users don't feel trapped on their bad server.

In addition, we of course also want it to prioritize privacy for hidden accounts. That would mean that users should be able to control their followers list, and that when a follower is removed from the list, they won't be able to view your old posts still on other servers that cached them. That is to say, servers will not transmit private content to one-another. Private content will only be sent from server-to-client. This way, users don't have to worry about extra copies lying around when they delete or edit posts.

Solutions

I'll admit, I don't have a full protocol designed in my head yet, but I do have a few ideas so far. From the get-go, users will need to have an account with some kind of server that they will use to prove their identity when requesting to view private content on their feed. And of course a content server which stores their posts and other media. These two tasks will probably be combined into a single server.

As for the general communication model, we've already established that clients will have to ping each server individually for the content of every user they follow. This is essentially the same as the way that web browsers do it, when loading embedded content. Perhaps servers will implement RSS feeds for each user's new posts, and clients could then compile all RSS feeds for all your following in order to load each post.

Some questions still remain, such as how interaction (likes, comments, etc) would work, and on which server those interactions would be stored. In addition, I would like there to be some kind of integration with a direct messaging functionality where you could send responses about posts, even if it gets outsourced to another service in order to accomplish it.

I'm going to continue working on my ideas for this, and posting updates on what I create, but that doesn't mean I'm closed off to collaboration or ideas from other developers!