I don’t particularly have a problem with naming it blocks
if it’s going to contain Block activities, but I think a blocked
collection is actually more useful and sensible. I don’t consider it a “past mistake” that all previous actor collections contained objects instead of activities; rather, I consider it a “current shortcoming” that the Undo
flow is not explicitly made simple. Or, as discussed previously, we should develop extensions for querying collections such as the outbox, and/or for allowing C2S Undo
without inner ids such that the server goes and finds the original activity. The former is very broadly and generally useful beyond just finding activities to Undo, while the latter allows for better supporting server implementations that don’t persist activities in the outbox. Per Section 6 about C2S, after an HTTP POST to the outbox:
The server MUST then add this new Activity to the outbox collection. Depending on the type of Activity, servers may then be required to carry out further side effects. (However, there is no guarantee that time the Activity may appear in the outbox. The Activity might appear after a delay or disappear at any period).
Emphasis mine. Granted, I don’t think it’s a particularly good idea to disappear any activities, but that door is technically open – implementers basically have the option to keep the activity in the outbox but require authentication to show it, or to not do that. It makes more sense to do that, but admittedly the purity of the data model is not very strongly maintained in practice. We already have cases such as Mastodon silently rewriting the original Create activity when a status is edited, instead of pushing the Update into the outbox.
Small inconsistencies like this add up into and contribute to a general incoherence for anyone surveying the spec and its landscape of implementations. We should reduce the inconsistencies where possible.
There is perhaps a larger tangential point here – is there any idempotency in processing activities, either from a C2S or S2S perspective? I have seen it proposed (albeit semi-unseriously) that you could send multiple Follow or Like activities in order to represent a “super follow” or a “super like”. The only explicitly idempotent bit is the side effect of adding the object to an unordered Collection, which is technically a set and therefore theoretically can’t contain duplicates. A more “common usage” interpretation would hold that follows and likes should be idempotent, but there’s nothing actually establishing this one way or the other. The most naive implementation of, say, C2S or S2S Like, is to handle each Like separately if each activity uses a different id. It then follows that you could post 10 likes of the same object and subsequently undo 3 of those specific activities. And for what it’s worth, adding each activity to either a Collection or an OrderedCollection will not be deduplicated, because each of those activities has a different id. You’ll effectively need to add an implementation quirk that tries to dedupe activities by their shape rather than by their id, in which case… of what purpose is the id? Why bother looking up the original id at all?
I bring the previous paragraph/point as an example because I assume blocks are idempotent in “common usage”. If this is indeed the case, then perhaps this should be stated as explicit guidance, and all such “idempotent activities” should be identified clearly. But I can also foresee challenges in trying to establish a conclusive judgement on this. Look no further than Announce – on Twitter and Twitter-like systems, the “retweet” can only be performed once, but on Tumblr and Tumblr-like systems, the “reblog” can be performed any number of times, including in direct succession. Similar reasoning can be extended to pretty much any other activity type. In fact, if you treat all activities as generic posts or items in the “activity stream”, you might not care if someone does a Follow of the same person multiple times in a row. There is a disconnect between each activity as a resource and each activity as a procedure call. I’m not entirely sure that this disconnect can be fully reconciled.