mirror of
https://codeberg.org/fediverse/fep.git
synced 2026-08-05 19:55:46 +00:00
190 lines
9.4 KiB
Markdown
190 lines
9.4 KiB
Markdown
---
|
|
authors: Claire <claire.fep-1d7d@sitedethib.com>
|
|
status: DRAFT
|
|
dateReceived: 2022-08-23
|
|
---
|
|
# FEP-5624: Per-object reply control policies
|
|
|
|
## Summary
|
|
|
|
Sometimes, users may want to share an information or a story without inviting replies from outside their circles or from anyone at all. In particular, individuals may want to restrict who can reply to them in order to avoid “reply guys” or limit outright harassment, while instutions may want to disable replies on their posts to provide information without having to deal with a moderation burden.
|
|
|
|
This can be broken into an advisory part advertising what sets of actors are expected to be able to reply, and a collaborative verification process where third-parties check with the actor being replied to that the reply is indeed allowed.
|
|
|
|
|
|
## Requirements
|
|
|
|
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this specification are to be interpreted as described in [RFC-2119].
|
|
|
|
In the remaining of this FEP, “distribution authority” (or “authority” for short) refers to an actor that controls the distribution and audience of replies. The purpose of this wording is to make this FEP applicable both for models where replies are first-class posts, and for “post and comments” models where comments only exist in the context of a post and the post author decides who gets to see the comments. In the absence of extensions, the “authority” is the author of the post being replied to.
|
|
|
|
## Declaring a reply policy
|
|
|
|
In order to advertise who is allowed to reply to an object, an author MAY set the `canReply` (`http://joinmastodon.org/ns#canReply`) property on their objects. If set, this property MUST be an empty array or one or more actors or collections.
|
|
|
|
To ease implementation, collections SHOULD be restricted to one of the following:
|
|
- `as:Public`, to indicate that anyone can reply
|
|
- the authority's followers collection (if defined)
|
|
- the authority's followed collection (if defined)
|
|
|
|
In addition, `canReply` SHOULD contain every actor mentioned in the original object.
|
|
|
|
Whenever one of these collections is used, the receiving end can easily know whether they are expected to be able to reply.
|
|
|
|
### Example object
|
|
|
|
```
|
|
{
|
|
"@context": [
|
|
"https://www.w3.org/ns/activitystreams",
|
|
{
|
|
"toot": "http://joinmastodon.org/ns#",
|
|
"canReply": "toot:canReply"
|
|
}
|
|
],
|
|
"attributedTo": "https://example.com/users/1",
|
|
"id": "https://example.com/users/1/statuses/1",
|
|
"type": "Note",
|
|
"content": "Hello world",
|
|
"canReply": "https://www.w3.org/ns/activitystreams#Public"
|
|
}
|
|
```
|
|
|
|
## Checking whether the user can reply and submitting the reply to the authority
|
|
|
|
When an object with `canReply` is set, it SHOULD be conveyed in human-readable form to the user if possible, for instance with something like “Only mentioned users can reply” or “Only people Authority follows and mentioned users can reply”.
|
|
|
|
The software SHOULD NOT offer the user to reply unless it is directly mentioned in the object's `tag` attribute or listed in `canReply` (either directly or through a collection), or `canReply` contains a collection for which the recipient cannot efficiently check the membership of the would-be replier.
|
|
|
|
After locally verifying that the replier should be allowed to reply, the replier's end SHOULD `POST` the `Create` activity for the reply to the authority's inbox *only*, and consider the reply to be pending approval.
|
|
|
|
## Receiving and accepting a reply
|
|
|
|
When receiving a reply to an object with a `canReply` property, the authority decides whether the reply is acceptable.
|
|
|
|
If the reply is considered acceptable, the authority MUST reply with an `Accept` activity with the `object` property set to the `id` of the reply object, and its `inReplyTo` property set to the object it is in reply to.
|
|
|
|
That `Accept` activity SHOULD be publicly dereferenceable and MUST be dereferenceable by all parties allowed to see the original post. It MUST NOT embed its `object` nor its `inReplyTo` as to avoid possible information leaks.
|
|
|
|
If the reply is considered unacceptable, the authority SHOULD reply with a `Reject` activity. This activity MAY be publicly accessible, but this is not a requirement.
|
|
|
|
### Example `Accept` activity
|
|
|
|
```
|
|
{
|
|
"@context": "https://www.w3.org/ns/activitystreams",
|
|
"actor": "https://example.com/users/1",
|
|
"id": "https://example.com/reply_approvals/1",
|
|
"type": "Accept",
|
|
"object": "https://example.org/users/bob/statuses/3",
|
|
"inReplyTo": "https://example.com/users/1/statuses/1"
|
|
}
|
|
```
|
|
|
|
### Example `Reject` activity
|
|
|
|
```
|
|
{
|
|
"@context": "https://www.w3.org/ns/activitystreams",
|
|
"actor": "https://example.com/users/1",
|
|
"id": "https://example.com/reply_approvals/1",
|
|
"type": "Reject",
|
|
"object": "https://example.org/users/bob/statuses/3"
|
|
}
|
|
```
|
|
|
|
## Receiving approval and distributing the reply
|
|
|
|
After sending the initial `Create`, the replier SHOULD wait for an `Accept` activity such as described above.
|
|
|
|
Once the `Accept` has been received, the replier SHOULD add a `replyApproval` (`http://joinmastodon.org/ns#replyApproval`) property to their reply object pointing to the `Accept` activity they received, and then MAY send a `Create` activity with the modified object to its intended audience.
|
|
|
|
If it instead receives a `Reject`, the reply SHOULD be immediately deleted and the replier MAY be notified.
|
|
|
|
### Example reply object with `replyApproval`
|
|
|
|
```
|
|
{
|
|
"@context": [
|
|
"https://www.w3.org/ns/activitystreams",
|
|
{
|
|
"toot": "http://joinmastodon.org/ns#",
|
|
"canReply": "toot:canReply",
|
|
"replyApproval": "toot:replyApproval"
|
|
}
|
|
],
|
|
"attributedTo": "https://example.com/users/1",
|
|
"id": "https://example.org/users/bob/statuses/3",
|
|
"type": "Note",
|
|
"content": "@alice hello!",
|
|
"inReplyTo": "https://example.com/users/1/statuses/1",
|
|
"canReply": "https://www.w3.org/ns/activitystreams#Public",
|
|
"replyApproval": "https://example.com/reply_approvals/1",
|
|
"tag": {
|
|
"type": "Mention",
|
|
"href": "https://example.com/users/1"
|
|
}
|
|
}
|
|
```
|
|
|
|
## Verifying third-party replies
|
|
|
|
When processing a reply from a remote actor to a remote authority, a recipient SHOULD discard any reply that does not match any of the following conditions:
|
|
- the object it is in reply to does not set a `canReply` property
|
|
- the object it is in reply to has a `canReply` containing the `as:Public` collection
|
|
- the author of the reply appears in a `Mention` object in the `tag` property of the object it is in reply to
|
|
- the object it is in reply to sets a non-empty `canReply`, and `replyApproval` can be dereferenced and is a valid `Accept` activity
|
|
|
|
To be considered valid, the `Accept` activity referenced in `replyApproval` MUST satisfy the following properties:
|
|
- its `actor` property is the authority
|
|
- its authenticity can be asserted
|
|
- its `object` property is the reply under consideration
|
|
- its `inReplyTo` property matches that of the reply under consideration
|
|
|
|
In addition, if the reply is considered valid, but has no valid `replyApproval` despite the object it is in reply to having a `canReply` property, the recipient MAY hide the reply from certain views.
|
|
|
|
## Revoking a previously-accepted reply
|
|
|
|
The authority may want to perform /a posteriori/ moderation of their replies.
|
|
|
|
To do this, the authority SHOULD send a `Reject` activity to the sender and the reply's audience, with the reply URI as the `object` property. The `object` property MUST NOT be embedded, as to avoid possible information leaks.
|
|
|
|
The URI at which the previously-offered `Accept` was available should return HTTP 404 or redirect to the newly-issued `Reject` activity.
|
|
|
|
## Handling a revocation
|
|
|
|
Upon receiving a `Reject` activity for a previously-accepted reply, third-parties SHOULD check that the `Reject` is valid and SHOULD delete or hide the revoked reply if it is.
|
|
|
|
To be considered valid, the `Reject` activity MUST satisfy the following properties:
|
|
- its `actor` property is the authority
|
|
- its authenticity can be asserted
|
|
- its `object` property is the reply under consideration
|
|
|
|
## Deployment considerations
|
|
|
|
Because it is unrealistic to expect all implementations and deployments to implement this proposal at the same time, deployment SHOULD be gradual, with verification of third-party replies only performed once the other steps are widely implemented. To encourage adoption without breaking compatibility altogether, implementations MAY want to hide non-validated replies from certain views (e.g. requiring a click to see “hidden replies”, or not showing the reply to non-followers).
|
|
|
|
## Security considerations
|
|
|
|
By not adding a hash or copy of the reply in the `Accept` activity, malicious actors could exploit this in a split horizon setting, sending different versions of the same activity to different actors. This is, however, already a concern in pretty much all contexts in ActivityPub, and enshrining that information in the `Accept` activity would have many drawbacks:
|
|
|
|
- significantly more complex implementation
|
|
- inability to change the JSON-LD representation after the fact
|
|
- possibly leaking private information if the `Accept` activity is publicly dereferenceable
|
|
|
|
|
|
## Implementations
|
|
|
|
None so far.
|
|
|
|
## References
|
|
|
|
- [RFC-2119] S. Bradner, [Key words for use in RFCs to Indicate Requirement Levels](https://tools.ietf.org/html/rfc2119.html)
|
|
|
|
|
|
## Copyright
|
|
|
|
CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
|
|
|
|
To the extent possible under law, the authors of this Fediverse Enhancement Proposal have waived all copyright and related or neighboring rights to this work.
|