Desired changes for a future revision of ActivityPub and ActivityStreams

@codenamedmitri says in A brief and unromantic history of ActivityPub - #17 by codenamedmitri

There was a previous discussion touching on this subject: Should we fork AS/AP specs to Codeberg, create vNext drafts?

To summarize, we can break changes up into three categories:

  1. minor corrections and clarifications
  2. backwards-compatible changes and progressive enhancements
  3. backwards-incompatible breaking changes

We also have some issues that have piled up on the Github repos for AS2 and AP, labeled “next version”:

1 Like

Awesome, thank you so much!

Couple of things where discussions rage on for years and years are whether AP is more JSON-first or rather a Linked Data spec, as mentioned in ActivityPub: A Linked Data spec or JSON spec with Linked Data profile?

There were long discussion threads on the fedi around this theme recently (particularly pinging @hrefna, @jenniferplusplus and @stevebate), and many others now lost in fedi history and link rot unfortunately. Key question is:

Is the linked data based extension mechanism sufficient to specify robust protocol extensions?

i get the feeling that the popular intent is JSON-first with LD compatibility, but if you want to do any sort of extensibility then it immediately becomes an LD spec or else you will go utterly mad trying to deal with the infinite possibilities and inherent ambiguity and lack of context. Or you force everyone to use the same context as you, which is… decidedly not how context works, and goes against the whole point of having context in the first place.

So basically, I think LD is definitely sufficient for robust extensions. It’s also necessary.

I’m not totally clear about what the “linked data based extension mechanism” is in ActivityPub. @evan has proposed a process for extending the JSON-LD context, but if that’s the whole mechanism, then I believe it’s insufficient (no structural definitions and almost no data constraints on serialized AP data/messages, for example). For non-LD consumers, the term definitions in the JSON-LD context are practically useless.

There’s a convention in the (plain) JSON community, to use “$schema” to refer to JSON Schema URIs for a given message. For non-LD usage (which @evan has stated is the primary intended usage of AP), I think that this approach could be more useful to developers.

I’m not claiming it’s a great idea, but I’ve also been wondering if we could fork the spec to create an ActivityPub-LD (with Linked Data (RDF) support) spec and vanilla JSON ActivityPub (not LD-focused) spec. The latter could use JSON Schema to define data structure and constraints. The former would fix the existing problems with ActivityPub in an LD context (like the errors in the C2S partial update approach). We’d need to work through some interop issues, if that’s a goal, but at least it would be less ambiguous for developers.

To be clear, I’d be more a fan of ActivityPub-LD, but I believe the current lack of clarity in the recommendation is a disservice to both LD and non-LD developers (who are a large majority of developers at this point).


Theoretically, we could revive the AS2 OWL ontology, fix it, update it to support ActivityPub, and make it normative. It could then provide additional semantics for the JSON-LD terms. However, that’s probably more in the scope of ActivityPub-LD since most developers aren’t going to be interested in learning about Linked Data, RDF, description logic, ontologies, and so on. @evan has accused me of conjuring dark and evil forces for even discussing it. :wink:

2 Likes

I had the same thoughts. But i think it’s better to have an LD Spec and a description “how to plain json”

1 Like

In no particular order:

  1. Any kind of mechanism to make it possible to migrate from one AP server implementation to another on the same domain without having to keep legacy IDs, see also this thread. This will likely not be backwards-compatible but I think it’s very important for the long-term success of the fediverse. Otherwise domains will be stuck with the same implementations (or maybe forks) forever. That seems bad.

  2. Eschew JSON-LD and just use JSON. To me, JSON-LD seems too complicated for its own good. Most (AFAIK) implementations don’t bother actually handling it as JSON-LD and just treats it as JSON. Personally I had never even heard of JSON-LD before I read about ActivityPub. This made understanding the spec majorly difficult as JSON-LD seemed very strange. I think using plain JSON would simplify things for almost no disadvantage. The argument that JSON-LD allows better extensibility falls kinda flat when most implementations do not even properly use JSON-LD. The different representations that JSON-LD has also makes treating it as plain JSON problematic, but AFAIK the spec doesn’t require using JSON-LD. It all seems very weird and again, plain JSON would just be simpler and I think simplicity should be prioritized a lot more than it has been. I believe extensibility could still be achieved quite painlessly with plain JSON. This is not backwards-compatible either.

  3. Support Dislike in the same fashion as Like, with a dislikes collection. The asymmetry here seems strange to me. Should be backwards-compatible.

  4. Support emoji reactions in the base spec. This is a very common thing on most social media so it is kind of strange that ActivityPub doesn’t support it natively. See also this thread. If added as a separate thing (which would seem fine to me), it should be backwards-compatible. It could also replace Likes/Dislikes and those could be modelled with :+1: and :-1: reactions, but that would not be backwards-compatible.

  5. Get rid of HTTP Signatures and instead provide a way to put signatures directly inside the JSON objects. This means that every object is fully self-describing and self-authenticating. The fact that the signature is associated with the request and not the object seems weird to me since it is the object that needs to be verified. In fact you need to cross-reference the HTTP Signature and the object anyway to properly verify the object, which should be a good hint that the signature should be on the object, not the request. Probably not backwards-compatible.

  6. Provide some way to send activities in bulk. I.e. instead of 1 request = 1 activity, allow 1 request = many activities. This just seems like a reasonable optimization as you can send a lot of activities to a shared inbox at once that way. If signatures are on the objects themselves, each object can also include a signature on its own and so the request doesn’t need the HTTP Signature (which would be difficult to provide for many activities at once). Probably not backwards-compatible.

  7. Provide better semantics for forums/reddit-like implementations in the base spec. As it is, ActivityPub is unfortunately quite focused on microblogging and the following of individual actors for content. However, social media like forums or reddit don’t work like that. You don’t follow actors, you follow “categories” or collections of posts. The way apps like Lemmy currently work around this is by modelling communities (subreddits) as Groups, where the group is a collection of all the people subscribed to the community. But this seems unnatural, as the more semantically accurate thing would be to follow a kind of category or collection, not an actor. It’s also slightly hacky as the community has to Announce (or boost in mastodon terms) every single piece of content (posts, comments, votes) to all the followers, even if that content comes from external users, which seems like a strange way to model it. Honestly don’t know if this could already be done more cleverly but long story short this use case seems poorly supported by ActivityPub right now. This could maybe be done backwards-compatibly?

  8. This could be very hard, but possibly provide some standard way to signify roles and permissions for actors. For instance, it is useful to know that a certain user is an admin of another instance and has certain permissions because of that. Currently Lemmy hardcodes a “moderator” role and assumes certain permissions based on that, but that seems rigid and not very flexible. Ideally roles and/or permissions could somehow be specified flexibly. Not sure if that is backwards-compatible.

3 Likes

Get rid of all types that are not unambiguously defined, and provide a first contact mechanism to declare supported extensions.

1 Like

I’m also personally quite confused about the distinction between Article, Document, Note and Page. They don’t seem to have any meaningful difference aside from the type name. It’d be great if this was consolidated into a single Post or something like that.

I also find it weird that Link is not a subtype of object.

On another note, I think in general inheritance is just bad and the Activity Vocabulary is built around an inheritance hierarchy. It should instead define each type independently and then say what behaviors are expected from each type. This is kind of analogous to hardcore object-oriented programming (such as in C++/Java) versus a type-class/trait system (such as in Rust/Haskell).

1 Like

A few of mine:

  1. Formally specify that “updated” is intended to be a machine-readable field that’s useful for “most recent wins” conflict resolution. That is, if you receive two different versions of the same object, you should keep the one with the most recent “updated” timestamp. I’m pretty sure Mastodon does this already, so hopefully this won’t be controversial.
  2. Formally specify how URLs with fragment IDs should be resolved.
  3. The sharedInbox mechanism would be more useful if it had a way to say “deliver to these specific recipients”, rather than making the receiver try to work it out from the addressing fields (without any knowledge of which recipients may have already been handled). Basically the same thing as the “envelope recipients” in SMTP. I’m not sure how best to add this - maybe a HTTP header, a new “Deliver” activity, or something else.
3 Likes

FWIW here’s my personal takes, at least for now:

Revive the Multibox endpoint, or some similar mechanism for specifying exact inboxes to deliver to.

The sharedInbox we ended up with has some pretty egregious shortcomings with respect to the receiving server having to interpret how it should handle delivery, and the popular use of followers collections in the addressing properties introduces a dependency on state synchronization that would otherwise be completely avoidable. For example, you may think you know who the local followers are for any given remote actor, but you actually don’t! The local actor may have been silently removed from the followers collection, or you might have gotten a removal activity that you didn’t understand for some reason and therefore didn’t process the correct side-effects for it. The problem only gets worse when you start to consider things like bto/bcc, or addressing arbitrary collections of actors a la “Circles” or “Aspects”.

Make Groups make sense

Looking at other vocabularies, you have things like foaf:Group which is a subclass of foaf:Agent that can have foaf:member statements. In VCard, you have vcard:Group which also uses vcard:hasMembership to point to constituent VCards. There is no such mechanism for AS2 Groups. It could make sense to use the Join/Leave activities to manage membership, where membership is denoted by an additional special collection. It could also make sense to extend this mechanism to Organization, although I imagine some hierarchy-related vocabulary might make more sense there.

Resolve the as:Public issue

The JSON-LD context defines Public as as:Public which in theory should expand to https://www.w3.org/ns/activitystreams#Public, and in theory, all three should be equivalent – but in reality, because the JSON-LD context also defines as: as a prefix mapping to https://www.w3.org/ns/activitystreams#, compaction will always generate as:Public and never generate anything else. Further compounding this issue is the fact that the properties you’d use such a Public term in… are not defined to take advantage of vocabulary mappings. Properties like to, cc, and so on are defined as @type: @id and not as @type: @vocab. Not that they necessarily should be defined as @type: @vocab, but if the intent is to be able to refer to Public, then this reference should be within a term that is defined as @type: @vocab. This means defining a new property dedicated specifically to denoting that an object is addressed to or intended for a specific class instead of specific actors. This is similar to how Web Access Control has predicates for both agent and also agentClass, the latter of which allows you to specify Agent or AuthenticatedAgent (while the former allows you to specify other people’s WebIDs). There’s also agentGroup for denoting instances of vcard:Group whose members are allowed to access the resource.

Better support for access control and not just delivery

Continuing from the above point, properties like to, cc, audience are intended to trigger ActivityPub delivery. But there are cases where you might want to allow an actor to fetch a resource without necessarily delivering to them. It might be possible to just use WAC for this, I’m not entirely sure. But there are going to be undefined interactions with the existing audience addressing properties, which seem to imply a limited form of access control already.

Redefine Mention in a way that doesn’t depend on microsyntax?

Right now, a Mention is a special type of Link that… “represents an @mention”? Even though it doesn’t even require an @ character? Basically, the definition of Mention doesn’t line up with anything useful in reality. There’s an aspect of linking to something that maps to a “user”, but this is artificial because ActivityPub doesn’t really have a concept of “users” or “accounts”, only “actors”. It’s not meant to generate a notification either, because that’s what to and cc are for. So what is it really for? What should it be for? Referring to an actor without generating a notification? It seems to be entangled with the more general issue of microsyntax, but surely there’s some semantic meaning we can extract out of it. Otherwise, we might as well just tag a Link instead of subclassing it as a Mention. For prior art or related concepts, we can look at Webmentions, where it is possible to mention pages or resources and not just people.

3 Likes

I think ActivityPub spec is mostly good as it is.

  1. Minor corrections and clarifications are very welcome. In particular, new version of the spec needs to somehow address common misconceptions such as “ActivityPub requires JSON-LD” and “identities are attached to domain names”.
  2. Some requirements can be relaxed to enable new kinds of applications. New protocol features can be added, but only if there’s an overwhelming support from implementers (only HTTP signatures and Webfinger qualify as such).
  3. No backwards-incompatible changes. ActivityPub should be treated similarly to other widely used web standards.
3 Likes