FEP-c648: Blocked Collection

Hello!

This is a discussion thread for the proposed FEP-c648: Blocked Collection.
Please use this thread to discuss the proposed FEP and any potential problems
or improvements that can be addressed.

Summary

Users need to review and revise the list of actors they have blocked. This FEP proposes a new collection property, the Blocked Collection, which contains the actors that a user has blocked and all metadata about the Block activity.

cc @eprodrom

The FEP says the blocked activities can be contained in an OrderedCollection or a Collection. I assume a Collection is unordered. However, the FEP also states:

The blocked collection MUST be sorted in reverse chronological order, with the most recent activity first.

Why is this necessary? In any case, is this a MUST only if an OrderedCollection is used?

The link to onepage.pub in the References section is broken. It has some hybrid codeberg/github URL in the FEP. It looks like the correct URL is this.

Repeating my concerns from the PR:

  • The collection is named blocked but contains Block activities instead of blocked actors.
  • The collection containing activities instead of objects is particularly odd because all other actor collections (liked, following, followers) contain objects instead of activities.
  • The concern of finding some original activity is best solved through some other mechanism. Either by C2S clients omitting an id you don’t have while expecting the server to find it, or by allowing C2S clients to filter or query the outbox for activities of a specific type.

Regarding the point above about ordering the collection:

  • I do believe an OrderedCollection in reverse chronological order makes sense, as this is once again the precedent established by the ActivityPub spec for other such collections.

Yes, if it’s an OrderedCollection that sorting criterion is as good as any for this kind of data. If I were implementing this, I’d use Collection, but the requirement makes it sound like even that must be reverse-chrono sorted.

So, as mentioned in the PR, this was changed based on developer experience coming from activitypub-express. It seems like a really good pattern to learn from developer experience!

The problem has been that Undo flows are harder when you don’t have access to the original activity. I agree that we need another mechanism for handling it for follows, following, and liked. However, that doesn’t mean we need to repeat past mistakes.

This collection is most useful for client developers if it includes activities and not just people.

Would you be OK if we changed the term from blocked to blocks or blockActivities to make it clear that it’s not parallel to the other object-only collections?

1 Like

I’m happy to remove the Collection option. It sounds like it’s confusing and not helpful.

Mastodon shows blocked users in reverse chronological order by time blocked. So do Facebook and Twitter. I haven’t checked other services.

I could see a good point of returning the list in alphabetical order by ID or name, maybe.

I can’t see a good point of returning it unordered. Would the idea be that it’s up to the client to fetch everything and sort it on the client side?

1 Like

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.

1 Like

It would be less confusing although I personally prefer using a Collection for a naturally unordered collection of data. For implementations that are using JSON-LD and RDF, maintaining the data as an OrderedCollection (RDF list) is less performant than a Collection. However, I realize that I’m conflating the stored representation with the network representation. An RDF-based server could still store the data unordered although it would require special “presentation level” processing to provide sorted pages upon request. That said, having both Collection and OrderedCollection options and fixing the wording about reverse-chrono ordering would be more consistent with the existing specification for similar collections.

I think those are two separate issues. It can be unordered and the client would still not be required to fetch everything. CollectionPage objects could still be returned without defined ordering if the client doesn’t care about ordering.

If the client wants the data ordered and we have guessed correctly about what specific order they will want, then the client will be pleased with whatever order we’ve chosen. If they want a different order or want their user interface to have flexible ordering, then they will need to fetch the entire collection since there’s no way to specify ordering during retrieval.

One of the more common use cases for accessing Block data may be to remind yourself if you have blocked someone or not. Chances are that the blocking occurred quite some time ago or you’d probably remember it. Reverse-chrono for that scenario is very suboptimal for someone with many blocks. Ordering by name would be better for this specific scenario but could be worse for others.

So, I really think a FEP for Undo that doesn’t require the ID of the activity to be undone is a great idea. Something like:

{
  "type": "Undo",
  "object": {
       "type": "Follow",
       "object": {
           "type": "Person",
           "id": "https://social.example/@evanp"
       }
   }
}

IDs aren’t actually required to refer to an activity, and in the case of follow, block, like, etc. the ID of the activity’s object is sufficient to identify the activity uniquely.

Likewise, I don’t think Collection should be removed or disallowed. ActivityPub gives you a choice of either type for the collections it defines.

Things like this make me wish we had first-class querying support. SPARQL ORDER BY can do this.

It is, in fact, the most common use case in my view; the user almost always cares about the blockee and not the block itself. The exception is that the user may wish to attach metadata about the block, such as a comment or reason why the block was performed. But the user may also wish to attach metadata to a liked object as part of the Like itself; this does not prevent us from maintaining a separated liked collection.

You essentially have two options for the defined side-effect:

  • “the object is added to the blocked collection” (parallel to other actor collections)
  • “the activity is added to the blocks collection”

The latter case can potentially be handled by querying the outbox for Block activities. In general, if you care to find an activity associated with an object in a special collection such as liked or following or followers, you can query for activities of a specific type and object. In the absence of server-side querying, your client currently has to download the entire outbox and perform the query locally.

Apologies for jumping into this discussion six months late. Hopefully this is still on everyone’s radar. I’m working to implement this FEP now, and I have some questions about how you all see blocks being represented.

1. Blocks: Not Just For Actors
I want to publish blocks on more than just Actors, but on entire Domains and Keywords too. For domains, I could probably abuse the “Service” actor type, but I don’t know how readable this would be to others. And I’m completely stumped about how to represent a block on a specific term.

Is there any room in this FEP (or some other specification) to include definitions for different kinds of blocks?

2. Mutes, Shadow Bans, and Quiet Blocks
Compare this line in the FEP…

The blocked collection SHOULD include all Block activities by the actor, except for those that have been reverted by an Undo activity.

…to how the Inbox is described in ActivityPub 5.2

The inbox stream contains all activities received by the actor. The server SHOULD filter content according to the requester’s permission.

I think there’s room in this FEP to say that the server MAY filter content based on requester’s permissions. This enables me as a user to choose which blocks I share publicly, and which ones I don’t.

Honestly, that feels out of scope. You should probably work on a separate extension on representing domains, hashtags and terms in blocks.

Sure. I’ll add that.

I’ve started working on updates to this FEP based on the feedback here. I’m tracking the issues in codeberg.

Once those are done and pushed, I’d like to take this FEP to final.