The ActivityPub protocol is a decentralized social networking protocol based upon the [[!ActivityStreams]] 2.0 data format. It provides a client to server API for creating, updating and deleting content, as well as a federated server to server API for delivering notifications and content.

Overview

ActivityPub は二つの層を提供します:

ActivityPub implementations can implement just one of these things or both of them. However, once you've implemented one, it isn't too many steps to implement the other, and there are a lot of benefits to both (making your website part of the decentralized social web, and being able to use clients and client libraries that work across a wide variety of social websites).

ActivityPub では、ユーザーはサーバ上のアカウントを通して actor として表現されます。 異なるサーバのユーザーアカウントはそれぞれ異なった actor に対応します。 全ての actor は次のものを持ちます:

Actor with inbox and outbox

これらはエンドポイント、つまり実際には ActivityPub actor の ActivityStreams 記述にある単なる URL です。 (ActivityStreams については後に触れます。)

以下は、我が友 Alyssa P. Hacker の記録の例です:

  {"@context": "https://www.w3.org/ns/activitystreams",
   "type": "Person",
   "id": "https://social.example/alyssa/",
   "name": "Alyssa P. Hacker",
   "preferredUsername": "alyssa",
   "summary": "Lisp enthusiast hailing from MIT",
   "inbox": "https://social.example/alyssa/inbox/",
   "outbox": "https://social.example/alyssa/outbox/",
   "followers": "https://social.example/alyssa/followers/",
   "following": "https://social.example/alyssa/following/",
   "liked": "https://social.example/alyssa/liked/"}
      

ActivityPub は語彙として [[!ActivityStreams]] を使います。 これはなかなか素晴らしいことです; ActivityStreams はソーシャルネットワークに 流れる全てのアクティビティと内容を表現する全ての一般的な用語を 含んでいるからです。 おそらく ActivityStreams は既にあなたが必要な全ての語彙を 含んでいるでしょうが、もしそうでなければ、ActivityStreams は [[!JSON-LD]] を使って拡張できます。 あなたが JSON-LD について知っているなら、JSON-LD によって提供される クールなリンク付きデータ手法の有用性を使えます。 もしそうでなくても、心配は要りません; JSON-LD 文書と ActivityStreams は どちらも単なる単純な JSON として理解すればよいです。 (もし拡張を追加しようとしているなら、ここが本当に JSON-LD が助けになるところです。)

さて。 Alyssa は彼女の友人と話したいと思っていて、彼女の友人も彼女と 話したいと思っています! 幸いにもこれらの "inbox" と "outbox" がその助けになります。 これらはそれぞれ GET と POST で異なった振る舞いをします:

Actor with messages flowing from rest of world to inbox and from outbox to rest of world

では、ここでおさらいです:

もちろん、もし最後のもの (誰かの outbox を GET する) が、人々が 送っているものを見る唯一の方法なら、これはとても効率的な 連合プロトコルとは言えません! 実際には、連合は普通サーバが他のサーバのactorのinboxに送るときに起こります。

例を見てみましょう! Alyssa は友人である Ben Bitdiddle と話したいとします。 彼女は彼に最近本を貸していて、それを返してくれるか確認したいです。 以下は、彼女が書いた、ActivityStreams オブジェクトとしての メッセージです。

  {"@context": "https://www.w3.org/ns/activitystreams",
   "type": "Note",
   "to": ["https://chatty.example/ben/"],
   "attributedTo": "https://social.example/alyssa/",
   "content": "Say, did you finish reading that book I lent you?"}
      

これは Ben に向けた note です。 彼女はこれを彼女の outbox に POST します。

Actor posting message to outbox

これは非アクティビティオブジェクトなので、サーバは これは新しく作成されたオブジェクトと認識し、これを Create アクティビティにラッピングします。 (ActivityPub で送られる Activity は一般的に ある actor があるオブジェクトに対して行われるアクティビティ、という パターンに従います。 この場合は、アクティビティは Person によって投稿される Note オブジェクトの Create です。)

  {"@context": "https://www.w3.org/ns/activitystreams",
   "type": "Create",
   "id": "https://social.example/alyssa/posts/a29a6843-9feb-4c74-a7f7-081b9c9201d3",
   "to": ["https://chatty.example/ben/"],
   "actor": "https://social.example/alyssa/",
   "object": {"type": "Note",
              "id": "https://social.example/alyssa/posts/49e2d03d-b53a-4c4c-a95c-94a6abf45a19",
              "attributedTo": "https://social.example/alyssa/",
              "to": ["https://chatty.example/ben/"],
              "content": "Say, did you finish reading that book I lent you?"}}
      

Alyssa のサーバは Ben の ActivityStreams actor オブジェクトを探し、 彼の inbox エンドポイントを見つけ、彼の inbox に彼女のオブジェクトを POST します。

Server posting to remote actor's inbox

技術的にはこれは二つに分割されたステップです…一つ目は クライアントからサーバへの通信、もう一つはサーバからサーバへの通信(連合)です。 しかし、この例では両方を使っているので、 outbox から inbox への一連の流れとしての投稿と抽象化して考えられます:

Note flowing from one actor's outbox to other actor's inbox

すばらしい! しばらく後に、Alyssa は彼女が受け取った新しいメッセージを チェックします。 彼女のスマートフォンは彼女の inbox を GET でポーリングし、 友人が投稿した大量の猫動画や姉が投稿した甥の写真の中から、 彼女は次のメッセージを見つけます:

  {"@context": "https://www.w3.org/ns/activitystreams",
   "type": "Create",
   "id": "https://chatty.example/ben/p/51086",
   "to": ["https://social.example/alyssa/"],
   "actor": "https://chatty.example/ben/",
   "object": {"type": "Note",
              "id": "https://chatty.example/ben/p/51085",
              "attributedTo": "https://chatty.example/ben/",
              "to": ["https://social.example/alyssa/"],
              "inReplyTo": "https://social.example/alyssa/posts/49e2d03d-b53a-4c4c-a95c-94a6abf45a19",
              "content": "<p>Argh, yeah, sorry, I'll get it back to you tomorrow.</p>
                          <p>I was reviewing the section on register machines,
                             since it's been a while since I wrote one.</p>"}}
      

Alyssa はほっとして、Ben の投稿に「いいね」します:

  {"@context": "https://www.w3.org/ns/activitystreams",
   "type": "Like",
   "id": "https://social.example/alyssa/posts/5312e10e-5110-42e5-a09b-934882b3ecec",
   "to": ["https://chatty.example/ben/"],
   "actor": "https://social.example/alyssa/",
   "object": "https://chatty.example/ben/p/51086"}
      

彼女はこのメッセージを彼女の outbox に POST します。 (これは activity なので、彼女のサーバは これを Create オブジェクトでラップする必要がないことを分かっています。)

幸せな気分になったので、彼女は彼女のフォロワーに公開メッセージを 投稿することにしました。 ほどなくして以下のメッセージが彼女の followers コレクションの全ての メンバーに送信され、またこれは特殊な Public グループ宛になっているので、 誰でも一般に読むことができます。

  {"@context": "https://www.w3.org/ns/activitystreams",
   "type": "Create",
   "id": "https://social.example/alyssa/posts/9282e9cc-14d0-42b3-a758-d6aeca6c876b",
   "to": ["https://social.example/alyssa/followers/",
          "https://www.w3.org/ns/activitystreams#Public"],
   "actor": "https://social.example/alyssa/",
   "object": {"type": "Note",
              "id": "https://social.example/alyssa/posts/d18c55d4-8a63-4181-9745-4e6cf7938fa1",
              "attributedTo": "https://social.example/alyssa/",
              "to": ["https://social.example/alyssa/followers/",
                     "https://www.w3.org/ns/activitystreams#Public"],
              "content": "Lending books to friends is nice.  Getting them back is even nicer! :)"}}
      

Social Web Working Group

ActivityPub is one of several related specifications being produced by the Social Web Working Group. Implementers interested in alternative approaches and complementary protocols should review [[Micropub]] and the overview document [[Social-Web-Protocols]].

仕様プロファイル

この仕様は、密接に関連し相互に作用する二つのプロトコルを定義する:

クライアント-サーバ間プロトコル(ソーシャル API)
このプロトコルは、クライアントがユーザーに代わって行動することを認める。 例えば、このプロトコルはあるユーザーのactorのソーシャルストリームに 相互作用するモバイルフォンアプリケーションで使われる。
サーバ-サーバ間プロトコル(連合プロトコル)
このプロトコルは、異なるサーバにあり、同じソーシャルグラフ上で 結びつけられているactorの間でアクティビティを配布するために使われる。

The ActivityPub specification is designed so that once either of these protocols are implemented, supporting the other is of very little additional effort. However, servers may still implement one without the other. This gives three conformance classes:

ActivityPub 準拠クライアント
This designation applies to any implementation of the entirety of the client portion of the client to server protocol.
ActivityPub 準拠サーバ
This designation applies to any implementation of the entirety of the server portion of the client to server protocol.
ActivityPub 準拠連合サーバ
This designation applies to any implementation of the entirety of the federation protocols.

It is called out whenever a portion of the specification only applies to implementation of the federation protocol. In addition, whenever requirements are specified, it is called out whether they apply to the client or server (for the client-to-server protocol) or whether referring to a sending or receiving server in the server-to-server protocol.

オブジェクト

オブジェクトは [[!ActivityStreams]] と ActivityPub 両方の中核となる概念である。 オブジェクトはしばしば Activity でラッピングされ、自身が Object の サブクラスである Collection に含まれる。 [[!Activity-Vocabulary]] 文書、特に Core Classes を参照のこと; ActivityPub はこの語彙のマッピングに非常に密接に従う。

ActivityPub は ActivityStreams によって提供されるものに加えていくつかの 用語を定義している。 これらの用語は https://www.w3.org/ns/activitystreams で ActivityPub JSON-LD context として提供される。 実装者はそのオブジェクト定義に ActivityPub context を含むべきである(SHOULD)。 実装者は追加の context を必要に応じて含んでも良い(MAY)。

ActivityPub は ActivityStreams の URI / IRI 仕様 と同じものを共有する。

サーバはコンテンツスプーフィング攻撃を防ぐために受信したコンテンツを 検証するべきである(SHOULD)。 サーバは少なくとも、そのオブジェクトがその発信元から受信したをチェックするのと 同じぐらい頑強な何かをするべきであるが、 可能であれば署名検証のような機構が望ましい。) 特定の検証機構をこの文書で命令的に指定することはしないが、 いくつかの提案と良い習慣については Security Considerations を参照してほしい。

例えば、example.com が次のアクティビティを受信すると、
         {
           "@context": "https://www.w3.org/ns/activitystreams",
           "type": "Like",
           "actor": "https://example.net/~mallory",
           "to": ["https://hatchat.example/sarah/",
                  "https://example.com/peeps/john/"],
           "object": {
             "@context": {"@language": "en"},
             "id": "https://example.org/~alice/note/23",
             "type": "Note",
             "attributedTo": "https://example.org/~alice",
             "content": "I'm a goat"
           }
         }
        
id を逆参照して、これが存在して妥当なオブジェクトであり、 このオブジェクトが不正確ではないことを確認するべきである。 (この例では、Mallory が Alice によって投稿されたとされているオブジェクトを 捏造している可能性がある。)

オブジェクト識別子

[[!ActivityStreams]] の全てのオブジェクトはユニークなグローバル識別子を 付けるべきとされている。 ActivityPub はこの要求を拡張する。 ActivityPub プロトコルで配布される全てのオブジェクトは、 意図的に一時的なもの(ある種のチャットメッセージやゲーム通知のような、短命の アクティビティで検索されることを意図していないもの)でない限り、 ユニークなグローバル識別子を持たなければならない(MUST)。 これらの識別子は以下のグループのどれか一つでなければならない:

  1. HTTPS URI のような、公に展開可能な URI で、その権限が発信元サーバに帰属するもの。 (公開用のコンテンツは HTTPS URI を使うべきである(SHOULD)。)
  2. 明示的に JSON null オブジェクトとして指定された ID; この場合は無名オブジェクト(親コンテキストの一部) を意味する。

識別子は、アクティビティが意図的に一時的なものでない限り、 サーバからサーバへの通信で投稿するアクティビティでは 提供しなければならない(MUST)。 しかし、クライアントからサーバへの通信では、id の指定なしに outbox に投稿されたオブジェクトを受信したサーバは、 その actor の名前空間の ID を割り当て、投稿されたオブジェクトに それを添付するべきである(SHOULD)。

全てのオブジェクトは以下の属性を持つ:

id
オブジェクトのユニークなグローバル識別子(オブジェクトが一時的なものの場合を 除く; この場合 id は省略しても良い(MAY))。
type
オブジェクトの型。

オブジェクトの取得

HTTP GET メソッドは、アクティビティを取得するためのオブジェクトの id 属性として展開されることがある。 リクエストに対するレスポンスとして返すデータの種類を選択するために、 サーバは [[!RFC7231]] で定義されている HTTP content negotiation を使っても良い(MAY)。 application/ld+json; profile="https://www.w3.org/ns/activitystreams" への返答として ActivityStreams オブジェクト表現を表現しなければならず(MUST)、 application/activity+json への返答としても ActivityStreams 表現を表現するべきである(SHOULD)。 クライアントはアクティビティを取得するために Accept ヘッダに application/ld+json; profile="https://www.w3.org/ns/activitystreams" メディアタイプを指定しなければならない(MUST)。

サーバは前述する要求に従わないリクエストに対して他の振る舞いを 実装しても良い(MAY)。 (例えば、サーバは追加でレガシーなプロトコルを実装しても良いし、 あるリソースの HTML 表現と ActivityStreams 表現で同じ URI を使っても良い。)

サーバは で指定された認証を要求したり、 独自の認証規則を実装したりしても良い(MAY)。 サーバは、認証チェックを通過しなかったリクエストに対して適切な HTTP エラーコードか、 オブジェクトの存在がプライベートなものと考えられる場合は 403 Forbidden エラーコードで失敗するべきである(SHOULD)。 プライベートターゲットの存在を公開したくない発信元サーバは、 代わりに 404 Not Found のステータスコードを返しても良い(MAY)。

source 属性

[[!Activity-Vocabulary]] で定義されている全ての属性に加えて、 ActivityPub は Objectsource 属性を提供するように拡張する。 source 属性は is intended to convey some sort of source from which the content markup was derived, as a form of provenance, or to support future editing by clients. 一般的に、クライアントは source から content への変換を行い、逆は行わない。

source の値は、 ソース情報を提供するために自身の contentmediaType フィールドを持つオブジェクトである。

          {
            "@context": ["https://www.w3.org/ns/activitystreams",
                         {"@language": "en"}],
            "type": "Note",
            "id": "http://postparty.example/p/2415",
            "content": "<p>I <em>really</em> like strawberries!</p>",
            "source": {
              "content": "I *really* like strawberries!",
              "mediaType": "text/markdown"}
          }
        

一般的に、元々作成したのと同じソース形式でユーザーに元の投稿を編集させるのが 最善である。 しかし、全てのクライアントが全てのソース型に対するよいインターフェースを 安定して提供できるわけではなく、 クライアントは source から content への変換が行われることを 想定するので、 クライアントによっては、他のクライアントがどのように動作するかを知らない メディア型で動作するかもしれない。 While a client could feasibly provide the content markup to be edited and ignore the source, this means that the user will lose the more desirable form of the original source in any future revisions. A client doing so should thus provide a minimally obtrusive warning cautioning that the original source format is not understood and is thus being ignored.

For example, Alyssa P. Hacker likes to post to her ActivityPub powered blog via an Emacs client she has written, leveraging Org mode. Later she switches to editing on her phone's client, which has no idea what text/x-org is or how to render it to HTML, so it provides a text box to edit the original content instead. A helpful warning displays above the edit area saying, "This was originally written in another markup language we don't know how to handle. If you edit, you'll lose your original source!" Alyssa decides the small typo fix isn't worth losing her nice org-mode markup and decides to make the update when she gets home.

actor

ActivityPub actor は一般的に ActivityStreams Actor Types の一つであるが、 それに制限されない。 例えば、 Profile オブジェクトが actor として使われるかもしれないし、 ActivityStreams 拡張からの型が使われるかもしれない。 actor は ActivityPub の他の Object と同様に 取得 される。 他の ActivityStreams オブジェクトと同様、actor は URI である id を持つ。 (例えばログインフォームのような)ユーザーインターフェースから直接入力された 場合、単純化した命名規則に対応しているのが望ましい。 この目的のため、ID 正規化は以下のように行われるべきである(SHOULD):

  1. 入力された ID が有効な URI の場合、これが直接使われる。
  2. ユーザーが URI にスキームを追加するのを怠ったがそれ以外は有効であるように 見える場合、クライアントはデフォルトのスキーム (https が望ましい) を提供しようとしても良い(MAY)。
  3. さもなければ、入力された値は不正として扱われるべきである。

一旦 actor の URI が識別されると、これは展開されるべきである。

ActivityPub は「ユーザー」と Actor との間で特定の関係を決定しない; 多くの設定が考えられる。 ある Actor を複数の人間や組織が制御しているかもしれないし、 一人の人間や組織が複数の Actor を制御しているかもしれない。 同様に、ある Actor はボットや自動化プロセスのようなソフトウェアの 一部を表現しているかもしれない。 より詳細な「ユーザー」のモデリングとしては、 for example linking together of Actors which are controlled by the same entity, or allowing one Actor to be presented through multiple alternate profiles or aspects, are at the discretion of the implementation.

Actor オブジェクト

Actor オブジェクトは、 で強制される属性に加えて、 以下の属性を持たなければならない(MUST):

inbox
この actor が受け取った全てのメッセージから成る [[!ActivityStreams]] OrderedCollection への参照; を参照のこと。
outbox
この actor によって作成された全てのメッセージから成る [[!ActivityStreams]] OrderedCollection ; を参照のこと。

実装は、これに加えて、以下の属性を提供するべきである(SHOULD):

following
この actor がフォローしている actor を示す [[!ActivityStreams]] コレクションへのリンク; 参照。
followers
この actor をフォローしている actor を示す [[!ActivityStreams]] コレクションへのリンク; 参照。

実装は以下の属性を提供しても良い(MAY):

liked
この actor が好んでいるオブジェクトを示す [[!ActivityStreams]] コレクションへのリンク; 参照。
{
  "@context": ["https://www.w3.org/ns/activitystreams",
               {"@language": "ja"}],
  "type": "Person",
  "id": "https://kenzoishii.example.com/",
  "following": "https://kenzoishii.example.com/following.json",
  "followers": "https://kenzoishii.example.com/followers.json",
  "liked": "https://kenzoishii.example.com/liked.json",
  "inbox": "https://kenzoishii.example.com/inbox.json",
  "outbox": "https://kenzoishii.example.com/feed.json",
  "preferredUsername": "kenzoishii",
  "name": "石井健蔵",
  "summary": "この方はただの例です",
  "icon": [
    "https://kenzoishii.example.com/image/165987aklre4"
  ]
}
        

実装は、これに加えて、以下の属性を提供しても良い(MAY):

streams
関心のある補助的な Collection のリスト。
preferredUsername
actor を参照するために使われる短いユーザー名; ユニーク性は保証されない。
endpoints
この actor またはこの actor を参照する誰かにとって有用かもしれない (典型的にはサーバ/ドメイン単位の) 追加のエンドポイントをマッピングした json オブジェクト。 このマッピングは actor 文書の中で値としてネストしても良いし、 これらの属性を持つ JSON-LD 文書へのリンクでも良い。

endpoints マッピングは以下の属性を含んでいても良い(MAY):

proxyUrl
actor のクライアントが、 アクセスするのに認証が必要なリモート ActivityStreams にアクセスするのに 使われる エンドポイント URI。 このエンドポイントを使うには、クライアントは 要求する ActivityStreams オブジェクトの id の値を持つ x-www-form-urlencoded id 引数を 投稿する。
oauthAuthorizationEndpoint
OAuth 2.0 bearer トークン [[RFC6749]] [[RFC6750]] が クライアントからサーバへの通信 の 認証として使われる場合、 このエンドポイントは、ブラウザ認証ユーザーが新しい認証グラントを得るための URI を指定する。
oauthTokenEndpoint
OAuth 2.0 bearer tokens [[RFC6749]] [[RFC6750]] が クライアントからサーバへの通信 の 認証として使われる場合、 このエンドポイントは、クライアントがアクセストークンを得るための URI を指定する。
provideClientKey
Linked Data Signatures と HTTP Signatures が認証と認可として使われている場合、 このエンドポイントはブラウザ認証ユーザーが クライアントからサーバへの通信 の ためのクライアントの公開鍵を認証する URI を指定する。
signClientKey
Linked Data Signatures と HTTP Signatures が認証と認可として使われている場合、 このエンドポイントは specifies a URI at which a client key may be signed by the actor's key for a time window to act on behalf of the actor in interacting with foreign servers.
sharedInbox
パブリックに宛先指定された アクティビティとフォロワーによって送られたアクティビティを 広く配布するために使われる オプションのエンドポイント。 publicInbox エンドポイントは、 パブリックに読み込み可能な、 Public 特殊コレクションを示す オブジェクトを含む OrderedCollection オブジェクトであるべきである(SHOULD)。 sharedInbox エンドポイントからの読み込みは、 Public エンドポイントにアドレス指定されていないオブジェクトを 表現してはならない(MUST NOT)。

ActivityPub のための上流語彙として、 任意の適用可能な [[!ActivityStreams]] 属性は ActivityPub Actor として使われる。 一部の ActivityStreams 属性は特に注目する価値がある; これが ActivityPub 実装でどう使われるかを例示する。

url
actor の「プロフィール web ページ」へのリンク (これが id の値と同じではない場合)。
name
actor の、望ましい「ニックネーム」や「表示名」。
summary
ユーザー自身の簡単な要約や経歴
icon
ユーザーのプロフィール画像を表現する、画像へのリンクまたは Image オブジェクト (これはサムネイルかもしれない)。

name, preferredUsername, summary の ような、自然言語値を含む属性は、 natural language support defined in ActivityStreams を使う。

コレクション

[[!ActivityStreams]] はコレクションの概念を定義している; ActivityPub は特殊な振る舞いをするコレクションをいくつか定義する。 ActivityPub は大きなオブジェクトの集合を辿るために ActivityStreams paging を使うことに注意すること。

これらのコレクションの一部は特に OrderedCollection 型を指定しており、一方その他は Collection または OrderedCollection の両方を許していることに注意すること。 OrderedCollection は一貫して逆時系列順で表現されなければならない(MUST)。

逆時系列順を決定するのにどの属性が使われるかは、意図的に実装詳細として 残してある。 例えば、多くの SQL スタイルのデータベースは識別子としてインクリメントする 整数を使う; これはほとんどの場合挿入順として合理的に使われる。 その他のデータベースでは、挿入時刻タイムスタンプが好まれるかもしれない。 何が使われるかは重要ではないが、新しいアイテムが最初になるような形で 要素の順序が保持されていなければならない。 「最終更新」タイムスタンプのような定期的に変更される属性は 使われるべきではない。

Outbox

outbox は actor のプロファイルの outbox プロパティを使って発見される。 outbox OrderedCollectionでなければならない(MUST)。

The outbox stream contains activities the user has published, subject to the ability of the requestor to retrieve the activity (that is, the contents of the outbox are filtered by the permissions of the person reading it). ユーザーが Authorization なしでリクエストを投稿した場合、 サーバは全てを Public 投稿として 応答しなければならない。 これは潜在的にそのユーザーによって発行された、全ての関連するオブジェクトと なるかもしれないが、 利用可能なアイテムの数は実装とデプロイされたサーバの自由裁量に任されている。

outbox は HTTP POST リクエストを受け付ける; その振る舞いは クライアントからサーバへの通信に 記述されている。

Inbox

inbox は actor のプロファイルの inbox プロパティを使って発見される。 inbox OrderedCollection でなければならない(MUST)。

inbox は actor が受信した全てのアクティビティを含む。 サーバは要求者の権限に応じてコンテンツをフィルタリングするべきである(SHOULD)。 一般的に、inbox の所有者は その inbox のコンテンツ全てにアクセスできる。 アクセス制御に依存して、その他のコンテンツの一部はパブリックで、 一方その他のコンテンツは非所有者のユーザーは認証を要求されるかもしれない; if they can access the inbox at all.

サーバは inbox に返されたアクティビティの重複解消を 実行しなければならない(MUST)。 Duplication can occur if an activity is addressed both to an actor's followers, and a specific actor who also follows the recipient actor, and the server has failed to de-duplicate the recipients list. このような重複解消は、アクティビティの id を比較して、 既に読んだアクティビティを落とす形で行われなければならない(MUST)。

連合サーバ上の actor の inbox は HTTP POST リクエストを受け付ける; その振る舞いは Delivery に記述されている。 非連合サーバは POST リクエストを受け取った場合は 405 Method Not Allowed を 返すべきである(SHOULD)。

Followers コレクション

actorfollowers コレクションを 持つべきである(SHOULD)。 これはこの actor に Follow アクティビティを送信したときに 副作用 として追加された送信者の一覧である。 これは誰かがある actor をフォローしている全てのユーザーの一覧を 見つける場所である。 followers コレクションは OrderedCollection または Collection でなければならず(MUST)、 認証されたユーザーの権限や、認証がない場合は適切な形でフィルタリングしても 良い(MAY)。

follow アクティビティは一般的には、ある actor が作成したオブジェクトを 見るための要求である。 This makes the Followers collection an appropriate default target for delivery of notifications.

Following コレクション

各 actor は following コレクションを持つべきである(SHOULD)。 これは 副作用 として追加された、 この actor がフォローした相手の一覧である。 following コレクションは OrderedCollection または Collection でなければならず(MUST)、 認証されたユーザーの権限や、認証がない場合は適切な形でフィルタリングしても 良い(MAY)。

Liked コレクション

各 actor は liked コレクションを持っても良い(MAY)。 これは 副作用 として追加された、 この actor の全ての Like のオブジェクトの一覧である。 liked コレクションは OrderedCollection または Collection でなければならず(MUST)、 認証されたユーザーの権限や、認証がない場合は適切な形でフィルタリングしても 良い(MAY)。

Public アドレス指定

[[!ActivityStreams]] コレクションとオブジェクトに加えて、 activity は追加で特殊な "public" コレクションを宛先に指定できる; これは識別子 https://www.w3.org/ns/activitystreams#Public である。 例:

          {
            "@context": "https://www.w3.org/ns/activitystreams",
            "id": "https://www.w3.org/ns/activitystreams#Public",
            "type": "Collection"
          }
        

この特殊な URI を宛先に指定された activity は全てのユーザーから 認証なしにアクセスできる。 実装者は "public" 特殊コレクションへ配送してはならない(MUST NOT); これは実際の activity を受信する能力を持たない。 しかし、 actor はパブリックな投稿の効率的な共有配送のために利用可能である sharedInbox エンドポイントを 持ってもよい(MAY); を参照のこと。

ActivityStreams JSON-LD コンテキストを使って ActivityStreams オブジェクトを短縮化すると、 https://www.w3.org/ns/activitystreams#Public は、 それぞれPublic コレクションの正当な表現である、 単に Public および as:Public と 表現できることに注意すること。 ActivityStreams に関して、 受信したアクティビティを JSON-LD ツールを使ってローカルなコンテキストに 変換するのではなく、単に JSON として扱う実装はこれに注意するべきで、 3 種類全ての表現を受け付けるように準備するべきである。

Likes コレクション

各オブジェクトは likes コレクションを持ってもよい(MAY)。 This is a list of all Like activities with this object as the object property, added as a side effect. The likes コレクションは OrderedCollection または Collection でなければならず(MUST)、 認証されたユーザーの権限や、認証がない場合は適切な形でフィルタリングしても 良い(MAY)。

コレクションを、似たような名前であるけれども異なる liked コレクションと 混同しないように注意すること。 まとめると:

  • liked: 特に actor の属性。 これは このアクターによって 行われた Like アクティビティのコレクションで、 outbox への配送の副作用 として コレクションに追加される。
  • likes: あらゆるオブジェクトの属性となり得る。 これはこのオブジェクトを参照している Like アクティビティの コレクションで、 inbox への配達の副作用 として コレクションに追加される。

Shares コレクション

各オブジェクトは shares コレクションを持っても良い(MAY)。 これは、このオブジェクトを object 属性に含む全ての Announce アクティビティの一覧で、 副作用 として追加されたものである。 shares コレクションは OrderedCollection または Collection でなければならず(MUST)、 認証ユーザーの権限によってや、認証が与えられなかったときに適切になるように、 フィルタリングしても良い(MAY)。

クライアントからサーバへの通信

[[!ActivityStreams]] で定義された Activity は、ソーシャルグラフ内で コンテンツを作成、変更、共有するための中心となる機構である。

クライアントからサーバへの通信は、クライアントが actor の outbox に Activitity 投稿することで行われる。 これを行うために、クライアントは actor の profile からその outbox の URL を 発見しなければならず(MUST)、 それから、Content-Type に application/ld+json; profile="https://www.w3.org/ns/activitystreams" を指定した POST リクエストをこの URL に行わなければならない(MUST)。 Servers MAY interpret a Content-Type or Accept header of application/activity+json as equivalent to application/ld+json; profile="https://www.w3.org/ns/activitystreams" for client-to-server interactions. このリクエストは、outbox を所有するユーザーの認証情報で 認証されなければならない(MUST)。 POST リクエストのボディは、単一の Activity (組み込みオブジェクトを含んでいても良い(MAY))、あるいは サーバによって Create アクティビティにラッピングされる 単一の非 Activity オブジェクトのどちらかを含んでいなければならない(MUST)。

POST /outbox/ HTTP/1.1
Host: dustycloud.org
Authorization: Bearer XXXXXXXXXXX
Content-Type: application/ld+json; profile="https://www.w3.org/ns/activitystreams"

{
  "@context": ["https://www.w3.org/ns/activitystreams",
               {"@language": "en"}],
  "type": "Like",
  "actor": "https://dustycloud.org/chris/",
  "name": "Chris liked 'Minimal ActivityPub update client'",
  "object": "https://rhiaro.co.uk/2016/05/minimal-activitypub",
  "to": ["https://rhiaro.co.uk/#amy",
         "https://dustycloud.org/followers",
         "https://rhiaro.co.uk/followers/"],
  "cc": "https://e14n.com/evan"
}
      

id 属性付きの Activity が投稿されたとき、 サーバはこれを無視してこの Activity のための新しい id を 生成しなければならない(MUST)。 サーバは 201 Created HTTP コードを返さなければならず(MUST)、 Activity が一時的なものでない限り、 Location ヘッダに新しい id を 含めなければならない(MUST)。

HTTP/1.1 201 Created
Location: https://dustycloud.org/likes/345
      

ActivityStreams オブジェクトに btobcc 属性がある 場合、サーバは配送の前にこれらを削除しなければならない(MUST)が、 もともと bto / bcc 属性に保管されていた宛先を delivery での宛先を決定するのに使用しなければならない(MUST)。

それからサーバは新しい Activity を outbox コレクションに 追加しなければならない(MUST)。 Activity の型に依存して、サーバはさらなる副作用を実行することが要求される。 (しかし、Activity が outbox に現れる時刻には保証されない。 Activity は遅延して現れたり、任意の時点で消滅したりするかもしれない。) これらは後述する個々の Activity に記述されている。

クライアントからサーバで実装されていないサーバにオブジェクトを投稿しようとした 場合、405 Method Not Allowed レスポンスを返すべきである(SHOULD)。

HTTP キャッシュ機構 [[!RFC7234]] は、 クライアントがサーバから応答を受信する場合とサーバがクライアントに 応答を送信する場合の両方において、適切な場合には遵守するべきである(SHOULD)。

クライアントアドレス指定

クライアント は、 新しい Activity を適切にアドレス指定することに責任を持つ。 To some extent, this is dependent upon the particular client implementation, but clients must be aware that the server will only forward new Activities to addressees in the to, bto, cc, bcc, and audience fields.

Followers CollectionPublic Collection は、 新しい Activity のデフォルトの宛先として良い選択肢である。

Clients SHOULD look at any objects attached to the new Activity via the object, target, inReplyTo and/or tag fields, retrieve their actor or attributedTo properties, また、そのアドレス指定属性を取得して、 作成された新しい Activity の to または cc フィールドに追加してもよい(MAY)。 クライアントは添付されたオブジェクトを再帰しても良い(MAY)が、 そうする場合はこの再帰に制限を設定するべきである(SHOULD) (これは、クライアントがアドレス指定されたactorのコレクションを個々の宛先として 「展開」することを提案しているのではないことに注意すること)。

クライアントは UI でユーザーに宛先を変更する機会を与えても良い(MAY)。

例えば、Chris が Amy による次の記事に「いいね」をするとき:

  {
    "@context": ["https://www.w3.org/ns/activitystreams",
                 {"@language": "en-GB"}],
    "id": "https://rhiaro.co.uk/2016/05/minimal-activitypub",
    "type": "Article",
    "name": "Minimal ActivityPub update client",
    "content": "Today I finished morph, a client for posting ActivityStreams2...",
    "attributedTo": "https://rhiaro.co.uk/#amy",
    "to": "https://rhiaro.co.uk/followers/",
    "cc": "https://e14n.com/evan"
  }
        

クライアントによって生成される「いいね」は:

  {
    "@context": ["https://www.w3.org/ns/activitystreams",
                 {"@language": "en"}],
    "type": "Like",
    "actor": "https://dustycloud.org/chris/",
    "summary": "Chris liked 'Minimal ActivityPub update client'",
    "object": "https://rhiaro.co.uk/2016/05/minimal-activitypub",
    "to": ["https://rhiaro.co.uk/#amy",
           "https://dustycloud.org/followers",
           "https://rhiaro.co.uk/followers/"],
    "cc": "https://e14n.com/evan"
  }
        

The receiving outbox can then perform delivery to not only the followers of Chris (the liker), but also to Amy, and Amy's followers and Evan, both of whom received the original article.

以下のアクティビティを outbox に投稿するクライアントは、 アクティビティに object 属性も提供しなければならない(MUST): Create, Update, Delete, Follow, Add, Remove, Like, Block, Undo. さらに、以下のアクティビティを outbox へ投稿するクライアントは、 target 属性も提供しなければならない(MUST): Add, Remove.

Create Activity

Create アクティビティは新しいオブジェクトを投稿するときに使われる。 これは、Activity の中に(object 属性として)埋め込まれている オブジェクトが作成されるという副作用がある。

Create アクティビティが投稿されたとき、アクティビティの actorobjectattributedTo フィールドにコピーされるべきである(SHOULD)。

Create アクティビティのアドレス指定とその object の 不一致はおそらく混乱を引き起こす。 従って、サーバは SHOULD copy any recipients of the Create activity to its object upon initial distribution, and 同様に object から外側の Create アクティビティに コピーするべきである(SHOULD)。 Create のアドレス指定を変更することなく (例えば Update アクティビティで) object のアドレス指定を変更することは 受け入れられることに注意すること。

Object creation without a Create Activity

クライアントからサーバへの投稿で、 周りのアクティビティなしでオブジェクトを作成することも可能である。 The server MUST accept a valid [[!ActivityStreams]] object that isn't a subtype of Activity in the POST request to the outbox. サーバはこのオブジェクトを Create Activityobject として添付しなければならない(MUST)。 非一時的オブジェクトに関しては、 サーバはラッピングした Create とラップされた Object に対して、id を 添付しなければならない(MUST)。

サーバから返された Location の値は、 新しい(オブジェクトではなく) Create アクティビティの URL であるべきである。

オブジェクトで指定されている to, bto, cc, bcc, audience 属性は、 サーバによって新しい Create アクティビティにコピーされなければならない(MUST)。

        {
          "@context": "https://www.w3.org/ns/activitystreams",
          "type": "Note",
          "content": "This is a note",
          "published": "2015-02-10T15:04:55Z",
          "to": ["https://example.org/~john/"],
          "cc": ["https://example.com/~erik/followers",
                 "https://www.w3.org/ns/activitystreams#Public"]
        }
        
前述の例は以下のように変換される:
        {
          "@context": "https://www.w3.org/ns/activitystreams",
          "type": "Create",
          "id": "https://example.net/~mallory/87374",
          "actor": "https://example.net/~mallory",
          "object": {
            "id": "https://example.com/~mallory/note/72",
            "type": "Note",
            "attributedTo": "https://example.net/~mallory",
            "content": "This is a note",
            "published": "2015-02-10T15:04:55Z",
            "to": ["https://example.org/~john/"],
            "cc": ["https://example.com/~erik/followers",
                   "https://www.w3.org/ns/activitystreams#Public"]
          },
          "published": "2015-02-10T15:04:55Z",
          "to": ["https://example.org/~john/"],
          "cc": ["https://example.com/~erik/followers",
                 "https://www.w3.org/ns/activitystreams#Public"]
        }
        

Update Activity

Update アクティビティは、既に存在するオブジェクトを更新するときに 使われる。 これの副作用として、actor がこのオブジェクトを更新する権限を持っている場合、 object は Update アクティビティで定義されている新しい構造を 反映した形で修正されなければならない(MUST)。

Partial Updates

クライアントからサーバへの通信では、更新は部分的である; 文書全体を一度に更新するのではなく、指定された任意のキー/値の組が 既存の値を新しい値に置き換えるために使われる。 これは更新されるオブジェクトの最上位のフィールドにのみ適用される。 特別な例外は、値が json の null 型の場合である; これは、このフィールドはサーバのオブジェクト表現から 削除されるべきと言うことを意味する。

この振る舞いは、クライアントがサーバに投稿したときのクライアントからサーバへの 通信のみであることに注意すること。 サーバからサーバへの相互作用と、サーバからクライアントへの更新は、 部分的更新が適用された後の、オブジェクトの完全に新しい表現を含むべきであることに注意すること。 より詳しくは サーバ間相互作用での Update アクティビティ の説明を参照のこと。

Delete Activity

Delete アクティビティは、既に存在するオブジェクトを 削除するために使われる。 この副作用として、サーバは objectTombstone of the object that will be displayed in activities which reference the deleted object に置き換えても良い(MAY)。 削除されたオブジェクトが要求された場合、サーバは、 レスポンスボディとして Tombstone オブジェクトが表現されている場合は HTTP 410 Gone ステータスを、 さもなければ HTTP 404 Not Found ステータスを返すべきである (SHOULD)。

削除されたオブジェクト:

          {
            "@context": "https://www.w3.org/ns/activitystreams",
            "id": "https://example.com/~alice/note/72",
            "type": "Tombstone",
            "published": "2015-02-10T15:04:55Z",
            "updated": "2015-02-10T15:04:55Z",
            "deleted": "2015-02-10T15:04:55Z"
          }
        

Follow Activity

Follow アクティビティは、他の actor のアクティビティを 購読するために使われる。

これを outbox に受信した場合の副作用として、 サーバは、 SHOULD add the object to the actor's following Collection when and only if an この Follow アクティビティを object とした Accept アクティビティを引き続いて受信した場合にのみ、

Add Activity

Add アクティビティを outbox に受け取ったとき、 以下の場合を除いて、サーバは objecttarget プロパティで指定されたコレクションに追加するべきである(SHOULD):

Remove Activity

outboxRemove アクティビティを受信すると、 サーバは次の場合を除いて、 target 属性で指定されたコレクションから object を削除するべきである(SHOULD)。

Like Activity

Like アクティビティは actorobject を好んでいることを示す。

これを outbox に受信したときの副作用として、 サーバは actorliked コレクション に この object を追加するべきである(SHOULD)。

Block Activity

Block アクティビティは、投稿したactorは (object属性で定義された)actorが Block アクティビティを投稿したactorによって投稿されたオブジェクトと 相互作用出来ることを望まないことを示すために使われる。 サーバはブロックしたユーザーと actor によって投稿された任意のオブジェクトとの 相互作用を防止するべきである (SHOULD)。

サーバは Block アクティビティをその object に 配送するべきではない(SHOULD NOT)。

Undo Activity

Undo アクティビティは以前のアクティビティを取り消すときに使われる。 Activity Vocabulary 文書の Inverse Activities and "Undo" を参照のこと。 例えば、Undo は以前の Like, Follow, Block のいずれかの 取り消しのために使われる。 Undo アクティビティと取り消されるアクティビティはどちらも同じ actor を 持っていなければならない(MUST)。 副作用として、できるだけ広範囲に取り消しを行うべきである。 例えば、もし Like を取り消すと、その前にインクリメントされた カウンタは適切にデクリメントされるべきである。

既存の明示的な「逆アクティビティ」を代わりに使うべき例外がある。 Create ベースのアクティビティは Delete を、 Add アクティビティは Remove を使うべきである。

Delivery

連合サーバは outbox に投稿された全ての Activity を outbox delivery に従って配送を実行しなければならない(MUST)。

Uploading Media

サーバは、画像、ビデオ、その他のバイナリデータのような、 アクティビティで参照される文書型のアップロードに対応しても良い(MAY)が、 正確な機構はこのバージョンの ActivityPub のスコープ外である。 The Social Web Community Group is refining the protocol in the ActivityPub Media Upload report.

サーバからサーバへの通信

サーバは、activity を actor の inbox エンドポイントに ポストすることで、他のサーバと通信し、情報をソーシャルグラフ上に伝搬させる。 ネットワーク上を送られる Activity は、一時的であることを意図している場合を 除き、id を持つべきである(SHOULD) (一時的な場合は id を省略しても良い(MAY))。

(inbox などへの) POST リクエストは Content-Type に application/ld+json; profile="https://www.w3.org/ns/activitystreams" を設定しなければならず(MUST)、GET リクエスト (も参照のこと) は Accept ヘッダに application/ld+json; profile="https://www.w3.org/ns/activitystreams" を 設定しなければならない(MUST)。 サーバは、サーバからサーバへの通信において、Content-Type や Accept ヘッダの application/activity+jsonapplication/ld+json; profile="https://www.w3.org/ns/activitystreams" と 等価なものとして扱うべきである(SHOULD)。

ソーシャルグラフ上に更新を伝搬させるために、Activity は適切な宛先に 送信される。 まず、これらの宛先は、actor に到達するまでオブジェクト間の適切なリンクを 辿ることで決定され、 それからこの Activity は actor の inbox に挿入される (delivery)。 これにより、宛先サーバは:

配送は通常、例えば以下のもので引き起こされる:

他のサーバ上の actor の inboxpublicInbox 属性への配送を実行するサーバは、 次のアクティビティ内に object 属性を提供しなければならない(MUST): Create, Update, Delete, Follow, Add, Remove, Like, Block, Undo さらに、以下のアクティビティのサーバ間配送を実行するサーバは、 target 属性も提供しなければならない(MUST): Add, Remove

他のサーバからの返答を受信するときと他のサーバへ返答を送信するときの 両方において、適切な場合には HTTP キャッシュ機構 [[!RFC7234]] に 遵守するべきである(SHOULD)。

配送

以下は他の連合サーバと通信する連合サーバのみに要求される。

アクティビティは、まずターゲット(これはactor)の inboxを探して、それからそのinboxにアクティビティを投稿することで配送される。 配送するターゲットは、 ActivityStreams audience targeting をチェックすることで決定される; つまり、アクティビティの to, bto, cc, bcc, and audience フィールドである。

inbox はまず ターゲットactorのJSON-LD表現を取得し、 それから inbox 属性を探すことで決定される。 宛先が Collection または OrderedCollection の場合、 サーバはコレクションを(ユーザーの認証情報と共に)展開し、コレクションの それぞれの要素の inbox を発見しなければならない(MUST)。 サーバはコレクションの展開を実行する層の数を制限しなければならない(MUST)。 これは 1 でもよい(MAY)。

サーバは最終的な宛先リストの重複を解消しなければならい(MUST)。 サーバはまた、通知される Activity の actor と同じ actor を リストから除去しなければならない(MUST)。 つまり、ユーザーは自分の activity を自分に配送することはできない。

宛先がない場合にどうするかは未定義であるが、もし宛先が指定されなかった場合、 オブジェクトを完全にプライベートな状態において、アクセスコントロールは そのオブジェクトへのアクセスを制限することが推奨される。 もしオブジェクトが単に "public" コレクションに送信された場合、 オブジェクトは誰にも配送されないが、actor の outbox で公に閲覧可能になる。

(投稿ユーザーの認証付きの) HTTP POST リクエストは、 アクティビティをリクエストのボディとして inboxに行われる。 このアクティビティは受信者によって inbox OrderedCollection の item として追加される。 非連合サーバの inbox へ配送しようとする試みは 405 Method Not Allowed レスポンスを返すべきである(SHOULD)。

連合サーバがサードパーティーサーバへ配送を実行する場合には、 配送は非同期に実行されるべきであり(SHOULD)、 これがネットワークエラーによって失敗した場合は受信者への配送を 再試行するべきである(SHOULD)。

Note: 同じ origin の actor 間で 配送される Activity は任意の内部機構を使ってもよく、HTTP を使うことは要求されない。

While it is not required reading to understand this specification, it is worth noting that ActivityPub's targeting and delivery mechanism overlaps with the Linked Data Notifications specification, and the two specifications may interoperably combined. In particular, the inbox property is the same between ActivityPub and Linked Data Notifications, and the targeting and delivery systems described in this document are supported by Linked Data Notifications. In addition to JSON-LD compacted ActivityStreams documents, Linked Data Notifications also supports a number of RDF serializations which are not required for ActivityPub implementations. However, ActivityPub implementations which wish to be more broadly compatible with Linked Data Notifications implementations may wish to support other RDF representations.

サーバ-サーバ間のoutbox配送の要件

オブジェクトを outbox に受信したとき( クライアントからサーバへの通信サーバからサーバへの通信 の両方に対応しているサーバの場合)、サーバは 以下にターゲットして配送しなければならい(MUST):

  • to, bto, cc, bcc, audience のいずれかのフィールド; その値が 個人かactorに所有されているコレクションの場合。

これらのフィールドは、このアクティビティをoutboxに投稿した クライアントによって適切に展開されている

inboxからの転送

以下の節は、連合ネットワークで時々問題を引き起こす、 「ゴーストリプライ」問題を緩和するためのものである。 この問題を例で示す。

Alyssa は、会議での論文の発表が上手くいったことを投稿し、 友人である Ben を含む彼女のフォロワーコレクションに送りました。 Ben は祝福する内容を Alyssa のメッセージに返信し、 宛先に彼女のフォロワーコレクションを含めました。 しかし、Ben は Alyssa のフォロワーコレクションの内容にアクセス出来ないので、 Ben のサーバは彼のメッセージを彼らの inbox に転送できません。 次の機構がない場合、その後 Alyssa が Ben に返信すると、 彼女のフォロワーは、Ben の返信を見ることなく Alyssa が Ben に返信するのを 見ることになります。 これはとても混乱します!

Activity を inbox に受信したとき、 サーバはこれらを送信元が配信できない宛先に転送する必要がある。 これを行うために、サーバは次の全てが真の場合にのみ、 to, cc, audience の値にターゲットして 配送 しなければならない(MUST):

  • サーバがこの Activity を見るのは初めてである。
  • to, cc, audience の値に サーバが所有しているコレクションが含まれている。
  • inReplyTo, object, target, tag の値が サーバが所有しているオブジェクトである。 サーバは、自身が所有しているリンクされたオブジェクトを探すためにこれらの値を 再帰するべきであり(SHOULD)、 再帰の上限を設定するべきである(SHOULD) (ie. the point at which the thread is so deep the recipients followers may not mind if they are no longer getting updates that don't directly involve the recipient). サーバは転送された元のオブジェクトの to, cc, audience の値のみを ターゲットし、(これらのアドレスが意図的に変更されたりクライアントによって) リンクされたオブジェクトを再帰している間の新しい受信者を拾わないように しなかければならない(MUST)。

サーバは配送ターゲットを実装依存の規則(例えば spam フィルタ)で フィルタリングしてもよい(MAY)。

共有 Inbox への配送

多くの actor をホスティングしているサーバでは、 全てのフォロワーへの配送は大量のメッセージを送信することになることがある。 一部のサーバはまた、パブリックに投稿された全てのメッセージのリストを "known network" として表示したい。 従って ActivityPub はこれら二つのユースケースを扱うためのオプションの機構を 提供する。

配送元actorのfollowersにオブジェクトが配送されるとき、 サーバは、同じ sharedInbox を持つ全ての フォロワーを識別して、 代わりにオブジェクトを sharedInbox という名前に配送することで 配送する受信アクターの数を減らしても良い(MAY)。. 従ってこのシナリオでは、 リモート/受信サーバは特定の inbox へのターゲットと配送の実行の 決定に関与する。

さらに、オブジェクトが Public 特殊コレクションに アドレス指定されている場合、 サーバはこのオブジェクトをネットワーク上の全ての既知の sharedInbox エンドポイントに配送しても良い(MAY)。

パブリックにアドレス指定されたアクティビティを sharedInbox エンドポイントに送信する送信元サーバは、 その他に (to, bto, cc, bcc, および audience を通して) アドレス指定された、 sharedInbox を持たないので sharedInbox 機構を通じてアクティビティを 受信できない actor やコレクションには配送しなければならない(MUST)。

Create Activity

inboxCreate アクティビティを受信したときには、 意外にもほとんど副作用はない; このアクティビティは actor の inbox に現れるべきで、 サーバはおそらくこのアクティビティとそれに添付されているオブジェクトの表現を ローカルに保管したいはずである。 しかし、これはとにかく inbox にアクティビティが配送されたときに ほとんど一般的に処理されることである。

Update Activity

サーバからサーバへの通信では、 Update アクティビティは、 同じ idobject のコピーを、 Update アクティビティの中に供給されているコピーで 更新するべきである(SHOULD)。 Update アクティビティのクライアントからサーバへの扱い と異なり、 これは部分更新ではなくオブジェクトの完全な置き換えである。

受信サーバは Update がその object を修正する権限があることを 確認することに注意しなければならない(MUST)。 最小限として、これは Update とその object が同じ送信元であることを確認することで行われる。

Delete Activity

object が送信した actor / server が所有していると仮定して) これを受信したときの副作用として、 delete アクティビティを受信したサーバは 同じ id を持つ object の表現を削除するべき(SHOULD)で、 表現を Tombstone オブジェクトに置き換えても良い(MAY)。

(あるアクティビティが発信元サーバからリモートサーバに転送された後、 オブジェクトの表現をリモートをリモートで削除することを 強制する 方法は、ActivityPub プロトコルにはないということに注意すること。)

Follow Activity

これを inbox に受信したときの副作用として、 サーバは、この Follow を object に設定した Accept または Reject アクティビティを生成し、 Follow した actor に配送するべきである(SHOULD)。 AcceptReject は自動的に生成しても良い(MAY)し、 (おそらくはユーザーの確認のための多少の遅延の後)ユーザー入力の 結果としてもよい(MAY)。 サーバは Follow への応答として明示的に Reject を 送らないという選択をしてもよい(MAY)が、実装者はリクエストを送信したサーバが 中間的な状態のままになるかもしれないことに注意するべきである。 例えば、サーバはユーザーのプライバシーを守るために Reject を 送信しないかもしれない。

この Follow を object として参照している Accept を 受信する場合、サーバは object の actor の Followers Collectionactor を追加するべきである(SHOULD)。 Reject の場合、object の actor の Followers Collection に actor を 追加してはならない(MUST NOT)。

時々、Follow 購読が成功したものの、将来のある時点で 長期間フォロワーへの配送が失敗するようになることがある。 実装は、ネットワーク上の actor が到達可能であり続ける保証がないことに注意し、 それに応じて実装するべきである。 例として、ある actor への配送の試みが例えば 6 ヶ月間フォロワーに 到達不能であり続けた場合、配送サーバがその購読者を followers から 削除するのは合理的である。 到達不能な actor を扱うための期間と振る舞いは配送サーバの 裁量に委ねられている。

Accept Activity

これを inbox に受信した場合の副作用は、受信した object の型によって決定され、(例えば Offer のような) この文書に記述していない型を受け入れることも可能である。

inbox に受信した Acceptobject が、以前受信者によって送られた Follow アクティビティの場合、 サーバは 受信者の Following Collectionactor を追加するべきである(SHOULD)。

Reject Activity

これを inbox に受信することによる副作用は、 受信した object の方によって決定され、 この文書に記述されていない型 (例えば Offer)を 拒否することもできる。

inbox に受信した Rejectobject が、以前受信者によって送られた Follow アクティビティの場合、 これは受け取り側が Follow リクエストを承認しなかったことを 意味する。 サーバは受信者の Following Collectionactor を追加してはならない(MUST)。

Add Activity

Add アクティビティを inbox に受け取ったとき、 次のような場合を除いて、サーバは target 属性で指定された コレクションに object を追加するべきである (SHOULD):

Remove Activity

Remove アクティビティを inbox に受け取ったとき、 次のような場合を除いて、サーバは target 属性で指定された コレクションから object を除去するべきである (SHOULD):

Like Activity

これを inbox に受信したときの副作用として、 サーバは、likes コレクションがある場合は、 このコレクションに受信したアクティビティを追加することで このオブジェクトのいいねのカウントを増やすべきである (SHOULD)。

Announce Activity (sharing)

Announce アクティビティを inbox に 受け取ったとき、サーバは、shares コレクションがある場合は、このコレクションに受信したアクティビティを 追加することで、 このオブジェクトの共有のカウントを増やすべきである (SHOULD)。

Announce アクティビティは事実上他のソーシャルネットワークでの "sharing", "reposting", "boosting" として知られているものである。

Undo Activity

Undo アクティビティは、以前のアクティビティの副作用を 取り消すために使われる。 ActivityStreams 文書の Inverse Activities and "Undo" を参照のこと。 Undo アクティビティのスコープと制限は クライアントサーバ間での Undo アクティビティ と同様であるが、 連合コンテキストに適用される。

国際化

連合ネットワークにおいてユーザーの国際化の基礎を構築することは重要である。 ActivityStreams はコンテンツの国際化のためのツールを提供 しており、 可能であればこれが使われるべきである。 しかし、ユーザーが投稿したコンテンツに対してどの @language 属性 を 提供するかを決定するのは実装上難しいかもしれない。 W3C Internationalization group はいくつかの 言語検出のガイド を提供している。

Security Considerations

Authentication and Authorization

ActivityPub は認証を二つの目的で用いる; 一つ目はクライアントからサーバへの認証、 二つ目は連合実装においてサーバ間の認証である。

残念ながら標準化の時点で、認証機構として強力に合意されたものはない。 認証で取り得る方向性は in the Social Web Community Group Authentication and Authorization best practices report にある。

Verification

何らかの形の検証なしに、サーバはクライアントが投稿したコンテンツを 信頼するべきではないし、 連合サーバはコンテンツの発信源以外のサーバから受け取ったコンテンツを 信頼するべきではない。

新しいコンテンツが、それを投稿したと主張している actor から本当に 投稿されていることと、その actor がそのリソースを更新する権限を 持っていることを、 サーバは慎重に検証するべきである。 も参照のこと。

Accessing localhost URIs

開発中、localhost で実行したプロセスに対してテストするのはしばしば有用である。 しかし、製品版クライアントやサーバインスタンスで localhost への リクエストを許すことは危険なことがある。 認証を必要としない localhost の URI へのリクエストは、localhost でのみ 利用可能として保護されていることを想定されているリソースへのアクセスや修正が 意図せず起きることがある。

自作の ActivityPub サーバやクライアントが開発目的のために localhost URI への リクエストを許す場合、デフォルトでオフの設定オプションにすることを 考慮すること。

URI Schemes

httphttps に加えて、様々な種類の URI がある。 ライブラリによっては様々な URI スキームでのフェッチリクエストを扱い、 賢くあろうとして、file のような 想定していないスキームを参照するかもしれない。 クライアントとサーバの作者はライブラリがリクエストをどのように扱うかを 注意深くチェックし、httphttps のような、 特定の安全な URI 型のみのホワイトリストを作るべきである。

Recursive Objects

サーバはオブジェクト、あるいは特に再帰参照を持つ ActivityStream オブジェクトの 解決中にどれだけ深く再帰するかの制限を設定するべきである。 これを適切に行うことに失敗すると、サービス拒否セキュリティ脆弱性を 起こすことがある。

スパム

スパムはあらゆるネットワークで問題だが、特に連合ネットワークではそうである。 ActivityPub ではスパムと闘うための特定の機構は提供しないが、 サーバは、ある種のスパムフィルタを通してローカルの信頼できないユーザーと全ての リモートユーザーの両方から入力される内容をフィルタリングすることが勧められる。

Federation denial-of-service

サーバは、その他の連合サーバからのサービス不能攻撃に対する防御を 実装するべきである。 これは、例えば、ある種のレート制限機構のようなものを使うことで実現できる。 Servers should be especially careful to implement this protection around activities that involve side effects. Servers SHOULD also take care not to overload servers with submissions, for example by using an exponential backoff strategy.

クライアントからサーバへの通信量制限

Servers should ratelimit API client submissions. This serves two purposes:

  1. It prevents malicious clients from conducting denial-of-service attacks on the server.
  2. It ensures that the server will not distribute so many activities that it triggers another server's denial-of-service protections.

Client-to-server response denial-of-service

大きすぎるコレクションによってクライアントが過負荷になることを防ぐために、 サーバはクライアントに返すコレクションページの大きさを制限することに 注意するべきである。 Clients should still be prepared to limit the size of responses they are willing to handle in case they connect to malicious or compromised servers, for example by timing out and generating an error.

Sanitizing Content

ブラウザ(またはその他のリッチテキストが有効なアプリケーション)で レンダリングされる全てのアクティビティフィールドは、 クロスサイトスクリプト攻撃を防ぐために、マークアップを含む フィールドのサニタイズに注意するべきである。

Not displaying bto and bcc properties

btobcc はすでに、 配送時に削除されなければならないが、 しかしサーバは自身のストレージシステムの中でオブジェクトをどのように表現するか 自由に決定できる。 However, since bto and bcc are only intended to be known/seen by the original author of the object/activity, servers should omit these properties during display as well.

Acknowledgements

This specification comes from years of hard work and experience by a number of communities exploring the space of federation on the web. In particular, much of this specification is informed by OStatus and the Pump API, as pioneered by StatusNet (now GNU Social) and Pump.io. Both of those initiatives were the product of many developers' hard work, but more than anyone, Evan Prodromou has been a constant leader in this space, and it is unlikely that ActivityPub would exist in something resembling its current state without his hard work.

Erin Shepherd built the initial version of this specification, borrowed from the ideas in the Pump API document, mostly as a complete rewrite of text, but sharing most of the primary ideas while switching from ActivityStreams 1 to ActivityStreams 2.

Jessica Tallon and Christopher Lemmer Webber took over as editors when the standard moved to the W3C Social Working Group and did the majority of transition from Erin Shepherd's document to its current state as ActivityPub. Much of the document was rewritten and reorganized under the long feedback process of the Social Working Group.

ActivityPub has been shaped by the careful input of many members in the W3C Social Working Group. ActivityPub especially owes a great debt to Amy Guy, who has done more than anyone to map the ideas across the different Social Working Group documents through her work on [[Social-Web-Protocols]]. Amy also laid out the foundations for a significant refactoring of the ActivityPub spec while sprinting for four days with Christopher Allan Webber. These revisions lead to cleaner separation between the client to server and server components, along with clarity about ActivityPub's relationship to [[!LDN]], among many other improvements. Special thanks also goes to Benjamin Goering for putting together the implementation report template. We also thank mray for producing the spectacular tutorial illustrations (which are licensed under the same license as the rest of this document).

Many people also helped ActivityPub along through careful review. In particular, thanks to: Aaron Parecki, AJ Jordan, Benjamin Goering, Caleb Langeslag, Elsa Balderrama, elf Pavlik, Eugen Rochko, Erik Wilde, Jason Robinson, Manu Sporny, Michael Vogel, Mike Macgirvin, nightpool, Puck Meerburg, Sandro Hawke, Sarven Capadisli, Tantek Çelik, and Yuri Volkov.

This document is dedicated to all citizens of planet Earth. You deserve freedom of communication; we hope we have contributed in some part, however small, towards that goal and right.