The author makes the basic mistake of most of the people implementing ActivityPub services: they want to map the logic of an existing type of web application and contort existing domain objects into encoding/decoding to an "impractically large number" of options. That happens because they want two things in one: a server and a client.
The ActivityPub specification needs to be read with a goal similar to an email server in mind. It should do one thing: receive JSON-LD objects in inbox, process them according to the specification, and(maybe) store them on disk.
The idea of "users", "friends", "posts", "feeds" etc, are concepts that belong to the clients on top of this server, not in the server itself.
This separation between clients and server will also allow better interop/graceful degradation of object types that the client/server don't specifically understand.
This comment raised a whole bunch of red flags for me.
Fist and foremost: Saying that something is like an email server translates for me into "this is an under- and over-specified swamp at the same time, full of quirks, and actually not implementable in any reasonable way". Because that's what email is. I almost can't think of a greater horror than writing an email server from scratch…
I don't know enough about ActivityPub to judge whether it's really like email. I would strongly hope it isn't, as otherwise it would be a tech you should probably better never touch as a developer.
The next thing is: If an ActivityPub server only receives and sends some opaque BLOBs what's the whole point of it?
But when it's not about opaque BLOBs you need to map the structures in the spec to proper types in a statically typed languages as you can't manipulate them otherwise in any meaningful way. If it's not possible to do that because the spec is vague and/or there is no coherent data model behind it that would be just another reason to not touch this tech. Nobody needs the next underspecified, stringly-typed "email".
The email comparison helps people to understand the directional way ActivityPub works, I don't know enough about email (whichever of SMTP or IMAP/POP3/samd you consider that to be) to make a comparison at protocol level.
If [...]receives and sends some opaque BLOBs what's the whole point of it?
There are some rules about how to have side effects for said blobs. Some of the blobs themselves have side effects. That's mostly what ActivityPub is: rules about how to distribute the blobs in the federated context, rules to what to do with the blobs when they reach your servers (when coming from other servers, or directly from clients).
The vocabulary that ActivityPub is based upon, is another whole specification, called ActivityStreams, and which didn't originate in the W3C group. This vocabulary has three (*main) types of objects: Activities - which provide the backbone of ActivityPub (Like, Follow, Create, Update), Actors - basically different types of users (these are the entities that operate the activities) and, Objects - whatever the Activities operate on.
If an ActivityPub server only receives and sends some opaque BLOBs what's the whole point of it?
There's still a difference between "try to black-box the incoming data as much as possible" and "treat the incoming data as opaque BLOBs and assume". The data is mostly JSON-LD which is a far cry from "binary large objects". It is always going to be "semi-transparent" as it will always be JSON. Whether or not you like the "-LD" extensions to JSON (they are heavy, they do have a lot of RDF baggage you may not desire), they give you a bunch of guaranteed "baseline schema" for the JSON objects that you can use for static typing that might be "good enough" for a lot of "meaningful manipulations" (such as following links to pick up related objects; LD => linking data) and that is all easily transparent.
A lot of the schemas beyond "LD" in ActivityPub are client/application-specific beyond most of the JSON-LD basics and should be easy to treat as a black box unless doing client/application-specific tasks. That's not necessarily "stringly typed", it's kind of a classic "serialization onion": The server at best needs to know that it is JSON and it may have JSON-LD metadata for relevant related linked objects (and a few other metadata fields common to "introspection", similar to "headers"). The client can dig deeper and know it is not just "any" JSON object but a more specific schema for a given class of thing the client cares about.
To be honest, this sounds indeed quite like the mess that email is.
If the server isn't just a "dumb 'BLOB' storage" it will need to handle application logic (sooner or later, as this is actually what servers are for)…
But given that the application logic seems to be mostly unspecified, kind of wild west, where every client application can do whatever it thinks it's users like, this will unavoidably end in all the problems you have with email, where the server needs to know about all the specific details, quirks, and idiosyncrasies of every client ever built.
The whole concept reads like an implementation of "'Postel's Law' fallacy".
The balance of client/server shared knowledge will always be a hard balance to strike in any protocol ever invented by people.
At least in contrast to email there is a stronger/higher baseline: HTTPS (primarily), transferring primarily one MIME type (application/json) and one "document" format (JSON-LD). The "headers" metadata and "content" are in the same parser format (JSON). That combination alone is far narrower than email protocols (which needs to support nearly any MIME type at any point in any envelope, the headers and content of envelopes have always been different parsers and much of the MIME parsers were bolted in after-the-fact making things worse).
application logic seems to be mostly unspecified, kind of wild west
Other comments in this thread point to the larger "stack" of specifications beyond ActivityPub. ActivityPub itself is just one "layer" in the "stack".
That stack does rely on JSON-LD itself very heavily and many of the clients are in languages where JSON-LD tooling alone is "well-typed" without much in the way of further schemata. I can appreciate where in some static-typed language backgrounds most everything defined as stacks of JSON schemas starts to feel "stringly typed" and idiosyncratic. I don't agree with that sentiment and think JSON in general is far from the worst of "stringly typed", but I appreciate where that sentiment comes from here even if I disagree with it.
I think the surface area overall is a lot narrower than email and many parts of the "stack" are better defined, especially for specific client types. I think there will be some in-theory avoidable problems that resemble the idiosyncrasies with email, but I think in practice they still have a smaller "blast radius" than any similar problems in email.
At least the "stringly-typing issue" seems to boil down to having proper JSON-LD machinery in your language of choice. (In strongly typed languages some code-gen likely.)
Whether a new protocol should really be HTTP-based remains still a question to me. But OK, it's fashionable right now, everybody is doing it, so I can understand why someone would chose to go down this route. HTTP/3 is even quite good (if only a little bit to complex; but that complexity is actually inherent so likely better when it's contained in one place).
I think we have to generally assume HTTPS is the "new Telnet" for protocol bootstrapping and may be so for some time to come. Everyone has HTTPS debugging tools of every level "already installed" (curl/httpie/web browsers/fiddler/etc) and are mostly already trained in them. Every language under the sun has strong HTTPS libraries. Meanwhile, HTTPS gives a nice baseline for things like security (TLS was designed for multiple protocols, but let's face it is best tested and deployed in HTTP and always has been), caching, compression, many quality-of-life and quality-of-service tools. It's so much easier to bootstrap protocols from HTTPS as a baseline than "from scratch like an Apple pie" just as HTTP and Email themselves bootstrapped from Telnet. In the post-TLS era, bootstrapping directly from Telnet doesn't seem like an easy bargain anymore and yeah there are definitely advantages to getting your TLS and a bunch of other useful features/services "for cheap as nearly free" all at once in something like HTTP/3 (even if that is inheriting possibly "a lot of complexity").
You don't seem to have much appreciation for how elegantly handled email is.
I for one have awe & respect for works like Dovecot, which can elegantly decompose a couple different ingress-email pieces of work into special-purpose daemons that each can be scaled & operated independently. The system is practically ancient at this point but a model of how powerful & amazing clearly separated concerns & loose coupled systems are.
You've been persistently negative & calling this all a mess. But it's unclear what you think is elegant & graceful, that does work well. And most of your accusations about things being bad and awful and messy and wild west and postel's law fallacy... none of them have refutable claims. None of them make a position that anyone can argue with. You just spread negativity around & insult thinks in vague terms. It's not very hackerly of you to make a bunch of mean-spirited assertions that arent even backed up enough for anyone else to go verify or test.
Cut the FUD man. Adjust your attitude some. Don't be Mr Rain. Not cool. Be cool.
It's both true than Dovecot is an elegantly designed piece of software and the protocoles surrounding email are a complete mess with decades of bolted on additions and a most used implementation - Gmail - which likes to do things in peculiar ways.
I think the complaints you see here are entirely legitimate. Anyone having been doing this job long enough knows that designing good protocoles is insanely hard and exemples of poorly designed ones in the commercial world abound. It would have been more surprising for the feediverse to get that entirely right than the reverse.
I say that while agreeing with the original comment which points out that a good implementation should solely focus on the specification and leave everything else to the clients.
The application logic is not mostly unspecified, but implementers seriously need to start actually reading the whole thing, and that includes reading the ActivityStreams specs and JSON-LD spec, since it seems like a whole lot of the objections comes from ignoring that there are several more documents to read other than just ActivityPub spec itself even though these documents contain explicit references.
If one were to implement it on top of a RDF database then it isn’t any different than a typical backend taking in SQL (or sparkQL) and spitting out json to the client.
People seem to want to fit a square peg in the round hole and then you have servers bucking over a handful of users.
I spent a day or two looking into this when the hype machine was going strong and it’s really not all that bad (with the right abstractions, I suppose).
E-mails are not opaque blobs, and neither are ActivityPub messages. The point is that at it's lowest layer an implementation should care about receiving messages addressed to one or more Collections. That's it. It makes implementing a functioning ActivityPub implementation a lot easier.
The next layer up then specifies some rules for how to process those messages: Like on an e-mail server, if a message is sent to your "local" server intended for onwards delivery, the server must forward it on. Otherwise it is added to an OrderedCollection - effectively a mailbox.
The spec then sets out a structure for giving the messages an Activity type that determines further fields, and for some of these activities there are rules specifying how the relevant Actor's should act when those activities / messages are processed by them.
You can decide to do that synchronously when receiving the message. Sometimes that may be fine. But you can also strictly layer the implementation and deliver to a collection first and then asyncronously have workers process those messages. What you in either case ought to do for your own sanity is to at least logically separate the low level message pump (inbox/outbox) from the processing of activities.
For starters, doing this separation cleanly makes writing a scaleable implementation far easier.
you need to map the structures in the spec to proper types in a statically typed languages as you can't manipulate them otherwise in any meaningful way
This is just not true. You can handle dynamic structures in statically typed languages just fine. It is in any case irrelevant, as ActivityStreams (which ActivityPub is based on) defines a typed vocabulary [1]. An implementation can choose to dynamically process extensions or it can choose to statically type the activities it understands and treat the rest as mostly opaque blobs other than the envelope/addressing -- this is exactly why it's beneficial to apply the layering as suggested with the comparison to e-mail and decouple the message pump from the processing of activities.
OK, but for someone who wants to build a useful tool that does what the author wants, "interacting with the Fediverse", such as federating with Mastodon, how useful is doing that one thing?
It depends on your goal. If your server is just a tool you use, you can ignore lot of concepts. There is no local timeline, there are no users, all follows belong to a single user, etc.
I can't find the link but a while back there was a post on the front page about how to get a findable, read only ActivityPub profile by just uploading some static JSON files. Not exactly a Twitter competitor, but you don't need much to start exchanging messages.
I think this is the wrong way of looking at it. If you're doing the whole stack, sure you will end up implementing quite a few things.
But consider that you can write a generic ActivityStreams server without supporting any of the ActivityPub activities. Now you have a generic platform to build on.
Tack on a tiny bit of support for e.g. addressing etc. as found in ActivityPub and you have what you need for federation.
With that generic platform, doing what you're suggesting is a matter of implementing a handful of Activities that mutates Objects and Collections.
What the author did is the equivalent of implementing a mailing-list manager by first writing a mail server from scratch instead of just writing the bits managing the list and sends, because he didn't have that lower level layer to build on.
There is indeed a lot of missing tooling to work with ActivityStreams/ActivityPub, that makes it painful now, and unfortunately a lot of ActivityPub implementers takes the same tack as the author and builds one big monolith instead of first building that lower layer.
There are no "small sample" projects as far as I know. But if you look in my profile (or other comments in this thread) I did develop a server which only does ActivityPub, client to server and server to server.
(My only knowledge of activitypub comes from reading this article.)
To receive JSON-LD messages don't you need to send follow requests? And to do that don't you need to deal with the fact the spec is too complicated and most servers implement inconsistent parts of it?
To receive JSON-LD messages, someone needs to send them to you. Sending follow requests is perhaps the easiest way to do that, but those follow requests do not need to be initiated by the same code that hosts the inbox.
The point is there are several potentially independent layers and modules there: The message pump itself at least can be implemented separately from the decoding of individual message types, and separate from managing followers and following, the same way e.g. a mail server knows nothing about how to follow mailing lists, or decoding email messages past the header.
It might sound like a mess if you see ActivityPub in terms of HTTP request, but ActivityPub is a protocol built on message passing, and what is a mess is trying to co-mingle the transport layer for the messages with processing those messages.
I'm not saying it doesn't have some warts and things that could do with being specified more clearly, but if you ignore a central aspect of the protocol and try to treat it as something it is not it will seem a whole lot messier than it is.
It might sound like a mess if you see ActivityPub in terms of HTTP request, but ActivityPub is a protocol built on message passing, and what is a mess is trying to co-mingle the transport layer for the messages with processing those messages.
You are defending it strongly but the spec is indeed written like that.
It's not even obviously message-oriented when you read it and the notion of following and managing followers is definitely put at the same level that transmitting new information regarding activities.
Don't get me wrong it can definitely be implemented but it's definitely not a good protocol nor is it well specified.
To me it was blatantly obvious that it is message-oriented when I read it given the vocabulary used. It could perhaps spell it out for people not used to it, but the use of e.g. "pub", "inbox", "outbox" and the use of addressing, including even "cc" fields in the spec should be enough for anyone used to writing message pump/queue based systems to see it as a pub/sub message based system. That it also talks of "actors" further underlines this, as the actor model is generally built on message passing.
As I said, it has warts and it'd be nice if the two layers specified had been separated out more clearly so it was more accessible to less experienced readers, but if a reader that don't see the message based foundation of the spec, it does speaks as much to the readers unfamiliarity with message passing systems as the spec.
The spec first definition paragraph is about "Objects". There is mention of object retrieval long before message passing. The concept of messages is introduced in relation to Actors inbox and outbox. It’s not written clearly as being a message passing system and I am not sure it was conceptualised this way. Only from the server to server part you can start infering that’s what it’s supposed to be.
Well, then I guess it's not clear enough for you. For me it is clear as day. The Actor model is inherently focused on concurrently processing messages acting on objects, and the very section you refer to when it talks of objects shows an example mentioning actors and it's followed by a section on Actors.
The inbox/outbox terminology is further inherently tied to async message passing with a message pump/queue, and so on.
You may not be sure it was conceptualised this way, but it really is irrelevant whether or not it was conceptualised this way because the spec-as-written describes an architecture that to someone with experience in the field is most reasonably interpreted that way as it is inherent to the vocabulary used, and where interpreting it that way creates a significantly more cohesive architecture. You're free to interpret it otherwise, but it's now been pointed out to you that treating it this way simplifies the understanding of it - if you choose to ignore that advice, then so be it.
I might be sympathetic to the argument that it is may not be spelled out sufficiently clearly to someone without experience in this area or unfamiliar with the actor model, but there's a question of to what extent a w3c working group should feel a need to assume readers are not familiar with these kinds of models..
Strangely I think we are fondamentaly in agreement. I think the spec is poorly written for the reasons you quote. I am not surprised to see people struggling with the implementation. It's not a good spec.
So we have just the next question: If it's message passing, why was it build on top of HTTP? Wouldn't a RPC-like protocol as base be much more adequate?
This would just strengthen the suspicion that this protocol is badly designed, to be honest.
Because HTTP is ubiquitous and passes through every firewall around, and has extensive tooling. You need a really good reason to pick a different choice if you're going to expose your endpoints to the public internet today.
Comments
The author makes the basic mistake of most of the people implementing ActivityPub services: they want to map the logic of an existing type of web application and contort existing domain objects into encoding/decoding to an "impractically large number" of options. That happens because they want two things in one: a server and a client.
The ActivityPub specification needs to be read with a goal similar to an email server in mind. It should do one thing: receive JSON-LD objects in inbox, process them according to the specification, and(maybe) store them on disk.
The idea of "users", "friends", "posts", "feeds" etc, are concepts that belong to the clients on top of this server, not in the server itself.
This separation between clients and server will also allow better interop/graceful degradation of object types that the client/server don't specifically understand.
This comment raised a whole bunch of red flags for me.
Fist and foremost: Saying that something is like an email server translates for me into "this is an under- and over-specified swamp at the same time, full of quirks, and actually not implementable in any reasonable way". Because that's what email is. I almost can't think of a greater horror than writing an email server from scratch…
I don't know enough about ActivityPub to judge whether it's really like email. I would strongly hope it isn't, as otherwise it would be a tech you should probably better never touch as a developer.
The next thing is: If an ActivityPub server only receives and sends some opaque BLOBs what's the whole point of it?
But when it's not about opaque BLOBs you need to map the structures in the spec to proper types in a statically typed languages as you can't manipulate them otherwise in any meaningful way. If it's not possible to do that because the spec is vague and/or there is no coherent data model behind it that would be just another reason to not touch this tech. Nobody needs the next underspecified, stringly-typed "email".
I really hope I'm reading this wrong!
The email comparison helps people to understand the directional way ActivityPub works, I don't know enough about email (whichever of SMTP or IMAP/POP3/samd you consider that to be) to make a comparison at protocol level.
There are some rules about how to have side effects for said blobs. Some of the blobs themselves have side effects. That's mostly what ActivityPub is: rules about how to distribute the blobs in the federated context, rules to what to do with the blobs when they reach your servers (when coming from other servers, or directly from clients).
The vocabulary that ActivityPub is based upon, is another whole specification, called ActivityStreams, and which didn't originate in the W3C group. This vocabulary has three (*main) types of objects: Activities - which provide the backbone of ActivityPub (Like, Follow, Create, Update), Actors - basically different types of users (these are the entities that operate the activities) and, Objects - whatever the Activities operate on.
There's still a difference between "try to black-box the incoming data as much as possible" and "treat the incoming data as opaque BLOBs and assume". The data is mostly JSON-LD which is a far cry from "binary large objects". It is always going to be "semi-transparent" as it will always be JSON. Whether or not you like the "-LD" extensions to JSON (they are heavy, they do have a lot of RDF baggage you may not desire), they give you a bunch of guaranteed "baseline schema" for the JSON objects that you can use for static typing that might be "good enough" for a lot of "meaningful manipulations" (such as following links to pick up related objects; LD => linking data) and that is all easily transparent.
A lot of the schemas beyond "LD" in ActivityPub are client/application-specific beyond most of the JSON-LD basics and should be easy to treat as a black box unless doing client/application-specific tasks. That's not necessarily "stringly typed", it's kind of a classic "serialization onion": The server at best needs to know that it is JSON and it may have JSON-LD metadata for relevant related linked objects (and a few other metadata fields common to "introspection", similar to "headers"). The client can dig deeper and know it is not just "any" JSON object but a more specific schema for a given class of thing the client cares about.
To be honest, this sounds indeed quite like the mess that email is.
If the server isn't just a "dumb 'BLOB' storage" it will need to handle application logic (sooner or later, as this is actually what servers are for)…
But given that the application logic seems to be mostly unspecified, kind of wild west, where every client application can do whatever it thinks it's users like, this will unavoidably end in all the problems you have with email, where the server needs to know about all the specific details, quirks, and idiosyncrasies of every client ever built.
The whole concept reads like an implementation of "'Postel's Law' fallacy".
The balance of client/server shared knowledge will always be a hard balance to strike in any protocol ever invented by people.
At least in contrast to email there is a stronger/higher baseline: HTTPS (primarily), transferring primarily one MIME type (application/json) and one "document" format (JSON-LD). The "headers" metadata and "content" are in the same parser format (JSON). That combination alone is far narrower than email protocols (which needs to support nearly any MIME type at any point in any envelope, the headers and content of envelopes have always been different parsers and much of the MIME parsers were bolted in after-the-fact making things worse).
Other comments in this thread point to the larger "stack" of specifications beyond ActivityPub. ActivityPub itself is just one "layer" in the "stack".
That stack does rely on JSON-LD itself very heavily and many of the clients are in languages where JSON-LD tooling alone is "well-typed" without much in the way of further schemata. I can appreciate where in some static-typed language backgrounds most everything defined as stacks of JSON schemas starts to feel "stringly typed" and idiosyncratic. I don't agree with that sentiment and think JSON in general is far from the worst of "stringly typed", but I appreciate where that sentiment comes from here even if I disagree with it.
I think the surface area overall is a lot narrower than email and many parts of the "stack" are better defined, especially for specific client types. I think there will be some in-theory avoidable problems that resemble the idiosyncrasies with email, but I think in practice they still have a smaller "blast radius" than any similar problems in email.
Thanks! This sounds now a bit nicer.
At least the "stringly-typing issue" seems to boil down to having proper JSON-LD machinery in your language of choice. (In strongly typed languages some code-gen likely.)
Whether a new protocol should really be HTTP-based remains still a question to me. But OK, it's fashionable right now, everybody is doing it, so I can understand why someone would chose to go down this route. HTTP/3 is even quite good (if only a little bit to complex; but that complexity is actually inherent so likely better when it's contained in one place).
I think we have to generally assume HTTPS is the "new Telnet" for protocol bootstrapping and may be so for some time to come. Everyone has HTTPS debugging tools of every level "already installed" (curl/httpie/web browsers/fiddler/etc) and are mostly already trained in them. Every language under the sun has strong HTTPS libraries. Meanwhile, HTTPS gives a nice baseline for things like security (TLS was designed for multiple protocols, but let's face it is best tested and deployed in HTTP and always has been), caching, compression, many quality-of-life and quality-of-service tools. It's so much easier to bootstrap protocols from HTTPS as a baseline than "from scratch like an Apple pie" just as HTTP and Email themselves bootstrapped from Telnet. In the post-TLS era, bootstrapping directly from Telnet doesn't seem like an easy bargain anymore and yeah there are definitely advantages to getting your TLS and a bunch of other useful features/services "for cheap as nearly free" all at once in something like HTTP/3 (even if that is inheriting possibly "a lot of complexity").
You don't seem to have much appreciation for how elegantly handled email is.
I for one have awe & respect for works like Dovecot, which can elegantly decompose a couple different ingress-email pieces of work into special-purpose daemons that each can be scaled & operated independently. The system is practically ancient at this point but a model of how powerful & amazing clearly separated concerns & loose coupled systems are.
You've been persistently negative & calling this all a mess. But it's unclear what you think is elegant & graceful, that does work well. And most of your accusations about things being bad and awful and messy and wild west and postel's law fallacy... none of them have refutable claims. None of them make a position that anyone can argue with. You just spread negativity around & insult thinks in vague terms. It's not very hackerly of you to make a bunch of mean-spirited assertions that arent even backed up enough for anyone else to go verify or test.
Cut the FUD man. Adjust your attitude some. Don't be Mr Rain. Not cool. Be cool.
It's both true than Dovecot is an elegantly designed piece of software and the protocoles surrounding email are a complete mess with decades of bolted on additions and a most used implementation - Gmail - which likes to do things in peculiar ways.
I think the complaints you see here are entirely legitimate. Anyone having been doing this job long enough knows that designing good protocoles is insanely hard and exemples of poorly designed ones in the commercial world abound. It would have been more surprising for the feediverse to get that entirely right than the reverse.
I say that while agreeing with the original comment which points out that a good implementation should solely focus on the specification and leave everything else to the clients.
The application logic is not mostly unspecified, but implementers seriously need to start actually reading the whole thing, and that includes reading the ActivityStreams specs and JSON-LD spec, since it seems like a whole lot of the objections comes from ignoring that there are several more documents to read other than just ActivityPub spec itself even though these documents contain explicit references.
If one were to implement it on top of a RDF database then it isn’t any different than a typical backend taking in SQL (or sparkQL) and spitting out json to the client.
People seem to want to fit a square peg in the round hole and then you have servers bucking over a handful of users.
I spent a day or two looking into this when the hype machine was going strong and it’s really not all that bad (with the right abstractions, I suppose).
Thank you for articulating this very well, I was getting a bit frustrated at OPs contrarianism. :)
E-mails are not opaque blobs, and neither are ActivityPub messages. The point is that at it's lowest layer an implementation should care about receiving messages addressed to one or more Collections. That's it. It makes implementing a functioning ActivityPub implementation a lot easier.
The next layer up then specifies some rules for how to process those messages: Like on an e-mail server, if a message is sent to your "local" server intended for onwards delivery, the server must forward it on. Otherwise it is added to an OrderedCollection - effectively a mailbox.
The spec then sets out a structure for giving the messages an Activity type that determines further fields, and for some of these activities there are rules specifying how the relevant Actor's should act when those activities / messages are processed by them.
You can decide to do that synchronously when receiving the message. Sometimes that may be fine. But you can also strictly layer the implementation and deliver to a collection first and then asyncronously have workers process those messages. What you in either case ought to do for your own sanity is to at least logically separate the low level message pump (inbox/outbox) from the processing of activities.
For starters, doing this separation cleanly makes writing a scaleable implementation far easier.
This is just not true. You can handle dynamic structures in statically typed languages just fine. It is in any case irrelevant, as ActivityStreams (which ActivityPub is based on) defines a typed vocabulary [1]. An implementation can choose to dynamically process extensions or it can choose to statically type the activities it understands and treat the rest as mostly opaque blobs other than the envelope/addressing -- this is exactly why it's beneficial to apply the layering as suggested with the comparison to e-mail and decouple the message pump from the processing of activities.
[1] https://www.w3.org/TR/activitystreams-vocabulary/
https://json-ld.org/ for anybody else not super familiar
OK, but for someone who wants to build a useful tool that does what the author wants, "interacting with the Fediverse", such as federating with Mastodon, how useful is doing that one thing?
It depends on your goal. If your server is just a tool you use, you can ignore lot of concepts. There is no local timeline, there are no users, all follows belong to a single user, etc.
I can't find the link but a while back there was a post on the front page about how to get a findable, read only ActivityPub profile by just uploading some static JSON files. Not exactly a Twitter competitor, but you don't need much to start exchanging messages.
I believe you're looking for this: https://blog.joinmastodon.org/2018/06/how-to-implement-a-bas...
I did that myself. It's quite a distance from passively accepting requests to interacting with the Fediverse.
I think this is the wrong way of looking at it. If you're doing the whole stack, sure you will end up implementing quite a few things.
But consider that you can write a generic ActivityStreams server without supporting any of the ActivityPub activities. Now you have a generic platform to build on.
Tack on a tiny bit of support for e.g. addressing etc. as found in ActivityPub and you have what you need for federation.
With that generic platform, doing what you're suggesting is a matter of implementing a handful of Activities that mutates Objects and Collections.
What the author did is the equivalent of implementing a mailing-list manager by first writing a mail server from scratch instead of just writing the bits managing the list and sends, because he didn't have that lower level layer to build on.
There is indeed a lot of missing tooling to work with ActivityStreams/ActivityPub, that makes it painful now, and unfortunately a lot of ActivityPub implementers takes the same tack as the author and builds one big monolith instead of first building that lower layer.
If you want to create one just for yourself, sure. If you want to create something for the rest of the world, probably not very much.
I get the "scratch your own itch" mentality, but not if you kneecap all efforts that try to build on top of it. :D
Do you know of a small sample project that does this as an example?
There are no "small sample" projects as far as I know. But if you look in my profile (or other comments in this thread) I did develop a server which only does ActivityPub, client to server and server to server.
(My only knowledge of activitypub comes from reading this article.)
To receive JSON-LD messages don't you need to send follow requests? And to do that don't you need to deal with the fact the spec is too complicated and most servers implement inconsistent parts of it?
To receive JSON-LD messages, someone needs to send them to you. Sending follow requests is perhaps the easiest way to do that, but those follow requests do not need to be initiated by the same code that hosts the inbox.
The point is there are several potentially independent layers and modules there: The message pump itself at least can be implemented separately from the decoding of individual message types, and separate from managing followers and following, the same way e.g. a mail server knows nothing about how to follow mailing lists, or decoding email messages past the header.
That sounds like a mess.
Reading through the other comments here it seems that the spec is in fact a mess…
Many people find whining about messes is more fun than doing anything useful.
It might sound like a mess if you see ActivityPub in terms of HTTP request, but ActivityPub is a protocol built on message passing, and what is a mess is trying to co-mingle the transport layer for the messages with processing those messages.
I'm not saying it doesn't have some warts and things that could do with being specified more clearly, but if you ignore a central aspect of the protocol and try to treat it as something it is not it will seem a whole lot messier than it is.
You are defending it strongly but the spec is indeed written like that. It's not even obviously message-oriented when you read it and the notion of following and managing followers is definitely put at the same level that transmitting new information regarding activities.
Don't get me wrong it can definitely be implemented but it's definitely not a good protocol nor is it well specified.
To me it was blatantly obvious that it is message-oriented when I read it given the vocabulary used. It could perhaps spell it out for people not used to it, but the use of e.g. "pub", "inbox", "outbox" and the use of addressing, including even "cc" fields in the spec should be enough for anyone used to writing message pump/queue based systems to see it as a pub/sub message based system. That it also talks of "actors" further underlines this, as the actor model is generally built on message passing.
As I said, it has warts and it'd be nice if the two layers specified had been separated out more clearly so it was more accessible to less experienced readers, but if a reader that don't see the message based foundation of the spec, it does speaks as much to the readers unfamiliarity with message passing systems as the spec.
Deeply disagree.
The spec first definition paragraph is about "Objects". There is mention of object retrieval long before message passing. The concept of messages is introduced in relation to Actors inbox and outbox. It’s not written clearly as being a message passing system and I am not sure it was conceptualised this way. Only from the server to server part you can start infering that’s what it’s supposed to be.
Well, then I guess it's not clear enough for you. For me it is clear as day. The Actor model is inherently focused on concurrently processing messages acting on objects, and the very section you refer to when it talks of objects shows an example mentioning actors and it's followed by a section on Actors.
The inbox/outbox terminology is further inherently tied to async message passing with a message pump/queue, and so on.
You may not be sure it was conceptualised this way, but it really is irrelevant whether or not it was conceptualised this way because the spec-as-written describes an architecture that to someone with experience in the field is most reasonably interpreted that way as it is inherent to the vocabulary used, and where interpreting it that way creates a significantly more cohesive architecture. You're free to interpret it otherwise, but it's now been pointed out to you that treating it this way simplifies the understanding of it - if you choose to ignore that advice, then so be it.
I might be sympathetic to the argument that it is may not be spelled out sufficiently clearly to someone without experience in this area or unfamiliar with the actor model, but there's a question of to what extent a w3c working group should feel a need to assume readers are not familiar with these kinds of models..
Strangely I think we are fondamentaly in agreement. I think the spec is poorly written for the reasons you quote. I am not surprised to see people struggling with the implementation. It's not a good spec.
So we have just the next question: If it's message passing, why was it build on top of HTTP? Wouldn't a RPC-like protocol as base be much more adequate?
This would just strengthen the suspicion that this protocol is badly designed, to be honest.
Because HTTP is ubiquitous and passes through every firewall around, and has extensive tooling. You need a really good reason to pick a different choice if you're going to expose your endpoints to the public internet today.