Wave

ActivityPub - Annoyingly useful

Melody

So, ActivityPub. You probably love its existence, considering that you probably found this article (or me or the creator of Wave) over one of the services implementing it, be it Mastodon, Misskey (or one of its many soft and hard forks), Plemora/Akoma or other. And they all do a great job of providing a nice UI for all the things you can do with ActivityPub (except for Akoma, I will stand with my take of its UI being badly made). What you don't see is the protocol layer though. And this is where it gets ugly.

ActivityPub has a few parts. Endpoints and what you transmit to and from those endpoints. The endpoints are fine. One inbox and one outbox endpoint per user and the same for the entire server too. Easy to solve with path parameters. The public page (the one you see when visiting the user) could be on that path too or a different one. Don't matter. Easy to do.
Webfinger? Also easy to do. Not funky yet. All nice and consistent.

The problem is what you have to transmit. Because ActivityPub is based on Json-LD. A dynamic extension of Json. Json alone would be fine. But the -LD part makes it really hard to manage in strongly typed languages. You either have to define every single element a message could have or go with whatever generic thing your language of choice has, in Go's case any. Or you could do what Mastodon and all those tutorials and guides on activitypub.rocks do and just treat everything as plain old json, no fancy extensions. And even with that, you still have fields that can be either an url to an object or the object directly. Welcome back any. Still a lot better to have most fields defined than to just throw everything into a map[string]any.

And speaking of Mastodon and activitypub.rocks, there are very few resources that show how to work with ActivityPub in a good way. For Mastodon, you have to know Ruby and download the entire source so that an IDE can decrypt all the includes happening for you. For Misskey, you have to know Japanese and also first figure out the project structure (hint: I still haven't found where they define their ActivityPub data). Akoma? Haven't looked at that yet. GoToSocial? Implemented in Go, but in a horrible way. No clear starting points that you could follow and also uses a fork of the ActivityPub vocabulary module, which went the route of everything that could be included will be included, even fields that I haven't seen on any traffic. And the guides and tutorials were all either the official specification of ActivityPub but reworded or the same webfinger to one minimal account to one minimal message. Not useful either.
So, the only option left was to reverse-engineer it in a live environment. Aka booting up a test server yourself and just monitoring all traffic and poke at it with curl or another rest explorer. Slow and annoying. Until I found https://activitypub.academy. A Mastodon server where you can get an anonymous account for a day, use it like you would use normal Mastodon, except that you now have a tab logging (almost) all ActivityPub actions, including the source json. Incredibly useful for figuring things out.

And that's about where I am right now with Linstrom. I got the ActivityPub types and events figured out (I hope) and now have to get working on the endpoints and linking it all together. And since I wanted to make Linstrom a good example of how you could work with ActivityPub, I tried my best to explain what different values are, what they are intended for as well as a decent project structure, seperating web endpoints into different categories (like ActivityPub, WebUI, Mastodon API, etc), but all under the umbrella of endpoints.

Additionally, I also plan to maybe integrate a more consistent gRPC based API as parallel to ActivityPub, focused on having one source of truth for the endpoints and data formats (a protobuf file) and maybe being extensible too via more gRPC and protobuf. But that'll only have a chance of happening once I have the main server running.

About the Author

Melody

Trans catgirl doing software things

Mia Rose WinterReviewer

This might also interest you

A Mystery Involving Hardware Security Modules and Value Tokens

Forbidden Tempura 10/7/2025

Context Historical context In July, 2021, the phenomenon known as the “Gigaleak” continued. The Gigaleak was a drip-feed of part of the ill-gotten data from the 2018 Nintendo data breach. On July 20, 2021, the iqcvs.tar.xz file was uploaded to the now-defunct file sharing website anonfiles.com and thereby made available to the public by The Hacker Known as 4chan. This file contains a dump of CVS repositories. The repository sw contains the BroadOn network infrastructure around the middle of the year 2006. This is shortly before the Nintendo Wii launched. The network infrastructure was initially launched alongside the iQue Player, a variant of the Nintendo 64 featuring downloadable games and some anti-piracy measures of questionable quality (non-HTTPS link) intended for the Chinese market, which was and still is notorious for being particularly prone to piracy. It was developed by a company then called BroadOn Communications Corp., a California corporation. The iQue Player u

ITInfodump

A Brief Look at the 3DS Cartridge Protocol

Forbidden Tempura 6/2/2024

About a week ago, there has been a little addition to the 3dbrew wiki page about 3DS cartridges (carts) that outlines the technical details of how the 3DS cartridge controller and a 3DS cartridge talk to each other. I would like to take this opportunity to also include the 3DS itself in the conversation to illuminate which part of which device performs which step. I will then proceed to outline where I think the corresponding design decisions originate. Finally, I will conclude with some concrete ideas for improvement. But first, we need to talk about parallel universes This protocol makes no sense unless you have a basic overview of the 3DS AES engine. The 3DS AES engine can load 128-bit AES keys in two ways: Using key-derivation from a keyX and keyY (officially called KeyId and KeySeed, respectively). Directly specifying a full AES key. The key derivation from a keyX and keyY works as follows: AES key = (((keyX ROL 2) XOR keyY) + C1) ROR 41, where ROL is left rotation on a 128-bit

ITGamesInfodump

Reconstructing the 3DS Bootstrapping Process at the Factory

Forbidden Tempura 5/13/2024

Motivation The Nintendo 3DS was a fairly popular console. In spite of that, surprisingly little is known about how it is put together at the factory. Working with information that was uncovered during the so-called Gigaleak, I will try to recover as much information as I can about the manufacturing process up and until the point the 3DS is able to complete a normal boot sequence. One-Time Programmable (OTP) region Every 3DS ships with 0x100 of one-time programmable persistent memory at 0x10012000-0x10012100, containing console-unique keys and information. This obviously has to occur before any normal firmware runs on the system because significant amounts of all data written would fail to account for console-unique information and thus the encrypted values would be all encrypted for the wrong keys. An interesting observations: ctr.7z (SHA-256: 8b05072361254437277576d53c08b95e5f076c6b33a2871fad74eaa5561d1d38) ctr/sources/bootrom/CTR/private/build/bootrom/ctr_bootrom/ARM9/main.c has a pr

ITGamesInfodump
Powered by Wave