fep

FEP-7458: Using the replies collection

Summary

Replies are not defined in ActivityPub, as there are no specified side effects for simply encountering objects or activities with inReplyTo set. Most current implementations implicitly reconstruct replies at consumption time, and may silently and implicitly maintain the replies collection at the producer’s side. This FEP provides guidance for explicitly using the replies collection, and explicitly managing it.

Problem statement

(This section is non-normative.)

ActivityPub defines side effects for activities, not side effects for encountering objects. One popular use-case in the social web is replying to an object with your own object; this indicates that your object is a response to the other object. However, this is about as far as most implementations go in maintaining the “reply” relation. It is generally assumed that objects will be delivered to other servers via a Create activity, and that the object of that Create activity will be cached, and that the “reply” will somehow be tracked and attached to the referent object. The ActivityPub spec only mentions “replies” in one place, in the context of inbox forwarding as intended to avoid the problem of “ghost replies”. The implication of this is that senders are expected to address all relevant parties ahead-of-time, as a matter of convention.

What is missing is a mechanism for managing replies that would recognize the canonicity and authority of the actor managing their own replies explicitly, rather than depending on implicit reconstruction after-the-fact. FEP-5624 takes a different approach that doubles down on this implicit reconstruction.

Meanwhile, FEP-7888 specifies a similar mechanism for managing contexts that recognizes the canonicity and authority of the actor managing the conversation explicitly, rather than depending on implicit reconstruction after-the-fact. Implicit reconstruction is usually based on reply trees, but explicit construction is based on Add and Remove activities. The current FEP aims to be written in a way that supports explicit replies management while being orthogonal to the use of context. In other words, the authoring actor has the option to use inReplyTo as metadata, while separately choosing to participate in a context or not.

Example flow

(This section is non-normative.)

Alice makes a post:

{
	"@context": "https://www.w3.org/ns/activitystreams",
	"id": "https://alice.example/outbox/1",
	"summary": "Alice created a note",
	"actor": "https://alice.example",
	"type": "Create",
	"object": {
		"id": "https://alice.example/objects/1",
		"type": "Note",
		"content": "Hello",
		"replies": "https://alice.example/objects/1/replies"
	},
	"cc": ["https://alice.example/followers", "as:Public"]
}

Bob makes a reply:

{
	"@context": "https://www.w3.org/ns/activitystreams",
	"id": "https://bob.example/outbox/2",
	"summary": "Bob replied to Alice's note",
	"actor": "https://bob.example",
	"type": "Create",
	"object": {
		"id": "https://bob.example/objects/2",
		"type": "Note",
		"content": "Hi!",
		"inReplyTo": "https://alice.example/objects/1"
	},
	"to": "https://alice.example",
	"cc": ["https://alice.example/followers", "https://bob.example/followers"]
}

Alice explicitly approves Bob’s reply, either automatically or manually. Alice forwards Bob’s activity to Alice’s followers, as requested by Bob. Alice also adds Bob’s reply to the replies collection:

{
	"@context": "https://www.w3.org/ns/activitystreams",
	"id": "https://alice.example/outbox/3",
	"summary": "Alice added Bob's note as a reply",
	"actor": "https://alice.example",
	"type": "Add",
	"object": "https://bob.example/objects/2",
	"target": "https://alice.example/objects/1/replies",
	"to": "https://bob.example",
	"cc": ["https://alice.example/followers", "https://bob.example/followers"]
}

Bob sees this and updates the original reply to something offensive:

{
	"@context": "https://www.w3.org/ns/activitystreams",
	"id": "https://bob.example/outbox/4",
	"summary": "Bob updated a note",
	"actor": "https://bob.example",
	"type": "Update",
	"object": {
		"id": "https://bob.example/objects/2",
		"type": "Note",
		"content": "Alice sucks lol",
		"inReplyTo": "https://alice.example/objects/1"
	},
	"to": "https://alice.example",
	"cc": ["https://alice.example/followers", "https://bob.example/followers"]
}

Perhaps Alice forwards this activity automatically, or perhaps not; at some later point, Alice notices that the reply has been edited. Alice therefore decides to remove the reply:

{
	"@context": "https://www.w3.org/ns/activitystreams",
	"id": "https://alice.example/outbox/5",
	"summary": "Alice removed a reply",
	"actor": "https://alice.example",
	"type": "Remove",
	"object": "https://bob.example/objects/2",
	"target": "https://alice.example/objects/1/replies",
	"to": "https://bob.example",
	"cc": ["https://alice.example/followers", "https://bob.example/followers"]
}

Bob maliciously chooses not to forward this removal activity.

Charlie follows Bob, but not Alice. Charlie’s client has received activities 2, 3, and 4 in Charlie’s inbox.

Under current behavior, Charlie would have fetched Alice’s post, but not have checked Alice’s replies collection or used it in any way. Bob’s reply would still be visible as a reply to Alice’s post.

Under proposed behavior, Charlie would instead defer to checking Alice’s replies collection. Bob’s reply would not be contained in that collection, as Alice has removed it. Therefore, Charlie does not see or treat Bob’s reply as a verified reply.

Behavioral requirements

References

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.