ActivityPub

**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](https://github.com/NodeBB/NodeBB/issues/12448), 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!

0
1

Note that I said "quote**d** posts", not "quote posts", don't @ me! After the last WG meeting @thisismissem@hachyderm.io @trwnh@mastodon.social and I chatted a bit about how NodeBB handles quoted posts, but also in relation to quote posts. I thought that it was an interesting chat that merited further discussion; also because some of it was over my head. When asked how NodeBB handles blockquotes specifically, I replied that blockquotes themselves are rather simple. We set _a copy of the text_ wrapped in `<blockquote>`. The rationale is simple: forums typically represent content in a linear fashion, and quoted posts are a handy way to reinforce subcontext within a topic. A typical topic/thread could have many separate discussions all happening together (aka thread drift), so quotes help others know what you're responding to. We don't have special handling or references to our blockquotes because there is a history in forums of **edited** blockquotes. > Perhaps you want to have a block quote and _add some emphasis_? It's also better netiquette (god, that term is old) to trim down the quote to only the relevant parts. Another upside is that a copy-paste of a post preserves that post to history. That can be useful if the quoted user tries to edit their post later, etc. vis-a-vis the concept of "quote posts", which I take to mean an embedded post within a post, allowing for replies, likes, etc. How that is represented via ActivityPub is probably detailed in some FEP, but NodeBB doesn't implement that yet. It's a more complicated mechanism that requires a lot more thinking through, and to be honest, we haven't had the need for that in the 10+ years we've been building NodeBB.

0
7

**tl;dr** — category actors in NodeBB now have better avatars/pictures! They're generated from the `icon`, `color`, and `bgColor` settings for each category. Did you know that categories in NodeBB can also be followed on the social web/fediverse? Categories, as they are known here, are also actors on the fediverse, so you can find them just like any other account. e.g. @general-discussion @support @nodebb-development @activitypub @liaizon@social.wake.st opened [an issue back in **April**](https://github.com/NodeBB/NodeBB/issues/12507) (!!) pointing out that the avatar/picture served by NodeBB for category actors was not as good as it could be. It's definitely possible to do something like this, although it is usually rather resource intensive. For example, when you paste a GitHub URL somewhere (e.g. Slack), it may try to unfurl the URL and display an image. [GitHub blogged about how they did this](https://github.blog/open-source/git/framework-building-open-graph-images/) using Puppeteer to generate the images. I knew right away I didn't want to bundle what was _basically_ an entire browser runtime into NodeBB's dependencies, so I needed a more lightweight solution. I attempted to build my own SVG string and send that through as a data-uri, but not surprisingly, it was not handled by the implementations I tested. Some more research this week led me to Vercel's [OG Image Generation](https://vercel.com/blog/introducing-vercel-og-image-generation-fast-dynamic-social-card-images), which allows you to create images on the fly using Vercel Edge Functions. Since NodeBB is neither a Vercel app, nor do any people running NodeBB use Vercel, that ruled out this product. However, more research into Vercel's implementation led me to Satori and resvg, a pair of programs that can generate an SVG from HTML, and a PNG from SVG. From there, it was a fairly standard technical exercise to combine these with our font-awesome libraries in order to output our own implementation of this to generate colourful category avatars for its category actors. For now, they are only generated on-demand when a category actor is requested, but if there are applications for the icons to be used elsewhere, then we could look into having them generated on direct file request. Enjoy! ![0ff837a6-8f76-4c81-a81f-d4ad6d24660e-image.png]()

2
3

Today I tagged the v4.0.0-beta.2 release purely to fix a single issue — `Update(Note)` federation. It turns out that just sending the `Update(Note)` activity was not enough, the underlying object needed to also have the `updated` field set in order to Mastodon to process the update. My guess is Mastodon checks that field and only processes the note if the value is greater than the last known value. I'd write it off as a Mastodon-ism, but it's actually better to have that property present, so now it is. **Edit** — does anyone know if Mastodon handles `Update(Tombstone)`? I sent one and Mastodon didn't do anything, which is technically ok. NodeBB handles it like a soft delete and removes it from public view.

0
0

Last friday I [quietly tagged a commit on the `activitypub` branch](https://github.com/NodeBB/NodeBB/commit/86f624f8172fb96fbd3c83683affd8814e8b5156) with `v4.0.0-beta.1`, which signals that the ActivityPub integration is now ready for beta testing. For the most complete (yet readable) list of new functionality from the alpha, check out [the "Road to Beta" project page](https://github.com/orgs/NodeBB/projects/2). **tl;dr** — some new features and a lot of fixes * Editing a category now issues an `Update(Actor)` * `replies` is now populated and responds with an OrderedCollection of direct replies ([see the post about _that_](https://community.nodebb.org/topic/18156/regarding-replies-and-inreplyto-traversal)) * Proper `sharedInbox` support * Better indicators for content that comes from non-local (aka "remote") users * Conversational `context` synchronization mechanic ([corresponding post for that](https://community.nodebb.org/topic/18184/the-current-state-of-context-resolution)) * Moving a topic out of the "uncategorized" category will now federate out an `Announce` By and large most incompatibilties have been resolved, although if you do find some issues, please do let me know in the corresponding bug report thread. I'm looking to wrap up the year with some of the more difficult projects I've put off * [Object Integrity Proofs](https://w3id.org/fep/8b32), which will also enable [Inbox Forwarding](https://www.w3.org/TR/activitypub/#inbox-forwarding) * Better handling of "Open in App" signals from third-party instances * Post visibility support (or at least better handling so non-public messages aren'y unceremoniously dropped!) * Ongoing integration with FEPs [400e](https://w3id.org/fep/400e) and [7888](https://w3id.org/fep/7888)

0
3

Now that the *alpha* version of NodeBB v4 has been released, it means that people are starting to look into using NodeBB for testing (or if they're really looking to have fun, production.) The first step in enabling those intrepid individuals is [providing documentation](https://docs.nodebb.org/activitypub/)! While a little bare-bones at the moment, I've written up a brief summary of what NodeBB brings to the ActivityPub landscape, as well as a run-down of various settings/toggles/switches, and how to switch over to the code branch that enables ActivityPub integration. What I *don't* know is what's missing. There's a lot about NodeBB's integration that's very obvious to me, since I built it, but what don't you see that you'd like me to write about? Let me know. Thanks!

0
0

I'm happy to announce that I have tagged the latest commit in the `activitypub` branch as `v4.0.0-alpha`. That designation means (mostly symbolically) that we have moved past the "proof-of-concept" stage of ActivityPub research and development, and into the alpha phase. This release has been a long time in coming. Work on the ActivityPub integration back in late 2023, although work accelerated around February of this year. The initial idea was to create a proof-of-concept build of NodeBB that could communicate with other fediverse apps, and federate local content outwards for other applications to consume. As it turns out, it is difficult to temper your expectations when using a protocol with implementations that expect richer compatibility than one can provide! It seemed like a disservice to only offer a minimal subset of expected features, and so we started a deeper integration into ActivityPub with the aims of providing full user-to-user following, notifications, and two-way communication. In the interim, [FediForum](https://fediforum.org/) happened, causing us to once again re-evaluate our short-to-medium term plans. Devs from NodeBB and Discourse, along with many other interested parties, formed the SWICG Forum and Threaded Discussions Task Force, which aims to promote the use and broader acceptance of threaded discussions as a modality of communication, as opposed to the expected "microblogging" format. ## What this release contains The alpha build contains a fully-capable ActivityPub server instance, including: * Two-way follow relationships between local and remote users * Two-way communication with fediverse content * A dedicated page (`/world`) to view remote content that is not organized into local categories * Categories followable from the fediverse (via FEP 1b12) * Integration with local flagging tools (reports sent to originating server) * Server-wide domain blocks (allow/deny list capability) ## What this release does not contain * Support for emoji (images are federated out, which are sometimes stripped) * Support for non-public notes, as NodeBB does not currently have the facility to maintain or display them. Research on this problem is ongoing. ## Roadmap Now that the alpha has been tagged and released, I will be making our working roadmap public &rarr; [you can take a look at it here](https://github.com/orgs/NodeBB/projects/1/views/1) I will be starting a new backlog/roadmap for beta items, and existing backlogged items will be carried over. ## Final Thoughts We wouldn't have even thought to implement ActivityPub if it were not for the funding granted to us by the NLNet foundation. They allowed us the runway to pursue the necessary R&D work, and we're pleased that everything has been pointing positively so far! This entire time, it has been particularly satisfying to continually see the integration working on this instance (the NodeBB support forum). Expanding the reach of NodeBB beyond the confines of the "local" mindset and into the "global fediverse" mindset has been daunting, but is well worth the price of admission. I'm happy to also say that now that we've proceeded to the alpha stage, it signifies a commitment toward a beta phase, then an RC, and then towards the release of NodeBB v4. ActivityPub has legs, and we're invested in making it work!

1
1

Is there a requirement that an activity ID be unique? Reason why I ask is it seems prudent to save a list of encountered activities, and drop those that have been seen before. However that caused me to run head-first into a NodeBB regression because we ourselves don't actually send unique activity IDs. For example, a `Follow-Undo(Follow)-Follow` chain would have the two `Follow`s with the same ID, since we just construct them ad-hoc based on request data. Easy fix is to throw in a timestamp there, but it got me wondering about whether there were uniqueness expectations at all, or whether I was being overzealous in checking for it.

1
0

I may regret creating this topic but here goes. If you experience a bug or other unexpected behavior while using NodeBB and its related ActivityPub integration, please post it here so it can be tracked and resolved. No formal process as of yet, and we're still at pre-alpha so expect many things to be broken or unavailable 😅

1
0