on the topic of ActivityPub: C2S (or how to design an alright protocol and have nobody use it)
if you were ever curious about (or god forbid, tried to implement) ActivityPub, chances are you've stumbled upon this cutesy looking image
[image courtesy of https://activitypub.rocks/]
it all looks fine... but what is “/outbox”? why do we have an actor reading from the “/inbox”? isn't inbox only for sending messages from one server to another? what's going on???
overview
what you see here is how ActivityPub was envisioned to be used. you had a server that interacted with other servers to exchange messages, which was supposed to actually be quite dumb. it sends stuff, it stores stuff, that's it.
and then, you had the client, who was actually quite smart! it read posts sent to it through the “/inbox” endpoint, it sent activities to the server to the “/outbox”, which the server then federated... all of this basically resulting in the client doing the majority of the work for the server.
and this idea was cool, at least in my opinion...
the good about C2S (as i see it)
the client-to-server protocol is kind of vague in points, but as i see it, it would've solved a lot of the issues i have with AP thus far.
1. up to date information
you've probably already stumbled upon this. you see a post that has 15 likes on your instance, but it has 3 likes on cats.social
and 400 likes on timsweeney.zone
which is the parent instance of the author of the post.
this is all due to the very quirky way likes get propagated across fedi, which in part is mastodon's fault.
[image courtesy of https://seb.jambor.dev/posts/understanding-activitypub-part-3-the-state-of-mastodon/]
mastodon only sends the like activity to the author of the post, and due to “performance reasons” mastodon doesn't forward the like to the instances of its followers, resulting in the like count varying from instance to instance.
(to my knowledge the pleroma family does do that, but still, there's a better solution...)
considering that ActivityPub is supposed to be a series of interconnected documents, with a C2S client and a conformant ActivityPub implementation, the client would directly query the parent server for the post's ActivityStreams representation, and check its likes
collection.
so, if a C2S client wanted to fetch this post [https://miku.place/notice/AfPB01gN5xEJ8VzB8S]
it would:
1. fetch the https://miku.place/objects/391f3893-009c-4b76-a39f-eded2e8941f6
object.
2. fetch its likes
collection (if the server supported it) to get the amount of likes this post has
3. fetch its shares
collection (if the server supported it) to get the amount of shares this post has
4. fetch the actor
responsible for the note, to then get their name, avatar, etc..
5. finally be able to display it, with all the up to date information!
same goes for user information, and other variable things.
this of course could be implemented in mastoapi clients (and as far as i know, a some implementations do that), but in C2S as far as i can tell it's the de-facto way of fetching any information.
2. any conformant implementation should be able to speak it
considering it's part of the spec, any conformant ActivityPub implementation would be able to speak at least a minimal subset of it (as described above).
meaning that your client would be able to connect to Mastodon, Pleroma, Misskey (but also WriteFreely, Bookwyrm, Funkwhale, etc...)
it all would depend on the client supporting all the different types of Activity Vocabulary objects.
the bad
C2S isn't without its quirks of course.
1. timelines don't exist
you only get what you receive in your inbox. period. no timelines, no anything.
of course, you can extend C2S with your own implementation, but then it's not conformant and you have to hope other clients support that too and yadda yadda...
2. too much implementation-defined behavior
so, C2S specifies how you're supposed to interface with the server... but it doesn't specify how you are supposed to even securely tell the server that you're @ishmael@mephistophel.es
and not someone completely different.
as defined in the ActivityPub spec:
Unfortunately at the time of standardization, there are no strongly agreed upon mechanisms for authentication. Some possible directions for authentication are laid out in the Social Web Community Group Authentication and Authorization best practices report.
if you follow the Social Web Authentication best practices report, you'll learn that:
Client to Server
ActivityPub clients authenticate against a server using OAuth 2.0 bearer tokens.
Bearer tokens may be acquired out of band. They may also be acquired using OAuth 2.0 authorization. To discover the correct endpoint for authorization, clients should use OAuth-Server-Metadata on the host part from the actor's ID URI.
which sounds good, but of course is only a recommendation that no server has to follow.
3. the base is kind of limited
you get as much as ActivityPub defines. the rest is implementation-defined and not standard. simple as.
4. and of course, the elephant in the room
there's genuinely one semi-complete C2S implementation. and its only for android. i'm talking of course about AndStatus
so we have no C2S clients, what does that result in? ah right. no C2S servers, lol. supposedly Pleroma (and by extension Akkoma) support it, but reading up on it it's kinda half-baked and not always works properly.
this kind of results in a chicken-and-egg problem, that in order to develop a C2S client, you need a conformant C2S server to test against... for which you then need a conformant C2S client to validate that it works properly. ouch.
so what went wrong?
mastodon.
mastodon is by far the biggest implementation of ActivityPub and the most popular fediverse software to date. and it omitted C2S in favor of the mastodon api (or thereafter referred to as mastoapi).
if you wanted to interface with a mastodon server, you had to talk with it via the mastoapi, as there was no other way. so of course, when new AP implementations came to be, they also had to implement mastoapi if they wanted user apps to be able to talk with them without waiting for them to implement their custom API. (notably, Misskey still doesn't implement mastoapi)
all of this resulted in mastoapi being the de facto standard for client to server communication, completely sunsetting C2S.
closing thoughts
i like C2S, i want it to be a viable replacement for mastoapi.
i've been thinking about writing a library/client for C2S to implement it in Toki, but it's still a far ahead thought... but who knows?