atprotoにおける「分散」もしくは「フェデレーション」は一意ではない。現状で考えられるアーキテクチャについて妄想してみる。
atprotoのfederationにおける登場人物は主に3つ。ユーザー(クライアント)から近い順にPDS・BGS・App Views(appview)の3つ。
詳細は公式ブログ参照。
なお、PDS間の通信も過去には想定されており、BGSやappviewを使う「big-world」と各PDSが直接通信する「small-world」という2種類のfederationが想定されていたが、後者は公式から言及されなくなってしまったのでここでは考慮しない。
ユーザーデータを管理するサーバー。ユーザーはatprotoに参加するにあたってPDSを一つ選んで所属する(移住可能)。 ユーザー本人すら知らないユーザーデータ署名用秘密鍵を唯一知る存在。
また、ユーザーが直接アクセスするサーバーは自身の所属するPDSのみで、他のサーバー(appview)へのアクセスは所属PDSが行う。
複数のPDSをクローリングして、更新情報を一つのストリームに集約する。挙動としてはオンラインRSSリーダーみたいなイメージが近い。
ここで流れるデータは入出力ともに、概ねクライアントから投稿した内容に署名が入った程度のものと思ってよい。
基本的にPDSから取得したデータをappviewに流すだけの仲介役だが、FireskyのようにBGSの出力を直接覗くこともできる。
atprotoにおいてユーザーデータの大半はrecordという形式で扱われる。ActivityPubでいうactivityのようなものと思っていい。
federationの話をするにあたって注意すべき性質のみ説明する。
atprotoでは、recordの中身については特に定義せず、ユーザーが定義できる仕組みを用意している。これもActivityPub風に言うなら、Activity Vocabularyが無いようなもの。
recordの型はlexiconという形式で定義され、どんなフィールドを持つかなどの情報はそこから取得できる。一方、その情報の解釈はクライアントとappviewに委ねられている。PDSは例えばユーザーがフォローしている相手を知っているが、「フォロー」にどんな意味があるかは知らない。[1]
PDS・BGS・appviewがそれぞれ一つだけある状態。現状のBluesky Socialはこれ。
諸々の処理を行うためにappviewもユーザーデータを記憶しているだろうことを考慮すると、PDSとBGSはほとんど中継地点でしかない。[4]
PDSが落ちれば当然何もできないが、appviewが落ちた場合もほぼ何もできない。PDSさえ生きていれば書き込み(新規投稿やフォロー)は可能だが、appviewが落ちている間は他ユーザーからは見えない。同じPDSに所属していようと、普通のBlueskyクライアントはappviewを経由してみているためあまり関係無い。[5]
BGSが落ちると復活するまで書き込みは反映されなくなるが、その時点までの情報はappviewに記録されていると思われるため、見る分には特に問題ない。
複数のPDSがあり、全てが一つのBGS, appviewに繋がっている状態。現状のsandboxはおそらくこれ。[6]
公式ブログやQiitaの解説記事ではここに重きをおいている。
メリットとして考えられるのは、ユーザー自身がPDSを立てることで署名鍵を管理できるあたりか?データを自分の手元においておけるというのもメリットではあるが、極端な話クライアントから定期バックアップしても大差ない。
PDSが落ちた場合、手元にバックアップデータを持っていれば他PDSに引越すことでほぼ何も変わらずにサービスの利用継続が可能。ただし、引越しはそれなりに重い処理なので、一時的な障害が発生する度に引っ越すことは推奨しない。そもそも現時点では引越しは未実装だが。
また、PDS管理者はモデレーション権限を持つ。特定のコンテンツを削除したり、ユーザーを蹴り出したりできるため、別PDSに退避できることが意味を持つかもしれない。ただし、PDSとは別にappviewでもモデレーションできることに注意。PDSが持つデータを消させることはできなくても、例えばシャドウバンのような処置はできる。
appviewやBGSが落ちた場合は分散していない場合と同様。
PDSの分散に加え、現状のbsky appviewのクローンがもう一つできたような状態。
同じ実装のappviewが2つあっても、機能的にはほとんど変わらない。どちらも同じBGSをソースにしているため、ユーザーやPDSは一方のappviewにだけ投稿を渡すといったことはできない点に注意。ただし、ミュート情報などの非公開情報はPDSが指定したappviewにしか届かないため、appviewを変えたら挙動は若干変わるはず。
最も大きな違いはやはりモデレーションで、ある投稿について一方のappviewでは見えないが他方では警告すら出ない、といったパターンもありうる。[7]
メインのappviewが落ちたら予備appviewに切り替えて使うというような使い方もできるかもしれない。あるAPIを呼んだ時にどのappviewに繋がるかは(現状では)PDSが決定するため、この辺りの使い方次第ではPDSの選択に別の意味が生まれる。
少し特殊なパターンとして、appviewを(lexiconが変わらない範囲で)改造して、類似サービスを作ることも考えられる。フォロワー数など特定の情報をマスクするとか。嫌な例としてはブロックを無視して全ての投稿を見せるとか。
これは他とちょっと毛色が違っており、Bluesky Socialとは機能もデータも異なるサービスを実装する話。新しいlexiconを定義してそのためのappview&クライアントを実装する。PSDやBGSは既存のものに便乗できる(ように将来的にはなるはず)。
とはいえ必ずしもBluesky Socialと完全に非互換になるとは限らない。例えば絵文字リアクション機能を追加するだけなら、同じタイムラインを見ることができる。もちろん完全に異なるサービスを実装することもできる。
感覚的にはActivityPubにおけるサービス(MastodonとかMisskeyとか)の違いに一番近い。lexiconの違いはクライアントの互換性にも影響してくるという意味でも近いか。
BGSを複数立て、PDSやappviewはどれを使うかそれぞれ選ぶ。実現可能性も実現後の機能も一番予想がつかないところ。
1つのPDSが複数BGSにデータを渡すことも1つのappviewが複数BGSからデータを取得することもありだと思うが、同じデータが異なるBGSから同じappviewに届く場合、一気に面倒になりそう。[8]
BGSの分け方としては、例えば以下のようなものが考えられる。
atprotoの上に複数のサービスができていくと、各サービスはユーザーデータのうち一部しか使わないようになる。そこで、データの種類ごとにBGSを分けることで、appviewとBGS両方の通信負荷を下げる。実質的にappviewとBGSがセットになることが想定され、分散のモチベーションとしても割とありえる案だと思う。
背景情報として、Bluesky Socialの実装は元々PDSの中にappviewも内包していて、これを分離しようとしている途中であるというのは置いておいた方がいいかもしれない。
現在もPDSの中にappviewの機能は残っていて、デフォルトの挙動だと外部のappviewにはアクセスしない。クライアントからXRPC叩く時のヘッダに"x-appview-proxy: true"を加えることでappviewを使うように分岐することができる。公式ウェブクライアント(bsky.app)の場合、Settingsで「Experiment: Use AppView Proxy」をトグルすることでこのヘッダを追加できるが、画面サイズによって出たり出なかったりする?