Chats are now federating as limited-visibility posts on the fediverse

tl;dr — you can now send me DMs. I blatently and unforgivingly abused the NodeBB chat system to make this work.


Ever since I started this project at the start of 2024, I knew that posts with limited visibility were going to be a sore spot. ActivityPub has the concept of "addressing", with the following valid entries:

  • An actor (as:Person or similar) uri
  • A followers collection (?!?!?!)
  • The public collection

However, posts and topics in NodeBB have their privileges and access scoped to the category, which meant that while it is able to restrict visibility/posting/etc. to specific users, the system was not flexible enough to handle individual posts with different user visibilities.

Given that limitation, up until this week, if your object did not contain the public collection https://www.w3.org/ns/activitystreams#Public, it was automatically and unceremoniously dropped because there was no way NodeBB could display it to the targeted user without leaking it to other users.

I had gone through a couple iterations to try to figure out a way to make this work, but none stuck (see the follow-up technical post for more details), and I had just about relegated it to the "think on this for awhile" pile until a recent post by @scott@authorship.studio got me thinking outside of the box:

and your forums, direct messages, and inbox can have different feature sets.

Emphasis mine.

Unlike topics and posts, NodeBB's chat system is not constrained by the privilege system, and each chat room has its own collection of members, which in many ways made it a better fit!

I put together a proof-of-concept in a couple days, and we're test driving it now. So my apologies if in the past year you tried to DM me, and I didn't respond. I wasn't ignoring you, NodeBB just didn't know how to handle it, promise!

5 Likes

Here's how NodeBB's chat system differs from other ActivityPub implementations that you might be aware of (*ahem hem* Mastodon):

  • NodeBB will accept and parse all non-public objects, but (for now) only sends out responses directly to recipients (aka "mentioned only")
    • That means "Followers only" posts are accepted but responses are scoped to the individuals themselves (no followers)
  • Mastodon has something called "unlisted" or "quiet public". These are still technically public and are parsed the same as any other topic/post.
  • Mastodon uses "mentions" as a form of addressing, and so the non-public notes are always addressed to the same set of people who are mentioned.
    • NodeBB does not do this. You can mention whoever you want without the message accidentally leaking out because who you mention is different from who is in the chat room.
  • If NodeBB receives a response to a chat message and it contains fewer recipients than expected, it will start a new chat room for privacy.
  • Conversely, if a response contains more recipients, then that user will be added to the chat room.
2 Likes

Read on for the technical stuff regarding limited visibility content.

The actual nuts-and-bolts of this system were actually fairly straightforward. Each chat room contains a member list, and when messages are sent in each chat room, we simply address and federate the note out directly to those users.

When posts come in, they go through a different logic path from public posts. Instead of a new reply/topic, they get added to a chat room, or if the visibility scope is narrowed (addressed to fewer people), then a new chat room is created.

There were multiple iterations in my attempts to get this to work.

Post Visibility

The first attempt involved each post maintaining its own list of recipients. Soon afterwards, it was determined that this would not scale well, and cause pagination issues similar to how NodeBB's soft-deleted posts are handled.

Topic visibility

The second attempt was to limit the visibility of posts within a topic. This made the most sense to start with as public objects as sent and received via ActivityPub are parsed as posts (and groups together into topics).

I quickly ran into database limitations because NodeBB is built on a NoSQL database abstraction. What would be straightforward (i.e. a join against a visibility table) became very very complicated as a lot of that optimized query work is not available with free-form NoSQL structures.

The reality would be that utilising the existing organizational structure (categories, topics, and posts) would end up causing so much overhead and data duplication that the fragility of the system made it an ultimate no-go.

Chats

Once I realized that we could potentially use the chats system for limited visibility, I set about building that proof-of-concept. Having built the chat system some 8ish years ago, I remembered that each user maintained their own collection of message ids per room — perfect! Each chat room's users could simply maintain their own set of messages they were allowed to view.

Alas, the chat system had actually been refactored for performance and simplicity by @baris, and this was no longer the case. Messages were more simply retrieved by timestamp from their chat room join date, which meant I needed to take an alternative approach.

Thankfully, I was able to sidestep that particular problem and altered the behaviour so that if incoming messages narrowed visibility, then a new chat room was created.

1 Like

Wow, that's great to see! And this in particular ...

You can mention whoever you want without the message accidentally leaking out because who you mention is different from who is in the chat room.
... is a very good call.

@julian@community.nodebb.org

Wow, that's great to see! And this in particular ...

You can mention whoever you want without the message accidentally leaking out because who you mention is different from who is in the chat room.
... is a very good call.

@julian@community.nodebb.org

@jdp23@blahaj.zone I've made this same mistake myself (although not in a leaking way). I removed the mentions in a reply and wondered why they didn't get my response!

The fact that this is a UX stumbling block that gets hit by users again and again and again means it's not a great UX!

2 Likes

@julian@community.nodebb.org yeah, horrible UX. talk about violating the principle of least surprised! it's happened to me more than once.

Sharkey bizarrely has almost the inverse UX problem. The 'to' list is separate, as it should be ... but if it's more than a couple of people it extends off the right side of the screen (at least in Firefox) and there's no way to scroll. So I replied to a DM that had five people in it, deleted their mentions from the main text ... and still replied to them because they were on the To line, just not visible.

And then I'm pretty sure that if you DM reply on Mastodon to the Sharkey message, accounts show up in the reply even though there's absolutely no evidence that they were on the message you were replying to (because the mentions weren't there in the text, and Mastodon doesn't show a separate To line, or something like that).
@stefan@stefanbohacek.online I think you ran into this as well?

Easy. Just like email. Yeah right. lolsob.

@julian@community.nodebb.org yeah, horrible UX. talk about violating the principle of least surprised! it's happened to me more than once.

Sharkey bizarrely has almost the inverse UX problem. The 'to' list is separate, as it should be ... but if it's more than a couple of people it extends off the right side of the screen (at least in Firefox) and there's no way to scroll. So I replied to a DM that had five people in it, deleted their mentions from the main text ... and still replied to them because they were on the To line, just not visible.

And then I'm pretty sure that if you DM reply on Mastodon to the Sharkey message, accounts show up in the reply even though there's absolutely no evidence that they were on the message you were replying to (because the mentions weren't there in the text, and Mastodon doesn't show a separate To line, or something like that).
@stefan@stefanbohacek.online I think you ran into this as well?

Easy. Just like email. Yeah right. lolsob.

It would be nice if Direct Messages (DMs) or Private Messages (PMs) were treated like email and only sent to the people you are sending it to.

But generally, on most platforms, if you mention someone in the top level post, they are assumed to be on the recipient list. (Note, some platforms, like Mastodon, treat every post as if it were a top level post.)

Hubzilla has more privacy features, which prevents your messages from leaking to others, but part of that is because we use the Zot protocol between Hubzilla instances, and can set privacy at the thread level (i.e. the permissions of the top level post is the permissions for the entire thread).

When the same conversation is sent via ActivityPub, we lose a lot of control over the privacy of that post. We can and do address it to specific recipients, but other platforms don’t have the same types of access controls, which means we can’t enforce the access control list for that conversation on those platforms.

@jdp23@blahaj.zone might be I can't send messages to you. Not sure if it's a Sharkey thing or a blahaj.zone thing.

Seems to work! WHy did you think it didn't?

Sharkey is kind of a mess these days, sigh.

@julian@community.nodebb.org

Seems to work! WHy did you think it didn't?

Sharkey is kind of a mess these days, sigh.

@julian@community.nodebb.org

@jdp23@blahaj.zone ah okay great! Just wasn't sure because I didn't get your replies (if any, but now I'm guessing you probably just +1'd them which I don't handle yet!)

@julian@community.nodebb.org no, no, i just edited my post, I was confused ... in fact it wasn't working, I'll try from a Mastodon account

@julian@community.nodebb.org no, no, i just edited my post, I was confused ... in fact it wasn't working, I'll try from a Mastodon account

@jdp23 @julian

"I think you ran into this as well?"

I only recall the situation you just described, when I received a mention without being included.

But I have seen others run into similar situations when they just didn't know that tagging people adds them to a group conversation.

@jdp23 @julian I've been pretty aware of this myself, but for some reason, on a few occasions I've replied to posts I thought were private, and were in fact public.

Nothing embarrassing though! It helps to just be nice to people privately *and* publicly.

@Stefan Bohacek @jdp23 @julian “Shadow mentioning” is a thing. (streams) and Forte do it to avoid clutter. Mentions don’t have to be visible in a post/comment to work.

@Stefan Bohacek @jdp23 @julian “Shadow mentioning” is a thing. (streams) and Forte do it to avoid clutter. Mentions don’t have to be visible in a post/comment to work.