fep

FEP-5711: Inverse Properties for Collections

Summary

This FEP defines inverse properties for collections that are important in ActivityPub.

Motivation

The Activity Vocabulary defines a number of important collection properties for organizing reactions to an object. ActivityPub augments these with additional properties that specify the activity streams and social graph for actors.

Out of context, though, it can be hard to determine if a collection has a defined relationship to an object or actor. This can be important for clients that give users the ability to manipulate collections with the Add, Remove, Update and Delete activities, since the special collections defined in ActivityPub are usually maintained with different flows.

Other methods exist to identify collections that are the value of properties of actors. It’s possible to use the attributedTo property to identify the actor, and then compare against all of the collection properties of the actor (inbox, outbox, and so on). This is a good fallback mechanism, but the inverse properties defined in this document are a more direct way to determine the relationship. There is no method for determining if a collection is the property of an object, however.

Additionally, one form of spoofing that a server could use is referring to collections as properties of objects that in fact are related to other objects. For example, a server could include a collection of likes as a property of an object that is not the object that the likes are for. This could be used to inflate the apparent popularity of an object. Inverse properties can help prevent this kind of spoofing by providing a two-way verification mechanism.

These inverse properties are most useful when the collections are represented separately from the object or actor they are related to. For example, this representation can help identify the object that the collection contains the likes of:

{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    "https://w3id.org/fep/5711"
  ],
  "type": "Collection",
  "id": "https://example.com/collection/b25kr36ief",
  "likesOf": "https://example.com/image/7pqs5i7c1e"
}

This representation, on the other hand, is redundant, since the collection is represented as the property of the object:

{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    "https://w3id.org/fep/5711"
  ],
  "type": "Image",
  "id": "https://example.com/image/7pqs5i7c1e",
  "likes": {
    "type": "Collection",
    "id": "https://example.com/collection/b25kr36ief",
    "likesOf": "https://example.com/image/7pqs5i7c1e"
  }
}

User stories

Specification

The following terms are defined in this vocabulary extension.

The examples in the following sections refer to the following example object:

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Image",
  "id": "https://example.com/image/7pqs5i7c1e",
  "name": "A beautiful image",
  "url": "https://files.example.com/image/29m2p4kdq15.jpg",
  "likes": "https://example.com/collection/b25kr36ief",
  "shares": "https://example.com/collection/hvjgqhpv3e",
  "replies": "https://example.com/collection/u9hwmfih7r"
}

…and/or the following actor:

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Person",
  "id": "https://example.com/person/bup9a8eqm",
  "name": "Alice",
  "inbox": "https://example.com/collection/tgiqwh6p3b",
  "outbox": "https://example.com/collection/hvf8crcd6r",
  "followers": "https://example.com/collection/x48dtnhlt9",
  "following": "https://example.com/collection/r9w7krxua",
  "liked": "https://example.com/collection/jzc50wc28l"
}

likesOf

Defines an object for which the collection is the value of the likes property.

Example:

{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    "https://w3id.org/fep/5711"
  ],
  "type": "Collection",
  "id": "https://example.com/collection/b25kr36ief",
  "likesOf": "https://example.com/image/7pqs5i7c1e"
}

sharesOf

Defines an object for which the collection is the value of the shares property.

Example:

{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    "https://w3id.org/fep/5711"
  ],
  "type": "Collection",
  "id": "https://example.com/collection/hvjgqhpv3e",
  "sharesOf": "https://example.com/image/7pqs5i7c1e"
}

repliesOf

Defines an object for which the collection is the value of the replies property.

Example:

{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    "https://w3id.org/fep/5711"
  ],
  "type": "OrderedCollection",
  "id": "https://example.com/collection/u9hwmfih7r",
  "repliesOf": "https://example.com/image/7pqs5i7c1e"
}

inboxOf

Defines an actor for which the collection is the value of the inbox property.

Example:

{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    "https://w3id.org/fep/5711"
  ],
  "type": "Collection",
  "id": "https://example.com/collection/tgiqwh6p3b",
  "inboxOf": "https://example.com/person/bup9a8eqm"
}

outboxOf

Defines an actor for which the collection is the value of the outbox property.

Example:

{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    "https://w3id.org/fep/5711"
  ],
  "type": "Collection",
  "id": "https://example.com/collection/hvf8crcd6r",
  "outboxOf": "https://example.com/person/bup9a8eqm"
}

followersOf

Defines an actor for which the collection is the value of the followers property.

Example:

{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    "https://w3id.org/fep/5711"
  ],
  "type": "Collection",
  "id": "https://example.com/collection/x48dtnhlt9",
  "followersOf": "https://example.com/person/bup9a8eqm"
}

followingOf

Defines an actor for which the collection is the value of the following property.

Example:

{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    "https://w3id.org/fep/5711"
  ],
  "type": "Collection",
  "id": "https://example.com/collection/r9w7krxua",
  "followingOf": "https://example.com/person/bup9a8eqm"
}

likedOf

Defines an actor for which the collection is the value of the liked property.

Example:

{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    "https://w3id.org/fep/5711"
  ],
  "type": "Collection",
  "id": "https://example.com/collection/jzc50wc28l",
  "likedOf": "https://example.com/person/bup9a8eqm"
}

Implementation notes

There should be only one inverse relationship property for a collection. There are conceivable structures where the replies collection of an object is also the liked collection of an actor, but these are rare.

All of these properties are functional, meaning that there is only one value for each collection.

Security considerations

Claims made by these properties should be verified by retrieving the referenced object or actor and checking the appropriate property. For example, if a server claims that a collection is the shares property of an object using the sharesOf property, the consumer should retrieve the referenced object and check that the shares property references the same collection.

Use of these inverse properties can help prevent spoofing of collections, but they do not provide verification of the contents of the collection. For example, a collection that uses the likesOf property to claim that it is the likes collection of a video, and which is in turn referenced by the video, may still contain Like activities that are not actually likes of the video.

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.