ActivityPub/Primer/Announce activity

From W3C Wiki

The Announce activity is used to "share" or "repost" objects across the network.

What can be "Announced"

Content object types can be announced; for example, Note, Article, Image, Video, Audio.

Activity object types can also be announced; for example, a Like activity, or a Question.

Other types of AS2 objects can also be announced; however, implementations are going to have limited ability to handle more obscure object types. In particular, actor types like Person are rarely used in Announce activities.

Idempotence of Announce activities

Announce activities are not idempotent. It's possible to announce the same object multiple times. For example, re-sharing an Event object with the invitees to remind them of the upcoming event perhaps 1 week, 1 day, and 1 hour before the event.

However, some social network platforms, like Twitter, have idempotent sharing; for example, you can only retweet a tweet once (though you can share a tweet multiple times by quoting it).

Inclusion of the shared object

There are two ways to include a shared object in an Announce activity delivered over the ActivityPub federation protocol: by reference, and by embedding.

Inclusion by reference

The shared object is included with minimal properties to allow the receiving server to fetch the object; typically just the id.

{
   "@context": "https://www.w3.org/ns/activitystreams",
   "id": "https://example.com/users/evan/announce/3",
   "to": "Public",
   "type": "Announce",
   "object": "https://example.org/users/alice/note/121"
}

This format is recommended when sharing objects from a remote server. It does not make any claims about properties of the object, so the receiving server doesn't have to make any decisions about whether to trust those claims.

Also, because the receiving server has to fetch the object in order to determine its properties, the remote server that hosts the object has a chance to make authorization checks. This helps keep user data safe, especially when the authorization rules aren't shared across server boundaries, like user or server blocks.

Inclusion by embedding

The shared object is included with sufficient properties to represent the object in a user interface. For example, the following activity shares a note, with sufficient properties to show the note in a Web UI:

{
   "@context": "https://www.w3.org/ns/activitystreams",
   "id": "https://example.com/users/evan/announce/4",
   "to": "Public",
   "type": "Announce",
   "object": {
       "id": "https://example.com/users/bob/note/37",
       "type": "Note",
       "attributedTo": { 
          "id": "https://example.com/users/bob",
          "icon": "https://example.com/avatars/bob.jpg",
          "type": "Person",
          "name": "Bob W."
       },
       "content": "Hello, World!",
       "published": "2024-04-03T00:01:22Z"
   }
}

Including objects by embedding them benefits server-to-server delivery, by saving a fetch by the receiving server. Embedding is recommended when sharing an object on the same server, because the sending server can check any authorization requirements, like user or server blocks, before sending. The receiving server can also verify the properties, since the ID of the included object will have the same origin as the delivering actor.

Side effects of Announce activities

The shares collection of an object contains all the Announce activities that apply to that object. The server responsible for an object is responsible for updating the shares collection of the object. Typically, this happens when the creator of the object (identified by the attributedTo property) receives the Announce activity in their inbox.

Each element in the collection is a unique Announce activity. However, the actor of each activity is not unique; the same actor can make multiple announcements of the same object.

Recommendations for Announce

Interoperability between systems that allow multiple Announce activities and systems that don't is tricky. Here are some guidelines for implementers:

  • Implementations that publish multiple Announce activities for the same object should be prepared to have the second and later activities rejected by other implementations.
  • Implementations that publish multiple Announce activities should not expect that all such activities will be in the shares collection of remote objects.
  • Implementations that intend to publish single Announce activities should not depend on remote services rejecting duplicate announcements to enforce that idempotence. Remote services may not share that extra requirement.
  • Implementations that intend to publish single Announce activities should not depend on remote services enforcing uniqueness by actor in the shares collection. There may be multiple activities by the same actor in the collection.
  • Client applications that show the contents of the shares collection should be prepared to either show multiple activities, or filter for unique actors if only showing actors.