ActivityPub

Orb implements the ActivityPub spec for server to server communication. Communication is based on posting an activity (JSON document) to the server’s local outbox which then gets delivered to one or more server inboxes. HTTP signatures are used for authentication and authorization.

Outbox/Inbox

Inter-server communication is performed by posting an Activity to the Orb server’s Outbox. The Outbox handler delivers the activity to one or more targets by resolving the URIs of the target inboxes (from the “to” field of the activity) and posting the activity to each of the URIs. The target Inbox authorizes the message and invokes the appropriate handler.

../../_images/ap-outbox-inbox.svg

Outbox

Messages are published to the AMQP orb.activity.outbox queue and are handled asynchronously by a single instance in the Orb domain. A message contains two fields:

  1. Type: One of ‘broadcast’, ‘deliver’, or ‘resolve-and-deliver’

  2. Activity: The posted ActivityPub activity

When an activity is posted to the Outbox, it is first validated and then a message of type, ‘broadcast’, is published to the AMQP orb.activity.outbox queue. The message is handled by a single instance in the Orb domain.

Broadcast Message Handler

The ‘broadcast’ message handler performs the following steps:

  1. Stores the activity (which is contained in the message) to the local outbox database.

  2. Invokes an activity handler (this handler may include additional steps, depending on the type of activity).

  3. Resolves the inboxes of the URIs in the “to” field of the activity. This may involve retrieving URIs from the followers or witnesses collections. The ActivityPub service (actor) of each recipient URI is resolved via .well-known and a result containing the resolved URI (and potentially an error) is returned for each resolved URI.

Each result returned from the Outbox Resolver contains a URI and potentially an error. For each result that does not contain an error, a message of type, ‘deliver’, is published to the orb.activity.outbox queue with the URI from the result. For each result containing an error, a message of type, ‘resolve-and-deliver’, is published to the orb.activity.outbox queue so that the URI may be retried.

Deliver Message Handler

The ‘deliver’ handler posts the activity to the inbox URI (contained in the message). (Note that the appropriate HTTP signatures are added to the HTTP request.) If a transient error occurs (such as HTTP 500) then the message is NACK’ed and the ‘deliver’ message will be retried (according to the message redelivery mechanism).

Resolve-and-Deliver Message Handler

The ‘resolve-and-deliver’ handler resolves the inboxes of the URI contained in the message. Each result returned from the Outbox Resolver contains a URI and potentially an error. For each result that does not contain an error, a ‘deliver’ message is published to the orb.activity.outbox queue with the URI from the result. If the result contains a transient error (e.g. HTTP 500) then the message is NACK’ed and the ‘resolve-and-deliver’ message is retried (according to the message redelivery mechanism). If a persistent error occurs (e.g. 400) then the URI is skipped.

Inbox

The inbox is a REST endpoint in Orb which accepts activities. When an activity is received, the HTTP signature in the header of the request is verified using the public key of the actor that sent the activity. After the actor is authenticated, a message is posted to the orb.activity.inbox queue and is processed by one of the server instances in the domain.

The inbox handler first stores the activity in the ‘inbox’ database and authorizes the activity. (Each activity could have different authorization criteria which are explained in each of the activities below.) The appropriate activity handler is then invoked.

Activities

Follow

A Follow activity is posted by a server to another server so that activities may be synchronized between them. For example, domain1 posts a Follow activity to domain2 indicating that it wants notifications of objects created by domain2 (via the Create activity). Domain1 is also notified of any objects created by servers that domain2 is following via the Announce activity. When a server receives a Follow activity in its inbox, it authorizes the ‘actor’ (which is the originating server) in the Follow request using a configurable Follow Authorization Policy. If authorized, the actor is added to the list of followers and an Accept activity is posted to the actor’s inbox. When an Accept activity is received in the inbox, the activity is first validated against a previously posted Follow activity and then the ‘actor’ in the Accept activity (which was the target server in Follow) is added to the following collection.

../../_images/ap-follow-accept.svg

If the actor posting the Follow activity is not authorized then a Reject activity is posted to the actor’s inbox. A Reject of a Follow activity simply logs the fact that the request was rejected.

../../_images/ap-follow-reject.svg

Undo Follow

An Undo activity is posted to ‘unfollow’ a server. The Undo activity is posted to the server to which the previous Follow activity was posted and the target server is removed from the following list. The target server handles the Undo activity by removing the originating server from the followers list.

Invite Witness

An Invite activity is posted to another server in order to invite that server to be a witness of Anchor Events. For example, domain1 posts an Invite activity to domain2 indicating that it wants domain2 to be a witness of Anchor Events produced by domain1 (using the Offer activity).

When a server receives an Invite witness activity in its inbox, it authorizes the actor (which is the originating server) in the Invite request using an Invite Witness Authorization Policy. If authorized, the actor is added to the witnessing collection and an Accept activity is posted to the actor’s inbox. When an Accept activity is received in the inbox, the activity is first validated against a previously posted Invite witness activity and then the ‘actor’ in the Accept activity is added to the witnesses collection.

../../_images/ap-invite-accept.svg

If the actor is not authorized, then a Reject activity is posted to the actor’s inbox. A Reject of an Invite witness activity simply logs the fact that the request was rejected.

../../_images/ap-invite-reject.svg

Undo Invite Witness

An Undo activity is posted to remove a server as a witness. The Undo activity is posted to the server to which the previous Invite activity was posted and the target server is removed from the witnesses list. The target server handles the Undo activity by removing the originating server from the witnessing list.

Offer/Accept

An Offer activity is posted to one or more servers that are contained in the witnesses collection in order to collect proofs. (The selection of witnesses is dictated by a Witness Policy which determines the minimum number of proofs required.) When a server receives an Offer activity in its inbox, the request is first authorized by ensuring that the actor of the Offer is in the witnessing collection. Once authorized, the Anchor Linkset which is embedded in the Offer activity is added to the ledger (VCT) and an Accept anchor activity (which contains the proof) is posted back to the originator of the offer. When an Accept anchor activity is received in the inbox, the activity is first validated against a previously posted Offer activity and then the embedded proof for the Anchor Linkset is added to the collection of existing proofs. Once a sufficient number of proofs is received (according to the Witness Policy) then a complete anchor linkset (containing all proofs) is constructed and the anchor linkset is posted to the queue, orb.anchor_linkset, to be processed by the Batch Writer.

../../_images/ap-offer-accept.svg

If the actor of the Offer is not in the witnessing collection then a Reject activity is posted to the originating actor. The Reject of an Offer activity simply logs the fact that the request was rejected.

../../_images/ap-offer-reject.svg

Create/Announce

A Create activity is posted by the Batch Writer to one or more servers that are contained in the followers collection.

When a server receives a Create activity in its inbox, the Anchor Linkset which is embedded in the Create activity is first stored to CAS and then the hashlink of the anchor linkset is posted to the orb.anchor queue so that it may be processed by the Observer. After the Observer processes the anchor linkset, it posts a Like activity back to the “actor” of the Create activity. The Create activity is also forwarded to the servers in the followers collection using the Announce activity.

When a server receives an Announce activity in its inbox the Anchor Linkset which is embedded in the Announce activity is first stored to CAS and then the hashlink of the anchor linkset is posted to the orb.anchor queue so that it may be processed by the Observer. After the Observer processes the anchor linkset, it posts a Like activity back to the “actor” of the Announce activity as well as to the originator of the anchor linkset.

../../_images/ap-create-announce.svg

Like

A Like activity is posted by the Observer after having processed an anchor linkset. The Like activity includes a “url” field which is a hashlink. This hashlink contains metadata of one or more locations where the anchor is replicated. (The alternate locations may be retrieved using WebFinger.) When a server receives the Like activity in its inbox, it adds the additional URIs to the anchor link database.

Undo Like

An Undo activity is posted to inform other servers that it no longer replicates an anchor. The Undo activity is posted to the server to which the previous Like activity was posted. The target server handles the Undo activity by removing the link from the anchor link database.

Authorization Policy

Authorization policies are applied when handling the Follow and Invite activities. If authorization fails then a Reject activity is posted to the originating server.

Follow Authorization Policy

An authorization policy may be configured for the Follow activity using the configuration parameters, follow-auth-policy. The possible values are accept-all and accept-list. If accept-all is used then all Follow requests are accepted. If accept-list is used then the actor in the Follow activity must be in the accept-list database.

Invite Witness Authorization Policy

An authorization policy may be configured for the Invite Witness activity using the configuration parameters, invite-witness-auth-policy. The possible values are accept-all and accept-list. If accept-all is used then all Invite witness requests are accepted. If accept-list is used then the actor in the Invite activity must be in the accept-list database.

Accept List

An accept-list is simply a database of server URLs that are authorized for a particular type of operation. The two types of operations are follow and invite-witness. If the actor URL is in the follow accept list then a Follow request from that server is authorized. If the actor URL is in the invite-witness accept list then an Invite witness request from that server is authorized.

The accept-list is managed via the REST endpoint /services/orb/acceptlist