The Block activity, how's that supposed to work?

I’m now at the point where I’m satisfied with my main features and almost ready to make my first release. Though in order to be a feasible fediverse server, I need to implement some sort of user blocking. So here goes.

The spec says that the Block activity is c2s only. Mastodon does send Block and Undo{Block} activities when you block and unblock a remote actor. What am I meant to do upon receipt of these activities? Remove all follow relationships and disallow the blocked actor any interactions with the originating actor and their content? Something else?

(I’m not really a fan of the whole “you see more if you log out” approach most social media implementations out there take, both centralized and not. I won’t be hiding anything publicly viewable if its author blocked you.)

1 Like

You basically have two options:

  • Send a Block to the remote server, and the remote server will interpret it however it wishes (remote-side signaling)
  • Do not send a Block, and simply discard any incoming activities received from the blocked actor (local-side filtering)

The C2S Block is the latter, and this is what was probably intended when the AP spec was being written; however, in reality, S2S Block (the former) is quite prevalent. The general semantics of the S2S Block are the following:

  • Do not allow the blocked actor to follow (it is also implied that the follow relationship should be broken even if an explicit Reject Follow is not sent, although it is probably good practice to do so)
  • Disallow any interactions with the blocker or the blocker’s objects (it is implied that any such interactions will simply be discarded if received[1])

  1. Note that Mastodon e.g. currently doesn’t actually do this – blocked users can still reply and have their reply show up beneath the posts of someone who blocked them, but this is probably a bug; Do not process side effects of incoming activities from blocked users · Issue #10916 · tootsuite/mastodon · GitHub should contain more information about this behavior. ↩︎

3 Likes

Sorry for necroing this old thread, but I have some follow-up questions and I feel it’d be better to keep it in this relevant thread rather than start a new one:


Question 1: Do blocks go both ways?

If Alice blocks Bob, Bob should obviously not be able to interact with Alice’s content. But can Alice continue to interact with Bob’s content?

Presumably most implementations would not even display Bob’s content to Alice, but you could imagine implementations that would only “grey out” or minimise Bob’s content and thus still allow Alice to see and maybe even interact with it (or perhaps Alice interacts with it via some kind of alternate API or whatever).

That would seem weird I’d say. It would basically devolve into one-way communication. A way to resolve this would be to consider the block to be in both directions, with the caveat that Bob should not be able to Undo the Block.


Question 2: Should blocking really end other relationships (e.g. follows), or just “suspend” them?

Isn’t it somewhat dangerous to assume that follow relationships should be broken? I could for instance imagine a situation where Bob follows Alice and they get into an argument, and then Alice blocks Bob for a while. Once the conflict has been resolved, Alice might unblock Bob. Presumably Bob would like to automatically follow Alice again (right? :person_shrugging:).

I’m kind of more leaning towards a model where the follow relationship (or any other relationship you might imagine, like a Friend relationship for instance) is suspended due to the block, and could be reinstated automatically if the block is undone. But this would not work if other implementations assume that a Block also means an Undo Follow.


Question 3: Should instance admins be able to override blocks, and if so, how?

Imagine the same situation as before with Alice and Bob, but they are on separate instances/domains and Bob happens to be the administrator of his instance. Alice is spamming Bob’s instance and has blocked Bob in an attempt to evade being banned.

This makes me think that, under the origin-based security model (cc: @silverpill), you should still allow remote actors to interact with local actors that have blocked the remote actor (i.e. allow Bob to interact with Alice) despite any blocking, because the remote actor may have special permissions (like being an admin) that should allow them to circumvent blocking.

I feel that Alice’s instance should assume that Bob’s instance is compliant and only allows Bob to interact with Alice despite the block if Bob’s instance considers Bob permitted to do so, which it would in this situation.

So with regards to this:

I actually feel that this isn’t a bug? And that Mastodon is doing the correct thing. It feels almost weird to say, but I think processing side effects from blocked users is the correct thing to do, because that user might be a privileged user from the remote instance’s perspective.

Now of course, you could have non-compliant implementations that allow any user to circumvent blocks. But such an implementation should probably be banned/defederated on an instance level, since they are not upholding the spirit of the protocol.

a1) blocks do not go both ways

i don’t think it makes sense for someone else’s activity to force you to publish/perform your own activity. A blocks B implies nothing about whether B blocks A.

this sounds more like a Mute than a Block, but it’s very implementation-specific

Bob should Block Alice if Bob wants to drop Alice’s activities. the real caveat is that depending on how the current implicit state machine works, two people Blocking each other runs the risk of a Block being dropped, essentially leading to a “first block wins” scenario. In fact, you can even get A and B to believe opposite things if you federate this information: Federated mutual Blocks can lead to irreconcilable state desyncs · Issue #498 · w3c/activitypub · GitHub


a2) blocks do not necessarily end follow relationships

an active block can be treated as a matter of policy where, while the block is active, incoming activities get dropped or rejected. if you want to end the relationship, you should do that separately by sending an Undo Follow (to unfollow them) and/or whatever comes out of Formally define a mechanism to remove a follower · Issue #471 · w3c/activitypub · GitHub as a way to destroy a subscription (to remove the follower).

this is probably where the “policy” approach makes more sense than the “state machine” approach, yes. Alice’s server might handle a Block by Alice like so:

  • do not federate it
  • if Bob POSTs to Alice’s inbox, return a 403 Forbidden (or return a 202 Accepted but do nothing)

again, this depends entirely on how Alice’s server is programmed to handle C2S Block in the outbox, but it makes more sense to also have Alice explicitly remove Bob as a follower (however that looks like – see Formally define a mechanism to remove a follower · Issue #471 · w3c/activitypub · GitHub again).


a3) why would instance admins be able to override blocks?

examples like this make it more apparent that the policy approach is the most sensible approach – Bob can apply a policy to drop Alice’s spammy activities without any requirement from Alice. why would Bob interact with Alice? why should Bob be allowed to personally interact with Alice? there is no good reason to “circumvent blocking” . i don’t think the concept of a “privileged user” makes sense per se.

You mean like an Ignore activity rather than a Block activity? I mean yea I’d say it really depends what you consider “ignore” and “block” to mean. The only concrete side effect I can read from the spec seems to be that when you block someone, they shouldn’t be able to interact with you (I don’t see any particular side effects for the Ignore activity). But I guess leaving it so that Alice could still interact with Bob is fine - if Bob doesn’t want that, he could just block Alice himself, as you say.

I get what you’re saying, but I don’t see anywhere in the spec that says that the Block activity works like this - i.e., where does it specify that the Block activity means that all activities from the object in the future will be dropped? From ActivityPub:

The Block activity is used to indicate that the posting actor does not want another actor (defined in the object property) to be able to interact with objects posted by the actor posting the Block activity. The server SHOULD prevent the blocked user from interacting with any object posted by the actor.

I don’t think sending a Block activity constitutes “interacting”, so in your steps to reproduce, I don’t think B blocks A should be dropped. I.e. I think this core assumption you make is wrong:

Core assumption: an active block results in incoming activities being dropped

I don’t think all incoming activities should be dropped/responded with 403.

I think federating the block and federating the unblock would also be okay - the remote instance could pause sending activities while the block is in place, or it could not and get the 403/202(drop) responses. As long as the remote instance does not consider the follows or other relationships over just because of the Block alone (which I feel that it shouldn’t), then it’s fine.

I’m thinking that this could be an additional option in a potential user interface. For instance, when you click the button to Block someone, you may be prompted with a confirmation dialog like “Are you sure you want to block Bob?” which could also contain a checkbox like “Also remove Bob from my followers” before clicking “Confirm”. So the user could have both options:

  1. Block while preserving relationships, so that they will be restored upon an Undo Block.
  2. Block while destroying relationships, so that they will need to be re-established from scratch upon an Undo Block.

Hmm I don’t think I agree with this. Just blocking the spammy activity is quite a nuclear option from a moderation perspective.

Imagine for instance that Alice is not spamming, but is just breaking the rules of a community, but not such a serious rule that it would warrant an instance-wide ban. You would want a moderator to talk to Alice to nudge her to improve her behavior. But if Alice has Blocked all the moderators, then this is impossible. I feel that the moderators, for cases like this, should be able to circumvent the Block.

On further reflection, this does of course raise a concern that you could circumvent a Block by hosting your own instance. So probably Bob should only be allowed to interact with Alice with this mod-block-circumvention in certain circumstances - for instance if Alice has replied to a user on Bob’s instance with a rude comment, Bob should be able to point it out, I feel. But Bob should not be able to contact Alice in general, out of the blue. Although this is starting to feel complicated…

FEP-fe34 is concerned with authentication and authorization, and doesn’t tell us how Block activity should work in this case, but generally, it follows from the server-centric view of Fediverse that activities should not be dropped. Inboxes are API endpoints controlled by servers, and actions of a regular user should not change their behavior. If actor blocks or ignores another actor, server should process activities differently (e.g. it may refuse to modify certain collections), but POST requests to inbox should not be rejected.

it does to me. “interacting” means any activity targeted towards me or my objects.

what’s the reasoning there? if someone is sending me unwanted activities, i want a way for my server to disregard those activities, so that my inbox doesn’t fill up with unwanted activities.

yes, an explicit activity should be used to destroy the relationship; it should not be inferred. the UI would probably be as you describe, with an additional checkbox for “also remove Bob from my followers”.

it’s always your prerogative if you want to disregard any activities you don’t want to consider. Alice’s server’s duty is to respect Alice’s wishes here: if Alice doesn’t want to be contacted by Bob, it doesn’t matter if Bob is an administrator on Bob’s server. This is irrelevant to Alice and to Alice’s server.

i believe the appropriate solution here is to use a Service actor representing Bob’s server, and this Service actor can proxy or act on behalf of Bob. this allows Alice to block Bob while still accepting messages from Bob’s server (which is logically distinct). the missing bit is how to signal the existence of this Service actor and probably how to signal that a given actor is being hosted by a service.

inboxes are not just API endpoints; they are also resources, particularly a Collection that contains delivered activities. POST to inbox can be rejected for any reason as a matter of policy. for example an invalid HTTP Signature can result in a 4xx error. this is what is meant by “dropping the activity”. firewall or filter policies might also apply to the keyId owner, as in the case of user blocks or domain blocks.

Well, that’s your interpretation, but unfortunately the standard is not precise about what “interact” means (unless I am missing something).

Side note out of curiosity/confusion: Is a Block activity really “targeted” towards the blocked user? I mean it uses the blocked actor as the object field, but does that necessarily mean it is delivered to the blocked actor’s inbox? Isn’t that the job of the to field? Or is there something about the object field I am missing here?

My reasoning is that Block activities should still be delivered, exactly to avoid the weird inconsistent situation you described earlier. Just because they are delivered does not however mean that your client needs to display them to you. Your client should know that you have blocked the user and thus when that user blocks you, that Block activity can still be delivered, but your client could just filter it out in the UI. Or your server could process the Block activity but filter it out of your inbox for your convenience.

There might be other situations where activities should be delivered in spite of blocks? Perhaps Flag activities or others might be relevant, but it’s not something I’ve thought much about.

Generally agree but I would also mention the caveat that Alice’s server also has an interest in allowing cross-server moderation to happen seamlessly - if moderation from Bob’s instance to Alice’s instance breaks down, Alice’s instance may risk defederation, if it becomes a big problem. Just as it is a server’s duty to respect their users’ wishes, it is also a server’s duty to keep a check on their own problematic users, as those users may represent a danger to the server’s reputation in the network. I feel this incentive is very much an intended side effect of federation which keeps servers and their admins motivated to keep their users on good behaviour.

What happens when Alice blocks the Service actor? :sweat_smile: Then we have the same problem again. But I guess at this point an instance-wide ban for Alice would be fairly warranted as this is ban-evasion to an extreme degree, so perhaps this solution is okay.

1 Like

this is why i advocate for a “moderation actor” or “moderation inbox” or “moderation endpoint” approach. you should be able to send your Block activity to the service and not to the user. and yes, Flag activities should be subject to the same considerations. this avoids the “weirdness” of interpersonal blocks. moderation activities should generally follow separate dedicated pathways rather than being mixed in with user-level activities.

you only have the problem if trying to communicate with Alice. however, if you communicate with Alice’s Service instead, then you don’t have the issue. at that point, it’s just two Service actors communicating with each other.

It looks like you mean delivery “targeting”. If so, I’d say no, it’s not targeted. In other words, the Block object is not a delivery target. From my reading of the AP spec (Section 6.9), a Block is not (should not be) delivered to any actor. First, it’s only for C2S (S2S federation of Block is outside the scope of the spec and I’m not commenting on that use case). In a C2S context, the Block is posted to the blocking actor’s outbox. The AP spec defines side-effects the client’s server should perform when a Block is posted. These side-effects do not require delivery targeting.

That said, Secton 6.9 has this odd sentence.

Servers SHOULD NOT deliver Block Activities to their object .

Since servers should never use object as a delivery target, I assume this means it should not deliver the activity to the object even if the object URI is specified as a delivery target (to, cc, etc.). However, it’s undefined what should be done if other delivery targets are specified.

2 Likes

There’s an issue here from the ActivityPub Trust & Safety taskforce to properly define S2S blocking: Define/document how blocking works in S2S · Issue #23 · swicg/activitypub-trust-and-safety · GitHub

In general, I think a user blocking another user should sever that relationship, as that is what people have come to expect (there is the notion of a “soft block” where you block and then unblock someone to quietly remove a nuisance follower). Perhaps software should implement functionality to allow you to remove someone as a follower, without blocking them.

I also agree that Block and Flag and potentially other activities related to moderation should probably have special delivery semantics (i.e., not delivered to the target/object, but rather to their moderation actor), though these still need to be formally defined.

For S2S, I’d say: Servers SHOULD NOT deliver Block or Flag activities to their object is probably appropriate, perhaps with unless no suitable inbox can be found for delivery

As argued above, I don’t think it should be assumed that any relationship should be automatically severed just because of a Block - if an instance wishes to have those semantics for Blocks, they can easily just send Undo Follow or Undo for any other relationship in addition to the Block. This is much more explicit and also allows for the use case of keeping the relationships in place, should the Block be undone (i.e. you automatically re-follow if you are unblocked, which I think is a nice mechanism).

I’d say this is a bit of a bad workaround for the missing functionality of removing a follower. There should just be a standard way to remove a follower and then we wouldn’t need to resort to such a weird workaround.

But again, a server should never deliver any activity to its object field, right? When has that ever been the semantics? You deliver activities via the addressing fields, i.e. to, bto, cc and bcc (which could of course contain the object, but not necessarily). So I feel this is already handled in the protocol.

It’s up to any implementation to decide where they send Block, Flag and so on, by using the addressing fields. Presumably an instance-wide shared inbox would be appropriate, as the receiving instance can then decide for itself where to send the activity (i.e. probably to a moderator or just for internal automatic handling with no delivery per se).

1 Like

The standard way is Reject(Follow) activity. Mastodon supports this too, but the option is hidden in settings, so the soft block workaround is still popular.

I should note that this notion of “soft block” is a user behavior, which has become popularized due to how other services work. Mastodon at present doesn’t provide an easily discoverable way to remove a follower (you need to go via Settings → Followers & Following → find the account → remove follower, instead of just going to their profile and clicking something to remove them as a follower), so there’s room for improvement there, which would reduce the likelihood of users performing so-called “soft blocks”

1 Like

Update: the new version of Mastodon will have the ability to remove a follower from the account page of the Web UI: Add option to remove account from followers in web UI by Gargron · Pull Request #34488 · mastodon/mastodon · GitHub

(You already could through the /relationships view)

But with this I think we’ll see a drop in usage of soft-blocks (although removing a follower won’t necessarily remove you from lists and such on their end, which blocking may)

mastodon at least should remove from lists on a destroyed follow relationship, regardless of how the destruction was initiated.

that is non-standard, but popularly supported. there are a few options here:

  • Undo Accept Follow. semantically the Undo undoes side effects of adding to followers collection, but leaves the Follow in a pending state where it may be Accepted again later. mastodon supports this.
  • Reject Follow. semantically unclear in that the Accept Follow continues to exist and was never technically undone, but practically supported by mastodon pleroma and misskey at least (although with significant interop issues when the activity gets dropped misskey → pleroma)
  • Remove targeting the followers collection. semantically clear but probably practically unsupported by any current implementation.

i think this is something that AP 1.1 should formally specify, most likely via Reject Follow, which somewhat mirrors WebSub here:

The subscription MAY be denied by the hub at any point (even if it was previously accepted). The Subscriber SHOULD then consider that the subscription is not possible anymore.

but could use some further thought and refinement, like instead of “subscription is not possible anymore” it would probably be weakened to “subscription has been terminated” (as it might be possible to resubscribe/refollow)

more broadly i think the “follow state machine” should be mapped out more fully by e.g. AP 1.1.