CIP-11: Realtime API
0. Abstract
本仕様は、Concrnt サーバーのエンドポイントを拡張し、サーバーで発生したリソースの変更イベントを リアルタイムにクライアントへ通知する手段を提供する。
1. Status of This Memo
このドキュメントは Realtime API の仕様を定義する。 Concrnt プロジェクトにより公開されるバージョン付き仕様であり、実装者およびプロトコル設計者を対象とする。
本 CIP はオプショナルな拡張であり、CIP-0, CIP-1 を前提とする。イベントの redaction には CIP-12 を必要とする。
本仕様はドラフトであり、後方互換性のない変更が行われる可能性がある。
2. 表記規則
このドキュメントにおける以下の語は、必ず大文字で記述される場合、 BCP 14 [RFC2119] [RFC8174] にしたがって解釈される。
MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, NOT RECOMMENDED, MAY, OPTIONAL
3. Realtime エンドポイント
本 CIP を実装するサーバーは、WebSocket [RFC6455] へアップグレード可能な HTTP GET エンドポイントを
提供し、CIP-0 のサービスディスカバリにおいて net.concrnt.core.realtime エンドポイント名で
広告しなければならない (MUST)。
{ "version": "2.0", "csid": "ccs1<bech32-encoded-address>", "endpoints": { "net.concrnt.core.resolve": "/resource/{uri}", "net.concrnt.core.realtime": "/realtime" }}3.1 購読の開始
クライアントは、Realtime エンドポイントに対して WebSocket ハンドシェイクを行い、 接続確立後に以下の JSON メッセージを送信して、リソースの変更イベントの購読を開始する。
{ "type": "subscribe", "prefixes": [ "<CCURI>", "<CCURI>" ]}-
typeメッセージ種別。購読の開始は"subscribe"を指定する。 サーバーは"listen"を"subscribe"の別名として受理してもよい (MAY。旧仕様との互換のため)。 このほか、"h"はハートビートを表すメッセージ種別であり、サーバーは何も行わず受理する。 -
prefixes購読するリソースの CCURI の配列。
購読のマッチングは、イベントの source (§3.2) の CCURI 文字列に対する単純な前方一致とする (MUST)。
指定した CCURI そのものに加え、それを接頭辞とするリソースで発生したイベントも通知される
(CIP-5 §3.1 の prefix と同じ規則であり、item の購読には兄弟キー item2 もマッチする点に注意)。
prefix 中の * ? [ 等の文字をワイルドカードとして解釈してはならない (MUST NOT)。
各 prefix は owner 部を持つ有効な CCURI でなければならない (MUST)。owner 部を持たない prefix
(空文字列や cckv:// 等) は、サーバー全体のイベントの購読を許すため、無視しなければならない (MUST)。
サーバーは、1 接続あたりの prefix 数に上限を設けるべきである (SHOULD)。
複数回 subscribe メッセージが送信された場合、サーバーは最新の購読リストのみを保持する (購読リストの全置換)。明示的な unsubscribe メッセージは存在せず、購読の解除は縮小した購読リストに よる subscribe の再送によって行う。
サーバーは、未知の type を持つメッセージを受信した場合、接続を切断せず無視するべきである (SHOULD)。
サーバーは接続の生存確認に WebSocket の Ping フレーム (RFC6455) を用いるべきであり (SHOULD)、
アプリケーションレベルの "h" メッセージの受信を接続維持の条件としてはならない (MUST NOT)。
3.1.1 外部リソースの購読 (中継)
prefixes に指定するリソースは、そのサーバーが管理しているものでなくてもよい。
外部リソースが要求された場合、サーバーはそのリソースの権威サーバーの Realtime エンドポイントへ
代理で購読を行い、イベントを中継してもよい (MAY)。
中継を行わないサーバーは、管理外の prefix に対するイベントを配信しない
(購読メッセージ自体はエラーとしない)。クライアントは、確実に受信するためには
対象リソースの権威サーバーへ直接接続することができる。
中継を行う場合、以下に従う。
- 上流接続の宛先が、プライベート・ループバック・リンクローカルアドレスへ解決される場合、 接続してはならない (MUST NOT)。
- 1 接続あたり、およびサーバー全体で確立する上流接続数に上限を設けなければならない (MUST)。
- 中継されたイベントを、それを受信した上流接続へ再送してはならない (MUST NOT)。 中継のホップ数に上限を設けるべきである (SHOULD)。
サーバー間中継の詳細プロトコル (上流の多重化、購読の張り替え、再接続方式等) は本仕様では 規定せず、将来の CIP に委ねる。
3.2 イベントの受信
サーバーは、購読されたリソースに変更が発生した場合、以下の JSON メッセージをクライアントに送信する。
{ "type": "created", "source": "<CCURI>", "uri": "<CCURI>", "association": "<CCURI>", "documents": { "<CCURI>": { ... } }, "timestamp": "2025-11-23T12:34:56Z"}-
type(required) 変更イベントの種類を示す文字列。とりうる値は以下の通り。"created": 新しい Document が作成されたことを示す。既存キーの上書き (CIP-3 §3.4) の場合も"created"を発行する (Document の作成を示すのであり、キーの新規性を示すものではない)。"deleted": Document が削除されたことを示す。"associated": Document に Association (CIP-9) が作成されたことを示す。"unassociated": Document から Association が削除されたことを示す。
クライアントは、未知の
typeを持つメッセージを、接続を切断せず無視しなければならない (MUST)。 -
source(required) イベントが発行されたチャンネル (変更が発生したリソース側) の CCURI を設定しなければならない (MUST)。 購読プレフィックスの値そのものを設定してはならない (MUST NOT)。 クライアントは、自身の購読プレフィックスとsourceの前方一致により、由来する購読を判別する。 -
uri(required) 変更対象となったリソースの CCURI。"created"/"deleted"では作成・削除された Document の URI、"associated"/"unassociated"では関連付けの対象となった Document の URI が入る。 -
association(OPTIONAL)"associated"/"unassociated"イベントにおいて、作成・削除された Association Document の ccfs URI を設定するべきである (SHOULD)。 -
documents(OPTIONAL) イベントに関連する Concrnt Signed Document (CIP-1) を、そのリソースの CCURI をキーとした マップで格納する。"created": 作成された Document (キーはuriと同じ) を含む。"associated": 作成された Association Document (キーはassociationと同じ) を含む。"deleted"/"unassociated": 通常このフィールドは省略される。
保護された Document の編集 (redaction): サーバーは、イベントの送出時に、対象 Document の 読み取りアクション (
record:read/association:read, CIP-12) をゲスト (匿名) リクエスタで 評価し、匿名での読み取りが許可されない Document についてはdocumentsフィールドから その内容を省略しなければならない (MUST)。この場合もイベント自体 (type/source/uri/timestamp等) は配送される。 同梱される Signed Document がネストされたreferences(CIP-1) を持つ場合 (例: 配布 Reference Document に内包された元 Document)、その各エントリにも同じ 匿名 read 評価を適用し、許可されないエントリは省略しなければならない (MUST)。 さらに深い階層のネストは一律に省略してよい (MAY)。参考実装は省略する。 クライアントは、内容が省略されたイベントを受信した場合、必要に応じて自身の認証情報を 用いた通常の Resolve / Query (CIP-0, CIP-5) で Document を取得する。 -
timestamp(required) イベントの発生時刻。"created"イベントでは Document のcreatedAtの値が入る。 それ以外のイベントでは、サーバーがイベントを発行した時刻が入る。
4. Security Considerations
- Realtime API の配信内容は匿名で閲覧可能な情報に限定される。購読自体には認証を要求しない 代わりに、匿名リクエスタで読み取りが許可されない Document の内容は §3.2 の redaction 規則により イベントから省略されなければならない (MUST)。これにより、購読者ごとの認可評価や サーバー間中継時のアイデンティティの伝搬を必要とせず、保護された Document の内容が 未認可の購読者 (および中継先) へ漏えいすることを防ぐ。
- イベントのメタデータ (
uri等のキー情報・イベントの発生事実) は保護の対象外である。 購読は前方一致 (§3.1) であるため、キー名そのものが機微である場合は保護されない。 リソースの存在自体を秘匿する必要がある用途では、Realtime API によるイベント配信を 行うべきではない (SHOULD NOT)。 - イベントは配信元サーバーが構成する助言的な通知であり、それ自体は暗号学的な証明を伴わない。
クライアントは、イベントのみを根拠にリソースの状態を確定せず、必要に応じて対象を resolve で
確認すること。特に
deleted/unassociatedイベントは、伝搬削除の受信処理 (CIP-4 §6.1) の 性質上、実際には削除されていない対象について発行されうる。 - 中継 (§3.1.1) は匿名クライアントの指定に基づく外向き接続であり、SSRF・増幅・ループの 温床となる。中継を行うサーバーは §3.1.1 の防御を省略してはならない。
5. References
- RFC 2119 – Key words for use in RFCs to Indicate Requirement Levels
- RFC 8174 – Clarifications to RFC 2119
- RFC 6455 – The WebSocket Protocol
- CIP-12 – Policy (record:read / association:read)
この文書は concrnt/CIPs-translated の ja/11-realtime.md から生成されています。原文(英語)は concrnt/CIPs を参照してください。