docs: rewrite reference and clarify interface abstraction

This commit is contained in:
2026-10-15 17:53:48 +09:00
parent 6e9e675c70
commit f6905074b1
20 changed files with 981 additions and 826 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
# WIP Reference
Web Interface Protocolの仕様文書と、その文書を読むための静的サイトです。
Worldspace Interface Protocolの仕様文書と、その文書を読むための静的サイトです。
## 構成
+7 -74
View File
@@ -1,79 +1,12 @@
# 1. コンセプト
## 背景
WIP(Worldspace Interface Protocol)は、人間・AI・システムがアプリケーションを操作するための共通インタフェースを目指す。
現在のLLMエージェントは、Filesystem、検索、Issue Tracker、データベース、外部API、他のAgentなどを、それぞれ別個のToolとして扱うことが多い。統合先が増えるほど、モデルに提示するTool SchemaとAction Spaceも増えていく。
同じアプリケーションでも、人間は画面、AIはTool、システムはAPIを通して利用することが多い。接点の違いは必要だが、その下にある操作対象や利用可能な操作まで、利用者の種類ごとに別のモデルとして扱う必要があるのだろうか。
Unix filesystemは、異なる資源を単一の名前空間へ配置し、少数の操作で探索できる強い抽象化を持つ。一方、file / directoryとread / write中心の操作だけでは、`Issue.close()`、`PullRequest.merge()`、`Agent.ask()`のような意味的操作を自然に表現しにくい。
WIPでは、対象を発見し、その対象で何ができるかを知り、操作するという共通モデルを定める。人間向けのView、AI向けのTools、プログラム向けのAPIは、そのモデルをそれぞれの用途に合わせて提示する。
## 中心アイデア
WIPは、任意のデジタル環境を一つの**Worldspace**として公開する。
WorldspaceはObjectのTreeとして構成される。本書では、Tree上に配置され、Pathで到達できるObjectを**エントリ**と呼ぶ。Objectとエントリは別スキーマではない。
Objectは、短いdescription、利用可能なOperation、子Object、必要に応じて`ref`を公開できる。本文やmetadataなどのドメインデータは常時露出せず、Operationを通して取得・操作することを基本とする。
## Tool DiscoveryではなくWorld Discovery
一般的なTool Callingでは、モデルは提示されたTool一覧から操作を選ぶ。
WIPでは、モデルは既知のWorldspaceを辿り、目的に関連する対象を見つけ、公開されたOperationを確認して実行する。Operation Resultの`entry`型から未知のpathを発見し、必要なものを取得してClientのKnown Spaceへ追加できる。
中心となる問題を**Tool SelectionからWorld Explorationへ移す**ことがWIPの狙いである。
## Worldspaceの構造
Pathはidentityではなく、現在のWorldspace上の配置位置である。同一Objectが複数のエントリとして現れてもよい。
親子関係は所有・内包を表す。所有関係にない意味的な関連は、それを表す名前付きOperationから関連エントリのpathを返し、Treeへ無理に押し込まない。
Worldspace全体を事前にmaterializeする必要はない。Hostはlazy / virtualなTreeとして、必要な範囲だけを動的に公開できる。
## 操作中心のモデル
WIPではObjectを受動的なJSON recordとして扱わない。
本文を読む、metadataを取得する、検索する、状態を変更するといった行為はいずれもOperationとして表現する。例えばIssueであれば、`read_body()`、`get_metadata()`、`close(reason)`などを公開できる。
Operationには、名前や型に加えて、用途を判断するための短いdescriptionを持たせる。長文documentationや大量のドメインデータをInterfaceへ埋め込むことは想定しない。
ObjectはOperation定義を直接埋め込まず、実装コード上のInterface Declarationから生成された0個以上のInterface Descriptorを参照する。各Interfaceに宣言された関数の集合が再利用可能なcapability unitとなり、複数のObjectが同じInterfaceを共有できる。Objectは現在公開するInterface集合を持ち、Operation callではそのうち一つを明示してOperationを実行する。
## 発見と既知世界
Clientは、これまでに発見したエントリを既知のWorldspaceとして保持できる。既知のエントリはClient側で自由に辿り、Operation結果から得たエントリを追加して、さらに探索できる。
機械的な広域探索の対象は、Hostがindexableとして公開した範囲に限定できる。これにより、大量の検索結果や動的Objectが自動的に探索indexへ流入することを防ぐ。
## Operation Resultと新規発見
OperationはHost背後の環境を変更し得るが、WIPはその状態遷移や変更差分をClientへ同期するprotocolではない。
Operation Resultは型付きの値であり、Interface Descriptorの`entry`型として、未観測だったエントリのpathを返せる。例えばRAG検索からResult群を発見したり、Agentへの問い合わせからConversationを発見したりできる。
Clientは必要に応じて返されたpathを取得し、変更後の状態を改めて観測する。
## Narrow Waist
WIPの目的は、Filesystem、GitHub、RAG、DBなどを一つの巨大APIへ統合することではない。
任意のデジタル環境を共通のWorldspaceとして投影し、発見・観測・Operation実行という小さなInteraction Modelへ収束させる。Host内部のAPI、DB、RPC、永続化方式は規定せず、TransportもProtocolのlogical data modelから分離する。
## 状態管理の非目標
WIPは、Host上の任意状態をClientへ同期するdata store protocolではない。Object propertyのreplication、change feed、reactive subscription、分散transaction、domain event deliveryはCore Modelの規定対象外とする。
Clientが保持するKnown SpaceとDiscoverable Spaceは、過去の観測から構成されたcacheであり、Host上の現在状態を同期したreplicaではない。HostがClientのcache状態を追跡または更新することを要求しない。Operationのauthorizationと実行条件はHostが実行時に評価する。
## Post-trainingとの仮説
Tool Useが事後学習の対象になるなら、個別Tool名ではなくWorldspace上のinteraction policyを学習できる可能性がある。
1. 既知の世界を探索する。
2. 対象の意味とOperationを理解する。
3. 必要ならOperationから未知のエントリを発見する。
4. Operationを実行する。
5. 必要ならOperation Resultやentry pathをもとに対象を再観測する。
最も強い仮説は、**未知のToolを使えるモデルではなく、未知のDigital Environmentを探索できるモデルを作れるのではないか**という点にある。
- [1.1. アプリケーション操作の抽象化](1.1-interaction-abstraction.md)
- [1.2. 既存の抽象化と、その範囲](1.2-existing-abstractions.md)
- [1.3. WIPの設計方針](1.3-design-principles.md)
- [1.4. WIPの概念と適用範囲](1.4-concepts-and-scope.md)
+31
View File
@@ -0,0 +1,31 @@
# 1.1. アプリケーション操作の抽象化
## 利用者が違っても、操作する対象は共通する
Issueを閉じるという操作は、人間が画面から行っても、AIがToolを呼んでも、別のシステムがAPIを呼んでも、アプリケーション上ではIssueに対する操作である。利用者によって入力の仕方や結果の見せ方は変わるが、対象の意味まで変わるわけではない。
それでも、各接点では操作を異なる形で記述する。画面にはボタンや入力欄を設け、AIにはTool名と引数のSchemaを提示し、プログラムにはendpointやmethodを提供する。内部で同じ処理を呼んでいても、外部からは、それぞれの接点に合わせて対象と操作を理解する必要がある。
WIPの出発点は、この違いの下に、アプリケーションを操作するための共通モデルを置けないかという問いである。AIのためだけにToolを整理したいのではない。人間もAIもシステムも利用できる、操作インタフェースそのものを抽象化したい。
## 共通化するのは操作モデルである
アプリケーションを使う主体には、少なくとも、操作する対象、その対象が何を表すか、利用可能な操作、操作に必要な入力、返される結果を知る手段が必要になる。これらを共通の契約として公開できれば、Clientは用途ごとの接点を、その契約に基づいて構成できる。
人間には対象の一覧や操作フォームとして、AIには対象の説明とTool呼び出しとして、プログラムには型付きのAPIとして提示できる。同じモデルを使うことは、全員に同じ表示や呼び出し構文を使わせることではない。
また、共通のモデルからUIやToolを作れることと、用途に最適なUIや判断手順まで自動的に得られることは別である。画面の構成、操作の選び方、結果の解釈には、それぞれのClientやアプリケーションに固有の設計が残る。共有したいのは、それらの設計が参照する対象と操作の契約である。
## 呼び出し方だけでは足りない
操作を呼び出す形式が揃っていても、利用者が呼出先と引数をすでに知っていることを前提にすると、未知のアプリケーションを扱う手順は共通にならない。何を対象にできるか、必要な機能がどこにあるか、どの操作が使えるかを、別の文書や個別の組み込み知識から得る必要がある。
プログラムが既知のAPIを呼ぶ場合には、その前提で足りることもある。一方、人間やAIが環境を調べながら操作する場合や、システムが公開された機能を動的に扱う場合には、対象と操作を発見する手段も必要になる。
そのためWIPでは、実行だけでなく、発見と観測も操作モデルに含める。どの対象へ作用するかを決め、その対象の公開情報を確認してから操作する。対象を知ることと操作を呼ぶことを、別々の接続方式へ分散させずに扱いたい。
## 共通の契約と、主体ごとの権限
人間・AI・システムが同じモデルを使っても、同じ対象や操作をすべての主体へ公開する必要はない。公開する範囲も、実行を認める条件も、主体によって異なり得る。
Issueを見つけられたことだけでは、そのIssueを閉じる権限があるとは限らない。共通インタフェースは、こうした区別をなくすものではない。公開された対象と操作を同じ形式で理解できるようにしながら、可視性と実行時の認可はHostが判断する。
+43
View File
@@ -0,0 +1,43 @@
# 1.2. 既存の抽象化と、その範囲
## HTTP API
HTTPを使えば、異なる言語や環境で実装されたClientとサーバーが、共通のrequest / response形式で通信できる。Method、URI、status、header、representationには共通の意味があり、アプリケーションごとに通信の基本から設計し直す必要はない。
ただし、HTTPを採用しただけでは、アプリケーションの操作モデルまでは揃わない。どのURIが操作対象を表すのか、どの操作を公開するのか、引数と結果をどう表現するのかは、個々のAPIの設計に依存する。呼び出し方を知るために、個別のAPI仕様を参照する場面は残る。
OpenAPIなどで操作やSchemaを機械可読に記述することもできる。それでも、APIを記述できることと、実行時に存在する対象を共通の方法で辿り、その対象が公開する操作を取得できることは同じではない。WIPでは、通信形式やAPI定義に加え、対象の発見から操作までを共通のモデルとして扱いたい。
HTTPが不足しているというのは、その用途に対して通信機能が足りないという意味ではない。HTTPの契約だけでは決まらない、アプリケーション操作の契約が必要だということである。WIPも、通信にはHTTPを利用できる。
## REST
RESTは、通信上の呼び出しを並べるだけの方式ではない。資源の識別、representationを通した操作、自己記述的なメッセージ、hypermediaによる状態遷移などを、統一インタフェースの制約として扱う。リンクや操作の手掛かりを辿って利用を進める考え方も含んでいる。
したがって、WIPの動機を「RESTでは対象を発見できない」「RESTでは意味的操作を表現できない」と説明するのは適切ではない。Issueを閉じることも、資源の状態変更や関連する資源への操作として表現できる。
一方、その表現をClientがどう理解するかには、media typeやドメイン固有の契約が必要になる。RESTの制約を採用することだけで、任意の対象に対するOperation名、引数と結果の型、操作の説明、それらを取得する手順まで、一つの共通モデルに決まるわけではない。
WIPでは、この部分をObjectとInterfaceの契約として明示したい。資源をどうHTTPへ対応付けるかに先立って、何が操作対象で、どの操作を持ち、その宣言をどう取得するかを定める。RESTで同様の仕組みを実装できないのではなく、WIPが求める共通化には、その仕組み自体の定義が必要になる。
## システムコール
システムコールは、プロセスからOSの機能を利用するための共通インタフェースを提供する。同じOSの契約に従えば、アプリケーション内部の実装が違っても、ファイル、プロセス、メモリなどを共通の操作で扱える。
この抽象化の対象は、OSが提供する機能である。Issueを閉じる、Pull Requestをmergeする、Agentへ問い合わせるといったアプリケーション固有の操作まで、共通のシステムコールとして公開されるわけではない。システムコールを使って通信やプロセス間連携を実装しても、その先の操作の意味は別途定める必要がある。
WIPで共通化したいのは、OS資源へのアクセスより上の、アプリケーションが公開する対象と操作である。対象の実装が同じプロセス内にあるか、別のserviceにあるかによらず、Clientから同じモデルで扱えることを目指す。
## Filesystem
Filesystemは、異なる資源を単一の名前空間へ配置し、少数の操作で探索するためのモデルになる。Pathを辿って対象へ到達できることは、対象ごとの呼出先を最初からすべて知っている方式とは異なる。
しかし、file / directoryとread / writeを中心にしたモデルだけでは、アプリケーション固有の操作を自然に表しにくい。Issueの内容をfileとして読めても、それだけでは`Issue.close()`の引数や意味は分からない。特殊なファイルへの書き込みなどで操作を表現することはできるが、その規約を別途理解する必要がある。
WIPは、名前空間を辿って対象を見つける性質を使いつつ、対象の操作をread / writeに限定しない。`Issue.close()`、`PullRequest.merge()`、`Agent.ask()`のような操作を、対象が公開するInterfaceの中に、それぞれの名前と型を持つOperationとして表す。
## WIPが共通化する範囲
HTTP API、REST、システムコール、Filesystemは、それぞれ異なる範囲を抽象化している。WIPはそれらをまとめて置き換えるのではなく、アプリケーションの操作対象、配置、利用可能な操作、引数と結果の型を、ClientとHostの間の共通契約にする。
Hostは、その背後でHTTP APIを呼んでも、Databaseへ問い合わせても、Filesystemへアクセスしてもよい。Clientに対しては、それらの内部構成とは独立に、対象の発見・観測・Operation実行を公開する。
+43
View File
@@ -0,0 +1,43 @@
# 1.3. WIPの設計方針
## 対象を見つけ、その対象の操作を知る
WIPでは、アプリケーションが公開する対象を辿り、各対象で利用できる操作を確認してから実行する。操作の一覧だけを独立して渡すのではなく、操作がどの対象に属するかも共通のモデルで表す。
対象の配置を表すTreeをWorldspace、その中で観測・操作できる対象をObjectと呼ぶ。Objectは公開するInterfaceへの参照を持ち、自身の短い説明も公開できる。InterfaceにはOperationとその引数・結果の型を宣言し、用途を判断するための説明を添えられる。説明の公開は必須ではない。
この分離によって、対象を探索するときには配置と公開情報を使い、操作を選ぶときには必要なInterfaceの宣言を使える。すべての対象の本文や、すべてのOperationの詳細を、探索の開始時にまとめて取得する必要はない。
## ドメイン固有の操作を残す
共通化するために、すべての操作をread / writeへ変換するわけではない。Issueを閉じるなら`close(reason)`というOperationを公開できる。本文の取得は`read_body()`、metadataの取得は`get_metadata()`として表せる。
これらのOperationの業務上の意味は、アプリケーションが定める。WIPが共通にするのは、Operationを宣言し、取得し、型に従って呼び出し、結果を受け取る方法である。Filesystem、Issue Tracker、Databaseなどの全操作を、単一の巨大な標準APIへ収めることは目指さない。
同じ操作定義を複数のObjectで使う場合は、Interfaceとして共有する。一つのObjectが複数のInterfaceを公開することもできる。対象ごとに操作定義を重複させず、かつ、その対象がどの機能を公開するかを明示できる。
## 共通モデルと提示方法を分ける
Hostは、対象とInterfaceを共通のProtocol dataとして公開する。Clientはそれを取得・検証し、人間向けのView、AI向けのTools、プログラム向けのAPIへ投影する。
人間向けには対象の配置や操作を画面へ表示し、AI向けには説明とsignatureを提示し、プログラム向けにはmethod呼び出しとして扱うことができる。表示の形が違っても、参照するObjectとInterfaceの契約は共有できる。
観測のcache、対象の同一性の追跡、観測時と操作時の対応関係の検証はClientが担う。利用者にProtocolのvalidatorを取得・更新させることを前提にしない。共通化のために、通信や整合性管理の詳細まで各利用者へ直接見せる必要はない。
## 環境全体を事前に列挙しない
アプリケーションが扱う対象は、実行時に増減し得る。Worldspace全体を事前にmaterializeしたり、すべてのObjectを常駐させたりすることは要求しない。Hostは必要な範囲をlazy / virtualなTreeとして公開できる。
ただし、遅延して列挙できることと、その集合をTreeへ展開するのが適切であることは別である。機械的な探索で辿る範囲は、Hostがindexableとして公開した親子関係に限る。大量の検索結果や動的Objectは、Operationの結果から発見できる。
Operation Resultには、型付きの値として未知の対象のpathを含められる。Clientは必要な対象を選んで観測し、保持できる。探索を始める前にすべての対象を知っている必要も、発見した対象をすべて即時に取得する必要もない。
## AIのTool利用に現れる課題
個別の機能をそれぞれToolとして登録する方式では、統合先や公開機能が増えると、提示するTool SchemaとAction Spaceも増えていく。Tool一覧を提示するだけでは、その環境にどの対象が存在し、何に対して操作するのかを把握する手段が別に必要になる。
WIPのAI向けインターフェースでは、配置を見る`tree`、対象の説明と操作を確認する`inspect`、選んだ操作を実行する`invoke`を使う。新しいOperationを発見しても、それを別のToolとして登録するのではなく、同じ`invoke`から呼び出す。
この方式でも、個々のOperationの意味や引数を理解する必要は残る。基礎Toolの数を固定するだけで、操作の選択や判断が自動的に正しくなるわけではない。違いは、操作定義を最初から一括して提示することを前提にせず、対象を探索しながら必要な操作を取得できる点にある。
Tool SelectionからWorld Explorationへ問題の扱い方を変えることは、この共通モデルをAIへ提示したときの狙いである。WIP全体の動機は、AI専用のToolを減らすことよりも広い。人間やシステムも同じ対象と操作の契約を使えるようにする。
+67
View File
@@ -0,0 +1,67 @@
# 1.4. WIPの概念と適用範囲
## WorldspaceとObject
WIPは、任意のデジタル環境を、ObjectのTreeであるWorldspaceとして公開する。Tree上に配置され、Pathで到達できるObjectをエントリと呼ぶ。Objectとエントリは、別のスキーマではない。
各Objectは、短いdescription、Interfaceへの参照、必要に応じて`ref`を公開できる。Tree上では子Objectを持つこともできる。本文やmetadataなどのドメインデータは常時公開するのではなく、Operationを通して取得・操作することを基本とする。
Pathは、現在のWorldspace上の配置位置を表す。同一Objectが複数のエントリとして現れてもよいため、PathをObjectのidentityとはみなさない。Hostは、同じ主体に公開した一つのWorldspace内での同一性を、optionalな`ref`によって示せる。
Treeの親子関係は所有・内包を表す。所有関係にない意味的な関連には、その関連を表す名前付きOperationを使い、関連エントリのpathを返す。これらの関連を、Treeの親子関係へ無理に押し込まない。
## InterfaceとOperation
ObjectはOperation定義を直接埋め込まず、0個以上のInterfaceを参照する。実装コード上のInterface Declarationから、機械可読なInterface Descriptorを生成する。各Interfaceに宣言された関数の集合が、再利用可能なcapability unitになる。
複数のObjectが同じInterfaceを共有でき、一つのObjectも複数のInterfaceを組み合わせて公開できる。Operation callでは、対象Objectが現在公開している集合から一つのInterfaceを明示して実行する。
Operationには、名前や型に加え、用途を判断するための短い説明を任意で添えられる。長文documentationや大量のドメインデータをInterfaceへ埋め込むことは想定しない。Objectも、受動的なJSON recordとしては扱わない。本文の取得、検索、状態変更はいずれもOperationとして表す。
## ClientとHost
Hostは、主体に応じたWorldspaceを公開し、Operationを実行する。Clientは、Hostから得たObjectとInterfaceを、View、Tool、APIなどとして利用者へ提示する。同じモデルを使っても、どの情報をどの順序で表示するか、どの取得を先行して行うかは、用途に応じて選べる。
Protocolの基本的なinteractionは、Objectを観測する`observe`、Interface Descriptorを取得する`fetch_interface`、Operationを実行する`call_operation`である。これらの具体的なrequest / responseは[3. Protocol](3-protocol.md)、上位の提示やcacheの責務は[4. クライアント](4-client.md)に従う。
AI向けの`tree` / `inspect` / `invoke`は、Clientが提供する上位インターフェースであり、Protocol interactionをそのままTool名にしたものではない。他のClientが同じ呼び出し構文を使う必要はない。
## 発見と既知世界
Clientは、発見して取得したエントリをKnown Spaceとして保持できる。既知のエントリをClient側で辿り、Operation結果から得たエントリを追加すれば、さらに探索を進められる。
ただし、保持したエントリすべてを、機械的な広域探索の対象にするわけではない。Hostがindexableとして公開した親子関係を観測して得た範囲を、Discoverable Spaceとして扱う。Operationから発見したpathだけを根拠に、Treeの親子関係を追加しない。
この分離によって、大量の検索結果や動的Objectが自動的に探索indexへ流入するのを防ぐ。HostはWorldspace全体を事前にmaterializeせず、必要な範囲を動的に公開できる。
## Operation Resultと再観測
RAG検索のResult群や、Agentへの問い合わせで得られたConversationは、Operation Resultから発見できる。Resultは型付きの値であり、Interface Descriptorの`entry`型として、未観測だったエントリのpathを返せる。
一方、OperationがHost背後の環境を変更しても、その状態遷移や変更差分がClientへ同期されるわけではない。変更後の状態が必要なら、Clientは返されたpathを取得するなどして改めて観測する。
観測したことと、現在の操作が許可されることも別である。Operationのauthorizationと実行条件は、Hostが実行時に評価する。
## Narrow Waist
Filesystem、GitHub、RAG、DBを同じWorldspaceへ投影しても、それらの内部APIまで一つにする必要はない。WIPは、発見・観測・Operation実行という小さなInteraction Modelを共通化する。
Host内部のAPI、DB、RPC、永続化方式は規定しない。TransportもProtocolのlogical data modelから分離する。人間向けの画面、AI向けのTools、プログラム向けのAPIと、Host内部の実装の間に、共通の対象・操作モデルを置く。
## 状態管理の非目標
Known SpaceとDiscoverable Spaceは、過去の観測から構成されたcacheである。Host上の現在状態を同期したreplicaではなく、HostにClientのcache状態を追跡・更新することも要求しない。
WIPは、Host上の任意状態をClientへ同期するdata store protocolではない。Object propertyのreplication、change feed、reactive subscription、分散transaction、domain event deliveryは、Core Modelの規定対象外とする。
## Post-trainingとの仮説
共通の操作モデルをAIへ提示することには、学習上の仮説もある。Tool Useが事後学習の対象になるなら、個別Tool名の使い方に代えて、Worldspace上でのinteraction policyを学習できる可能性がある。
1. 既知の世界を探索する。
2. 対象の意味とOperationを理解する。
3. 必要ならOperationから未知のエントリを発見する。
4. Operationを実行する。
5. 必要ならOperation Resultやentry pathをもとに対象を再観測する。
この探索の仕方を学習できれば、未知のToolを使うだけでなく、未知のDigital Environmentを探索できるモデルを作れるのではないか。ただし、これは学習に関する仮説であり、WIPを採用しただけで得られる能力の保証ではない。人間・AI・システムに共通の操作モデルを提供するという目的は、この仮説の成立を前提にしない。
+33 -58
View File
@@ -1,80 +1,66 @@
# 2. コアモデル
WIP Core Modelは、ClientがHostの提供するWorldspaceを観測し、Objectを発見し、Interfaceに従って操作するための意味論を定義する。
Clientは、Hostが提供するWorldspaceからObjectを発見し、Interfaceに従って操作する。WIP Core Modelは、その観測と操作の意味論を定義する。
具体的なrequest / response structは[3. Protocol](3-protocol.md)、Transport Bindingの共通要件は[5. Transport Bindings](5-transports.md)、HTTPとJSONへの対応付けは[5.1. WIP over HTTP](5.1-wip-over-http.md)で定義する。
## 基本構造
Worldspaceは、Clientが探索できる**ObjectのTree**として公開される。
Worldspaceは、Clientが探索できるObjectのTreeである。Treeの途中にあるNodeも操作対象になってよい。例えば、`articles`というObjectに集合を扱う`query`等のOperationをInterfaceとして公開し、その配下へ個別Articleを配置できる。
WIPではObjectとエントリを別の構造として定義しない。**ObjectをWorldspaceのTree上の位置として扱うとき、そのObjectをエントリと呼ぶ。**
したがって、ObjectはTree上で親子関係を持ち得るし、途中のNodeもそのまま操作対象になってよい。例えば`articles`は対象の集合を扱うObjectとして、そのInterfaceに`query`等を宣言し、配下に個別Articleを配置できる。
ObjectをTree上の位置として扱うとき、そのObjectを**エントリ**と呼ぶ。Objectとエントリを別の構造として定義するわけではない。
## ClientとHost
WIP上の主要な実装主体は**Client**と**Host**である。
Worldspaceを提供するのがHostであり、それをユーザーまたはAIへ提示するのがClientである。
### Client
Clientは、Hostが提供するWorldspaceをユーザーまたはAIへ提示する。
Hostから取得したObjectとInterface Descriptorをcacheし、`ref`によるObject同一性の追跡、観測時と操作時の対応関係の検証、GUI、AI用Tools、PTC / REPL向けAPI等への投影を行う。
ClientはHostから取得したObjectとInterface Descriptorをcacheする。その観測を使って、`ref`によるObject同一性の追跡、観測時と操作時の対応関係の検証、GUI、AI用Tools、PTC / REPL向けAPI等への投影を行う。
### Host
Hostは、Clientに対して一つのWorldspaceを提供する。
Hostは、Clientに対して一つのWorldspaceを提供する。どのObject、エントリ、Interface、可視性を公開するかを決め、そのClientから見えるWorldspaceを構成する。
どのObject、エントリ、Interface、可視性を公開するかを決定し、そのClientから見えるWorldspaceを構成する。
Host内部でGitHub API、Database、Filesystem、RAG、他Agent、別protocol等をどう接続、集約、永続化するかはWIPの規定対象外とする。
ClientとHostの境界は通信境界であると同時に、ある主体へどのWorldspaceを公開するかを決めるtrust boundaryである。
内部でGitHub API、Database、Filesystem、RAG、他Agent、別protocol等をどう接続、集約、永続化するかは、WIPの規定対象外である。ClientとHostの境界は通信境界であると同時に、ある主体へどのWorldspaceを公開するかを決めるtrust boundaryでもある。
## Object / エントリ
**Object**は、Worldspace上で観測および操作できる対象のprotocol-level projectionである。
Objectは、Worldspace上で観測・操作できる対象をProtocolとして表現したものである。探索に必要な公開情報とInterface参照の集合を持つが、Host内部のdomain entityやApplication dataをそのまま公開する必要はない。本文、状態、domain metadata等は、現在公開しているInterfaceのOperationを通して取得・変更する。
Objectは、探索に必要な公開情報とInterface参照の集合を持つ。Host内部のdomain entityやApplication dataをそのままObjectとして公開する必要はない。Objectの本文、状態、domain metadata等は、現在公開されているいずれかのInterfaceに宣言されたOperationを通して取得または変更する。
そのObjectをTree上の位置として見たときの呼び名が、エントリである。Protocolの交換形式に「Objectへの参照を別途持つエントリ」という二重構造を要求しない。ただし、Client内部のcacheでは、Objectをflat storeへnormalizeし、Entry Treeから内部keyで参照してよい。
**エントリ**は、そのObjectをTree上の位置として見たときの呼び名である。
Tree上の位置を示すpathは、rootから各Objectの`name`を順に`/`で連結して構成する。同じ親の直下では`name`は一意であり、非root Objectの`name`は空であってはならない。
エントリがObjectへの参照を別途持つ、という二重構造はProtocolの交換形式として前提としない。Clientはcache実装上、Objectをflat storeへnormalizeし、Entry Treeから内部keyで参照してよい。
Tree上の位置はpathで表される。Pathはrootから各Objectの`name`を順に`/`で連結して構成する。Pathは恒久的なIdentityではなく、その時点でのnavigation coordinateである。
同じ親の直下ではObjectの`name`は一意であり、非root Objectの`name`は空であってはならない。同じObjectが複数の位置に現れる場合、そのObjectは同じ`name`を持ち、異なる親を経由する複数のpathで観測され得る。Objectの公開情報、name、path、Tree上の配置については[2.1. Object tree / Schema](2.1-object-tree-schema.md)で扱う。
同じObjectが複数の位置に現れる場合、そのObjectは同じ`name`を持ちながら、異なる親を経由する複数のpathで観測され得る。Pathは恒久的なidentityではなく、その時点でのnavigation coordinateである。公開情報、name、path、配置の詳細は[2.1. Object tree / Schema](2.1-object-tree-schema.md)で定義する。
## Interface
ObjectはOperation定義を直接持たず、0個以上のInterface参照をordered setとして持つ。
ObjectはOperation定義を直接持たず、0個以上のInterface参照をordered setとして持つ。Interfaceは、Operation、parameter、return type、documentationをまとめた、再利用可能なcapability unitである。
各Interfaceは、Objectで利用できるOperation、parameter、return type、documentationを定義する再利用可能なcapability unitである。Interface実装者はRustのtraitやTypeScriptのdefinition API等を使って実装コード上でInterfaceを宣言し、Libraryはその宣言からmachine-readableなInterface Descriptorを生成する。
実装者はRustのtraitやTypeScriptのdefinition API等でInterfaceを宣言し、Libraryがその宣言からmachine-readableなInterface Descriptorを生成する。複数のObjectが同じInterfaceを共有でき、一つのObjectも複数のInterfaceを組み合わせて公開できる。Operation定義を各Objectへ重複して持たせずに済み、ClientもDescriptorを参照単位でcacheできる。
複数のObjectが同じInterfaceを共有でき、一つのObjectも複数のInterfaceを組み合わせて公開できる。ObjectとInterfaceを分離することで、Operation定義を各Objectへ重複して持たせず、ClientがInterface Descriptorを参照単位でcacheできる。
Interface集合のmembershipはset semanticsを持ち、同じ参照を重複して含めない。列挙順はOperation解決には影響しないが、Hostが公開した順序としてUI表示に使える。
Interface集合のmembershipはset semanticsを持ち、同じ参照を重複して含めない。列挙順はOperation解決には影響しないが、HostがInterfaceを公開した順序としてUI表示に使用できる。
InterfaceとOperationの意味論は[2.2. Operation and Interface](2.2-operation-and-interface.md)、Descriptorのlogical structは[3. Protocol](3-protocol.md)、AI向け操作は[4.1. AI Tools](4.1-ai-tools.md)、人間とAIへのsignature表記は[4.2. Text View](4.2-text-view.md)で扱う。
InterfaceとOperationの意味論は[2.2. Operation and Interface](2.2-operation-and-interface.md)、Descriptorのlogical structは[3. Protocol](3-protocol.md)、AI向け操作は[4.1. AI Tools](4.1-ai-tools.md)、人間とAIへのsignature表記は[4.2. Text View](4.2-text-view.md)で定義する。
## Core interaction
Clientは、次の3操作によってWorldspaceを観測および操作する。
Worldspaceの観測と操作には、次の3操作を使う。
- `observe(path, depth)` — 指定pathのObjectと、指定した深さまでのindexableな子Objectを一つの観測として取得する。`depth = 0`では対象Objectだけを取得する。
- `fetch_interface(interface)` — Interface参照から現在のInterface Descriptorとoptionalなvalidatorを取得する。
- `call_operation(target, interface, operation, arguments)` — `path`とoptionalなObject validatorを持つtarget、およびObjectが現在公開する一つのInterface observationを指定してOperationを実行する。
この節は各操作の意味だけを定める。Parameterとreturn valueの具体的なstructはProtocolで定義する。
各parameterとreturn valueの具体的なstructは、Protocolで定義する。
複数の`observe`や`fetch_interface`は、それぞれ独立したCore interactionである。Clientは必要なinteractionを個別に並行実行でき、Transport実装は複数のexchangeを一つのconnection上でmultiplexできる。並行実行やmultiplexingによって新しいCore interaction、request間のdata dependency、共通snapshot、または暗黙の先読みを導入しない。
複数の`observe`や`fetch_interface`は、それぞれ独立したCore interactionである。Clientは個別に並行実行でき、Transport実装は複数のexchangeを一つのconnection上でmultiplexできる。ただし、並行実行やmultiplexingによって、新たなCore interaction、request間のdata dependency、共通snapshot、暗黙の先読みを導入しない。
## `ref`
Objectは、同じ主体に公開された一つのWorldspace内でObjectの同一性を示すために、optionalな`ref`を公開できる。
異なるpathで観測したObjectが同じ対象を表す場合、Hostはoptionalな`ref`でその同一性を示せる。有効範囲は、同じ主体に公開された一つのWorldspace内である。
`ref`はopaque stringであり、Objectのprimary key、永続的なUID、navigation coordinateではない。Backendに適切なUIDがある場合、Hostはそれを直接または変換して使用できるが、WIPはbackend data形式から得られるUIDの公開を要求しない。
`ref`はopaque stringであり、Objectのprimary key、永続的なUID、navigation coordinateではない。Backendに適切なUIDがあれば、Hostは直接または変換して使用できるが、WIPはbackend dataから得られるUIDの公開を要求しない。
- 同じWorldspace内で同じ有効な`ref`を持つObjectは、同じObjectを表す。
- Hostは同じ有効な`ref`を異なるObjectへ付与してはならない。
@@ -85,19 +71,15 @@ Objectは、同じ主体に公開された一つのWorldspace内でObjectの同
- Session、再接続、Host restart、Worldspace再構築をまたぐ永続性を要求しない。
- `ref`からObjectを取得するinteractionは提供しない。Objectの取得にはpathを使用する。
`ref`は完全なidentity systemではなく、Hostが明示した場合だけ複数の観測またはエントリを同一Objectとしてcorrelateするためのmarkerである。
つまり、`ref`によって複数の観測やエントリを同一Objectとして対応付けられるのは、Hostがその同一性を明示した場合だけである。完全なidentity systemではない。
## 観測整合性
エントリ自体をObjectとは別実体として扱う必要はない。ただし、あるpath上のObjectを観測した後、Operationを実行するまでの間に、そのpathが別のObjectを指すことはあり得る。
AIが`/issues/current`を観測したときにはIssue Aだったのに、`invoke`時にはIssue Bへ差し替わっていることがある。そのまま実行すれば、Issue Aを操作するつもりでIssue Bへ作用してしまう可能性がある。
その場合、Client / Runtimeは、以前のObjectを対象としたOperationを新しいObjectへ黙って適用してはならない。実行前に観測時の対応関係を検証し、変化していればOperationを中止する。この性質を**observation consistency**と呼ぶ。
Client / Runtimeは、以前のObjectを対象としたOperationを、新しいObjectへ黙って適用してはならない。実行前に観測時の対応関係を検証し、変化していれば中止する。この性質を**observation consistency**と呼ぶ。エントリをObjectとは別実体にする必要はないが、観測から実行までの変化は扱う必要がある。
例えば、AIが`/issues/current`を観測した時点ではIssue Aだったが、`invoke`時にはIssue Bへ差し替わっていた場合、AIはIssue Aへ作用するつもりでIssue Bを操作してしまう可能性がある。
この観測整合性は利用者に追跡させるのではなく、Clientの責務とする。
処理の流れは次の通り。
観測整合性の管理は利用者ではなくClientの責務である。
1. Clientがpath上のObjectを観測する。
2. Objectがvalidatorを持つ場合、ClientはObjectとrequest pathを対応付けて保持する。
@@ -105,33 +87,26 @@ Objectは、同じ主体に公開された一つのWorldspace内でObjectの同
4. 同じObjectへ条件付きで操作する場合、Clientは`path`とObjectの`validator`をtargetとしてHostへ渡す。
5. Hostは現在のvalidatorとの一致確認とOperation実行をatomicに行う。
ValidatorはClientとHostの間で扱い、AIやユーザーに直接管理させない。Transport Bindingはvalidatorを対応するProtocol fieldとして保持し、HTTP ETag等のrepresentation metadataで置き換えない。
ValidatorはClientとHostの間で扱い、AIやユーザーに直接管理させない。Transport Bindingも対応するProtocol fieldとして保持し、HTTP ETag等のrepresentation metadataで置き換えない。
Validatorが一致しない場合、Hostは`validator_mismatch`を返してOperationを実行しない。同じOperationを再試行するなら、先に新しい観測を取得しなければならない。
Validatorが一致しなければ、Hostは`validator_mismatch`を返し、Operationを実行しない。同じOperationを再試行するには、先に新しい観測を取得しなければならない。
## 同一性と観測整合性の分離
WIPでは次の二つを分けて扱う。
`ref`は、複数の観測またはエントリが同じObjectを表すことを明示するmarkerである。一方、validatorは、条件付きOperationにおいてHostが定める現在状態との一致を検証するための値である。
- **Object identity (`ref`)** — 一つのClient-facing Worldspace内で、複数の観測またはエントリが同じObjectを表すことを明示するoptionalなmarker。
- **Observation consistency** — `ref`の有無にかかわらず、観測したpath上のObjectと操作対象のObjectが一致していることを保証する仕組み。
したがって、`ref`を持たないObjectであっても安全な操作対象になり得る。`ref`は同一性を公開する仕組みであり、validatorはHostが定める現在状態との一致を条件付きOperationで検証する仕組みである。
この二つを区別することで、`ref`のないObjectも安全な操作対象になり得る。Object identityの公開はoptionalであり、観測したpath上のObjectと操作対象のObjectの一致を保証するobservation consistencyは、`ref`の有無とは別に扱う。
## Application data
WIPは、Host上の任意状態をClientへ同期するdata store protocolではない。Object propertyのreplication、change feed、reactive subscription、分散transaction、domain event deliveryはCore Modelの規定対象外とする。
Operationが交換するApplication dataについて、WIPが規定するのは、Interfaceに宣言された型、wire encoding、boundary validationである。値のdomain上の意味、保存方法、business validation、Client内部での利用方法はApplicationの責務とする。
Operationが交換するApplication dataについて、WIPはInterfaceに宣言された型、wire encoding、boundary validationを規定する。値のdomain上の意味、保存方法、business validation、Client内部での利用方法はApplicationの責務である。
ClientのKnown SpaceとDiscoverable Spaceは、過去の観測から構成されたcacheであり、Hostの現在状態を同期したreplicaではない。HostにClientのcache状態を追跡・更新することは要求しない。
Clientが保持するKnown SpaceとDiscoverable Spaceは、過去の観測から構成されたcacheであり、Host上の現在状態を同期したreplicaではない。HostがClientのcache状態を追跡または更新することを要求しない。
この責務境界はObject、Interface、Operationの各節で一貫して適用する。
WIPは任意状態を同期するdata store protocolではないため、Object propertyのreplication、change feed、reactive subscription、分散transaction、domain event deliveryもCore Modelの規定対象外とする。この責務の分担は、Object、Interface、Operationに共通する。
## Transportとの分離
Core ModelとProtocol structは、HTTP、TCP、WebSocket等の特定transportを要求しない。
Core ModelとProtocol structは、HTTP、TCP、WebSocket等の特定transportを要求しない。通信方式、concrete encoding、endpointへの対応付けはTransport Bindingとして定義する。
通信方式、concrete encoding、endpointへの対応付けはTransport Bindingとして定義する。共通要件は[5. Transport Bindings](5-transports.md)、標準bindingは[5.1. WIP over HTTP](5.1-wip-over-http.md)で扱う。
この分離により、Worldspaceの意味論、Client / Host間のlogical contract、通信方式を独立して進化させる。
共通要件は[5. Transport Bindings](5-transports.md)、標準bindingは[5.1. WIP over HTTP](5.1-wip-over-http.md)に定める。Worldspaceの意味論、Client / Host間のlogical contract、通信方式を分け、それぞれを独立して進化させる。
+51 -47
View File
@@ -2,9 +2,9 @@
## Objectの公開情報
Objectは、Worldspace上の対象を発見し、理解し、操作するためのprotocol-level projectionである。
Objectは、Worldspace上の対象をprotocol-level projectionとして公開するものである。Clientはその公開情報を使って対象を発見し、理解し、操作する。
Objectは少なくとも次の公開情報を持つ。
少なくとも次の情報がObjectの公開情報に含まれる。
- **name** — 親Objectの下でのpath segment。
- **description** — Objectが何を表すかを説明する情報。
@@ -12,32 +12,32 @@ Objectは少なくとも次の公開情報を持つ。
- **ref** — 同じClient-facing Worldspace内で複数の観測またはエントリが同じObjectを表すことを示すoptionalなmarker。
- **validator** — HostがObjectの現在状態へ付与する任意のopaque value。
`interfaces`のmembershipはset semanticsを持ち、同じInterface参照を重複して含めてはならない。集合は空でもよい。列挙順はOperation解決には影響せず、HostがInterfaceを立項した順序としてUI表示に使用できる。
`interfaces`のmembershipにはset semanticsを適用し、同じInterface参照を重複して含めてはならない。空の集合も許可する。列挙順はOperation解決には影響しないが、HostがInterfaceを立項した順序としてUI表示に使用できる。
具体的な型、必須性、resource limitは[3. Protocol](3-protocol.md)で定義する。
各情報の具体的な型、必須性、resource limitは[3. Protocol](3-protocol.md)で定義する。
Objectの本文、状態、domain metadata等のApplication dataを、共通のproperty bagとしてObjectへ格納しない。それらはInterfaceに宣言されたOperationを通して取得または変更する。
Objectの本文、状態、domain metadata等のApplication dataは、Interfaceに宣言されたOperationを通して取得または変更する。Objectへ共通のproperty bagとして格納しない。
`description`は探索時に対象を理解するための短い公開情報であり、長い本文やdomain entityの完全な表現を格納する場所ではない。
`description`も、長い本文やdomain entityの完全な表現を格納する場所ではない。探索時に対象を理解するための短い公開情報である。
### 同じ`ref`を持つObject
同じClient-facing Worldspace内で同じ`ref`を持つObjectは、一つの共有された現在状態を持つ。同じObjectを異なるpathへ配置したことを理由に、path固有の`name`、`description`、Interface集合を返してはならない。
同じClient-facing Worldspace内で同じ`ref`を持つObjectには、一つの共有された現在状態がある。同じObjectを異なるpathへ配置しても、path固有の`name`、`description`、Interface集合を返してはならない。
- 同じ`ref`と同じvalidator valueを持つObjectは、validatorが存在する場合、`name`、`description`、Interface集合を含むObject representationが一致しなければならない。
- 同じ`ref`と異なるvalidatorを持つObjectは、同一Objectの異なる状態として扱う。
- Hostは異なるpathから同じ`ref`を観測した場合も、一つの現在状態を一貫して返す。
- Clientは最後に成功した観測を、その`ref`を持つObjectの現在状態として扱う。
同じObjectを異なる親の下へ配置する場合もObjectの`name`は共通である。Pathは親から各Objectの`name`を辿って構成するため、同じObjectは異なる親を経由して異なるpathに現れ得る。
異なる親の下へ配置した場合も、同じObjectの`name`は共通である。Pathは親から各Objectの`name`を辿って構成するので、異なる親を経由すれば、同じObjectが異なるpathに現れ得る。
## Interface参照
Objectは0個以上のInterfaceを参照する。各Interface Descriptorは、Objectに対して実行可能なOperationの一つのcapability namespaceを宣言する。
Objectは0個以上のInterfaceを参照する。Interface Descriptorは、Objectに対して実行可能なOperationを宣言するものであり、一つのcapability namespaceを定義する。
Operation名は一つのInterface Descriptor内で一意であればよく、異なるInterface間で同じOperation名を使用できる。Operation callはscopeとlocal nameからなるInterface参照を明示するため、Protocol上の解決は曖昧にならない。人間・AI向けのqualified表記は[Text Viewの参照表記](4.2-text-view.md#参照表記)に従う。
Operation名は、一つのInterface Descriptor内で一意であればよい。異なるInterface間では同じOperation名を使用できる。Operation callではscopeとlocal nameからなるInterface参照を明示するため、Protocol上の解決は曖昧にならない。人間・AI向けのqualified表記は[Text Viewの参照表記](4.2-text-view.md#参照表記)に従う。
Interfaceは次を定義する。
Interfaceには次の定義を含める。
- Operation名
- Operationの説明
@@ -45,31 +45,31 @@ Interfaceは次を定義する。
- Return type
- Named typeとdocumentation
Interface実装者は実装コード上でInterfaceを宣言し、Libraryはその宣言からInterface Descriptorを生成する。ClientはObjectの各Interface参照を使ってDescriptorを取得し、検証、cache、表示、Operation callのvalidationに利用する。
Interface実装者が実装コード上でInterfaceを宣言すると、Libraryはその宣言からInterface Descriptorを生成する。ClientはObjectの各Interface参照でDescriptorを取得し、検証、cache、表示、Operation callのvalidationに利用する。
同じInterfaceを持つObjectは同じDescriptor参照を共有できる。
同じInterfaceを持つObjectは、同じDescriptor参照を共有できる。
## Interface scope
Objectをpath `P`で公開するとき、そのInterface参照のscopeは`P`自身またはその祖先でなければならない。Self-scopeを許可し、rootから`P`までの各pathを含む。Path segmentの完全一致で判定し、単純な文字列prefixで判定しない。本仕様でInterface scopeの「祖先制約」と呼ぶ場合もself-scopeを含む。
Objectをpath `P`で公開する場合、Interface参照のscopeは`P`自身か、その祖先でなければならない。Self-scopeも許可するので、rootから`P`までの各pathが候補となる。祖先かどうかはpath segmentの完全一致で判定し、単純な文字列prefixでは判定しない。本仕様のInterface scopeに関する「祖先制約」にはself-scopeも含む。
例えば`/github/my-rep/issues`は、scope `/`、`/github`、`/github/my-rep`、`/github/my-rep/issues`のInterfaceを公開できる。`/gitlab`、`/github/other-rep`、`/github/my-rep/issues/123`のscopeは使用できない。`/github`は`/github-extra`の祖先ではない。Root Objectはscope `/`のInterfaceを公開できる。
例えば、`/github/my-rep/issues`で公開できるのは、scopeが`/`、`/github`、`/github/my-rep`、`/github/my-rep/issues`であるInterfaceである。Scopeが`/gitlab`、`/github/other-rep`、`/github/my-rep/issues/123`であるInterfaceは使用できない。文字列の先頭が一致しても、`/github`は`/github-extra`の祖先にはならない。Root Objectはscope `/`のInterfaceを公開できる。
この制約は配置pathに基づき、indexableかどうかには依存しない。非indexableなObjectを直接観測した場合も同じ規則を適用する。Scope Objectを先に観測することも、そのObject自身が同じInterfaceを公開することも要求しない。
この制約の基準は配置pathであり、Objectがindexableかどうかではない。非indexableなObjectを直接観測した場合にも同じ規則を適用する。Scope Objectを先に観測する必要はなく、そのObject自身が同じInterfaceを公開する必要もない。
Scopeの適合と`Object.interfaces`への明示的なmembershipは別の条件である。祖先scopeのInterfaceを自動継承せず、scopeをauthorizationの証明として扱わない。
Scopeが適合していても、`Object.interfaces`への明示的なmembershipは別に必要である。祖先scopeのInterfaceは自動継承せず、scopeをauthorizationの証明にも使わない。
ScopeはそのpathにあるObjectに紐づき、Objectとは独立して存続するnamespaceではない。Scope Objectがそのpathから消えれば、そのscopeのInterfaceの公開も終了する。消えたObjectの配下を、親Objectの存在しない孤立したsubtreeとして公開し続けない。別のObjectを同じpathへ公開し直すことはできる。
Scopeは、そのpathにあるObjectに紐づく。Objectとは独立して存続するnamespaceではないため、scope Objectがそのpathから消えると、そのscopeのInterfaceの公開も終了する。消えたObjectの配下を、親Objectの存在しない孤立したsubtreeとして公開し続けない。同じpathへ別のObjectを公開し直すことはできる。
Scope Objectに`ref`があれば、ClientはそのObjectとの紐付きを確認できる。`ref`はoptionalであり、存在しない場合は同じpathでの差し替えをidentityによって追跡できない。これは許可された公開形態であり、Hostに`ref`の生成を強制したり、Clientが代替identityを推測したりしない。参照の有効期間、呼出時の確認、移動とcacheの扱いは[Operation and Interface](2.2-operation-and-interface.md#scope-objectと有効期間)および[Protocol](3-protocol.md#scope-objectの紐付き)に従う。
Scope Objectに`ref`があれば、ClientはそのObjectとの紐付きを確認できる。一方、`ref`はoptionalなので、存在しない場合には、同じpathでの差し替えをidentityによって追跡できない。この公開形態も許可されており、Hostに`ref`の生成を強制したり、Clientが代替identityを推測したりしない。参照の有効期間、呼出時の確認、移動とcacheの扱いは[Operation and Interface](2.2-operation-and-interface.md#scope-objectと有効期間)および[Protocol](3-protocol.md#scope-objectの紐付き)に従う。
## Object / エントリ / path
WIPでは、Objectとエントリを別のdomain entityとして定義しない。ObjectをTree上の位置として扱うとき、そのObjectをエントリと呼ぶ。
ObjectをTree上の位置として扱うときは、そのObjectをエントリと呼ぶ。WIPでは、Objectとエントリを別のdomain entityとしては定義しない。
### `name`
Objectの`name`は表示用labelではなく、親Objectの下でそのObjectを識別するpath segmentである。
Objectの`name`は、親Objectの下でそのObjectを識別するpath segmentである。表示用labelとは区別し、次の条件を適用する。
- Root Objectの`name`は空文字列とする。
- 非root Objectの`name`は空であってはならない。
@@ -80,11 +80,11 @@ Objectの`name`は表示用labelではなく、親Objectの下でそのObjectを
- Nameの比較はUnicode code point sequenceの完全一致で行う。
- 同じ親の直接のchildrenは、互いに異なる`name`を持たなければならない。
`name`を人間向けの自由なtitleとして扱わない。探索時の短い説明には`description`を使い、domain上のtitle等はOperationからApplication dataとして取得する。
このようにpath segmentとして使う`name`を、人間向けの自由なtitleとして扱わない。探索時の短い説明は`description`で公開し、domain上のtitle等はOperationからApplication dataとして取得する。
### Pathの構成
Rootのpathは`/`とする。非root Objectのpathは、rootからそのObjectまでの各`name`を`/`で連結して構成する。
Rootのpathは`/`とする。非root Objectのpathは、rootからそのObjectまでの各`name`を`/`で連結する。
```text
root.name = ""
@@ -97,18 +97,18 @@ example.name = "example"
example.path = "/projects/example"
```
Pathには空segment、`.`、`..`を含めない。Root以外のpathは末尾に`/`を持たない。Nameに`/`を許可しないため、Core Modelではsegment escapeを定義しない。Transport BindingがPathをURL componentへ格納する場合のURL encodingは、WIP Pathの構成とは別に扱う。
Pathには空segment、`.`、`..`を含めず、root以外のpathの末尾には`/`を付けない。Nameに`/`を許可しないため、Core Modelではsegment escapeを定義しない。Transport BindingでPathをURL componentへ格納するときのURL encodingは、WIP Pathの構成とは別に扱う。
非root pathについては、最後のsegmentと取得したObjectの`name`が一致しなければならない。
また、非root pathの最後のsegmentは、取得したObjectの`name`と一致しなければならない。
```text
observe("/projects/example", depth = 0)
-> ObjectObservation.object.name == "example"
```
同じObjectが複数のpathへ配置される場合、同じ`ref`と`name`を持ち、異なる親を経由して異なるpathに現れる。Objectをrenameすると、そのObjectを参照するすべての配置とdescendantのpathが変化する。Pathは恒久的なObject identityとして使用しない。
同じObjectを複数のpathへ配置するときは、各配置で同じ`ref`と`name`を持ち、異なる親を経由して異なるpathに現れる。Renameすると、同じObjectを参照するすべての配置とdescendantのpathが変化する。このため、pathを恒久的なObject identityとして使用しない。
`ref`、path、Interface参照は異なる役割を持つ。
`ref`、path、Interface参照は、それぞれ次の役割を持つ。
| 値 | 役割 |
| --- | --- |
@@ -116,54 +116,54 @@ observe("/projects/example", depth = 0)
| `ref` | 複数の観測にまたがる任意のObject identity |
| Interface参照 | Objectで利用可能なcapability definition |
通常のstringを内容だけからpathまたは`ref`と推測しない。Operation value内でWorldspace上の位置を返す場合は、Descriptorで`entry`型として宣言する。
Operation value内でWorldspace上の位置を返す場合は、Descriptorで`entry`型として宣言する。通常のstringを、内容だけからpathや`ref`と推測しない。
## Tree
Objectは子Objectを持つことができる。
Parent / child関係はWorldspaceにおける**所有または内包**を表す。
Objectは子Objectを持つことができる。このparent / child関係は、Worldspaceにおける**所有または内包**を表す。
- Filesystem: Directory / File
- GitHub: Repository / Issue
- Database: Database / Table
- RAG: Index / Document
関連、依存、参照等の非所有関係を、Treeの親子関係として濫用しない。そのような関係はOperationのresultとして`entry`を返し、Clientが必要に応じて移動できるようにする。
これに対し、関連、依存、参照等の非所有関係をTreeの親子関係として濫用しない。そのような関係はOperationのresultとして`entry`を返し、Clientが必要に応じて移動できるようにする。
### `children`の意味
`children`はApplication dataではなく、Objectを指定pathで観測した時点におけるWorldspace上のprojectionである。
`children`は、指定pathでObjectを観測した時点のWorldspace上のprojectionである。Application dataには含めない。
一つのObjectが複数pathへ配置される場合、そのObjectから見えるchildrenは配置ごとに異なり得る。したがって、childrenを`ref`が示すObject identityの一部とはみなさない。
一つのObjectを複数pathへ配置した場合、見えるchildrenは配置ごとに異なり得る。そのため、childrenは`ref`が示すObject identityの一部とはみなさない。
Protocolでは`Object`自体にchildrenとpathを含めず、`observe` responseの`ObjectObservation`としてObjectとoptionalなchildren observationをまとめる。ValidatorはObjectに含まれる。各nodeのpathは、request pathを起点にObjectの`name`を辿って導出する。このwrapperはObjectとは別のdomain entityを導入するものではなく、指定depthまでの観測結果を表すresponse shapeである。
Protocolでは、`Object`自体にchildrenとpathを含めない。`observe` responseの`ObjectObservation`で、Objectとoptionalなchildren observationをまとめる。ValidatorはObjectに含め、各nodeのpathはrequest pathを起点にObjectの`name`を辿って導出する。
`children` fieldが省略されているnodeではchildrenを観測していない。`children` fieldが存在する場合、そのarrayはその主体へ公開された直接のindexable childrenをすべて含み、空arrayは観測時点でindexable childが存在しなかったことを表す。
`ObjectObservation`は、指定depthまでの観測結果を表すresponse shapeである。このwrapperによって、Objectとは別のdomain entityを導入するわけではない。
Nodeの`children` fieldを省略した場合、そのnodeのchildrenは観測していない。Fieldが存在する場合、そのarrayには、その主体へ公開された直接のindexable childrenをすべて含める。空arrayは、観測時点でindexable childが存在しなかったことを表す。
## Objectの可視性
Hostは、主体に認識させるObjectだけでClient-facing Worldspaceを構成する。ObjectをWorldspaceへ公開することは、そのpathとObjectの公開情報を主体が認識できることを意味する。
Client-facing Worldspaceは、Hostがその主体に認識させるObjectだけで構成する。Objectを公開すると、そのpathとObjectの公開情報を主体が認識できる。
主体に認識させないObjectは、そのWorldspaceに存在しないものとして扱う。
反対に、主体に認識させないObjectは、そのWorldspaceには存在しないものとして扱う。
- `observe`では、そのObjectと、そのObjectだけを経由して到達するsubtreeをresponseから省略する。
- 省略されたObjectやchild数を示すredaction markerは返さない。
- 非公開pathを起点とする`observe`には、Host内部での存在理由にかかわらず`NotFound`を返す。Object観測に対する`PermissionDenied`は使用しない。
Objectを公開しながら、特定Interfaceを集合から除外すること、公開したInterfaceから一部のOperationを除外すること、公開されたOperationの実行を認可時に拒否することはできる。Operationの可視性と`PermissionDenied`の使い分けは[2.2. Operation and Interface](2.2-operation-and-interface.md)で定義する。
Objectを公開する場合でも、特定Interfaceを集合から除外したり、公開したInterfaceから一部のOperationを除外したりできる。公開されたOperationの実行を認可時に拒否することもできる。Operationの可視性と`PermissionDenied`の使い分けは[2.2. Operation and Interface](2.2-operation-and-interface.md)で定義する。
Objectの`description`には、その主体へ公開できる説明だけを含める。安全な説明を公開できない場合はoptionalな`description`を省略できるが、Protocolはfield-level redaction markerを定義しない。Objectの本文やdomain dataの部分的な開示は、各Operationのresult schemaとdomain semanticsで表現する。
`description`に含めるのは、その主体へ公開できる説明だけである。安全な説明を公開できない場合は、optionalな`description`を省略できる。ただし、Protocolはfield-level redaction markerを定義しない。本文やdomain dataを部分的に開示する場合は、各Operationのresult schemaとdomain semanticsで表現する。
## `observe`
`observe(path, depth)`は、指定pathのObjectと、そのObjectからindexable child edgeを指定depthまで辿った範囲を一つの観測として取得する。
`observe(path, depth)`は、指定pathのObjectを起点に、indexable child edgeを指定depthまで辿った範囲を一つの観測として取得する。
```text
observe(path, depth) -> ObjectObservation
```
起点Objectをdepth `0`とする。`depth = 0`では起点Objectだけを返し、そのnodeの`children` fieldを省略する。成功responseはrequested depthまでの公開されたindexable childrenを完全に含み、requested depthより深いObjectを含めない。
起点Objectのdepthは`0`である。`depth = 0`では起点Objectだけを返し、そのnodeの`children` fieldを省略する。成功responseには、requested depthまでの公開されたindexable childrenを完全に含め、それより深いObjectは含めない。
- Nodeのdepthがrequestの`depth`より小さい場合、`children` fieldを必ず含める。
- 観測した直接のindexable childが存在しない場合、`children`は空arrayとする。
@@ -171,7 +171,9 @@ observe(path, depth) -> ObjectObservation
- 同じparent nodeのchildrenは、互いに異なる`name`を持つ。
- Clientはrequest pathとchildrenの`name`から各nodeのpathを導出する。
各ObjectはHostが発行したvalidatorを持ち得るため、Clientは導出したpathとvalidatorから条件付きOperationのtargetを構築できる。Responseを部分的な成功として返す`limit`や`truncated`は定義しない。Requested depthまでの完全な観測をresource budget内で構築できない場合、Hostはsuccess responseの代わりに`ResourceLimitExceeded`を返す。
各ObjectはHostが発行したvalidatorを持ち得る。Clientは、導出したpathとvalidatorから条件付きOperationのtargetを構築できる。
Responseを部分的な成功として返すための`limit`や`truncated`は定義しない。Requested depthまでの完全な観測をresource budget内で構築できない場合、Hostはsuccess responseを返さず、`ResourceLimitExceeded`を返す。
## Indexable children
@@ -181,9 +183,9 @@ Tree上のchildrenとして自然に列挙できるのは、**indexableなObject
- 比較的安価に取得できる。
- 所有または内包関係として自然に理解できる。
全件列挙が高コストまたは不自然な集合は、Treeへ直接展開しない。対象の集合を扱うObjectのOperationを使って検索、filter、paginationを行い、resultとして関連する`entry`を返す。
全件列挙が高コストまたは不自然な集合は、Treeへ直接展開しない。その集合を扱うObjectのOperationで検索、filter、paginationを行い、関連する`entry`をresultとして返す。
例えば、大規模なIssue collectionは次のように公開できる。参照はscope `/`を含む短縮表記で示す。
例えば、大規模なIssue collectionは次の形で公開できる。参照には、scope `/`を含む短縮表記を使う。
```text
/issues
@@ -191,12 +193,14 @@ Tree上のchildrenとして自然に列挙できるのは、**indexableなObject
operation: /::IssueCollection#query(filter, cursor, limit) -> IssueQueryResult
```
そのquery resultでは、itemsを`entry`のarrayとして返す。
```text
IssueQueryResult.items: [entry]
```
## 複数の取得
複数のObjectやInterface Descriptorが必要な場合も、各`observe`と`fetch_interface`は独立したCore interactionである。Clientは必要なrequestを個別に並行実行でき、Transport実装はconnection reuseやmultiplexingを利用できる。
複数のObjectやInterface Descriptorを取得する場合でも、各`observe`と`fetch_interface`は独立したCore interactionである。Clientは必要なrequestを個別に並行実行できる。Transport実装ではconnection reuseやmultiplexingを利用できる。
WIPは複数のinteractionを包む共通request envelope、自動的な全量取得、暗黙の再帰展開、Clientが要求していない先読みを定義しない。
WIPは、複数のinteractionを包む共通request envelope、自動的な全量取得、暗黙の再帰展開、Clientが要求していない先読みを定義しない。
+62 -56
View File
@@ -2,52 +2,56 @@
## Interface
ObjectはOperation定義を直接持たず、0個以上のInterface参照をordered setとして持つ。各InterfaceはObjectが公開する一つのcapability namespaceである。
Objectは、Operation定義を直接持つ代わりに、0個以上のInterface参照をordered setとして持つ。各Interfaceは、Objectが公開する一つのcapability namespaceであり、利用できるOperationと各Operationのparameter、return type、documentationを定義する。
Interfaceは、Objectで利用できるOperationと、各Operationのparameter、return type、documentationを定義する。複数のObjectが同じInterfaceを共有できるため、Operation定義をObjectごとに重複して送る必要はない。
複数のObjectで同じInterfaceを共有できるため、ObjectごとにOperation定義を重複して送る必要はない。ObjectのInterface集合にはset semanticsを適用し、同じ参照を重複して含めない。列挙順はOperation解決には影響しないが、Hostの立項順としてUI表示に使用できる。
ObjectのInterface集合はset semanticsを持ち、同じ参照を重複して含めない。列挙順はOperation解決には影響しないが、Hostの立項順としてUI表示に使用できる。Operation callは集合から一つのInterfaceを明示して、そのDescriptor内のOperationを実行する。
Operation callでは、この集合から一つのInterfaceを明示し、そのDescriptor内のOperationを実行する。
Interface実装者は、RustのtraitやTypeScriptのdefinition API等を使って実装コード上でInterfaceを宣言する。Libraryはその宣言から、typed handler、runtime validation、およびmachine-readableなInterface Descriptorを生成する。
Interface実装者は、RustのtraitやTypeScriptのdefinition API等を使い、実装コード上でInterfaceを宣言する。Libraryはこの宣言から、typed handler、runtime validation、machine-readableなInterface Descriptorを生成する。
Interface Descriptorは人間が手書きするschema fileではない。Hostが`fetch_interface`で公開し、Clientが参照単位でcacheするprotocol dataである。
したがって、Interface Descriptorは人間が手書きするschema fileではない。Hostが`fetch_interface`で公開し、Clientが参照単位でcacheするprotocol dataである。
## Interfaceの識別とscope
Interface参照は、Worldspace上の絶対pathである`scope`と、そのscope内のlocal nameである`name`を別fieldとして持つ構造化データである。同じClient-facing Worldspace内の同じ有効な`(scope, name)`は同じInterfaceを表す。
Interface参照は、`scope`と`name`を別fieldとして持つ構造化データである。`scope`はWorldspace上の絶対path、`name`はそのscope内のlocal nameを表す。同じClient-facing Worldspace内では、同じ有効な`(scope, name)`が同じInterfaceを表す。
```text
{ scope: "/github", name: "issue.read" }
{ scope: "/gitlab", name: "issue.read" }
```
この二つは同じlocal nameを持つが、異なるInterface参照である。Local nameの`.`等に階層やOperationとの区切りの意味を持たせない。同じscope内の異なるInterfaceへ同じnameを割り当てない。複数Providerを同じscopeへ登録する場合も、Hostが名前の衝突を検出・解消する。
この二つの参照はlocal nameが同じでも、scopeが異なるため別のInterface参照となる。Local nameの`.`等には、階層やOperationとの区切りの意味を持たせない。同じscope内の異なるInterfaceに同じnameを割り当てない。複数Providerを同じscopeへ登録する場合にも、Hostが名前の衝突を検出・解消する。
ScopeはClientに対してHostが公開するWorldspaceのrootを基準とする。Backendのpath、filesystem root、HTTP endpointのprefixではなく、相対pathは認めない。異なるWorldspace間で同じ`(scope, name)`を同一Interfaceとして扱わない。
Scopeの基準は、HostがClientへ公開するWorldspaceのrootである。Backendのpath、filesystem root、HTTP endpointのprefixを基準にはせず、相対pathも認めない。異なるWorldspaceにある同じ`(scope, name)`を、同一Interfaceとして扱わない。
Objectが利用できるscopeは、そのObjectの配置pathとの[祖先関係](2.1-object-tree-schema.md#interface-scope)に従う。この制約はInterfaceの自動継承ではない。Objectは使用するInterfaceを明示的に公開し、scopeだけを根拠にOperationを追加したり、実行を認可したりしない。
Objectが利用できるscopeは、そのObjectの配置pathとの[祖先関係](2.1-object-tree-schema.md#interface-scope)に従う。ただし、祖先関係だけでInterfaceを自動継承するわけではない。使用するInterfaceはObjectで明示的に公開し、scopeだけを根拠にOperationを追加したり、実行を認可したりしない。
構造とvalidationは[3. Protocol](3-protocol.md#interface-reference)、`/github::issue.read#read`等の人間・AI向け短縮表記は[4.2. Text View](4.2-text-view.md#参照表記)で定義する。Interface参照とOperation名を連結した表示文字列をProtocolの参照fieldへ格納しない。
Protocolの参照fieldへは、Interface参照とOperation名を連結した表示文字列を格納しない。構造とvalidationは[3. Protocol](3-protocol.md#interface-reference)に従う。`/github::issue.read#read`等の人間・AI向け短縮表記は[4.2. Text View](4.2-text-view.md#参照表記)で定義する。
Hostによるproxy・Worldspace合成では、Hostがscopeを公開先の配置へ変換する。Path、typed `entry`、identity、validatorとの一貫性は[Worldspace composition](3-protocol.md#worldspace-composition)に従う。
HostがproxyやWorldspace合成を行う場合は、scopeを公開先の配置へ変換する。その際のpath、typed `entry`、identity、validatorとの一貫性は[Worldspace composition](3-protocol.md#worldspace-composition)に従う。
## Scope Objectと有効期間
Scopeは、そのpathにあるObject(scope Object)に紐づく。Object自身のpathをscopeにするself-scopeを許可し、root Objectもscope `/`を利用できる。Scope Object自身がそのscopeの全Interfaceを`interfaces`へ公開する必要はない。
Scopeは、そのpathにあるObject(scope Object)に紐づく。Object自身のpathをscopeにするself-scopeも許可し、root Objectはscope `/`を利用できる。Scope Object自身の`interfaces`に、そのscopeの全Interfaceを公開する必要はない。
Interfaceの識別は`(scope, name)`のままであり、scope Objectの`ref`はその識別子の第三成分ではない。`ref`がある場合は観測したObjectとの紐付きを確認するために用いる。Objectの状態を確認するvalidatorや、Descriptorの版を確認するInterface validatorとは役割が異なる。Scope Objectの通常の状態更新だけを理由に、scopeの紐付きを無効にしない。
Scope Objectの`ref`がある場合は、観測したObjectとの紐付きを確認するために用いる。Interfaceの識別子はあくまで`(scope, name)`であり、`ref`を第三成分にはしない。
Scope Objectがそのpathから削除・移動・差し替えられると、旧Objectに紐づくInterface参照の有効期間は終了する。同じpathへ新しいObjectとInterfaceを公開することは許可するが、旧Objectの登録を暗黙に引き継がない。移動先では新しいscopeによる別の参照となり、同じ`ref`を観測してもClientにInterface参照の移動追跡やcacheの付け替えを要求しない。
この`ref`は、Objectの状態を確認するvalidatorとも、Descriptorの版を確認するInterface validatorとも役割が異なる。Scope Objectの通常の状態更新だけを理由に、scopeの紐付きを無効にしない。
Scope Objectの`ref`はoptionalである。`ref`のないObjectが同じpathで差し替えられても、そのidentityを追跡できないことは仕様上許容される。これを不正なHostとしたり、差し替えの検出を必須にしたりしない。ただし、現在のObjectへのInterface membership、scopeの適合、指定されたvalidator、authorizationは引き続き検証する。存続中の同じInterfaceについて、`ref`がないことを理由にDescriptorのimmutable / validator規則を弱めない。
一方、scope Objectがそのpathから削除・移動・差し替えられると、旧Objectに紐づくInterface参照の有効期間は終了する。同じpathへ新しいObjectとInterfaceを公開することは許可するが、旧Objectの登録を暗黙には引き継がない。移動先では新しいscopeによる別の参照となる。同じ`ref`を観測しても、ClientにInterface参照の移動追跡やcacheの付け替えを要求しない。
Clientはscope Objectがそのpathから消えたことを確認した場合、そのscopeのInterface cacheを破棄できる。Client-localなcache evictionやindexable edgeの消失だけをObject削除の証拠にしない。実行中callは固定済みの観測を使用し、結果検証が終わるまで必要なDescriptorを保持する。削除通知やClientによる常時監視は要求しない。
Scope Objectの`ref`はoptionalである。`ref`のないObjectが同じpathで差し替えられた場合、そのidentityを追跡できないことは仕様上許容される。そのHostを不正とみなしたり、差し替えの検出を必須にしたりしない。
ただし、`ref`の有無にかかわらず、現在のObjectへのInterface membership、scopeの適合、指定されたvalidator、authorizationは検証する。存続中の同じInterfaceでは、`ref`がないことを理由にDescriptorのimmutable / validator規則を弱めない。
Clientは、scope Objectがそのpathから消えたと確認した場合、そのscopeのInterface cacheを破棄できる。Client-localなcache evictionやindexable edgeの消失だけを、Object削除の証拠にはしない。実行中callでは固定済みの観測を使い、結果検証が終わるまで必要なDescriptorを保持する。削除通知やClientによる常時監視は要求しない。
具体的な紐付きの観測とcall preconditionは[Protocol](3-protocol.md#scope-objectの紐付き)に従う。
## Interface Descriptor
一つのInterface Descriptorは一つのInterfaceを定義し、少なくとも次を保持する。
一つのInterface Descriptorは一つのInterfaceを定義し、少なくとも次の情報を保持する。
- Format version
- Interface documentation
@@ -56,15 +60,15 @@ Clientはscope Objectがそのpathから消えたことを確認した場合、
- Operationごとのparameterとreturn type
- Type、field、parameter、case等のdocumentation
Descriptorのlogical structは[3. Protocol](3-protocol.md)で定義する。Code-firstな生成は本章、人間とAIへのInterface signatureは[4.2. Text View](4.2-text-view.md)で扱う。
Descriptorのlogical structは[3. Protocol](3-protocol.md)で定義する。実装コードの宣言から生成するcode-firstの形をとり、人間とAIへのInterface signatureは[4.2. Text View](4.2-text-view.md)に従う。
Clientは取得したDescriptorを構造検証および意味検証してからcacheする。Named typeの参照解決、Operation callのvalidation、表示生成には検証済みのInterfaceだけを使用する。
Clientは、取得したDescriptorの構造と意味を検証してからcacheする。Named typeの参照解決、Operation callのvalidation、表示生成に使うのは、検証済みのInterfaceだけである。
## Operation declaration
Operationは、名前付きparameter、return type、documentationを持つ。
Operationには、名前付きparameter、return type、documentationを宣言する。
人間とAIへ提示する場合は、Interface DescriptorからIDL風のInterface signatureを生成できる。以下はOperation部分の表示例である。
人間とAIへ提示するときは、Interface DescriptorからIDL風のInterface signatureを生成できる。Operation部分は、例えば次のように表示する。
```text
/// "Returns items related to this Object."
@@ -77,61 +81,61 @@ operation get_related_items(
};
```
Interface signatureはInterfaceの交換形式や入力言語ではなく、検証済みDescriptorから生成する表示である。Object signatureとInterface signatureの表記は[4.2. Text View](4.2-text-view.md)で定義する。
このInterface signatureは、検証済みDescriptorから生成する表示であり、Interfaceの交換形式や入力言語ではない。Object signatureとInterface signatureの表記は[4.2. Text View](4.2-text-view.md)で定義する。
Parameterは常に名前付きとし、位置引数は用いない。引数を持たないOperationは空のparameter listとして表し、`call_operation`には空のrecordを渡す。
Parameterは常に名前付きとし、位置引数は用いない。引数を持たないOperationは空のparameter listで表し、`call_operation`には空のrecordを渡す。
```wip
operation refresh() -> unit;
```
Return typeにはDescriptorで定義される任意のvalue typeを使用できる。Evolution compatibilityが必要なOperationでは、fieldを追加できるrecordをreturn typeの基本とする。
Return typeには、Descriptorで定義される任意のvalue typeを使用できる。Evolution compatibilityが必要なOperationでは、fieldを追加できるrecordをreturn typeの基本とする。
Operationの用途は短いdocumentationで説明する。長文documentationや大量のApplication dataをInterface Descriptorへ埋め込まない。
Operationの用途は短いdocumentationで説明し、長文documentationや大量のApplication dataをInterface Descriptorへ埋め込まない。
Operation名は一つのInterface Descriptor内で一意とする。異なるInterface間では同じOperation名を使用でき、`call_operation`は構造化Interface参照とOperation名の組で解決する。表示用のqualified表記は[Text Viewの参照表記](4.2-text-view.md#参照表記)に従い、Protocolでは参照とOperation名を別fieldとして扱う。
Operation名は、一つのInterface Descriptor内で一意とする。異なるInterface間では同じOperation名を使用できる。`call_operation`は構造化Interface参照とOperation名の組で解決し、Protocolでは両者を別fieldとして扱う。表示用のqualified表記は[Text Viewの参照表記](4.2-text-view.md#参照表記)に従う。
## `fetch_interface`
`fetch_interface(interface)`は、Interface参照に対応する現在のInterface Descriptor、optionalなscope Objectの`ref`(`scope_ref`)、optionalなInterface validatorを一つの観測として取得する。
`fetch_interface(interface)`は、Interface参照に対応する現在のInterface Descriptorを取得する。同時に、optionalなscope Objectの`ref`(`scope_ref`)とoptionalなInterface validatorを、一つの観測として取得する。
```text
fetch_interface(interface) -> Interface Descriptor, scope_ref?, validator?
```
ObjectはInterface参照のordered setだけを持ち、Descriptorを先行同梱しない。ClientはInterface cacheと各参照を比較し、未知のDescriptorを取得する。Interface validator mismatch等で更新が必要になった参照は再取得する。Hostは主体へ公開したObjectの各Interface参照について、現在のDescriptorをその主体から取得可能にしなければならない。
Objectが持つのはInterface参照のordered setだけであり、Descriptorは先行同梱しない。Clientは各参照をInterface cacheと比較して未知のDescriptorを取得し、Interface validator mismatch等で更新が必要になった参照を再取得する。Hostは、主体へ公開したObjectの各Interface参照について、現在のDescriptorをその主体から取得可能にしなければならない。
同じ有効期間内のInterface参照とvalidatorの組は同じDescriptorを表す。Validatorを返さないInterface参照は、その参照の有効期間中immutableでなければならない。`scope_ref`はこの観測の紐付きmetadataとして保持し、参照の識別子へ組み込まない。
同じ有効期間内では、同じInterface参照とvalidatorの組は同じDescriptorを表す。Validatorを返さないInterface参照は、その有効期間中immutableでなければならない。`scope_ref`は、観測の紐付きmetadataとして保持し、参照の識別子へは組み込まない。
HostはClientのcache状態を推測して、要求されていないDescriptorをObject responseへ追加しない。複数のDescriptorが必要なClientは、それぞれの`fetch_interface`を個別に並行実行できる。
HostはClientのcache状態を推測し、要求されていないDescriptorをObject responseへ追加しない。複数のDescriptorが必要なら、Clientはそれぞれの`fetch_interface`を個別に並行実行できる。
## Operationの可視性
Hostは、主体の権限やrole / capabilityに基づいて、その主体へ公開するInterface参照の集合を決定してよい。同じObjectでも、主体ごとに異なるInterface集合を返してよい。
Hostは、主体の権限やrole / capabilityに基づいて、その主体へ公開するInterface参照の集合を決定してよい。同じObjectに対しても、主体ごとに異なるInterface集合を返してよい。
Operationを主体に認識させない場合、Hostは次のいずれかを選べる。
Operationの存在を主体に認識させない場合には、次のいずれかを選べる。
- そのOperationをcapabilityとしてまとめたInterface参照をObjectの集合から除外する。
- そのOperationを宣言しない別のInterface Descriptorを参照する。
ClientがObjectで公開されていないInterface参照を指定した場合は`InterfaceMismatch`、公開されているInterfaceに宣言されていないOperation名を指定した場合は`OperationNotFound`を返す。
ClientがObjectで公開されていないInterface参照を指定すると、`InterfaceMismatch`を返す。公開されているInterfaceに宣言されていないOperation名を指定すると、`OperationNotFound`を返す。
Operationの存在を公開しつつ実行だけを認めない設計も可能である。この場合はOperationをいずれかのInterfaceに宣言し、`call_operation`時のauthorizationで拒否して`PermissionDenied`を返す。
これとは別に、Operationの存在を公開し、実行だけを認めない設計も可能である。その場合は、OperationをいずれかのInterfaceに宣言したうえで、`call_operation`時のauthorizationで拒否し、`PermissionDenied`を返す。
したがって、Hostは主体に対して次を独立に選択できる。
Hostは、主体に対する公開と実行の条件を次のように独立に選択できる。
- Object自体を公開せず、そのObjectへの`observe`とOperation callを`NotFound`にする。
- Objectを公開するが、特定Interfaceを集合から除外する。
- Objectを公開し、特定Operationを含まないInterfaceを使用する。
- Object、Interface、Operationを公開するが、そのOperationの実行を`PermissionDenied`にする。
Interface集合と各Interface内のOperation可視性は、頻繁に変化する実行可否やdomain stateを表すものではなく、**その主体に対してどのcapabilityを公開するか**というprojectionとして扱う。
Interface集合と各Interface内のOperation可視性は、**その主体に対してどのcapabilityを公開するか**を表すprojectionである。頻繁に変化する実行可否やdomain stateを表すものとしては扱わない。
WIPはOperationの`available` / `disabled`のような揮発的状態をInterface集合へ同期することを前提としない。現在状態を判断する必要がある場合は、必要に応じてdomain固有のOperationで観測する。公開されたOperationについても、最終的なauthorizationと実行条件の判定は`call_operation`時にHostが行う。
WIPは、Operationの`available` / `disabled`のような揮発的状態をInterface集合へ同期することを前提としない。現在状態の判断が必要なら、必要に応じてdomain固有のOperationで観測する。公開されたOperationでも、最終的なauthorizationと実行条件は、`call_operation`時にHostが判定する。
## `call_operation`
`call_operation`は、指定pathにあるObjectに対して、Interfaceに宣言されたOperationを実行する。
`call_operation`は、指定pathにあるObjectに対し、Interfaceに宣言されたOperationを実行する。
```text
call_operation(target, interface, operation, arguments) -> result, validator?
@@ -147,7 +151,7 @@ call_operation(target, interface, operation, arguments) -> result, validator?
- `result`はOperationのreturn typeに従うvalue。
- Responseの`validator`はOperation実行後のObject状態に対してHostが発行したoptionalな値。
HostはOperationを実行する前に、次を検証する。
Hostは、Operationを実行する前に次の条件を検証する。
1. `target.path`が存在する。
2. `target.validator`が指定されている場合、現在のObject validatorと一致する。
@@ -157,26 +161,28 @@ HostはOperationを実行する前に、次を検証する。
6. Argumentsがparameter declarationに従っている。
7. ClientがOperationを実行できる。
対象Objectが現在のClient-facing Worldspaceへ公開されていない場合は`not_found`、指定Interfaceが対象Objectの現在の`interfaces`に含まれない場合や、指定された`scope_ref`の紐付きを確認できない場合は`interface_mismatch`、Operationが指定Interfaceに宣言されていない場合は`operation_not_found`、宣言されたOperationの実行が認められない場合は`permission_denied`を返す。`scope_ref`を持たない観測とcallも許可し、その省略だけでは拒否しない。
対象Objectが現在のClient-facing Worldspaceへ公開されていなければ、`not_found`を返す。指定InterfaceがObjectの現在の`interfaces`に含まれない場合、または指定された`scope_ref`の紐付きを確認できない場合は、`interface_mismatch`を返す。指定InterfaceにOperationが宣言されていなければ`operation_not_found`、宣言されたOperationの実行が認められなければ`permission_denied`を返す。`scope_ref`を持たない観測とcallも許可し、省略したことだけを理由には拒否しない。
Object validator、Interface membership、scope Objectの紐付きと指定された`scope_ref`、Interface validator、Descriptor、Operation implementation、backend対象の確認と固定は、Operation実行に対して一貫したpreconditionとして扱う。Object validatorが一致しない場合は`validator_mismatch`、要求されるObject validatorがない場合は`validator_required`を返す。Mutable Interfaceのvalidatorがない場合は`interface_validator_required`、一致しない場合は`interface_validator_mismatch`を返す。いずれの場合もHostはOperationを実行しない。
Object validator、Interface membership、scope Objectの紐付きと指定された`scope_ref`、Interface validator、Descriptor、Operation implementation、backend対象の確認と固定は、Operation実行に対して一貫したpreconditionとして扱う。
Argumentsに未知のfieldがある場合、必須parameterがない場合、またはvalueが宣言型に一致しない場合、HostはOperationを実行せず`invalid_arguments`を返す。
Object validatorが一致しない場合は`validator_mismatch`を、要求されるObject validatorがない場合は`validator_required`を返す。Mutable Interfaceのvalidatorがない場合は`interface_validator_required`を、一致しない場合は`interface_validator_mismatch`を返す。いずれの場合も、HostはOperationを実行しない。
ClientはHostから受け取ったsuccess responseのresultをreturn typeに従って検証する。Hostが宣言と異なるresultを返した場合はHostが返したProtocol failureではなく`InvalidResponse`として扱い、そのvalueをApplicationへ渡さない。Host Runtimeがinvalidなimplementation resultを送信前に検出した場合は、effectがcommitされていないと保証できるときだけ`Internal`を返し、保証できない場合は`OperationOutcomeUnknown`を返す。
Argumentsに未知のfieldがある場合、必須parameterがない場合、valueが宣言型に一致しない場合にも、HostはOperationを実行せず、`invalid_arguments`を返す。
Clientは、Hostから受け取ったsuccess responseのresultをreturn typeに従って検証する。宣言と異なるresultが返された場合は、Hostが返したProtocol failureではなく`InvalidResponse`として扱い、そのvalueをApplicationへ渡さない。
Host Runtimeが送信前にinvalidなimplementation resultを検出した場合は、effectがcommitされていないと保証できるときだけ`Internal`を返す。保証できない場合は`OperationOutcomeUnknown`を返す。
## Application data
Operation argumentsとresultは、Applicationが定義し、利用するdataである。
WIPは次を規定する。
Operation argumentsとresultは、Applicationが定義して利用するdataである。WIPが規定する内容は次のとおりである。
- Descriptor上の型表現
- Transport上のencoding
- ClientとHostのboundary validation
- `entry`等のWIP固有型の意味
WIPは次を規定しない。
一方、次の内容はWIPでは規定しない。
- Dataのdomain上の意味
- 永続化方法
@@ -184,19 +190,19 @@ WIPは次を規定しない。
- Business rule
- Clientが取得したdataを利用する方法
Wire schema上正しいことと、domain上有効であることは別である。例えばargumentsが型に従っていても、現在のdomain stateが操作を許可しない場合、Operation implementationはdomain failureを返し得る。
例えば、argumentsが型に従っていても、現在のdomain stateが操作を許可しない場合には、Operation implementationはdomain failureを返し得る。Wire schema上の正しさと、domain上の有効性は別の条件である。
## Operation Resultとエントリの発見
Operation Resultには、Descriptorの`entry`型として新しいエントリのpathが含まれ得る。
Operation Resultには、Descriptorの`entry`型として、新しいエントリのpathが含まれ得る。`entry`は、同じWorldspace内のcanonical absolute pathである。
`entry`は同じWorldspace内のcanonical absolute pathである。Clientはreturn typeに従って`entry`型の位置を認識する。通常の`string`やopaqueな`json`に含まれるpathらしい文字列を、エントリとして推測してはならない。
Clientは、return typeに従って`entry`型の位置を認識する。通常の`string`やopaqueな`json`に含まれるpathらしい文字列を、エントリとして推測してはならない。
Clientは発見したpathを参照として利用でき、Objectの公開情報が必要になったときに、必要な深さで`observe`する。発見したすべてのpathの即時取得は要求しない。Operation ResultへObject公開情報やInterface Descriptorを先行同梱しない。
発見したpathは参照として利用できる。Clientは、Objectの公開情報が必要になったときに、必要な深さで`observe`する。すべてのpathの即時取得は要求せず、Operation ResultへObject公開情報やInterface Descriptorを先行同梱しない。
Operationの実行対象と、結果として発見されたエントリのTree上の位置は独立している。発見されたエントリは実行対象の子である必要はなく、親、兄弟、またはWorldspace内の任意の位置にあってよい。
発見されたエントリは、実行対象の子である必要はない。親、兄弟、Worldspace内の任意の位置にあってよい。Operationの実行対象と、結果として発見されたエントリのTree上の位置は独立している。
Operationがpathを返したこと自体から、実行対象との間に親子関係や意味的関係を推論しない。親子関係はTree上の配置で表し、非内包の意味的関係はOperation名、result field名、またはApplication固有のrelation型で表現する。
また、pathが返されたこと自体から、実行対象との親子関係や意味的関係を推論しない。親子関係はTree上の配置で表し、非内包の意味的関係はOperation名、result field名、Application固有のrelation型で表現する。
## Protocol failureとdomain failure
@@ -217,9 +223,9 @@ Protocol failureは、WIPのrequest、対象、Interface、validation、validato
- `internal`
- `operation_outcome_unknown`
`InvalidResponse`はClientが受信したsuccess responseまたはerror responseのProtocol違反を表すlocal classificationであり、Hostが返すProtocol failureではない。`UnsupportedDescriptorFormat`もClient-localであり、validだが未対応のDescriptorをProtocol違反として扱わない。
これに対し、`InvalidResponse`は、Clientが受信したsuccess responseまたはerror responseのProtocol違反を表すlocal classificationである。Hostが返すProtocol failureには含めない。`UnsupportedDescriptorFormat`もClient-localであり、validだが未対応のDescriptorをProtocol違反としては扱わない。
`call_operation`が`operation_outcome_unknown`以外のProtocol failureを返した場合、HostはOperationのeffectがcommitされていないことを保証する。`operation_outcome_unknown`またはresponse不達の場合、ClientはOperationを自動再実行せず、対象を再観測するかdomain固有の照会手段を利用する。
`call_operation`が`operation_outcome_unknown`以外のProtocol failureを返した場合、HostはOperationのeffectがcommitされていないことを保証する。`operation_outcome_unknown`またはresponse不達の場合、ClientはOperationを自動再実行しない。対象を再観測するか、domain固有の照会手段を利用する。
Domain failureは、型として正しいOperationをApplicationが実行した結果として生じる失敗である。
@@ -227,4 +233,4 @@ Domain failureは、型として正しいOperationをApplicationが実行した
- `payment_declined`
- `merge_conflict`
Domain failureをProtocol failureへ混在させない。現在のProtocolでは、Domain failureをOperation return typeのUnion caseとして宣言する。専用のfailure declarationは定義しない。
これらのDomain failureをProtocol failureへ混在させない。現在のProtocolでは、Operation return typeのUnion caseとして宣言し、専用のfailure declarationは定義しない。
+143 -119
View File
@@ -1,19 +1,19 @@
# 3. Protocol
WIP Protocolは、ClientとHostの間で交換するlogical data modelと、Core interactionのrequest / responseを定義する。
WIP Protocolは、ClientとHostが交換するlogical data modelと、Core interactionのrequest / responseを定義する。
この章のstructはRust風の記法を使用するが、Rust固有のmemory layoutやserialization libraryを要求しない。TypeScriptを含む他言語でも同じ型、必須性、validation semanticsを実装できなければならない。
Structの記法はRust風だが、Rust固有のmemory layoutやserialization libraryは要求しない。TypeScriptを含む他言語でも、同じ型、必須性、validation semanticsを実装できなければならない。
HTTP endpoint、JSON fieldへのencoding、status codeはTransport Bindingの責務とし、共通要件を[5. Transport Bindings](5-transports.md)、標準bindingを[5.1. WIP over HTTP](5.1-wip-over-http.md)で扱う。
HTTP endpoint、JSON fieldへのencoding、status codeはTransport Bindingの責務である。共通要件は[5. Transport Bindings](5-transports.md)、標準bindingの定義は[5.1. WIP over HTTP](5.1-wip-over-http.md)にある。
## Protocol dataの分類
WIPがfirst-classなprotocol dataとして定義し、Clientが取得およびcacheするものは次の二つである。
Clientが取得してcacheするfirst-classなprotocol dataは、次の二つである。
- `Object`
- `InterfaceDescriptor`
Operationのargumentsとresultには、Interface Descriptorで宣言された`Value`を使用する。Application dataは独立したWIP resourceではなく、Operation callの入力または出力として交換される。
一方、Operationのargumentsとresultには、Interface Descriptorで宣言された`Value`を使用する。Application dataは独立したWIP resourceにはせず、Operation callの入力または出力として交換する。
```text
Protocol data
@@ -25,11 +25,11 @@ Operation value
`-- result
```
Path、Object参照、Interface参照、validator、error等の意味は、それらが現れるfieldまたはenvelopeによって決まる。Protocol上のnamed scalarとしては定義しない。
Path、Object参照、Interface参照、validator、error等は、現れるfieldやenvelopeに応じて意味が決まる。Protocol上のnamed scalarとしては定義しない。
## 記法
この章では次の記法を使用する。
Logical structの型とfieldは、次の記法で表す。
```rust
struct T { ... } // 名前付きfieldを持つrecord
@@ -39,13 +39,13 @@ Vec<T> // 順序付きlist
BTreeMap<String, T> // string keyを持つlogical map
```
`Option<T>`はfieldの省略を表し、`null`を表さない。Transport Bindingは、省略されたfieldをwire valueへ出力してはならない。
`Option<T>`はfieldの省略を表し、`null`を表すものではない。Transport Bindingは、省略されたfieldをwire valueへ出力してはならない。
`BTreeMap`はstring-keyed mapをRust風に示すための記法であり、keyのiteration orderをProtocol semanticsには含めない。
`BTreeMap`はstring-keyed mapをRust風に示す記法にすぎない。Keyのiteration orderはProtocol semanticsに含めない。
## Protocol primitives
Protocol structは、次のprimitiveおよびcompositeだけで表す。
Protocol structを表すprimitiveとcompositeは、次のものだけに限定する。
```text
unit
@@ -58,9 +58,9 @@ list
record
```
Path、Interface参照、Object identity、validator、Operation名等を独立したProtocol scalarにはしない。同じprimitiveを使用するfieldでも意味は交換可能ではなく、各fieldの定義とvalidation ruleに従って解釈する。
Path、Interface参照、Object identity、validator、Operation名等を独立したProtocol scalarにはしない。ただし、同じprimitiveを使うfieldでも、その意味を交換可能とはしない。各fieldの定義とvalidation ruleに従って解釈する。
Rust SDKは利便性や安全性のために`Path`等のnewtypeを公開してよく、TypeScript SDKはbrand等を利用してよい。それらは言語別SDKのAPIであり、Protocol structの一部ではない。
Rust SDKは、利便性や安全性のために`Path`等のnewtypeを公開してよい。TypeScript SDKもbrand等を利用してよい。これらは言語別SDKのAPIであり、Protocol structの一部ではない。
## Path
@@ -75,11 +75,11 @@ Pathとして宣言されたfieldのvalueは、同じWorldspace内のObjectを
- Segmentの比較はUnicode code point sequenceの完全一致で行う。
- Navigationに使用できるが、恒久的なObject identityとして使用しない。
Nameに`/`を許可しないため、Protocolはpath segment escapeを定義しない。Transport BindingによるURL encodingはWIP Pathの構成とは別に扱う。
Nameに`/`を許可しないため、Protocolはpath segment escapeを定義しない。Transport Bindingが行うURL encodingは、WIP Pathの構成とは別に扱う。
## Interface Reference
Interface参照は、scopeとlocal nameからなるrecordとして表す。新しいfirst-class resourceやnamed scalarではなく、Objectやinteractionが使用する参照のstructである。
Interface参照は、scopeとlocal nameを持つrecordである。Objectやinteractionで使う参照のstructであり、新しいfirst-class resourceやnamed scalarではない。
```rust
struct InterfaceReference {
@@ -94,15 +94,15 @@ struct InterfaceReference {
- `Object.interfaces`の重複判定、membership、request / responseの参照一致、Interface cacheのkeyにはこの組を使う。Object member順や短縮表記の引用・escapeの違いは参照の同一性へ影響しない。
- Interface Descriptorはscopeやnameを自身のfieldとして持たない。同じ構造のDescriptorであることから参照の同一性を推測しない。
`Object.interfaces`の各要素、`FetchInterfaceRequest.interface`、`FetchInterfaceResponse.interface`、`InterfaceTarget.reference`はすべてこのstructを使用する。Opaque stringや`scope::name`という連結stringを代替として受理しない。Operation名は`CallOperationRequest.operation`に独立して保持する。
このstructは、`Object.interfaces`の各要素、`FetchInterfaceRequest.interface`、`FetchInterfaceResponse.interface`、`InterfaceTarget.reference`で共通して使用する。Opaque stringや`scope::name`を連結したstringを代わりに受理しない。Operation名は、別fieldの`CallOperationRequest.operation`に保持する。
人間・AI向けの短縮表記は[4.2. Text View](4.2-text-view.md#参照表記)に従う。Scope省略形を入力として受けるadapterも、明示されたcontextから絶対scopeを確定してからProtocol requestを構築する。
不正な参照shape、relative scope、空name等はCore request validationで`InvalidRequest`とする。Responseに不正な参照がある場合はClient-localな`InvalidResponse`とする。Validな参照に対応するInterfaceが主体へ公開されているか、対象Objectで使えるかはinteractionごとに検証する。
参照shapeの不正、relative scope、空name等は、Core request validationで`InvalidRequest`とする。Responseに不正な参照があれば、Client-localな`InvalidResponse`として扱う。参照自体がvalidであることと、そのInterfaceが主体へ公開されていること、対象Objectで使えることは別の条件であり、後者はinteractionごとに検証する。
## Documentation
Interface、Operation、type、field、parameter、caseに付与するdocumentationを次のlogical structで表す。
`Documentation`は、Interface、Operation、type、field、parameter、caseへ付与する説明のlogical structである。
```rust
struct Documentation {
@@ -111,13 +111,13 @@ struct Documentation {
}
```
`summary`は一覧やInterface signatureへ短く表示する説明、`details`は明示的に展開したときに使用する説明である。
`summary`は一覧やInterface signatureに短く表示する説明である。`details`は、説明を明示的に展開したときに使用する。
DocumentationはHostが提供するplain text dataであり、Clientのsystem instructionとして信頼しない。Transport BindingおよびClientはresource limitを適用できる。Markup、localization、構造化exampleは現在のProtocolに含めない。
これらはHostが提供するplain text dataであり、Clientのsystem instructionとして信頼しない。Transport BindingとClientはresource limitを適用できる。Markup、localization、構造化exampleは、現在のProtocolには含めない。
## Object
`Object`は、一つのpathで現在公開されているprotocol-level projectionを表す。
`Object`は、一つのpathで現在公開されているprotocol-level projectionである。
```rust
struct Object {
@@ -131,17 +131,17 @@ struct Object {
### `name`
親Objectの下でObjectを識別するpath segment。Root Objectの`name`は空文字列とし、非root Objectの`name`は空であってはならない。Nameに`/`を含めてはならず、Name全体が`.`または`..`であってはならない。
`name`は、親Objectの下でObjectを識別するpath segmentである。Root Objectでは空文字列とし、非root Objectでは空であってはならない。Nameに`/`を含めてはならず、Name全体が`.`または`..`であってはならない。
NameはUnicode stringとして扱い、Unicode normalizationを行わない。同じ親のchildrenは、Unicode code point sequenceの完全一致で互いに異なる`name`を持たなければならない。
### `description`
Objectが何を表すかを説明する短い公開情報。Objectの本文やApplication data全体を格納するfieldではない。
`description`は、Objectが何を表すかを説明する短い公開情報である。Objectの本文やApplication data全体を格納するfieldではない。
### `interfaces`
Objectで利用できるOperationを定義するInterface Descriptorへの参照を、Hostの立項順で保持するordered set。
`interfaces`は、Objectで利用できるOperationを定義するInterface Descriptorへの参照を保持するordered setである。順序はHostの立項順とする。
- 集合は空でもよい。
- 同じInterface参照を重複して含めてはならない。Clientは重複を含むObject responseをHostから返されたProtocol failureではなく`InvalidResponse`として扱う。
@@ -149,13 +149,13 @@ Objectで利用できるOperationを定義するInterface Descriptorへの参照
- Clientは列挙順をInterfaceおよびOperationのUI表示順として使用してよい。
- Operation callは集合から一つのInterface参照を明示する。
異なるInterfaceでは同じOperation名を宣言できる。Protocolでは構造化参照とOperation名を別fieldとして扱い、表示用の短縮表記は[4.2. Text View](4.2-text-view.md#参照表記)に従う。
異なるInterfaceでは、同じOperation名を宣言できる。Protocol上は構造化参照とOperation名を別fieldで扱い、表示用の短縮表記は[4.2. Text View](4.2-text-view.md#参照表記)に従う。
Hostはvalidatorを発行することで、同じInterface参照のDescriptorを時間とともに変更できる。Validatorを発行しない参照のDescriptorは、その参照が有効な間は変更しない。Clientは`fetch_interface`でDescriptorとvalidatorを一つの観測として取得する。
同じInterface参照のDescriptorを時間とともに変更するHostは、validatorを発行する。Validatorを発行しない参照のDescriptorは、その参照が有効な間は変更しない。Clientは`fetch_interface`でDescriptorとvalidatorを一つの観測として取得する。
### `ref`
同じ主体に公開された一つのWorldspace内で、複数の観測またはエントリが同じObjectを表すことを示すoptionalなopaque string。
`ref`はoptionalなopaque stringであり、同じ主体に公開された一つのWorldspace内で、複数の観測やエントリが同じObjectを表すことを示す。
- 同じ有効な`ref`は同じObjectを表す。
- Hostは同じ有効な`ref`を異なるObjectへ付与してはならない。
@@ -164,19 +164,19 @@ Hostはvalidatorを発行することで、同じInterface参照のDescriptorを
- Session、再接続、Host restart、Worldspace再構築をまたぐ永続性を要求しない。
- Navigationには使用せず、`ref`からObjectを取得するinteractionは提供しない。
Backendに適切なUIDがある場合、Hostはそれを直接または変換して使用できるが、Protocolはbackend UIDの存在または公開を要求しない。
Backendに適切なUIDがある場合、Hostは直接、または変換して`ref`に使用できる。ただし、Protocolはbackend UIDの存在も公開も要求しない。
### `validator`
HostがそのObjectの現在状態へ付与するoptionalなopaque bytes。Clientは内容を解釈せず、観測に基づくOperationを条件付きで実行するときに、pathとともに`target.validator`へコピーする。
`validator`は、HostがObjectの現在状態に付与するoptionalなopaque bytesである。Clientは内容を解釈しない。観測に基づくOperationを条件付きで実行する場合は、pathとともに`target.validator`へコピーする。
Hostはvalidatorの生成方法を自由に選べる。Generation、content hash、database revision等を使用してよい。ValidatorはObject identityとHostが保護する現在状態の両方へ結び付け、target pathが別Objectを指す場合は、内容が同じでも一致させてはならない。Content hashを使用する場合はObject identityをhashへ含めるか、Hostがidentityを別途検証する。
生成方法はHostが自由に選べる。Generation、content hash、database revision等を使用してよい。ただし、validatorはObject identityとHostが保護する現在状態の両方に結び付ける。Target pathが別Objectを指す場合は、内容が同じでも一致させてはならない。Content hashを使う場合は、Object identityをhashに含めるか、Hostがidentityを別途検証する。
Hostは、どの状態変化によってObject validatorを無効にするかについて、そのObjectに対して一貫した方針を適用する。Object validatorはpathに固有ではなく、同じ`ref`を持つObjectの現在状態に付与する。
どの状態変化によってvalidatorを無効にするかは、HostがそのObjectに対して一貫した方針を適用する。Object validatorはpathに固有のものではなく、同じ`ref`を持つObjectの現在状態に付与する。
Object validatorはAIやユーザーへ公開するApplication dataではない。Client runtimeがObject observationとともに保持するprotocol metadataである。
Object validatorは、Client runtimeがObject observationとともに保持するprotocol metadataである。AIやユーザーへ公開するApplication dataではない。
ここでいうObjectの「現在状態」は、Hostがvalidatorによってobservation consistencyを保護する対象を指す。WIP Objectはprotocol-level projectionであり、Application stateを格納する共通containerではない。WIPは状態遷移modelを定義せず、OperationをObject stateに対するread / writeとして分類しない。
Objectの「現在状態」とは、Hostがvalidatorによってobservation consistencyを保護する対象を指す。WIP Objectはprotocol-level projectionであり、Application stateを格納する共通containerではない。WIPは状態遷移modelを定義せず、OperationをObject stateに対するread / writeとして分類しない。
### 同じ`ref`を持つObjectの整合性
@@ -187,15 +187,15 @@ Object validatorはAIやユーザーへ公開するApplication dataではない
- HostはObjectが配置されたpathを理由に、同じ`ref`へ異なる`name`、`description`、`interfaces`を同時に公開してはならない。
- Clientは最後に成功した観測を、その`ref`を持つObjectの現在状態として扱う。
同じObjectを複数のpathへ配置する場合、各配置は同じObjectの`name`を使用する。異なる親を経由することでpathが異なる。
同じObjectを複数のpathへ配置する場合も、各配置には同じObjectの`name`を使用する。Pathの違いは、異なる親を経由することで生じる。
`Object`はchildrenとpathを直接持たない。これらはObject identityに固有とは限らず、Objectを観測したentryのcontextに属するため、request pathと`ObjectObservation`で表す。
`Object`自体はchildrenとpathを直接持たない。これらはObject identityに固有とは限らず、Objectを観測したentryのcontextに属する。そのため、request pathと`ObjectObservation`で表す。
Objectの意味とApplication dataとの境界は[2. Core Model](2-core-model.md)と[2.1. Object tree / Schema](2.1-object-tree-schema.md)で扱う。
Objectの意味とApplication dataとの境界については、[2. Core Model](2-core-model.md)と[2.1. Object tree / Schema](2.1-object-tree-schema.md)に定義がある。
## Interface Descriptor
`InterfaceDescriptor`は、実装コード上のInterface Declarationから生成されるmachine-readable metadataである。
`InterfaceDescriptor`は、実装コード上のInterface Declarationから生成するmachine-readable metadataである。
```rust
struct InterfaceDescriptor {
@@ -206,9 +206,9 @@ struct InterfaceDescriptor {
}
```
Interface実装者がこのstructのJSON encodingを手書きすることは想定しない。Rust macro、TypeScript definition API、code generator等が生成し、Hostが公開する。
生成にはRust macro、TypeScript definition API、code generator等を用い、Hostが公開する。Interface実装者がこのstructのJSON encodingを手書きすることは想定しない。
`types`と`operations`のdeclaration順は表示時に保持してよいが、名前解決とvalidationの結果には影響しない。
`types`と`operations`のdeclaration順は、表示時に保持してよい。ただし、名前解決やvalidationの結果には影響しない。
### Type declaration
@@ -220,7 +220,7 @@ struct TypeDeclaration {
}
```
一つのDescriptor内でType名は一意でなければならない。
Type名は、一つのDescriptor内で一意でなければならない。
### Type expression
@@ -257,7 +257,7 @@ enum TypeExpr {
}
```
`Named`は同じInterface Descriptor内の`TypeDeclaration`を参照する。External type importとrecursive type referenceは定義しない。Descriptorの意味検証では、存在しないTypeへの参照と参照cycleを拒否する。
`Named`の参照先は、同じInterface Descriptor内の`TypeDeclaration`である。External type importとrecursive type referenceは定義しない。Descriptorの意味検証では、存在しないTypeへの参照と参照cycleを拒否する。
### Record
@@ -270,9 +270,9 @@ struct FieldDeclaration {
}
```
一つのRecord内でfield名は一意でなければならない。`required = false`はfieldの省略を許可するが、`null`を許可する意味ではない。
Field名は、一つのRecord内で一意でなければならない。`required = false`で許可するのはfieldの省略であり、`null`ではない。
Record valueに未宣言fieldが存在する場合はvalidation failureとする。
また、Record valueに未宣言fieldがある場合はvalidation failureとする。
### Enum
@@ -283,7 +283,7 @@ struct EnumCase {
}
```
Enum caseはpayloadを持たない。一つのEnum内でcase名は一意でなければならない。
Enum caseはpayloadを持たない。Case名は、一つのEnum内で一意でなければならない。
### Union
@@ -295,7 +295,7 @@ struct UnionCase {
}
```
Union caseは、caseごとに0個または1個のpayloadを持つ。一つのUnion内でcase名は一意でなければならない。
Union caseのpayloadは、caseごとに0個または1個とする。Case名は、一つのUnion内で一意でなければならない。
### Operation declaration
@@ -320,13 +320,13 @@ struct ReturnDeclaration {
}
```
一つのDescriptor内でOperation名は一意でなければならない。一つのOperation内でparameter名は一意でなければならない。
Operation名は、一つのDescriptor内で一意でなければならない。Parameter名は、一つのOperation内で一意でなければならない。
Interface Descriptorの生成と意味論は[2.2. Operation and Interface](2.2-operation-and-interface.md)、人間とAIへのInterface signatureは[4.2. Text View](4.2-text-view.md)で扱う。
Interface Descriptorの生成と意味論は[2.2. Operation and Interface](2.2-operation-and-interface.md)、人間とAIへのInterface signatureは[4.2. Text View](4.2-text-view.md)に従う。
## Value
Operation argumentsとresultは、schema上の意味を持たない次のlogical valueで表す。
`Value`は、Operation argumentsとresultを表すlogical valueである。Schema上の意味は、この型自体には含めない。
```rust
enum Value {
@@ -341,7 +341,7 @@ enum Value {
}
```
`Value`はHostとClientが交換するprimitiveおよびcompositeだけを表す。Path、enum case、union case等のsemantic variantを持たない。既知のInterfaceに対するgenerated bindingは、言語固有DTOと`Value`のcodecを提供できる。
`Value`が表すのは、HostとClientが交換するprimitiveとcompositeだけである。Path、enum case、union case等のsemantic variantは持たない。既知のInterfaceに対するgenerated bindingは、言語固有DTOと`Value`のcodecを提供できる。
### Primitive semantics
@@ -356,13 +356,13 @@ enum Value {
| `Record` | String keyを持つvalueの集合 | Key順に意味を持たない |
| `List` | 順序付きvalue | — |
`integer`の範囲はRustとTypeScript間でlosslessに相互運用できる範囲へ制限する。
`integer`の範囲は、RustとTypeScriptの間でlosslessに相互運用できる範囲に制限する。
`number`を受信したruntimeは、有限値であることを検証する。
### Descriptorによる解釈
Interface Descriptorの`TypeExpr`は、rawな`Value`に意味と追加validationを与える。
Rawな`Value`の意味と追加validationは、Interface Descriptorの`TypeExpr`によって決まる。
| TypeExpr | 対応するValue | 追加の解釈 |
| --- | --- | --- |
@@ -379,15 +379,15 @@ Interface Descriptorの`TypeExpr`は、rawな`Value`に意味と追加validation
| `Enum` | `Value::String` | 宣言されたcase名として検証する |
| `Union` | `Value::Record` | Discriminatorとpayloadをcase declarationに従って検証する |
`Json`が受け付けるのはJSONのnull、boolean、number、string、array、objectに対応するValueだけであり、`Bytes`は含まない。JSON内の整数と数値にも`Value::Integer`と`Value::Number`と同じ範囲および有限性の制約を適用する。
`Json`が受け付けるのは、JSONのnull、boolean、number、string、array、objectに対応するValueだけである。`Bytes`は含まない。JSON内の整数と数値にも、`Value::Integer`と`Value::Number`と同じ範囲および有限性の制約を適用する。
`Entry`と`String`は同じprimitiveで交換する。ClientはDescriptor上で`Entry`と宣言された位置だけをWorldspace pathとして扱い、通常のStringを内容からEntryへ変換しない。
`Entry`と`String`は、同じprimitiveで交換する。Worldspace pathとして扱うのは、Descriptor上で`Entry`と宣言された位置だけである。Clientは通常のStringを、その内容からEntryへ変換しない。
EnumもString、UnionもRecordとして交換する。SDKまたはruntimeは、Descriptorによるvalidation後の内部表現としてtyped enum、union、Path等を構築してよい。それらはProtocolの送受信形式ではない。
同様に、EnumはString、UnionはRecordとして交換する。SDKやruntimeは、Descriptorによるvalidationを終えた内部表現としてtyped enum、union、Path等を構築してよい。ただし、これらはProtocolの送受信形式ではない。
### Value validation
Valueは、Operation declarationのTypeExprと照合して検証する。
Valueの検証には、Operation declarationのTypeExprを使用する。
- `Named`を参照先Typeへ解決する。
- Required fieldまたはparameterの欠落を拒否する。
@@ -400,17 +400,17 @@ Valueは、Operation declarationのTypeExprと照合して検証する。
## Core request validation
Transport Bindingがframing、media type、authentication等を受理した後、Hostはinteraction固有のObject / Interface解決より前にlogical requestを検証する。
Hostは、Transport Bindingがframing、media type、authentication等を受理した後にlogical requestを検証する。この検証は、interaction固有のObject / Interface解決より前に行う。
1. Request structとして解釈できない、required fieldがない、未知fieldがある、Path等のfield semanticsに違反する場合は`InvalidRequest`。
2. Field長、nesting、collection件数、`observe`のdepth等がHostのboundedな上限を超える場合は`ResourceLimitExceeded`。
3. 検証済みrequestについて、各interaction固有のtarget resolutionとpreconditionを評価する。
`InvalidArguments`は`call_operation` request自体がvalidであり、固定したOperation declarationに対して`arguments`が適合しない場合だけに使用する。Transport route、authentication、media type、framing等のfailureはCore interactionのProtocol failureではない。
`InvalidArguments`を使用するのは、`call_operation` request自体はvalidであり、固定したOperation declarationに`arguments`が適合しない場合だけである。Transport route、authentication、media type、framing等のfailureは、Core interactionのProtocol failureとして扱わない。
## `observe`
一つのpathで現在公開されているObjectと、そのObjectから指定depthまでのindexable childrenを一つの観測として取得する。
`observe`は、一つのpathで現在公開されているObjectと、そこから指定depthまでのindexable childrenを、一つの観測として取得する。
```rust
struct ObserveRequest {
@@ -426,7 +426,7 @@ struct ObjectObservation {
type ObserveResponse = ObjectObservation;
```
起点Objectをdepth `0`とする。`depth = 0`は対象Objectだけを観測する通常の形であり、root nodeの`children`を省略する。
起点Objectのdepthを`0`とする。通常の`depth = 0`では対象Objectだけを観測し、root nodeの`children`を省略する。
- Root nodeのObjectはrequest pathが指すObjectである。Root pathが`/`の場合はObjectの`name`が空文字列でなければならず、非root pathでは最後のsegmentとObjectの`name`が一致しなければならない。
- Request pathのObjectがその主体へ公開されていない場合は`NotFound`を返す。
@@ -437,23 +437,23 @@ type ObserveResponse = ObjectObservation;
- Requested depthより深いnodeをresponseへ含めない。
- その主体へ公開されていないObjectはresponseへ含めず、存在や省略を示すmarkerも返さない。
Success responseはrequested depthまで完全である。Node数によるpartial success、`limit`、`truncated`は定義しない。Hostが完全なresponseをresource budget内で構築できない場合は`ResourceLimitExceeded`を返す。
Success responseは、requested depthまで完全でなければならない。Node数によるpartial success、`limit`、`truncated`は定義しない。Hostがresource budget内で完全なresponseを構築できなければ、`ResourceLimitExceeded`を返す。
各nodeのObjectがvalidatorを持つ場合、Clientはrequest pathとchildrenの`name`から導出したpathに対応付けてcacheし、条件付きOperationの`target`を構築できる。
HostとClientは各nodeの配置pathに対して[Interface scopeの祖先制約](2.1-object-tree-schema.md#interface-scope)を検証する。Self-scopeを含み、root Objectではscope `/`を使用できる。制約に違反する参照を含むObject responseは`InvalidResponse`であり、そのObjectを操作へ使用しない。
HostとClientは、各nodeの配置pathに対して[Interface scopeの祖先制約](2.1-object-tree-schema.md#interface-scope)を検証する。Self-scopeを含み、root Objectではscope `/`を使用できる。制約に違反する参照を含むObject responseは`InvalidResponse`とし、そのObjectを操作に使用しない。
## `fetch_interface`
Interface参照に対応する現在のInterface Descriptorを取得する。
`fetch_interface`は、Interface参照に対応する現在のInterface Descriptorを取得する。
### Interface参照とvalidator
`Object.interfaces`の各要素、`FetchInterfaceRequest.interface`、`FetchInterfaceResponse.interface`、`InterfaceTarget.reference`は`InterfaceReference`である。同じWorldspace context内の同じ有効な`(scope, name)`は同じInterfaceを表すが、Hostはvalidatorを使用してDescriptorを時間とともに変更できる。
`Object.interfaces`の各要素、`FetchInterfaceRequest.interface`、`FetchInterfaceResponse.interface`、`InterfaceTarget.reference`には、いずれも`InterfaceReference`を使用する。同じWorldspace context内の同じ有効な`(scope, name)`は、同じInterfaceを表す。ただし、Hostはvalidatorを使用してDescriptorを時間とともに変更できる。
`FetchInterfaceResponse.validator`は、HostがそのInterface Descriptorの現在状態へ付与するoptionalなopaque bytesである。Clientは内容を解釈せず、観測したDescriptorに基づいてOperationを実行するときに、Interface参照とともに`InterfaceTarget`へコピーする。
`FetchInterfaceResponse.validator`は、HostがInterface Descriptorの現在状態に付与するoptionalなopaque bytesである。Clientは内容を解釈しない。観測したDescriptorに基づいてOperationを実行するときは、Interface参照とともに`InterfaceTarget`へコピーする。
同じ有効期間内のInterface参照とvalidatorには次の規則を適用する。有効期間とscope Objectの紐付きは次節に従う。
Interface参照とvalidatorには、同じ有効期間内で次の規則を適用する。有効期間はscope Objectとの紐付きに依存する。
- 同じInterface参照と同じvalidator valueを持つ観測は、validatorが存在する場合、同じInterface Descriptorを表す。
- 同じInterface参照と異なるvalidatorを持つ観測は、同じInterfaceの異なる状態を表す。
@@ -462,25 +462,33 @@ Interface参照に対応する現在のInterface Descriptorを取得する。
- Validator valueはInterface参照と組み合わせて比較する。異なるInterface参照で同じopaque bytesを使用してもよい。
- Validatorから状態の順序、新旧、Descriptor内容を推測してはならない。
HostはInterface validatorの生成方法を自由に選べる。Generation、content hash、database revision等を使用してよい。Clientは生成方法を解釈せず、Interface参照とvalidator valueの組をOperation executionのpreconditionとして使用する。
生成方法はHostが自由に選べる。Generation、content hash、database revision等を使用してよい。Clientはその方法を解釈せず、Interface参照とvalidator valueの組をOperation executionのpreconditionとして使用する。
Interface validatorはAIやユーザーへ公開するApplication dataではない。Client runtimeがInterface Descriptor observationとともに保持するprotocol metadataである。
Interface validatorは、Client runtimeがInterface Descriptor observationとともに保持するprotocol metadataである。AIやユーザーへ公開するApplication dataではない。
### Scope Objectの紐付き
Interface scopeはそのpathのObjectに紐づく。Scope Objectがそのpathから消えれば、そのObjectに紐づくInterface参照の有効期間は終了し、未公開のInterfaceへの`fetch_interface`は`InterfaceNotFound`となる。削除されたObject自身と消えた配下への`observe` / `call_operation`は`NotFound`となる。同じpathへ別Objectが公開された場合は現在の公開状態で解決する。
Interface scopeは、そのpathのObjectに紐づく。Scope Objectがpathから消えると、そのObjectに紐づくInterface参照の有効期間が終了する。未公開のInterfaceへの`fetch_interface`は`InterfaceNotFound`、削除されたObject自身と消えた配下への`observe` / `call_operation`は`NotFound`となる。同じpathへ別Objectが公開された場合は、現在の公開状態で解決する。
`FetchInterfaceResponse.scope_ref`は、scope Objectが同じ主体へ公開する`Object.ref`である。Hostはその`ref`があれば同じstringを返し、なければfieldを省略する。別のscope専用identityやvalidatorを生成するfieldではない。Scope Objectとの紐付き、Descriptor、Interface validatorは一つの整合した観測として取得し、別々の時点の値を組み合わせない。Clientにscope Objectやその祖先の追加取得を必須にしない。
`FetchInterfaceResponse.scope_ref`は、scope Objectが同じ主体へ公開する`Object.ref`である。Hostはその`ref`があれば同じstringを返し、なければfieldを省略する。別のscope専用identityやvalidatorを生成するfieldではない。
Clientは`scope_ref`をInterface observationとともに保持し、その観測を使うcallの`InterfaceTarget.scope_ref`へ存在する値をコピーする。Hostは指定された`scope_ref`を、現在のscope Objectの`ref`とUnicode code point sequenceの完全一致で比較する。一致しない場合、または現在のObjectが`ref`を持たない場合、その紐付きは確認できず`InterfaceMismatch`とする。異なる`ref`から別Objectだと断定するものではなく、指定された同一性条件を満たせないことを表す。Clientの事前確認だけで済ませず、Hostがcallの他のpreconditionと一貫して確認する。
Scope Objectとの紐付き、Descriptor、Interface validatorは、一つの整合した観測として取得する。別々の時点の値を組み合わせず、Clientにscope Objectやその祖先の追加取得を必須にしない。
`scope_ref`は参照の識別子に含めない。Interfaceの識別とmembershipは引き続き`(scope, name)`であり、通常の表示も変更しない。Scope Objectの状態validatorはこの確認に使わず、通常の状態更新でscopeの紐付きを無効にしない。Descriptorの変更検出には独立したInterface validatorを使う。
Clientは`scope_ref`をInterface observationとともに保持し、その観測を使うcallでは、存在する値を`InterfaceTarget.scope_ref`へコピーする。Hostは指定された`scope_ref`と、現在のscope Objectの`ref`をUnicode code point sequenceの完全一致で比較する。一致しない場合、または現在のObjectが`ref`を持たない場合は、紐付きを確認できないため`InterfaceMismatch`とする。
`scope_ref`が省略されたcallにはscope Objectのidentity preconditionを適用しない。Scope Objectの`ref`はoptionalであり、`ref`なしで同じpathのObjectが差し替わったことをClientが追跡できないのは仕様上許容される。Hostは`ref`がないことやidentityを追跡できないことだけを理由に拒否せず、現在の公開状態と残るpreconditionに従う。Hostにref生成、Clientに疑似refやscope validatorの生成を要求しない。
この不一致は、異なる`ref`から別Objectだと断定するものではない。指定された同一性条件を満たせないことを表す。確認はClientの事前確認だけで済ませず、Hostがcallの他のpreconditionと一貫して行う。
Scopeの削除・移動・差し替えによる有効期間終了を確認したClientは、旧Interface observationを新しいcallへ再利用せず、必要なら現在の参照を再取得する。同じpathへ再公開された参照の観測と、終了した有効期間のcacheは区別する。`scope_ref`の相違や欠落により以前の紐付きを確認できなくなった場合も、旧観測をそのまま付け替えない。異なる有効期間のDescriptorを、同じvalidatorであることだけから同一とみなさない。
`scope_ref`は、Interface参照の識別子には含めない。識別とmembershipには引き続き`(scope, name)`を使用し、通常の表示も変更しない。Scope Objectの状態validatorは紐付きの確認に使わず、通常の状態更新で紐付きを無効にしない。Descriptorの変更検出には、独立したInterface validatorを使う。
`ref`も削除の観測もない場合、有効期間の切り替わりを検出できるとは限らない。Clientは得られた情報で通常のvalidationを行うが、検出不能な差し替えを防ぐ保証はない。この許容は、存続中の同じInterfaceのDescriptor整合性を弱めない。Scopeが別pathへ移動すれば別参照として扱い、Clientは移動を追跡しない。実行開始済みcallが固定した観測と結果検証用Descriptorの保持は、有効期間終了後も維持する。
Callで`scope_ref`が省略された場合は、scope Objectのidentity preconditionを適用しない。Scope Objectの`ref`はoptionalであり、`ref`なしではClientが同じpathのObjectの差し替えを追跡できないことも、仕様上許容される。
Hostは、`ref`がないことやidentityを追跡できないことだけを理由に拒否せず、現在の公開状態と残るpreconditionに従う。Hostにref生成を要求せず、Clientにも疑似refやscope validatorの生成を要求しない。
Clientがscopeの削除・移動・差し替えによる有効期間終了を確認した場合は、旧Interface observationを新しいcallへ再利用しない。必要なら現在の参照を再取得し、同じpathへ再公開された参照の観測と、終了した有効期間のcacheを区別する。`scope_ref`の相違や欠落によって以前の紐付きを確認できなくなった場合も、旧観測をそのまま付け替えない。異なる有効期間のDescriptorを、同じvalidatorであることだけから同一とみなさない。
一方、`ref`も削除の観測もなければ、有効期間の切り替わりを検出できるとは限らない。Clientは得られた情報で通常のvalidationを行うが、検出不能な差し替えを防ぐ保証はない。この許容によって、存続中の同じInterfaceのDescriptor整合性が弱まることはない。
Scopeが別pathへ移動した場合は別参照として扱い、Clientは移動を追跡しない。実行開始済みcallが固定した観測と、結果検証用Descriptorは、有効期間終了後も保持する。
### Requestとresponse
@@ -497,31 +505,35 @@ struct FetchInterfaceResponse {
}
```
Clientは次を検証する。
Clientはresponseに対して、次の検証を行う。
- Responseの`interface`がrequestと一致する。
- Descriptorが構造検証および意味検証に成功する。
- Descriptorの`format`がClientの対応するversionである。
- 同じ有効期間のInterface参照と同じvalidator valueを持つ既存cache entryがある場合、validatorが存在する観測ではDescriptorがそのentryと一致する。Scopeの紐付きが確認できなくなった旧cacheとの比較は、前節の規則に従う。
ResponseまたはDescriptorがProtocol contractに違反する場合、ClientはHostが返したProtocol failureではなく`InvalidResponse`として扱う。Descriptorが構造的にはvalidだが、その`format`をClientが実装していない場合は`UnsupportedDescriptorFormat`として扱い、`InvalidResponse`と混在させない。
ResponseやDescriptorがProtocol contractに違反した場合は、Hostが返したProtocol failureとはせず、Client-localな`InvalidResponse`として扱う。Descriptorが構造的にはvalidでも、その`format`をClientが実装していない場合は`UnsupportedDescriptorFormat`とする。この二つのclassificationを混在させない。
Clientはvalidatorが存在するInterface observationを、同じ有効期間内の`(interface, validator)`の組でcacheし、`scope_ref`も観測metadataとして保持する。Interface参照ごとに最後に成功した観測を現在のcache entryとしてよいが、実行中のOperationが参照する観測はresponseのvalidationが完了するまで保持する。次の規則は同じ有効期間の観測に適用し、終了・紐付きの不一致を確認した旧cacheは新しいcallに使わない。
Validatorが存在するInterface observationは、同じ有効期間内の`(interface, validator)`をkeyとしてcacheする。Clientは`scope_ref`も観測metadataとして保持する。Interface参照ごとに最後に成功した観測を現在のcache entryとしてよいが、実行中のOperationが参照する観測は、responseのvalidationが完了するまで保持する。
同じ有効期間の観測には、次の規則を適用する。終了や紐付きの不一致を確認した旧cacheは、新しいcallには使用しない。
- 同じInterface参照でvalidatorが異なる場合は、同じInterfaceの新しい状態としてlatest observationを更新する。
- Validatorが存在しないInterface参照はimmutableなDescriptorとして、Interface参照だけをcache keyに使用できる。
- 同じInterface参照と同じvalidator valueで異なるDescriptorを受け取った場合は`InvalidResponse`として扱い、そのDescriptorをOperationへ使用しない。
- 新しい観測を得ても、異なるvalidatorを使用して実行中のrequestに必要なDescriptorをresponse validation前に破棄しない。
`fetch_interface`は現在のDescriptorを観測するinteractionであり、requestにvalidatorを含めない。Responseにvalidatorが存在する場合、Clientは後続の`call_operation`で、そのDescriptorに基づくOperation実行の必須preconditionとして使用する。Responseにvalidatorが存在しない場合、そのInterface参照のDescriptorはimmutableであり、`call_operation`の`interface.validator`を省略する。
`fetch_interface`は現在のDescriptorを観測するinteractionであり、requestにvalidatorを含めない。Responseにvalidatorがあれば、Clientは後続の`call_operation`で、そのDescriptorに基づくOperation実行の必須preconditionとして使用する。Validatorがなければ、そのInterface参照のDescriptorはimmutableであり、`call_operation`の`interface.validator`を省略する。
Hostは、主体へ公開したObjectの`interfaces`に含まれる各参照について、現在のDescriptorをその主体の`fetch_interface`で取得可能にしなければならない。現在公開されていないInterface参照には`InterfaceNotFound`を返し、Descriptor取得の認可失敗として`PermissionDenied`は使用しない。
Hostは、主体へ公開したObjectの`interfaces`に含まれる各参照について、その主体が`fetch_interface`で現在のDescriptorを取得できるようにしなければならない。現在公開されていないInterface参照には`InterfaceNotFound`を返す。Descriptor取得の認可失敗として`PermissionDenied`を使用しない。
`fetch_interface`は完全な`(scope, name)`を受け取るため、Clientに祖先Objectを順に取得するlookupを要求しない。Hostはscope Objectと、そのObjectに紐づくInterfaceの現在の公開状態を解決し、近い祖先の同名Interfaceへのfallbackは行わない。Requestに対象Objectのpathはなく、特定Objectで利用できるかの祖先制約(self-scopeを含む)は`observe`と`call_operation`で検証する。Scope外のObjectで使えないことと、Interface単独の取得可否は同一視しない。
`fetch_interface`には完全な`(scope, name)`を指定するため、Clientに祖先Objectを順に取得するlookupは要求しない。Hostはscope Objectと、それに紐づくInterfaceの現在の公開状態を解決する。近い祖先の同名Interfaceへfallbackしない。
このrequestは、対象Objectのpathを持たない。特定Objectで利用できるかを判定する祖先制約(self-scopeを含む)は、`observe`と`call_operation`で検証する。Scope外のObjectでは使えないことと、Interface単独の取得可否は同一視しない。
## `call_operation`
指定pathにあるObjectへOperationを実行する。
`call_operation`は、指定pathにあるObjectへOperationを実行する。
```rust
struct Target {
@@ -548,15 +560,15 @@ struct CallOperationResponse {
}
```
`target.path`はOperationを実行するObjectのpathである。`target.validator`は、Clientが観測したObjectのvalidatorを条件として指定する。Validatorを持たないObjectまたは無条件実行では省略する。
`target.path`には、Operationを実行するObjectのpathを指定する。`target.validator`には、Clientが観測したObjectのvalidatorを条件として指定する。Objectがvalidatorを持たない場合や、無条件実行の場合は省略する。
`interface.reference`は、ClientがObjectの`interfaces`から選択し、そのOperation schemaを取得するために使用したInterface参照である。`interface.validator`は、その参照への`fetch_interface`で観測したvalidatorである。`fetch_interface` responseにvalidatorが存在する場合は必ず指定し、validatorが存在しないimmutableなInterface参照では省略する。
`interface.reference`には、ClientがObjectの`interfaces`から選択し、Operation schemaを取得するために使ったInterface参照を指定する。`interface.validator`は、その参照への`fetch_interface`で観測したvalidatorである。Responseにvalidatorが存在する場合は必ず指定し、validatorが存在しないimmutableなInterface参照では省略する。
`interface.scope_ref`は、そのDescriptor observationで得たscope Objectのoptionalな`ref`である。観測に存在する場合はコピーし、存在しない場合は省略する。Scope Objectを別途観測して得た新しい`ref`だけを古いDescriptorへ付け替えてはならない。紐付きが確認できなくなった場合はInterface observationを取得し直す。
`interface.scope_ref`は、そのDescriptor observationで得たscope Objectのoptionalな`ref`である。観測に存在する場合はコピーし、存在しない場合は省略する。Scope Objectを別途観測して得た新しい`ref`だけを、古いDescriptorへ付け替えてはならない。紐付きが確認できなくなった場合は、Interface observationを取得し直す。
`arguments`はOperation parameterに対応する名前付きrecordである。引数がない場合は空のmapを送る。
`arguments`は、Operation parameterに対応する名前付きrecordである。引数がない場合も、空のmapを送る。
Hostは、現在その主体へ公開しているObjectとInterfaceに基づいてOperationを解決する。複数のfailure条件が同時に成立する場合は、次の順で最初のcodeだけを返す。
Hostは、現在その主体へ公開しているObjectとInterfaceに基づいてOperationを解決する。複数のfailure条件が同時に成立する場合も、次の順で最初に該当するcodeだけを返す。
1. `target.path`のObjectが公開されていない場合は`NotFound`。
2. 指定された`target.validator`が現在のObject validatorと一致しない場合は`ValidatorMismatch`。
@@ -568,27 +580,27 @@ Hostは、現在その主体へ公開しているObjectとInterfaceに基づい
8. `arguments`が現在のOperation declarationに適合しない場合は`InvalidArguments`。
9. 宣言されたOperationの存在を公開しつつ、その主体による実行を認めない場合は`PermissionDenied`。
指定されたObject validatorまたはInterface validatorの不一致は、現在のDescriptorに基づくOperation lookupとarguments validationより先に判定する。これによりClientは、古いObjectまたはschemaに基づくrequestを`OperationNotFound`や`InvalidArguments`として扱わず、対応する観測を更新できる。
指定されたObject validatorやInterface validatorの不一致は、現在のDescriptorに基づくOperation lookupとarguments validationより先に判定する。古いObjectやschemaに基づくrequestを`OperationNotFound`や`InvalidArguments`として扱わず、Clientが対応する観測を更新できるようにするためである。
Hostは一つのlinearization pointで、現在のObject identityと状態、Object validator、Objectが公開するInterface参照、scope Objectとの紐付きと指定された`scope_ref`、Interface validator、Interface Descriptor、Operation implementation、実行対象を解決し、各preconditionを確認して、そのcallが使用する観測を固定する。ObjectまたはInterfaceが後から変化しても、callの途中で別のscope Object、Descriptor、Operation implementation、実行対象へ解決し直してはならない。
Hostは一つのlinearization pointで、現在のObject identityと状態、Object validator、Objectが公開するInterface参照、scope Objectとの紐付きと指定された`scope_ref`、Interface validator、Interface Descriptor、Operation implementation、実行対象を解決する。同じ時点で各preconditionを確認し、そのcallが使用する観測を固定する。
Argumentsとresultのvalidationは、固定したInterface Descriptorの同じOperation declarationを使用する。Authorizationも固定したObject、Interface、主体のcontextに対して評価する。
その後にObjectやInterfaceが変化しても、callの途中で別のscope Object、Descriptor、Operation implementation、実行対象へ解決し直してはならない。Argumentsとresultのvalidationには、固定したInterface Descriptorの同じOperation declarationを使用する。Authorizationも、固定したObject、Interface、主体のcontextに対して評価する。
Hostが`target.validator`をbackendへのcommit条件として使用する場合、validatorの比較とcommitをatomicに行う。Responseの`validator`は、Operation完了後にHostがそのObjectについて発行する現在のvalidatorである。Operationが何を行ったか、またはApplication dataを変更したかをvalidatorの有無や値から推測しない。Object validatorを提供しない場合は省略する。
Hostが`target.validator`をbackendへのcommit条件として使用する場合は、validatorの比較とcommitをatomicに行う。Responseの`validator`は、Operation完了後にHostがそのObjectについて発行する現在のvalidatorであり、Object validatorを提供しない場合は省略する。Validatorの有無や値から、Operationが何を行ったか、Application dataを変更したかを推測しない。
Validatorの比較はopaque bytesの完全一致で行う。Clientはvalidatorの生成方法または内容に基づいて分岐してはならない。
Validatorはopaque bytesの完全一致で比較する。Clientは生成方法や内容に基づいて分岐してはならない。
HostはOperationをInterfaceから除外して存在を非公開にすることも、Interfaceへ含めたうえで実行時に`PermissionDenied`として拒否することもできる。
Hostは、OperationをInterfaceから除外して存在を非公開にしてもよい。Interfaceに含めたうえで、実行時に`PermissionDenied`として拒否することもできる。
Clientはresultを、requestの`interface`が指定し、Hostがpreconditionを確認して固定したOperation return typeに従って検証する。Validationに失敗したsuccess responseはHostから返されたProtocol failureではなく`InvalidResponse`として扱い、そのvalueをApplicationへ渡さない。
Clientはresultを、requestの`interface`が指定し、Hostがprecondition確認時に固定したOperation return typeに従って検証する。Success responseがvalidationに失敗した場合は、Hostから返されたProtocol failureとはせず、`InvalidResponse`として扱う。そのvalueをApplicationへ渡さない。
Host Runtimeがimplementation resultのencodeまたはvalidation failureを送信前に検出し、Operationのeffectがcommitされていないと保証できる場合は`Internal`を返す。Operationが未実行またはrollback済みであることを保証できず、validなsuccess responseも返せない場合は`OperationOutcomeUnknown`を返す。
Host Runtimeがimplementation resultのencodeやvalidationのfailureを送信前に検出した場合は、effectのcommit状況に応じてerrorを返す。Operationのeffectがcommitされていないと保証できる場合は`Internal`とする。未実行またはrollback済みであることを保証できず、validなsuccess responseも返せない場合は`OperationOutcomeUnknown`とする。
## Worldspace composition
Clientが扱う絶対pathとInterface scopeは、常に接続先Hostが公開するClient-facing Worldspaceのrootに基づく。Proxyや合成によってUpstream Worldspaceの公開位置が変わる場合、Hostが公開先とUpstreamの座標を対応付ける。Upstreamのrootやmount構成をClientに追跡・補完させない。
Clientが扱う絶対pathとInterface scopeは、常に接続先Hostが公開するClient-facing Worldspaceのrootを基準にする。Proxyや合成によってUpstream Worldspaceの公開位置が変わる場合は、Hostが公開先とUpstreamの座標を対応付ける。Upstreamのrootやmount構成を、Clientに追跡・補完させない。
Upstreamのrootを`/github`へ配置する例:
Upstreamのrootを`/github`へ配置する場合、座標は次のように対応する。
| 項目 | Upstream | 公開先 |
| --- | --- | --- |
@@ -598,11 +610,13 @@ Upstreamのrootを`/github`へ配置する例:
| Repository scope | `/my-rep` | `/github/my-rep` |
| `entry` | `/my-rep/issues/123` | `/github/my-rep/issues/123` |
別のUpstreamを`/gitlab`へ配置した場合、その`{ scope: "/", name: "issue.read" }`は`{ scope: "/gitlab", name: "issue.read" }`となる。同じlocal nameでもscopeによって区別される。さらに全体を`/services`へ配置するHostは、`/github`を`/services/github`へ変換する。Worldspaceの配置を変えないHTTP proxyはscopeを変更する必要がない。HTTP endpointのpath prefixとWorldspace pathを混同しない。
別のUpstreamを`/gitlab`へ配置した場合、その`{ scope: "/", name: "issue.read" }`は`{ scope: "/gitlab", name: "issue.read" }`となる。同じlocal nameでも、scopeによって区別する。さらに全体を`/services`へ配置するHostは、`/github`を`/services/github`へ変換する。
一方、Worldspaceの配置を変えないHTTP proxyは、scopeを変更する必要がない。HTTP endpointのpath prefixとWorldspace pathは混同しない。
### 座標の変換
合成Hostは次の対応を一貫させる。
合成Hostは、次の対応を一貫させる。
- `observe`のrequest pathをUpstreamへ変換する。ResponseのObjectの`name`とchildrenは公開先pathの規則を満たすようにする。特にUpstream rootの空の`name`を、非rootのmount先へそのまま公開しない。
- `Object.interfaces`の各構造化参照のscopeを公開先へ変換し、公開先での祖先制約と名前の一意性を保つ。
@@ -611,9 +625,11 @@ Upstreamのrootを`/github`へ配置する例:
- `scope_ref`は公開先scope Objectの`ref`と一致させる。Upstreamのscope Objectが持つ`ref`との対応をHostが保持し、公開先で指定されたpreconditionを検証してからUpstreamへ対応付ける。Opaqueな`ref`へpath prefixを機械的に加えたり、指定された条件を転送時に落としたりしない。公開先scope Objectが`ref`を持たない形態も許可する。
- Descriptorで`entry`と宣言されたargumentsをUpstreamへ、resultを公開先へ変換する。Named type、record、list、unionの内部にある`entry`も同じ規則で扱う。
通常の`string`、opaqueな`json`、documentation内のpathらしい文字列を推測して書き換えない。Application固有の別の座標系はApplication adapterの責務とする。
通常の`string`、opaqueな`json`、documentation内のpathらしい文字列は、推測して書き換えない。Application固有の別の座標系は、Application adapterが扱う。
公開subtree外のscopeや`entry`に対応付けがない場合、Upstream pathをそのまま公開したり、scopeを削除・rootへ付け替えたりしてはならない。部分合成の対応付け方針と詳細な拒否条件は未確定だが、失敗時も既存のProtocol failure契約を守る。特にUpstreamでeffectがcommit済みのOperationのresultを変換できない場合、未実行を保証するerrorへ置き換えない。Validなsuccessを返せず、未実行またはrollbackを保証できない場合は`OperationOutcomeUnknown`として扱う。
公開subtree外のscopeや`entry`に対応付けがない場合、Upstream pathをそのまま公開したり、scopeを削除したりrootへ付け替えたりしてはならない。部分合成の対応付け方針と詳細な拒否条件は未確定だが、失敗時にも既存のProtocol failure契約を守る。
特に、Upstreamでeffectがcommit済みのOperationについてresultを変換できない場合は、未実行を保証するerrorへ置き換えない。Validなsuccessを返せず、未実行またはrollbackを保証できない場合は`OperationOutcomeUnknown`として扱う。
### 同一性と観測整合性
@@ -623,11 +639,13 @@ Upstreamのrootを`/github`へ配置する例:
- Upstream validatorをそのまま使用するか、Host側で対応付け・wrapするかは、これらの保証を満たす範囲でHostが決める。
- Scopeが変わればProtocol上は別のInterface参照である。Clientに移動前後の同一性を推測させない。
同じUpstream Objectを複数のscope配下へ配置すると、公開するInterface集合が配置ごとに変わり得る。異なる公開representationへ同じ`ref`とvalidatorを無条件に引き継げない。共通祖先scopeでの共有やprojectionごとのidentity割当等の選択は[未解決事項](draft/unresolved-issues.md)に残す。Renameやmount変更では新しいscopeを別参照として扱い、同じpathでのscope Objectの差し替えには上述のoptionalな`scope_ref`の確認を適用する。Clientによる移動追跡は要求しない。これらは既存のvalidator・実行中callの一貫性を弱めない。
同じUpstream Objectを複数のscope配下へ配置すると、公開するInterface集合は配置ごとに変わり得る。このため、異なる公開representationへ同じ`ref`とvalidatorを無条件には引き継げない。共通祖先scopeでの共有や、projectionごとのidentity割当等の選択は、[未解決事項](draft/unresolved-issues.md)に残る。
Renameやmount変更では、新しいscopeを別参照として扱う。同じpathでscope Objectが差し替わる場合は、optionalな`scope_ref`の確認を適用する。Clientによる移動追跡は要求しない。これらの扱いによって、既存のvalidatorと実行中callの一貫性を弱めない。
## Protocol responseとfailure
Core interactionは、成功responseまたはProtocol failureを返す。
Core interactionの結果は、成功responseまたはProtocol failureである。
```rust
enum ProtocolResult<T> {
@@ -658,9 +676,9 @@ enum ProtocolErrorCode {
}
```
`message`は人間向けのboundedな診断であり、Clientが分岐に使用する安定した値ではない。Clientは`code`を使用する。Hostは秘密情報、非公開Object、backend path、credential、内部stack traceをmessageへ含めない。
Clientが分岐に使用するのは`code`である。`message`は人間向けのboundedな診断であり、分岐用の安定した値ではない。Hostは秘密情報、非公開Object、backend path、credential、内部stack traceをmessageへ含めない。
各interactionが返してよいcodeは次に限定する。
返してよいcodeは、interactionごとに次のものへ限定する。
| Code | `observe` | `fetch_interface` | `call_operation` |
| --- | --- | --- | --- |
@@ -679,9 +697,9 @@ enum ProtocolErrorCode {
| `Internal` | ✓ | ✓ | ✓ |
| `OperationOutcomeUnknown` | — | — | ✓ |
Hostがinteractionに許可されていないcodeを返した場合、Clientはそのerror responseを`InvalidResponse`として扱う。
Hostがそのinteractionに許可されていないcodeを返した場合、Clientはerror responseを`InvalidResponse`として扱う。
Validatorおよび観測関連errorの回復対象は次のとおりである。
Validatorと観測に関するerrorの回復対象は、次のとおりである。
- `NotFound`では、Clientは対象Entryをstaleとして扱い、必要に応じて親を再観測する。
- `InterfaceNotFound`では、ClientはそのInterface observationを使用せず、参照元Objectを再観測できる。
@@ -689,28 +707,30 @@ Validatorおよび観測関連errorの回復対象は次のとおりである。
- `InterfaceMismatch`では、Clientは対象Objectを再観測し、現在公開されているInterface参照の集合を取得する。Scopeの紐付きが変わった可能性もあるため、使用したInterface observationを新しいcallへ再利用せず、必要なら`fetch_interface`で再取得する。
- `InterfaceValidatorRequired`または`InterfaceValidatorMismatch`では、Clientは同じInterface参照を`fetch_interface`で再観測し、現在のDescriptorに基づいてOperationを再構築する。
同じOperationを再試行するなら、先に新しい観測を取得しなければならない。
同じOperationを再試行する場合は、先に新しい観測を取得しなければならない。
- `InvalidRequest`または`InvalidArguments`では、Clientは同じrequestを変更せずに再送しない。
- `ResourceLimitExceeded`では、Clientはlogical request shapeやobservation depth等を削減できるが、`call_operation`を自動再実行しない。
`call_operation`が`OperationOutcomeUnknown`以外のProtocol failureを返した場合、HostはOperationのeffectがcommitされていないことを保証する。`OperationOutcomeUnknown`は、HostがOperationの未実行またはrollbackを保証できず、validなsuccess responseも返せないことを示す。Clientは対象Objectをstaleとして扱い、Operationを自動再実行せず、再観測またはdomain固有の照会手段を利用者へ提示する。
`call_operation`が`OperationOutcomeUnknown`以外のProtocol failureを返した場合、HostはOperationのeffectがcommitされていないことを保証する。`OperationOutcomeUnknown`を返すのは、未実行またはrollbackを保証できず、validなsuccess responseも返せない場合である。
`Internal`はHost内部のfailureであり、`call_operation`ではeffectがcommitされていないと保証できる場合だけ返す。Clientは`Internal`を理由にOperationを自動再実行しない。Transport timeoutやconnection lossでresponse自体を受け取れない場合もOperation outcomeは不明になり得るが、それはProtocol failureではなくTransport failureとして扱う。
`OperationOutcomeUnknown`を受けたClientは、対象Objectをstaleとして扱い、Operationを自動再実行しない。再観測またはdomain固有の照会手段を、利用者へ提示する。
Objectを主体へ公開しない場合、HostはそのObjectをClient-facing Worldspaceに存在しないものとして扱い、`observe`と`call_operation`へ`NotFound`を返す。Objectの存在を秘匿する目的で`PermissionDenied`を返してはならない。
`Internal`はHost内部のfailureであり、`call_operation`ではeffectがcommitされていないと保証できる場合だけ返す。Clientは`Internal`を理由にOperationを自動再実行しない。Transport timeoutやconnection lossでresponse自体を受け取れない場合も、Operation outcomeは不明になり得る。ただし、これはProtocol failureではなくTransport failureとして扱う。
`PermissionDenied`は、現在公開されているInterfaceに宣言されたOperationについて、その存在を公開しつつ実行を認めない場合に使用する。Operation自体をInterfaceから除外している場合は`OperationNotFound`を返す。Operation argumentが参照するdomain resourceの不存在やbusiness rule failureを、対象Objectの`NotFound`へ変換しない。
Objectを主体へ公開しない場合、HostはそのObjectをClient-facing Worldspaceに存在しないものとして扱う。`observe`と`call_operation`には`NotFound`を返し、存在を秘匿する目的で`PermissionDenied`を返してはならない。
`InvalidResponse`と`UnsupportedDescriptorFormat`はClient-localなclassificationであり、`ProtocolErrorCode`ではない。前者はsuccess responseまたはerror responseがProtocol contractに違反した場合、後者はvalidなDescriptor formatをClientが実装していない場合に使用する。
`PermissionDenied`は、現在公開されているInterfaceに宣言されたOperationの存在を公開しつつ、実行を認めない場合に使用する。Operation自体をInterfaceから除外している場合は、`OperationNotFound`を返す。Operation argumentが参照するdomain resourceの不存在やbusiness rule failureを、対象Objectの`NotFound`へ変換しない。
Protocol failureとdomain failureを混在させない。現在のProtocolでは、Domain failureをApplicationのOperation resultに含まれるUnion caseとして明示する。専用のfailure envelopeは定義しない。
`InvalidResponse`と`UnsupportedDescriptorFormat`は、いずれもClient-localなclassificationであり、`ProtocolErrorCode`には含めない。Success responseまたはerror responseがProtocol contractに違反した場合は前者、validなDescriptor formatをClientが実装していない場合は後者を使用する。
Transport BindingはProtocol Resultをstatus code、response envelope、stream termination等へ対応付ける。Authentication、route、media type、framing、response不達等のTransport failureをProtocol errorへ変換しない。
Protocol failureとdomain failureは混在させない。現在のProtocolでは、domain failureをApplicationのOperation resultに含まれるUnion caseとして明示する。専用のfailure envelopeは定義しない。
Transport Bindingは、Protocol Resultをstatus code、response envelope、stream termination等へ対応付ける。Authentication、route、media type、framing、response不達等のTransport failureを、Protocol errorへ変換しない。
## Resource limit
HostとClientは、untrusted inputによるresource exhaustionを避けるため、少なくとも次へ上限を設ける。
HostとClientは、untrusted inputによるresource exhaustionを避けるため、少なくとも次の対象へ上限を設ける。
- Pathとして解釈するstring、validator、name、description、documentationの長さ。
- Interface Descriptor内のdeclaration、documentation、field等の総量。
@@ -721,13 +741,17 @@ HostとClientは、untrusted inputによるresource exhaustionを避けるため
- `observe`のdepthとresponse node数。
- Protocol error messageの長さ。
各実装はこれらにboundedな上限を設定する。Request fieldだけで判定できる上限違反は、interaction固有のtarget resolutionまたはOperation dispatchより前に`ResourceLimitExceeded`として拒否する。Hostが取得responseを構築する途中でresponse node数やlogical collection size等の上限超過を検出した場合も、success responseの代わりに`ResourceLimitExceeded`を返してよい。
各実装は、これらにboundedな上限を設定する。Request fieldだけで判定できる上限違反は、interaction固有のtarget resolutionやOperation dispatchより前に、`ResourceLimitExceeded`として拒否する。
`call_operation`では、dispatch後にresultのlogical size、validation、backend budget等の問題を検出しても、effectがcommitされていないと保証できる場合だけ`ResourceLimitExceeded`または`Internal`を返す。未実行またはrollbackを保証できない場合は`OperationOutcomeUnknown`とする。Transport implementationまたはdeploymentのmessage-size上限、response不達等はProtocol failureへ変換せず、Transport failureとして扱う。
Hostが取得responseを構築する途中で、response node数やlogical collection size等の上限超過を検出した場合も、success responseの代わりに`ResourceLimitExceeded`を返してよい。
`call_operation`では、dispatch後にresultのlogical size、validation、backend budget等の問題を検出した場合、effectがcommitされていないと保証できるときだけ`ResourceLimitExceeded`または`Internal`を返す。未実行またはrollbackを保証できない場合は`OperationOutcomeUnknown`とする。
Transport implementationやdeploymentのmessage-size上限、response不達等は、Protocol failureへ変換しない。これらはTransport failureとして扱う。
## Transport Bindingの要件
Transport Bindingは、この章のlogical structについて次を定義する。
Transport Bindingは、これらのlogical structに対して次を定義する。
- Requestとresponseのframing。
- Protocol primitiveのconcrete encoding。
@@ -736,6 +760,6 @@ Transport Bindingは、この章のlogical structについて次を定義する
- Protocol failureのmapping。
- Object validator、Interface validator、Operation preconditionのmapping。
Transport固有のmessage size、timeout、concurrency、security、connection policyはTransport実装とdeploymentの責務であり、BindingがWIP Protocolとして値またはnegotiationを定義する必要はない。複数のinteractionを並行実行またはmultiplexする場合も、それぞれは独立したrequestとresponseを持つ。
Transport固有のmessage size、timeout、concurrency、security、connection policyは、Transport実装とdeploymentの責務である。BindingがWIP Protocolとして値やnegotiationを定義する必要はない。複数のinteractionを並行実行またはmultiplexする場合も、それぞれは独立したrequestとresponseを持つ。
Transport Bindingは、logical typeの区別またはvalidation semanticsを失ってはならない。
Transport Bindingは、logical typeの区別やvalidation semanticsを失ってはならない。
+67 -65
View File
@@ -2,57 +2,55 @@
## 役割
Clientは、Hostが提供するWorldspaceを利用する実装主体である。WIP Protocolを利用しつつ、Objectが参照するInterface集合を解決し、用途に応じたView、Tool、API等の上位インターフェースへ投影する。
Clientは、Hostが提供するWorldspaceを利用する実装主体である。WIP ProtocolでObjectを観測し、そのObjectが参照するInterface集合を解決して、用途に応じたView、Tool、API等へ投影する。
ClientはHostから得た情報をinteractionごとに破棄するだけでなく、rootからindexable edgeを辿って構成したエントリツリーと、必要に応じて選択したエントリを保持し、上位層にとっての**既知の空間**を構成する。
取得した情報は、interactionごとに捨てる必要はない。Rootからindexable edgeを辿って得たエントリツリーや、必要に応じて選んだエントリを保持すれば、上位層はそれを既知の空間として利用できる。
## Known Space
Known Spaceは、Clientが**現在保持しているエントリの集合**である。過去に発見したすべてのエントリを単調に蓄積する集合ではない。
Known Spaceは、Clientが現在保持しているエントリの集合である。過去に発見したすべてのエントリを、増え続ける集合として蓄積するわけではない。
Known SpaceとDiscoverable SpaceはClientが過去の観測から構築したcacheであり、Host上の現在状態を同期したreplicaではない。HostはClientのcache状態を追跡または更新しない。
Known SpaceとDiscoverable Spaceは、過去の観測から構築したcacheである。Hostの現在状態を同期したreplicaではなく、HostはClientのcache状態を追跡・更新しない。
Clientは、観測結果が同じeffective Worldspace viewに属する範囲でcacheを共有する。接続先、認証主体、tenant、その他のsecurity contextによって異なるWorldspaceが公開され得る場合、それらのKnown Space、Object observation、Interface cacheを混在させない。具体的なcache namespaceの構成はClientおよびTransport Bindingに委ねる。
Cacheを共有できるのは、観測結果が同じeffective Worldspace viewに属する範囲に限られる。接続先、認証主体、tenant、その他のsecurity contextによって異なるWorldspaceが公開され得る場合、それらのKnown Space、Object observation、Interface cacheを混在させない。具体的なcache namespaceの構成は、ClientとTransport Bindingに委ねる。
次のような経路で得られたエントリをKnown Spaceへ追加できる。
Known Spaceへ追加できるのは、例えば次のエントリである。
- `observe`で取得したエントリ
- Operation結果の`entry`型pathを`depth = 0`で`observe`して取得したエントリ
Operationを通して発見されたpathは、必ずしもKnown Spaceへ追加する必要はない。Clientは現在の結果として一時的に扱うことも、取得後に必要なエントリだけを選択して保持することもできる。
既知エントリ間の移動や参照はClient側で処理できる。既知の空間を辿るたびにHostへ問い合わせる必要はない。
Operationで発見したpathを、すべてKnown Spaceへ追加する必要はない。現在の結果として一時的に扱っても、取得後に必要なエントリだけを保持してもよい。保持したエントリ間の移動や参照はClient側で処理でき、辿るたびにHostへ問い合わせる必要はない。
## 取得・保持・提示の分離
ユーザーやAIがpathを知っていること、ClientがObjectを観測・保持していること、Clientがindexable edgeも観測・保持していることは別の状態である。
Pathを知っていても、ClientがそのObjectを観測しているとは限らない。Objectを観測・保持していても、そこへ至るindexable edgeを観測・保持しているとは限らない。この三つは別の状態である。
ClientはKnown Spaceにない有効なpathも取得対象にできる。過去に観測していないことだけを理由に取得を拒否せず、現在のHostの公開状態に従って`observe`する。取得前に仮のObjectをKnown Spaceへ登録する必要はない。Pathを知っていること自体は公開可視性や実行権限を保証しない。
Clientは、Known Spaceにない有効なpathも取得対象にできる。未観測であることだけを理由に拒否せず、現在のHostの公開状態に従って`observe`する。取得前に仮のObjectをKnown Spaceへ登録する必要はない。ただし、pathを知っていることは、公開可視性や実行権限の保証にはならない。
観測したObjectのどの情報を提示するかは、上位インターフェースの責務である。ClientがObject情報を保持していても、配置だけを提示する場面ですべての説明やInterfaceを展開する必要はない。提示済みの情報とcache内容を同一視しない。
観測した情報のうち何を提示するかは、上位インターフェースが決める。配置だけを提示する場面では、保持している説明やInterfaceをすべて展開しなくてもよい。提示済みの情報とcache内容を同一視しない。
Objectを観測・保持したことだけでは、そのpathを既知のtreeへ接続するindexable edgeを得たことにはならない。Treeの構成には観測済みのedgeを使い、pathのprefixや階層関係からedgeを推測しない。
同様に、Objectを保持していることだけを根拠に、既知のtreeへ接続してはならない。Treeは観測済みのindexable edgeから構成し、pathのprefixや階層関係からedgeを推測しない。
## Entry TreeとObject observation
Clientは、観測したObjectをcanonical path上のEntryへ対応付け、観測済みのindexable child edgeとともに保持できる。具体的なcache表現は規定しない。Clientは`ObjectObservation`に近い入れ子構造またはforestを保持しても、path index、flatなObject store、Entry Treeへnormalizeしてもよい。
Clientは、観測したObjectをcanonical path上のEntryに対応付け、観測済みのindexable child edgeとともに保持できる。Cacheの表現は規定しない。`ObjectObservation`に近い入れ子構造やforestを使っても、path index、flatなObject store、Entry Treeへnormalizeしてもよい。
EntryのpathとchildrenはWorldspace上の配置contextであり、Object identityそのものには含まれない。同じObjectが複数のEntryから観測される場合、Clientはshared record、複製したsnapshot、その他の内部表現を使用できる。ただし、保存形式によって`ref`、validator、Object representationのconsistencyを変えてはならない。
Entryのpathとchildrenは配置contextであり、Object identityには含まれない。同じObjectが複数のEntryから観測される場合、shared record、複製したsnapshot、その他の内部表現を使える。ただし、保存形式を変えても、`ref`、validator、Object representationのconsistencyは変えてはならない。
- 同じ有効な`ref`を持つ観測は、同じWorldspace内の同じObjectを表す。Clientは一つのObject stateを共有しても、Entryごとにsnapshotを保持してもよい。
- `ref`がないこと、または異なることから、複数のEntryが同じObjectか異なるObjectかを判断しない。Clientはrepresentationが同じという理由だけでObject identityを推測しない。
- Objectの`interfaces`はmembershipをsetとして扱い、同じ参照の重複を`InvalidResponse`として拒否する。ClientはHostの立項順を保持し、InterfaceやOperationの提示順に使用してよい。
- 同じ`ref`と同じvalidator valueを持つObjectを再観測したとき、validatorが存在するにもかかわらずObject representationが異なる場合、Clientはresponseを`InvalidResponse`として扱う。同じ`ref`でvalidatorが異なる場合、またはvalidatorが存在しない場合は、同一Objectの新しい観測として扱い、最後に受理した成功観測をその`ref`の現在状態とする。
このcache表現はClient内部の実装であり、Objectと別のWIP resourceまたはProtocol上のEntry resourceを導入するものではない。
Entry TreeはClient内部のcache表現であり、Objectとは別のWIP resourceやProtocol上のEntry resourceを追加するものではない。
## Interface cache
Interface参照は`{ scope, name }`のrecordであり、同じeffective Worldspace view内の`(scope, name)`の完全一致で比較する。Local nameだけ、表示用の短縮表記、JSON serializationのbyte列をcache keyにしない。Scopeが異なれば別参照であり、Host内部のUpstream座標へ読み替えない。
Interface参照は`{ scope, name }`というrecordである。比較には、同じeffective Worldspace view内の`(scope, name)`の完全一致を使う。Local nameだけ、表示用の短縮表記、JSON serializationのbyte列をcache keyにしない。Scopeが異なれば別参照であり、Host内部のUpstream座標へ読み替えない。
Clientは各Objectの配置pathに対して[scopeの祖先制約](2.1-object-tree-schema.md#interface-scope)を検証する。参照の解決には完全なscopeとnameを使い、祖先Objectの順次取得、同名Interfaceの探索、shadowingを導入しない。Scopeの適合だけでInterface membershipやauthorizationを推測しない。
Clientは各Objectの配置pathに対して[scopeの祖先制約](2.1-object-tree-schema.md#interface-scope)を検証する。解決には完全なscopeとnameを使い、祖先Objectの順次取得、同名Interfaceの探索、shadowingを導入しない。Scopeが適合しても、それだけでInterface membershipやauthorizationがあるとは判断しない。
Objectの公開情報はOperation定義を直接含まず、Interface参照のordered setを持つ。Clientは必要な参照を`fetch_interface`で解決し、取得したInterface Descriptorとoptionalなvalidatorを観測としてcacheする。
Objectの公開情報には、Operation定義そのものではなく、Interface参照のordered setが含まれる。Clientは必要な参照を`fetch_interface`で解決し、Descriptorとoptionalなvalidatorを観測としてcacheする。
```rust
struct CachedInterface {
@@ -62,91 +60,95 @@ struct CachedInterface {
}
```
Clientは同じ有効期間内でvalidatorが存在する観測を`(interface, validator)`の組で識別し、Interface参照ごとに最後に成功した観測をcurrent entryとして保持できる。Validatorが存在しないInterface参照は、その参照が有効な間Descriptorがimmutableなので、参照だけをcache keyに使用できる。
Validatorがある観測は、同じ有効期間内で`(interface, validator)`の組により識別する。ClientはInterface参照ごとに、最後に成功した観測をcurrent entryとして保持できる。Validatorがない場合、その参照が有効な間はDescriptorがimmutableなので、参照だけをcache keyに使える。
`scope_ref`は`fetch_interface`が返すscope Objectのoptionalな`ref`であり、参照の第三成分ではなく観測metadataとして保持する。観測に存在する場合はcallの`interface.scope_ref`へコピーし、なければ省略する。Clientはscope Objectや祖先を追加取得する必要がない。Scope Objectを別途観測して紐付きを確認できなくなった場合は、古いDescriptorの`scope_ref`だけを更新せず、Interface observationを取得し直す。
`scope_ref`は、`fetch_interface`が返すscope Objectのoptionalな`ref`である。参照の第三成分ではなく、観測metadataとして保持する。存在する場合はcallの`interface.scope_ref`へコピーし、なければ省略する。Scope Objectや祖先を追加取得する必要はない。
Scope Objectがそのpathから消えたことを確認したClientは、そのscopeのInterface cacheを破棄できる。Scope Objectの`ref`が以前の紐付きを確認できない値へ変わった場合や`ref`がなくなった場合も、旧観測を新しいcallへ使用しない。有効期間が終了した旧観測と、同じpathへ再公開された新しい観測を区別する。Scopeの移動先を追跡してcacheを付け替えない。
Scope Objectを別途観測した結果、以前の紐付きを確認できなくなった場合は、Interface observationを取得し直す。古いDescriptorの`scope_ref`だけを更新してはならない。
`ref`のないscopeが同じpathで差し替わる場合、Clientがそのidentityや有効期間の切り替わりを追跡できないことは仕様上許容される。欠落を不正なresponseとしたり、疑似identityを生成したりしない。得られた情報によるDescriptor・validatorの検証は引き続き行うが、検出不能な差し替えの防止は保証しない。
Scope Objectがそのpathから消えたことを確認したClientは、そのscopeのInterface cacheを破棄できる。`ref`が以前の紐付きを確認できない値に変わった場合や、`ref`がなくなった場合も、旧観測を新しいcallに使わない。有効期間が終了した旧観測と、同じpathへ再公開された新しい観測を区別し、scopeの移動先を追跡してcacheを付け替えない。
削除の確認とClient-localなcache evictionを混同しない。Indexable edgeが一覧から消えただけでは、直接観測可能な非indexable Objectとして存続している可能性があり、scope Objectの削除を断定しない。削除の即時検出、監視、全Interfaceの先行再取得は要求しない。破棄可能なcacheであっても、実行中callの結果検証に必要なDescriptorは完了まで保持する。
一方、`ref`のないscopeが同じpathで差し替わる場合、Clientがidentityや有効期間の切り替わりを追跡できないことは許容される。`ref`の欠落を不正なresponseとしたり、疑似identityを生成したりしない。得られた情報によるDescriptorとvalidatorの検証は続けるが、検出不能な差し替えの防止までは保証しない。
一つのInterface Descriptorに宣言されたOperationの集合が、そのInterfaceのOperation一覧である。Objectは複数のInterfaceを組み合わせられ、複数のObjectも同じInterfaceを共有できる。
Indexable edgeが一覧から消えても、scope Objectが削除されたとは限らない。直接観測可能な非indexable Objectとして存続している可能性があるためである。削除の確認と、Client-localなcache evictionを混同しない。削除の即時検出、監視、全Interfaceの先行再取得も要求しない。
ClientはDescriptorが必要なInterface参照とcacheを比較し、未知のInterfaceだけを取得する。Objectの`interfaces`からDescriptor interestを先行して導出しても、Operationを選択した時点で必要な参照だけを取得してもよい。Interface validator mismatch等で更新が必要になった参照は再取得する。複数の`fetch_interface`が必要な場合、それぞれを個別のrequestとして並行実行できる。
Objectは複数のInterfaceを組み合わせられ、複数のObjectも同じInterfaceを共有できる。それぞれのOperation一覧は、そのInterface Descriptorに宣言されたOperationの集合である。
異なるInterfaceで同じOperation名が存在しても、Clientは構造化Interface参照とOperation名の組で識別する。UIやAI Toolのqualified表示は[Text Viewの参照表記](4.2-text-view.md#参照表記)に従う。Operation callではsignature全体をparseせず、Interface参照とOperation名を別fieldとして送る。
Clientは、必要なInterface参照とcacheを比較し、未知のInterfaceだけを取得する。Objectの`interfaces`からDescriptor interestを先行して導出しても、Operationを選択した時点で必要な参照だけを取得してもよい。Interface validator mismatch等で更新が必要になった参照は再取得する。複数の`fetch_interface`は、それぞれ個別のrequestとして並行実行できる。
実行中のOperationが使用するDescriptor observationは、resultのvalidationが完了するまで保持する。新しいvalidatorのDescriptorを観測しても、古いvalidatorで開始済みのcallに必要なDescriptorを早期に破棄しない。
同名Operationが異なるInterfaceに存在しても、Clientは構造化Interface参照とOperation名の組で識別する。UIやAI Toolのqualified表示は[Text Viewの参照表記](4.2-text-view.md#参照表記)に従う。Callではsignature全体をparseせず、Interface参照とOperation名を別fieldとして送る。
実行中のOperationが使うDescriptor observationは、resultのvalidationが終わるまで保持する。Cacheを破棄できる場合や、新しいvalidatorのDescriptorを観測した場合も、開始済みのcallが必要とするDescriptorを早期に捨てない。
## Discoverable Space
Clientは、Hostから`observe`で取得したindexableなエントリツリーをDiscoverable Spaceとして保持する。Discoverable Spaceとして扱う間、Clientはその観測済みtreeの構造を保持する必要がある。
Discoverable Spaceは、Clientが`observe`で取得・保持したindexableなエントリツリーである。Worldspace rootまたはClientが選んだ起点から、観測済みのindexable edgeで到達できるmaterialize済みの範囲を指す。
Discoverable SpaceはKnown Spaceの部分集合であり、AI向けの`tree`など、indexableな配置の探索に利用する。Worldspace rootまたはClientが選択した起点からindexable edgeで到達できる、materialize済みの範囲によって構成される。
Known Spaceの部分集合であり、AI向けの`tree`など、indexableな配置の探索に使う。Discoverable Spaceとして扱う間は、観測済みtreeの構造を保持する必要がある。
Clientが`observe`結果をmergeし、`children`が存在するparent nodeから以前のindexable edgeが返されなくなった場合、その子エントリをDiscoverable Spaceから除外する。その結果、保持しているどの起点からも到達不能になったsubtreeは、その場で破棄できる。ただし、別の経路から到達できるエントリ、Clientがpinしたエントリ、実行中のOperationが参照しているエントリは引き続き保持してよい。`children`が省略されたnodeはedge削除の根拠にしない。
Clientが`observe`結果をmergeしたとき、`children`のあるparent nodeから以前のindexable edgeが返されなくなった場合は、その子エントリをDiscoverable Spaceから除外する。保持するどの起点からも到達不能になったsubtreeは、その場で破棄できる。ただし、別経路から到達できるエントリ、pinしたエントリ、実行中のOperationが参照するエントリは保持してよい。`children`が省略されたnodeは、edge削除の根拠にしない。
Operationを通して発見されたpathは、それだけではDiscoverable Spaceへ追加しない。そのエントリを起点として`depth > 0`で`observe`した場合に、そのindexableな範囲をDiscoverable Spaceへ追加できる。
Operationからpathを発見しても、それだけではDiscoverable Spaceへ追加しない。そのエントリを起点に`depth > 0`で`observe`した場合に、取得したindexableな範囲を追加できる。
## 一時的な発見とpin
Clientは、Operation Resultの`entry`型として発見したpathを、そのObjectを即時に観測せず、現在の結果として提示・利用できる。結果のpathを提示することと、Objectを取得することは別であり、発見したすべてのpathの即時取得は要求しない。
Operation Resultの`entry`型pathは、Objectを即時に観測しなくても、現在の結果として提示・利用できる。Pathの提示とObjectの取得は別であり、発見した全pathの即時取得は要求しない。
Objectの公開情報が必要になった時点で、Clientは必要なpathを観測できる。対象Objectだけが必要なら`depth = 0`を使う。Client policyとして先行取得してもよく、その場合はOperationのreturn typeからentry pathを抽出して重複を除去し、保持済みの観測と比較して必要な取得を行う。複数の`observe`が必要な場合、それぞれを個別のrequestとして並行実行できる。
公開情報が必要になった時点で、必要なpathを観測できる。対象Objectだけなら`depth = 0`を使う。Client policyとして先行取得してもよい。その場合はOperationのreturn typeからentry pathを抽出し、重複を除去して、保持済みの観測と比較したうえで必要な取得を行う。複数の`observe`は、それぞれ個別のrequestとして並行実行できる。
一時的に取得したエントリは、結果の利用が終わった時点で破棄してよい。
一時的に取得したエントリは、結果を使い終えた時点で破棄してよい。後続のInteractionでも必要なら、Client側でpinしてKnown Spaceに保持できる。PinはClient内部の保持方針であり、Host上のObject lifetimeやWIP Protocol上の状態を変えない。
後続のInteractionでも必要なエントリは、Client側でpinしてKnown Spaceへ保持できる。PinはClient内部の保持方針であり、Host上のObject lifetimeやWIP Protocol上の状態を変更しない。
単純なClientは発見したエントリをすべて保持してもよいが、WIPはそれを必須としない。具体的な容量制限やeviction algorithmはClient実装に委ねる。
単純なClientは、発見したエントリをすべて保持してもよい。ただし必須ではなく、容量制限やeviction algorithmはClient実装に委ねる。
## Objectとchildrenの観測
Clientは`observe(path, depth)`を使い、対象Objectだけが必要なら`depth = 0`、indexableな配下も必要なら正のdepthを指定する。一つのinteractionでrequested depthまでを取得するため、Clientが各nodeについてdata-dependentな取得requestを逐次発行する必要はない。
`observe(path, depth)`では、対象Objectだけが必要なら`depth = 0`、indexableな配下も必要なら正のdepthを指定する。一つのinteractionでrequested depthまで取得するため、Clientが各nodeに対してdata-dependentなrequestを逐次発行する必要はない。
Response nodeの`children`が省略されている場合、そのnodeのchildrenは未観測であり、空であるとは扱わない。`children`が存在する場合、その一覧は完全であり、空arrayならindexable childが存在しない。Clientは起点pathと各Objectの`name`からchild pathを導出する。`children`が存在するnodeをcacheへmergeするときは、そのEntryで観測済みのdirect child edgeをresponseの完全な一覧で置き換える。`children`が省略されたnodeは構造について新しい情報を持たないため、既存edgeを削除したり、観測済みの一覧を未観測へ戻したりしない。
Response nodeの`children`が省略されていれば、そのchildrenは未観測である。存在する場合は完全な一覧であり、空arrayならindexable childが存在しない。未観測と空を同じ状態として扱わない。
件数の非常に多い集合の個々の要素は、通常indexableな子エントリとして露出しない。個別要素は対象の集合を扱うObjectの`query`や`list`等のOperationを通して発見することを想定する。
Clientは起点pathと各Objectの`name`からchild pathを導出する。`children`があるnodeをcacheへmergeするときは、そのEntryの観測済みdirect child edgeを、responseの完全な一覧で置き換える。省略されたnodeは構造について新しい情報を持たないため、既存edgeを削除したり、観測済み一覧を未観測に戻したりしない。
件数の非常に多い集合では、通常、個々の要素をindexableな子エントリとして公開しない。集合を扱うObjectの`query`や`list`等のOperationを通して、個別要素を発見することを想定する。
## Interestと取得計画
Clientの上位層は、特定pathについて必要な観測depth、または特定Interface参照についてDescriptorが必要であることを、Client-localな**interest**として示せる。InterestはProtocol dataではなく、Hostはその状態を追跡しない。Interestの追加または削除は、保持済み観測のProtocol上の意味や有効性を変更しない。Interestがなくなった観測を保持するかevictするかはClient policyに委ねる。
Interestは、上位層がClientへ示す取得上の要求である。特定pathに必要な観測depthや、特定Interface参照のDescriptorが必要であることを示せる。Client-localな情報であり、Protocol dataではなく、Hostも追跡しない。
Clientはinterestを、現在有効なObject observation、children coverage、Interface Descriptor observation、および進行中の取得requestと比較し、不足するlogical interactionだけを発行できる。要求されたdepthまでのcoverageがすでに存在する場合、または進行中のrequestによって満たされる場合、同じinterestの調整処理は重複requestを発行しない。Depth境界で`children`が省略されたnodeは、その配下に対する正のdepthのinterestを満たさない。
Interestを追加・削除しても、保持済み観測のProtocol上の意味や有効性は変わらない。Interestがなくなった観測を保持するかevictするかは、Client policyに委ねる。
Clientは、interestを満たすためのidempotentな調整と、既存の観測を置き換える明示的な再観測を区別できる。明示的な再観測は、現在有効な観測または同じ対象の進行中requestがあっても新しいrequestを発行し、それ以前のrequestをsupersedeしてよい。
Clientはinterestを、現在有効なObject observation、children coverage、Interface Descriptor observation、進行中の取得requestと比較し、不足するlogical interactionだけを発行できる。要求depthまでのcoverageがすでにある場合や、進行中requestで満たされる場合、同じinterestの調整処理は重複requestを発行しない。Depth境界で`children`が省略されたnodeは、その配下への正のdepthのinterestを満たさない。
Clientは、保持する観測、進行中request、並列度、request rateへboundedな上限を設ける。上限によって新しい取得を開始できない場合、interest自体をProtocol failureとして扱わず、別のrequestの完了、容量の解放、またはinterestの変更後に再評価できる。具体的な優先順位、並行実行、prefetch範囲、fairness、cache容量、eviction algorithmはClient実装に委ねる。
このidempotentな調整と、既存観測を置き換える明示的な再観測は区別できる。明示的な再観測では、現在有効な観測や同じ対象の進行中requestがあっても、新たなrequestを発行して、それ以前のrequestをsupersedeしてよい。
Clientは、上位層から直接示されたinterestに加えて、観測したObjectのInterface参照やindexable child edgeから次のinterestを先行して導出してよい。WIPは全量取得、暗黙の再帰展開、または特定のprefetch範囲を要求しない。取得計画とevictionは、interestの変更や明示的な再観測がないまま同じ観測を繰り返し破棄して再取得する、自己維持的なloopを作ってはならない。
Clientは、保持する観測、進行中request、並列度、request rateに上限を設ける。上限のために取得を開始できなくても、interest自体をProtocol failureにはしない。別requestの完了、容量の解放、interestの変更後に再評価できる。優先順位、並行実行、prefetch範囲、fairness、cache容量、eviction algorithmはClient実装に委ねる。
複数の取得requestを並行実行するClientは、各responseを元のrequestとそのeffective Worldspace viewへ対応付ける。Clientがある観測状態のownershipを後続requestへ移した場合、supersedeされたrequestのresponseでその状態を上書きしない。Overlapping observationを部分的にmergeする場合も、後続requestが所有するObjectまたはchild coverageを以前のresponseで置き換えない。Success、Protocol failure、Transport failure、またはlocal cancellationによって終了したrequestを、進行中として残してはならない。
上位層から直接示されたinterestに加え、観測したObjectのInterface参照やindexable child edgeから、次のinterestを先行して導出してもよい。WIPは全量取得、暗黙の再帰展開、特定のprefetch範囲を要求しない。取得計画とevictionは、interestの変更や明示的な再観測がないまま、同じ観測を繰り返し破棄・再取得する自己維持的なloopを作ってはならない。
`observe`または`fetch_interface`の失敗を自動的に再試行するかはClient policyに委ねるが、retry回数、間隔、並列度はboundedでなければならない。取得requestのretry policyを`call_operation`の再実行へ適用せず、OperationについてはProtocolのfailure semanticsに従う。
並行取得では、各responseを元のrequestとそのeffective Worldspace viewに対応付ける。ある観測状態のownershipを後続requestへ移した場合、supersedeされたrequestのresponseでその状態を上書きしない。Overlapping observationを部分的にmergeする場合も、後続requestが所有するObjectやchild coverageを以前のresponseで置き換えない。
Success、Protocol failure、Transport failure、local cancellationで終了したrequestは、進行中として残してはならない。`observe`や`fetch_interface`の失敗を自動retryするかはClient policyに委ねるが、回数、間隔、並列度には上限が必要である。取得requestのretry policyを`call_operation`の再実行へ流用せず、OperationにはProtocolのfailure semanticsを適用する。
## Objectの同一性
`ref`は、同じ主体に公開された一つのWorldspace内で、複数の観測またはエントリが同じObjectを表すことを示すoptionalなopaque markerである。
`ref`は、複数の観測やエントリが同じObjectを表すことを示すoptionalなopaque markerである。同じ主体に公開された一つのWorldspace内で、同じ有効な`ref`があれば、同じObjectであることを保証する。
同じ有効な`ref`は同じObjectを保証する。異なるまたは欠落した`ref`からObjectが異なるとは判断しない。Clientは異なるWorldspaceの`ref`を比較せず、`ref`を永続的なprimary keyまたはNavigationに使用しない。
逆に、`ref`が異なる、あるいは欠けていることから、Objectが異なるとは判断しない。異なるWorldspace間の`ref`も比較しない。Clientは`ref`を永続的なprimary keyやNavigationに使わない。
Backend UIDが適している場合、Hostはそれを直接または変換して`ref`に利用できる。ただし、Clientは`ref`がbackend UIDであること、またはsessionやHost restartをまたいで安定することを仮定しない。
適したbackend UIDがあれば、Hostは直接または変換して`ref`に利用できる。ただしClientは、それがbackend UIDであることや、session・Host restartをまたいで安定することを仮定しない。
## 観測整合性
Clientは、Hostが提供した`ref`とvalidatorの保証範囲で、観測とOperation実行の整合性を管理する。Scopeの`ref`や対象Objectのvalidatorがない場合に、pathだけから観測時と同じObjectであると保証してはならない。Optional metadataの欠落自体は有効な公開形態であり、identity追跡不能を理由にProtocol違反としない。
Clientが観測とOperation実行の整合性を管理できるのは、Hostから得た`ref`とvalidatorの保証範囲である。Scopeの`ref`や対象Objectのvalidatorがない場合、pathだけで観測時と同じObjectだと保証してはならない。Optional metadataの欠落は有効な公開形態であり、identityを追跡できないことをProtocol違反にはしない。
Objectが`validator`を持つ場合、Clientは観測したpathとvalidatorを対応付ける。条件付きOperationでは両者をtargetとしてHostへ渡し、validatorの比較と実行をHost上でatomicに行わせる。ValidatorはAIやユーザーに直接管理させず、Transport BindingでもProtocol struct上のfieldとして保持する。HTTP ETag等のrepresentation metadataをWIP validatorの代用として解釈しない。
Objectに`validator`があれば、Clientは観測したpathと対応付ける。条件付きOperationでは両者をtargetとしてHostへ渡し、validatorの比較と実行をHost上でatomicに行わせる。AIやユーザーにvalidatorを直接管理させず、Transport BindingでもProtocol structのfieldとして保持する。HTTP ETag等のrepresentation metadataをWIP validatorの代用にしない。
ClientはOperationに選択したInterface参照と、`fetch_interface`で観測したoptionalな`scope_ref`およびInterface validatorもrequestへ含める。MutableなInterfaceがvalidatorを返す場合は必須preconditionとして使用し、`InterfaceValidatorMismatch`ではInterfaceだけを再観測する。`InterfaceMismatch`ではObjectを再観測して現在のInterface集合を取得し、scopeの紐付きが変わった可能性もあるため、使用したInterface observationも無効化して必要なら再取得する。
Interfaceについても、選択した参照と、`fetch_interface`で観測したoptionalな`scope_ref`およびInterface validatorをrequestへ含める。MutableなInterfaceがvalidatorを返す場合は、必須preconditionとして使う。`InterfaceValidatorMismatch`ではInterfaceだけを再観測する。
Operation responseが新しいObject validatorを返した場合、Clientは対応するObject observationへ反映する。
`InterfaceMismatch`では、Objectを再観測して現在のInterface集合を取得する。Scopeの紐付きが変わった可能性もあるため、使ったInterface observationも無効化し、必要なら再取得する。Operation responseが新しいObject validatorを返した場合は、対応するObject observationへ反映する。
## Failure handling
ClientはHostが返すProtocol errorの`code`で回復actionを決定し、人間向け`message`やTransport statusからcodeを推測しない。各interactionで許可されていないcode、schemaに違反するsuccess / error response、同じvalidatorに矛盾するrepresentationは`InvalidResponse`として拒否する。Validだが未対応のInterface Descriptor formatは`UnsupportedDescriptorFormat`として区別する。
回復actionは、Hostが返すProtocol errorの`code`で決める。人間向け`message`やTransport statusからcodeを推測しない。Interactionで許されないcode、schemaに違反するsuccess / error response、同じvalidatorに矛盾するrepresentationは、`InvalidResponse`として拒否する。有効だが未対応のInterface Descriptor formatは、`UnsupportedDescriptorFormat`として区別する。
- `NotFound`では対象Entryをstaleとして扱い、必要に応じて親を再観測する。
- `InterfaceNotFound`では参照元Objectを再観測できる。
@@ -154,32 +156,32 @@ ClientはHostが返すProtocol errorの`code`で回復actionを決定し、人
- `InterfaceValidatorRequired`または`InterfaceValidatorMismatch`では対象Interfaceを再観測する。
- `ValidatorRequired`または`ValidatorMismatch`では対象Objectを再観測する。
同じOperationを再試行するなら、先に新しい観測を取得しなければならない。
同じOperationを再試行するには、先に新しい観測を取得しなければならない。
- `InvalidRequest`または`InvalidArguments`では同じrequestを変更せずに再送しない。
- `ResourceLimitExceeded`ではlogical request shapeやobservation depth等を削減できるが、Operationを自動再実行しない。
- `PermissionDenied`では公開済みOperationが実行拒否されたことを示し、Object自体が閲覧禁止で存在するとは推測しない。
`OperationOutcomeUnknown`では、Operationが未実行またはrollback済みであることが保証されない。ClientはOperationを自動再実行せず、対象Objectをstaleとして再観測するか、domain固有の照会手段を提示する。`Internal`、Transport timeout、connection lossの場合もOperationを自動再実行しない。Response不達はProtocol errorへ変換せず、Transport failureとOperation outcomeが不明な状態をClient内部で保持する。WIPはOperationをObject stateへのeffectで分類してretry可否を推測しない。
`OperationOutcomeUnknown`は、Operationの未実行やrollback済みを保証しない。自動再実行せず、対象Objectをstaleとして再観測するか、domain固有の照会手段を提示する。`Internal`、Transport timeout、connection lossでも、Operationを自動再実行しない。
ClientがOperation結果の`entry`を付随的に取得する場合、その取得の成否は元のOperationの成否と分けて扱う。参照先の`observe`が失敗しても、成功済みOperationを失敗扱いしたり、そのOperationを再実行したりしてはならない。取得失敗は、その参照先への別のinteractionの失敗として提示・処理する。
Responseが届かなかった場合は、Protocol errorへ変換せず、Transport failureとOperation outcomeが不明な状態をClient内部に保持する。OperationをObject stateへのeffectで分類し、retry可否を推測することもしない。
HTTP authentication failureとWorldspace endpoint全体のaccess denialはTransport layerのfailureであり、WIPの`PermissionDenied`へ変換しない。
Operation結果の`entry`を付随的に取得するときは、その取得と元のOperationの成否を分ける。参照先の`observe`が失敗しても、成功済みOperationを失敗扱いしたり、再実行したりしてはならない。その参照先に対する別interactionの失敗として提示・処理する。
HTTP authentication failureとWorldspace endpoint全体のaccess denialは、Transport layerのfailureである。WIPの`PermissionDenied`へ変換しない。
## 想定実装
Clientは用途に応じて複数の上位インターフェースを提供できる。
Clientは、用途に応じて複数の上位インターフェースを提供できる。
- GUI上のWorldspace View
- [AI Tools](4.1-ai-tools.md)
- PTC / REPL向けスクリプティングAPI
これらは同一のKnown Space、Discoverable Space、Object identity、観測整合性管理を共有してよい。
PTC / REPL bindingでは、Operationを通常のメソッド呼び出しへ投影してよい。
これらは同じKnown Space、Discoverable Space、Object identity、観測整合性管理を共有してよい。PTC / REPL bindingでは、Operationを通常のメソッド呼び出しとして提示することもできる。
```python
issue.close(reason="duplicate")
```
この場合もClientがInterfaceとOperationを解決して`call_operation`を利用し、Object identityと観測整合性を管理する。AI Toolsの3操作は、そのAI向けインターフェースの契約であり、PTC / REPLの呼び出し構文を制限しない。
この呼び方でも、ClientがInterfaceとOperationを解決して`call_operation`を使い、Object identityと観測整合性を管理する。AI Toolsの3操作はAI向けインターフェースの契約であり、PTC / REPLの呼び出し構文を制限しない。
+26 -31
View File
@@ -2,9 +2,9 @@
## 目的と適用範囲
AI Toolsは、WIP ClientがAIへ提供する、対象の配置を見て、できることを理解し、操作するための上位インターフェースである。本章で定義するAI向けの基礎ツールは **tree / inspect / invoke** の3操作に固定する。
AIがWIPの対象を操作するには、その配置を見つけ、何ができるかを確認し、操作を選ぶ必要がある。Clientはこのための基礎ツールとして、**tree / inspect / invoke**の3操作を提供する。
Protocol interactionをそのままToolとして公開するものではない。Protocolの`observe` / `fetch_interface` / `call_operation`は[3. Protocol](3-protocol.md)、取得・cache・観測整合性の責務は[4. Client](4-client.md)に従う。GUIやPTC / REPLなど、他のClientインターフェースの構成は本章で制限しない。
この3操作は、Protocolの`observe` / `fetch_interface` / `call_operation`をそのまま公開したものではない。必要な取得、cache、観測整合性の管理はClientが引き受ける。Protocol interactionは[3. Protocol](3-protocol.md)、Clientの責務は[4. Client](4-client.md)に従う。GUIやPTC / REPLなど、他のClientインターフェースの構成は、この3操作に制限しない。
## 基本的な利用モデル
@@ -14,18 +14,17 @@ Protocol interactionをそのままToolとして公開するものではない
| `inspect(path)` | 対象の説明とできることを知る | Object観測、Interface集合の解決、signature生成 |
| `invoke(target, interface, operation, arguments)` | 選択した操作を名前付き引数で呼ぶ | 引数検証、観測との対応、validator、Protocol requestと結果の処理 |
これらはProtocol interactionとの一対一対応ではない。特に`inspect`の対象はInterface参照ではなく、Objectを指すpathである。必要な`observe`と複数の`fetch_interface`はClient内部で行う。
例えば`inspect`が受け取るのは、Interface参照ではなくObjectのpathである。Clientはそのpathに必要な`observe`と複数の`fetch_interface`を内部で行う。AI向け操作とProtocol interactionは、一対一には対応しない。
Inspectで見つけたOperationも`invoke`から呼び出し、Operationごとに新しいToolを登録しない。
Inspectで見つけたOperationは、`invoke`で呼ぶ。Operationごとに新しいToolを登録することはない。
大量のObjectの発見は、各ドメインのObjectが公開する`list` / `search` / `query`等のOperationで行う。件数制限、検索条件、ページング等は、そのドメインに応じて各Operationが管理する。AIはこれらのOperationも`inspect`で確認し、`invoke`で呼び出す。発見方法が増えても基礎ツールは追加・変更しない。
大量のObjectを発見する場合も、各ドメインのObjectが公開する`list` / `search` / `query`等をinspectし、invokeする。件数制限、検索条件、ページング等は、それぞれのOperationがドメインに応じて管理する。発見方法が増えても、基礎ツールは3操作のままである。
## `tree`: indexableな配置を見る
`tree(path, depth)`は、起点をdepth 0として、指定depth内のindexableなツリーを全量取得・表示する。
`tree(path, depth)`は、起点をdepth 0として、指定depth内のindexableなツリーを全量取得・表示する。「全量」の範囲は、指定した起点・depth・主体に公開されたindexableな範囲であり、Worldspace全体ではない。
- 必要なcoverageを持つ観測を再利用できる。不足する場合はClientが`observe`で取得する。
- 全量とは、指定した起点・depth・主体に公開されたindexableな範囲の全量であり、Worldspace全体ではない。
- 名前、path、親子構造を中心に提示する。すべてのObjectのDescriptorやドメインデータを展開しない。
- Protocolのdepth境界にある未観測のchildrenと、観測済みの空のindexable childrenを混同しない。
- 指定depth内の一部を黙って省略して完全なtreeとして返さない。既存のresource limit内で成立しない場合は、その失敗を伝える。
@@ -35,17 +34,17 @@ HostがTreeへ公開する範囲は、[Indexable childrenの条件](2.1-object-t
## `inspect`: 対象の説明とできることを知る
`inspect(path)`は、そのpathで公開されているObjectの説明と操作を返す。
`inspect(path)`は、そのpathで公開されているObjectの説明と操作を返す。AIは、treeでまだ見ていないpathも直接指定できる。
AIがそのpathをtree、会話、Operation結果のいずれから知ったかは、事前条件にしない。ClientがまだObjectを観測していなくても、有効なpathを直接指定できる。Known Spaceにないことだけを理由に拒否せず、現在のHostの公開状態に従って観測する。
Pathをtree、会話、Operation結果のどこから知ったかは事前条件にしない。Clientが未観測であっても、Known Spaceにないことだけを理由に拒否せず、現在のHostの公開状態に従って観測する。
Clientは次の情報を保持済みの観測から解決し、不足するものを取得する。
Clientは、保持済みの観測を使い、不足する情報を取得する。
1. 対象pathのObject。対象だけが必要なら`observe`の`depth = 0`を使用する。
2. Objectが公開するInterface参照のordered set。
3. 表示対象のInterfaceに対応する、取得・検証済みのDescriptor。
Clientはこれらの情報から、Objectの説明とInterfaceごとの操作を提示する。AIに「先にObjectをobserveして、Interface参照を抜き出し、一つずつfetchする」という手順を要求しない。一方で、Objectの本文やドメインmetadataまで暗黙に読み込むわけではない。それらの取得は対象のOperationとして扱う。
この情報から、Objectの説明とInterfaceごとの操作を提示する。AIにObjectのobserve、Interface参照の抽出、個別のfetchという手順を管理させない。ただし、Objectの本文やドメインmetadataまで暗黙に読み込むことはなく、それらは対象のOperationで取得する。
### 表示に必要な情報
@@ -54,47 +53,43 @@ Clientはこれらの情報から、Objectの説明とInterfaceごとの操作
- Operation名、短い用途説明、名前付き引数、必須性、引数・結果の型。
- 操作を理解するために必要な名前付き型・複合型の定義。
生のDescriptor JSONを返すだけではなく、検証済みの情報から読みやすいObject signatureとInterface signatureを生成する。各signatureの表記は[4.2. Text View](4.2-text-view.md)に従う。同名Operationが複数Interfaceに存在しても、一つへ平坦化したり、出所を失ったりしない。
Clientは生のDescriptor JSONを返すだけでなく、検証済み情報からObject signatureとInterface signatureを生成する。表記は[4.2. Text View](4.2-text-view.md)に従う。同名Operationが複数Interfaceにあっても、一つへ平坦化したり、出所を失ったりしない。
Invokeへ渡すInterface参照とOperation名は区別して保持し、表示textを再parseして呼出先を決めない。Interfaceの未展開や取得失敗を「操作が存在しない」と誤表示しない。
Invokeへ渡すInterface参照とOperation名は、表示とは別に保持する。表示textを再parseして呼出先を決めず、Interfaceの未展開や取得失敗も「操作が存在しない」と誤表示しない。
Signatureの配置や、詳細表示・表示対象を選択する具体的なTool引数は本章で固定しない。個々のsignatureを生成するときの全宣言の表示規則はText Viewに従い、表示側でInterface内部を切り詰めない。
Signatureの配置、詳細表示、表示対象を選ぶ具体的なTool引数は固定しない。一方、個々のsignatureはText Viewの全宣言の表示規則に従う。表示側でInterface内部を切り詰めない。
## `invoke`: 選んだ操作を実行する
`invoke(target, interface, operation, arguments)`は、対象ObjectのInterfaceとOperationを明示して呼び出す。`target`は対象Objectのpathを指定するものであり、AIにProtocolのvalidator付きTargetを組み立てさせるものではない。
`invoke(target, interface, operation, arguments)`は、対象ObjectのInterfaceとOperationを明示して呼び出す。同じObjectの複数Interfaceに同名Operationがあり得るため、Interfaceも選ぶ必要がある。
`arguments`はOperationのparameter declarationに従う名前付きfieldのrecordであり、位置引数ではない。引数を持たないOperationには空のrecordを渡す。
`target`で指定するのは対象Objectのpathである。Protocolのvalidator付きTargetをAIに組み立てさせるものではない。`arguments`はparameter declarationに従う名前付きfieldのrecordであり、位置引数ではない。引数のないOperationには空のrecordを渡す。
Interfaceを明示するのは、同じObjectの複数Interfaceに同名Operationがあり得るためである。Interfaceの選択をAIへ示すことと、Descriptorの取得手順をAIに管理させることは別である。
Interfaceの選択はAIへ示すが、Descriptorの取得手順はAIに管理させない。選択するInterfaceは、絶対scopeとlocal nameの組で識別する。Adapterが[Text Viewの短縮表記](4.2-text-view.md#参照表記)を入力として受ける場合は、入力境界で構造化参照へ変換し、Operation名を独立して保持する。Scopeの省略には明示contextが必要であり、対象pathからの推測や相対scopeの解決はしない。短縮表記のstringをProtocolへそのまま送らない。
選択するInterfaceは絶対scopeとlocal nameの組で識別する。Adapterが[Text Viewの短縮表記](4.2-text-view.md#参照表記)を入力として受ける場合も、入力境界で構造化参照へ変換し、Operation名は独立して保持する。Scope省略には明示contextが必要であり、対象pathからの推測や相対scopeの解決はしない。Protocolへ短縮表記のstringをそのまま送らない。
ClientはObjectとDescriptorの観測を保持して引数を検証し、path、Object validator、Interface参照とvalidator、観測に存在する`scope_ref`をProtocol requestへ設定する。AIにvalidatorやscope Objectの`ref`を取得・コピー・更新させず、同一性管理やvalidatorをsignatureにも含めない。`ref`のないscopeではidentityによる差し替え検出ができないことを許容し、AIへ代替identityを要求しない。
ClientはObjectとDescriptorの観測を保持し、引数を検証し、path、Object validator、Interface参照とvalidator、および観測に存在する`scope_ref`をProtocol requestへ設定する。AIにvalidatorやscope Objectの`ref`の取得・コピー・更新をさせない。同一性管理やvalidatorはsignatureに含めない。`ref`のないscopeではidentityによる差し替え検出ができないことを許容し、AIへ代替identityの指定を要求しない。
Interfaceが表示されていても、それだけで実行権限があるとは限らない。Pathを知っていることも同様である。Hostは呼出時の公開状態、権限、capability、実行条件を検証し、Clientは返されたresultをDescriptorに従って検証してから提示する。
Pathを知っていることやInterfaceが表示されたことは、実行権限を意味しない。Hostは呼出時の公開状態、権限、capability、実行条件を引き続き検証する。ClientはresultをDescriptorに従って検証してから提示する。
再観測とOperationの再実行を同一視しない。Stale、取消、拒否、結果不明などの扱いはProtocolと[ClientのFailure handling](4-client.md#failure-handling)に従う。結果不明のOperationを自動再実行せず、Operation名からread / writeやretry可否を推測しない。
再観測とOperationの再実行は、別の処理である。Stale、取消、拒否、結果不明などは、Protocolと[ClientのFailure handling](4-client.md#failure-handling)に従って扱う。結果不明のOperationを自動再実行せず、Operation名からread / writeやretry可否を推測しない。
## Pathの発見と移動
AIはtree、会話で示されたpath、Operation結果の`entry`などから次の対象を知ることができる。Pathを知っていること、ClientがObjectを観測・保持していること、indexable edgeも観測していることは別の状態である。[Clientの取得・保持・提示の分離](4-client.md#取得保持提示の分離)に従い、未観測のpathは必要になった時点でinspectできる。
AIはtree、会話で示されたpath、Operation結果の`entry`などから次の対象を知ることができる。しかし、pathを知ること、ClientがObjectを観測・保持すること、indexable edgeも観測することは別である。[Clientの取得・保持・提示の分離](4-client.md#取得保持提示の分離)に従い、未観測のpathは必要になった時点でinspectできる。
Clientが内部で保持する情報とAIに表示済みの情報は一致する必要がない。Treeの取得でObject情報を保持していても、AIには名前と構造だけを見せ、詳しい説明と操作はinspectで提示できる。
Clientが保持する情報と、AIに表示済みの情報も一致する必要はない。Treeの取得でObject情報を保持していても、AIには名前と構造だけを見せ、詳しい説明と操作はinspectで提示できる。
Operation結果の`entry`型pathは、そのまま次の対象への参照として提示できる。すべての結果を即時に観測したり、再帰展開したりすることを必須にしない。AIが必要なpathを選んでinspectするときに、Clientが観測できる。
Operation結果の`entry`型pathは、次の対象への参照としてそのまま提示できる。全件を即時に観測したり再帰展開したりする必要はなく、AIが必要なpathを選んでinspectするときに観測できる。Entryの抽出はDescriptorの型に従い、普通のstringを内容だけからpathと推測しない。結果のentryを観測・保持しても、それだけではindexable edgeを追加しない。
Entryの抽出はDescriptorの型に従う。普通のstringを内容だけからpathと推測しない。結果のentryを観測・保持しても、それだけでindexable edgeを追加しない。
Clientが付随的なentry取得を行う場合、その取得失敗と元のOperationの成否を混同しない。成功済みOperationを、結果の参照先が取得できなかったために失敗扱いして再実行させてはならない。
Clientが付随的にentryを取得する場合、参照先の取得失敗を元のOperationの失敗と混同しない。すでに成功したOperationを、参照先が取得できなかったために失敗扱いして再実行させてはならない。
## Tool bindingと表示
本章の小文字表記は操作の呼称であり、providerごとのTool登録名の大文字・小文字やProtocol名の接頭辞は規定しない。AI providerがTool schemaを要求する場合は、Client adapterがこの3操作のschemaを提供する。Hostにprovider固有のTool schemaを提供させたり、取得したDescriptorごとにToolを追加登録したりしない。DescriptorはClient内部のOperation validationとsignature生成に用いる。
`tree`、`inspect`、`invoke`という小文字表記は操作の呼称であり、providerごとのTool登録名の大文字・小文字やProtocol名の接頭辞を規定しない。AI providerがTool schemaを要求する場合は、Client adapterが3操作のschemaを提供する。Hostへprovider固有のschemaを要求したり、取得したDescriptorごとにToolを追加登録したりしない。DescriptorはClient内部のOperation validationとsignature生成に使う。
Treeの具体的なtext layout、`depth`等の引数のdefault、inspectの表示選択引数、Tool response envelopeについて、本章は共通の具体schemaを定義しない。各bindingは、それらを提供するときにAIへ明示する契約として定め、本章の操作の意味を変えない。Text Viewもsignatureを包むresponse構造や配置を定義するものではない。
Treeのtext layout、`depth`等のdefault、inspectの表示選択引数、Tool response envelopeには、共通の具体schemaを定めない。各bindingは、それらを提供するときにAIへ明示する契約として定め、3操作の意味は変えない。Text Viewも、signatureを包むresponse構造や配置までは定義しない。
取得・表示・cache保持を分離するが、特定の内部class構成、eviction algorithm、prefetch schedulerは要求しない。
取得・表示・cache保持は分離する。ただし、特定の内部class構成、eviction algorithm、prefetch schedulerは要求しない。
## 検証する利用シナリオ
+31 -21
View File
@@ -2,13 +2,13 @@
## 位置付け
WIP Text Viewは、ObjectとInterfaceをAIおよび人間へ提示するためのプレーンテキスト表示形式である。ClientのTool結果、CLI、GUIのテキスト表示などで共通に利用できる。
Objectの公開情報と、Interfaceの型・Operation・documentationは、Clientが取得・検証したデータである。それをAIや人間へプレーンテキストで示す形式が、WIP Text Viewである。Tool結果、CLI、GUIのテキスト表示などで共通に使える。
この章では、一つのObjectの公開情報を表す **Object signature** と、一つのInterfaceの型・Operation・documentationを表す **Interface signature** の表記を定義する。ここでのsignatureは表示上のまとまりを指し、暗号学的な署名やidentityではない。
一つのObjectの公開情報を表すまとまりをObject signature、一つのInterfaceの型・Operation・documentationを表すまとまりをInterface signatureと呼ぶ。Signatureは表示上のまとまりであり、暗号学的な署名やidentityではない。
どのObjectやInterfaceを表示するか、各signatureをどこにどの順序で並べるか、同時に提示するかは表示側が決める。本章はsignatureを包む共通document構造、ObjectとInterfaceの組み合わせ、Tool response envelopeを定義しない。
表示対象、配置、順序、両signatureを同時に提示するかは、表示側が決める。Signatureを包む共通document構造、ObjectとInterfaceの組み合わせ、Tool response envelopeは定義しない。
データの正本は[3. Protocol](3-protocol.md)のObjectおよびInterface Descriptorであり、Text Viewは検証済みの情報から生成する表示である。
データの正本は[3. Protocol](3-protocol.md)のObjectとInterface Descriptorである。Text Viewは、検証済みの情報から生成する表示である。
- Interfaceの交換形式、手書きのschema言語、Objectのserializationではない。
- Parser、round-trip、表示textからのDescriptor復元は要求しない。
@@ -18,11 +18,11 @@ WIP Text Viewは、ObjectとInterfaceをAIおよび人間へ提示するため
## 表示の入力と責務
Object signatureは検証済みObjectと、分かる場合はそのObjectを観測したpathから生成する。PathはObjectのfieldではなく配置contextである。Object signatureの生成にInterface Descriptorは必要ない。
Object signatureの入力は、検証済みObjectと、分かる場合はそのObjectを観測したpathである。Interface Descriptorは必要ない。PathはObjectのfieldではなく、配置contextとして使う。
Interface signatureは、Interface参照と、それに対応する検証済みかつ対応formatのInterface Descriptorから生成する。Interface参照はDescriptor自身のfieldではない。Interface signatureの生成にObjectは必要ない。
一方、Interface signatureの入力は、Interface参照と、それに対応する検証済みかつ対応formatのDescriptorである。Objectは必要ない。Interface参照も、Descriptor自身のfieldではない。
観測、Descriptor取得、cache、表示対象の選択、rendererの呼び出しAPIや内部structは本章で規定しない。表示は観測時点の公開情報であり、最新状態、Operationの実行権限、実行成功を保証しない。
どちらも観測時点の公開情報を表示するものであり、最新状態、Operationの実行権限、実行成功は保証しない。観測、Descriptor取得、cache、表示対象の選択、rendererの呼び出しAPIや内部structは規定しない。
Object tree全体の描画、Operation arguments / resultのvalue表示、Protocol errorや診断metadataの表示は本章の対象に含めない。
@@ -54,19 +54,25 @@ Interface参照のscopeとlocal nameの境界は`::`、InterfaceとOperationの
"/github"::"issue.read"#"read"
```
最後の例は`/github::issue.read#read`と同じ成分を表す。引用やescapeは元の値を変えず、ProtocolへASCII制限や禁止文字を追加しない。Unicode normalization、case変換、URL encodingをしない。制御文字等には[名前と文字列](#名前と文字列)の安全なescape規則も適用する。境界を読む場合は引用とescapeを考慮し、単純な文字列splitを使用しない。
最後の例と`/github::issue.read#read`は、同じ成分を表す。引用やescapeを変えても、元の値は変わらない。ProtocolへASCII制限や禁止文字を追加せず、Unicode normalization、case変換、URL encodingも行わない。
制御文字等には[名前と文字列](#名前と文字列)の安全なescape規則も適用する。境界を読むときは引用とescapeを考慮し、単純な文字列splitを使わない。
### Scope省略とcontext
Scopeの相対pathは、Protocol dataにも短縮表記にも認めない。`github::issue.read`や`../github::issue.read`を相対scopeとして解決しない。Scopeを明示するなら、引用の有無にかかわらずcanonical absolute pathを使う。
`issue.read#read`やInterfaceだけの`issue.read`は、scopeが別途明示されたcontextでのみ使える省略形である。Scopeの省略はroot scope `/`の指定とは異なる。Contextがなければ解決できず、rootへのdefault、対象Objectのpathからの推測、祖先の同名Interfaceの探索は行わない。Scopeが確定してもmembership、祖先制約、authorizationは検証する。
`issue.read#read`や、Interfaceだけの`issue.read`は、scopeが別途明示されたcontextでのみ使える省略形である。省略はroot scope `/`の指定ではない。Contextがなければ解決できず、rootへのdefault、対象Objectのpathからの推測、祖先の同名Interfaceの探索も行わない。
Scopeが確定した後も、membership、祖先制約、authorizationは検証する。
短縮表記を入力として受けるかはToolやUIが決める。受ける場合は専用の入力境界で成分を検証し、構造化参照とOperation名へ変換する。Signature全体を再parseして呼出先を決めることとは区別し、`invoke`を単一string引数の操作へ変更しない。
### Signature内の参照
Object signatureとInterface signatureでは、公開先の絶対scopeを含む完全な短縮表記を生成し、その全体をJSON stringとして引用表示する。外側の引用はsignatureの文字列表記であり、成分の引用とは別の層である。例えばscope `/github`、name `issue#read`の参照は`"/github::\"issue#read\""`と表示する。Scopeを省略したり、Upstreamの参照へ戻したりしない。
両signature内のInterface参照は、公開先の絶対scopeを含む完全な短縮表記を生成し、その全体をJSON stringとして引用する。例えば、scope `/github`、name `issue#read`の参照は`"/github::\"issue#read\""`となる。
成分ごとの引用と、参照全体をsignature内の文字列として示す外側の引用は、別の層である。Scopeを省略したり、Upstreamの参照へ戻したりしない。
## Object signature
@@ -88,11 +94,11 @@ Block内は次の順に表示する。
Descriptionがない場合はそのpropertyを省略し、存在する空文字列は`description: "";`と表示する。説明の欠落からObjectの用途を補完しない。
Rootは`object at "/"`かつ`name: "";`となり、scope `/`のInterfaceを公開できる。Interface参照は[参照表記](#参照表記)に従い絶対scopeを含め、別の参照やlocal nameだけへ置き換えない。Scope Objectの`ref`やvalidatorを`@...`として参照へ付け足さず、`scope_ref`はClient runtimeの観測・precondition metadataとして扱う。
Rootの表示は`object at "/"`かつ`name: "";`となり、scope `/`のInterfaceを公開できる。Interface参照は[参照表記](#参照表記)に従って絶対scopeを含め、別の参照やlocal nameだけへ置き換えない。
`ref`とvalidatorはObject signatureへ含めない。同一性管理と条件付き実行はClient runtimeの責務のままである。Objectの本文やdomain metadataを推測してpropertyとして追加しない。
Scope Objectの`ref`やvalidatorを`@...`として参照に付け足さない。`scope_ref`はClient runtimeが扱う観測・precondition metadataである。Object自身の`ref`とvalidatorもsignatureへ含めず、同一性管理と条件付き実行はClient runtimeが引き受ける。
ChildrenもObject signatureに含めない。表示にchildrenがないことは、未観測または観測済みの空集合を意味しない。
Objectの本文やdomain metadataを推測してpropertyとして追加しない。Childrenもsignatureに含めないため、表示にchildrenがないことから、未観測か観測済みの空集合かを判断することはできない。
## Interface signature
@@ -120,11 +126,11 @@ interface "/::issue.read" {
Interfaceは`interface "<reference>" { ... }`と表示する。`<reference>`は構造化参照から生成した完全な短縮表記であり、前述の規則で全体を引用表示する。
Block内では、Descriptorの全`types`を宣言順に、続いて全`operations`を宣言順に表示する。Record field、parameter、enum / union caseもすべて元の順序で表示する。この順序はsignature内部の表示規則であり、Protocol上の名前解決やvalidationを変更しない。
Block内には、Descriptorの全`types`、全`operations`の順で、それぞれを宣言順に表示する。Record field、parameter、enum / union caseも元の順序を保つ。これは表示の順序であり、Protocol上の名前解決やvalidationには影響しない。
Interface signatureでは宣言の折りたたみや抜粋、budgetによる省略を行わない。型を`...`へ置き換えたり、field、parameter、caseを削ったりしない。DescriptorにtypeもOperationもない場合は空のblockとなる。
宣言を折りたたんだり抜粋したりせず、budgetによる省略も行わない。型を`...`へ置き換えず、field、parameter、caseを削らない。DescriptorにtypeもOperationもなければ、空のblockを表示する。
異なるInterfaceの宣言を一つのnamespaceへ平坦化しない。同名Operationも各Interfaceのblock内に表示する。Blockの参照が出所を示すため、Operation名を改名したり、参照をOperation名へ連結したりしない。
同名Operationが異なるInterfaceにあっても、それぞれのblock内に表示する。Blockの参照によって出所を示し、Operation名を改名したり、参照をOperation名へ連結したりしない。異なるInterfaceの宣言を、一つのnamespaceへ平坦化しない。
### 型の表記
@@ -140,9 +146,9 @@ Interface signatureでは宣言の折りたたみや抜粋、budgetによる省
Named type declarationは`type Name = Type;`とする。Enum、unionを含むすべてのTypeExprを、Descriptorで現れる位置にそのまま表示する。Named typeは同じInterface Descriptor内の宣言を参照し、別Interfaceの同名typeとは混同しない。
`?`は`required = false`のfieldまたはparameterにだけ付ける。Nullable、default value、一般化したoptional型は意味しない。`unit`とoptionalの違いを維持する。
`?`を付けるのは、`required = false`のfieldまたはparameterだけである。Nullable、default value、一般化したoptional型を示す記号ではなく、`unit`とも区別する。
Payloadのないunion caseは`empty`、payloadがあるcaseは`found(Type)`とする。`empty`と`empty(unit)`を区別する。
Unionでは、payloadがなければ`empty`、あれば`found(Type)`と表示する。そのため、`empty`と`empty(unit)`は異なる表示になる。
```text
type CloseResult = union {
@@ -202,9 +208,11 @@ Escapeは表示上のものであり、元の値は変更しない。
## Documentation
Documentationがある場合は対象の直前に`/// "<summary>"`を表示する。対象はInterface、type、Operation、parameter、record field、enum / union caseである。Objectの説明はこの表記ではなく、Object signatureの`description` propertyで表示する。
Documentationは、対象の直前に`/// "<summary>"`として表示する。対象はInterface、type、Operation、parameter、record field、enum / union caseである。Objectの説明だけは、Object signatureの`description` propertyを使う。
通常表示では`summary`を使う。表示側がdetailsを含める場合は、同じ対象のsummary行に続けて`/// details "<details>"`を追加する。Summaryと選択されたdetailsは短縮せず表示し、documentationがない対象へ説明を生成しない。存在する空文字列は`""`として表示する。
通常表示には`summary`を使い、detailsを含める場合は、同じ対象のsummary行に続けて`/// details "<details>"`を追加する。表示するsummaryと、選択されたdetailsは短縮しない。
Documentationがなければ、説明を生成して補わない。空文字列が存在する場合は、`""`として表示する。
ReturnDeclarationのdocumentationは、parameter listの閉じ括弧の後、return arrowの直前に置く。
@@ -225,4 +233,6 @@ operation search(
Text ViewはUTF-8 plain textとし、ANSI color、Markdown、syntax highlightingがなくても読めるようにする。本章のcode fenceは説明用であり、signatureそのものの一部ではない。Markdown内へ埋め込む場合は、表示側が内容に衝突しないcode fence等を選ぶ。
Signature内部の標準的なlayoutはLF、2 space indentとする。短いrecord、parameter list、enum / unionは1行に置ける。Documentationを持つfieldやcaseは別行に置く。表示用の改行幅やindentの違いは意味を持たず、byte単位のcanonical renderingは要求しない。文字列・名前の内部にある空白は元の値として保持する。
標準的なsignature内部のlayoutは、LFと2 space indentを使う。短いrecord、parameter list、enum / unionは1行に置けるが、documentationを持つfieldやcaseは別行に置く。
表示用の改行幅やindentの違いに意味はなく、byte単位のcanonical renderingは要求しない。一方、文字列・名前の内部にある空白は表示上の余白ではないため、元の値として保持する。
+22 -22
View File
@@ -1,12 +1,12 @@
# 5. Transport Bindings
WIP Transport Bindingは、[3. Protocol](3-protocol.md)のlogical data modelとCore interactionを、具体的な通信方式とwire representationへ対応付ける。
WIP Transport Bindingは、[3. Protocol](3-protocol.md)で定義するlogical data modelとCore interactionを、具体的な通信方式とwire representationへ対応付ける。
標準bindingは[5.1. WIP over HTTP](5.1-wip-over-http.md)で定義する。
標準bindingの定義は[5.1. WIP over HTTP](5.1-wip-over-http.md)にある。
## 責務
Transport Bindingは、少なくとも次を定義する。
Transport Bindingには、少なくとも次の定義が必要になる。
- Endpointまたはpeerの指定方法。
- Requestとresponseのframing、および一つのlogical interactionとの対応付け。
@@ -16,27 +16,27 @@ Transport Bindingは、少なくとも次を定義する。
- Transport failureとProtocol failureの区別。
- ValidatorおよびOperation preconditionのmapping。
BindingはProtocolのlogical type、validation、error、visibility、Operation executionの意味を変更してはならない。Binding固有のstatus、header、stream event等を根拠として、新しいProtocol failureまたは回復actionを暗黙に追加してはならない。
これらは通信上の表現を定めるものであり、BindingはProtocolのlogical type、validation、error、visibility、Operation executionの意味を変更してはならない。Binding固有のstatus、header、stream event等を根拠に、新しいProtocol failureや回復actionを暗黙に追加してはならない。
## Logical interactionとphysical exchange
一つのCore interactionは、一つ以上のphysical messageを使用して実装できる。ただし、ClientとHostは各successまたはProtocol failureを、元のlogical requestおよびそのeffective Worldspace viewへ一意に対応付けられなければならない。
一つのCore interactionを、一つ以上のphysical messageで実装してよい。その場合も、ClientとHostは各successまたはProtocol failureを、元のlogical requestとそのeffective Worldspace viewへ一意に対応付けられなければならない。
複数のCore interactionは、それぞれ独立したrequestとresponseを持つ。Clientはそれらを並行実行でき、Transport実装は複数のexchangeを一つのconnection上でmultiplexできる。WIPは複数のinteractionを包む共通request / response envelope、transaction、共通snapshot、request間のdata dependencyを定義しない。
複数のCore interactionは、それぞれ独立したrequestとresponseを持つ。Clientは並行実行でき、Transport実装は複数のexchangeを一つのconnection上でmultiplexできる。ただし、WIPは複数のinteractionを包む共通request / response envelope、transaction、共通snapshot、request間のdata dependencyを定義しない。
## Effective Worldspace view
Endpoint、認証主体、tenant、capability、その他のdeployment contextによって、同じHostが異なるClient-facing Worldspaceを公開できる。
同じHostでも、endpoint、認証主体、tenant、capability、その他のdeployment contextに応じて、異なるClient-facing Worldspaceを公開できる。
Clientは異なるeffective Worldspace viewのObject observation、Interface observation、validator、Known Spaceを混在させない。Transport connectionの再利用やmultiplexingによって、この分離を失ってはならない。
Clientは、異なるeffective Worldspace viewのObject observation、Interface observation、validator、Known Spaceを混在させない。Connectionを再利用したりexchangeをmultiplexしたりする場合も、この分離を失ってはならない。
どのauthentication方式または通信securityを使ってviewを確立するかは、Transport実装とdeploymentの責務であり、WIPは標準化しない。
Viewを確立するためのauthentication方式と通信securityは、Transport実装とdeploymentが選択する。WIPはこれらを標準化しない。
## Protocol failureとTransport failure
Hostがlogical interactionを受理して返す`ProtocolError`はProtocol failureである。Transport Bindingは、これを機械可読なwire representationへ対応付ける。
Hostがlogical interactionを受理したうえで返す`ProtocolError`がProtocol failureである。Transport Bindingは、そのerrorを機械可読なwire representationへ対応付ける。
次はProtocol failureではない。
一方、次のfailureはProtocol failureではない。
- Endpointまたはrouteへ到達できない。
- Transport implementationまたはdeploymentがrequestを拒否する。
@@ -47,32 +47,32 @@ Hostがlogical interactionを受理して返す`ProtocolError`はProtocol failur
ClientはTransport failureから`ProtocolErrorCode`を推測しない。Transport authentication failureを`PermissionDenied`へ、未知routeを`NotFound`へ、timeoutを`Internal`または`OperationOutcomeUnknown`へ変換しない。
Protocol上の`OperationOutcomeUnknown`はHostが返すProtocol failureである。Response不達によってClient側でOperation outcomeを確定できない状態はTransport failureであり、Hostから同codeを受信したことにはしない。
`OperationOutcomeUnknown`も、Hostが返すProtocol failureの一つである。Response不達によってClientがOperation outcomeを確定できない場合はTransport failureとして扱い、Hostから同codeを受信したことにはしない。
## Dispatchとreplay
Transport Bindingは、physical exchangeの再送によって一つのlogical `call_operation`を複数回dispatchしてはならない。
Transport Bindingは、physical exchangeを再送することで、一つのlogical `call_operation`を複数回dispatchしてはならない。
RequestがHostへdispatchされた可能性のある状態でresponseを取得できなかった場合、Clientは`call_operation`を自動再実行しない。Connection close、timeout、local cancellationは、Host上の実行またはcommitを取り消した証拠ではない。
RequestがHostへdispatchされた可能性があり、responseを取得できなかった場合、Clientは`call_operation`を自動再実行しない。Connection close、timeout、local cancellationが起きても、Host上の実行やcommitが取り消された証拠にはならない。
取得interactionを再送するか、どのtimeoutやretry policyを使用するかはClientとTransport実装の責務である。取得用policyを`call_operation`へ適用しない。
取得interactionの再送とtimeout・retry policyは、ClientとTransport実装が決定する。取得用のpolicyを`call_operation`へ適用しない。
## Validator
Object validatorとInterface validatorはProtocol structのlogical fieldであり、Bindingはそれらをlosslessにencodeする。
Object validatorとInterface validatorは、Protocol structのlogical fieldである。Bindingはこれらをlosslessにencodeする。
Transport固有のcache validator、conditional request metadata、message identifier等は、WIP validatorと独立している。それらを理由にProtocol bodyのvalidatorを省略せず、ClientもTransport metadataをWIP validatorとして解釈しない。
Transport固有のcache validator、conditional request metadata、message identifier等は、WIP validatorとは独立している。これらのmetadataがあってもProtocol bodyのvalidatorを省略せず、ClientもTransport metadataをWIP validatorとして解釈しない。
## Transport運用との境界
通信scheme、TLS、peer authentication、proxy、gateway、HTTP cache、compression、connection管理、message size、timeout、concurrency、rate limit等はTransport実装またはdeploymentの関心であり、WIPは値、negotiation、運用profileを定義しない。
通信scheme、TLS、peer authentication、proxy、gateway、HTTP cache、compression、connection管理、message size、timeout、concurrency、rate limit等は、Transport実装またはdeploymentが設定・運用する。WIPはそれらの値、negotiation、運用profileを定義しない。
それらの設定によってrequestまたはresponseを交換できない場合はTransport failureである。HTTP status等がProtocol errorのcanonical mappingと偶然一致しても、validなProtocol error representationを受信しない限りProtocol failureへ変換しない。
これらの設定によってrequestやresponseを交換できない場合は、Transport failureとなる。HTTP status等がProtocol errorのcanonical mappingと偶然一致しても、validなProtocol error representationを受信しない限り、Protocol failureへ変換しない。
WIPのlogical struct、observation completeness、TypeExpr / Value、Host execution等に対する`ResourceLimitExceeded`は[3. Protocol](3-protocol.md)で定義する。Transport implementation自身のmessage-size、timeout、queue、connection等の上限を同codeで包まない。
これに対し、WIPのlogical struct、observation completeness、TypeExpr / Value、Host execution等に対する`ResourceLimitExceeded`は[3. Protocol](3-protocol.md)に従う。Transport implementation自身のmessage-size、timeout、queue、connection等の上限を、同codeで包まない。
## Versioning
各Bindingは、wire互換性へ影響するmajor versionの選択方法を定義する。異なるmajor version間でroute、message、fieldを推測変換しない。
各Bindingは、wire互換性に影響するmajor versionの選択方法を定義する。異なるmajor version間で、route、message、fieldを推測して変換しない。
ProtocolまたはInterface Descriptorのversionと、Transport Bindingのversionは別である。Transport major versionが同じでも、Interface Descriptorの`format`は独立して検証する。
ProtocolまたはInterface Descriptorのversionは、Transport Bindingのversionとは別に扱う。Transport major versionが同じ場合も、Interface Descriptorの`format`を独立して検証する。
+107 -93
View File
@@ -1,33 +1,33 @@
# 5.1. WIP over HTTP
WIP over HTTPは、[3. Protocol](3-protocol.md)のlogical data modelをHTTP request / responseとJSONへ対応付ける標準Transport Bindingである。[5. Transport Bindings](5-transports.md)の共通要件に従う。
WIP over HTTPは、[3. Protocol](3-protocol.md)のlogical data modelをHTTP request / responseとJSONへ対応付ける標準Transport Bindingである。HTTP上の表現は、[5. Transport Bindings](5-transports.md)の共通要件に従って定める。
## 目的と範囲
このbindingは、次のCore interactionをHTTPへ対応付ける。
HTTPへ対応付けるCore interactionは、次の三つである。
- `observe`
- `fetch_interface`
- `call_operation`
HTTP version、communication scheme、TLS、authentication方式、connection reuse、multiplexing、proxy、gateway、cache、Host内部のframework、backend接続方式は規定しない。HTTP実装とdeploymentは、それらをWIPとは独立して選択する。複数のCore interactionが必要な場合も、それぞれを独立したHTTP request / responseとして交換する。
HTTP version、communication scheme、TLS、authentication方式、connection reuse、multiplexing、proxy、gateway、cache、Host内部のframework、backend接続方式は規定しない。これらはHTTP実装とdeploymentが、WIPとは独立して選択する。複数のCore interactionが必要な場合も、それぞれを独立したHTTP request / responseとして交換する。
OperationがWebSocket等のendpointをApplication dataとして返すことは妨げない。そのendpoint上のprotocol、状態、lifecycleはWIPの規定対象外である。
Operationは、WebSocket等のendpointをApplication dataとして返してよい。ただし、そのendpoint上のprotocol、状態、lifecycleは、WIPの規定対象外である。
## Endpoint
WIP endpointは、一つのWorldspace access surfaceを指すabsolute hierarchical base URLである。Endpoint URLのpath prefixはdeploymentが任意に選択できる。Clientはorigin直下、`/wip`等の既定prefix、またはWorldspace pathとの対応を仮定しない。
WIP endpointは、一つのWorldspace access surfaceを指すabsolute hierarchical base URLである。URLのpath prefixはdeploymentが任意に選択できる。Clientはorigin直下や`/wip`等の既定prefixを仮定せず、Worldspace pathとの対応も仮定しない。
Endpoint URLは次を満たす。
Endpoint URLには、次の条件を適用する。
- HTTP実装がrequest先として使用できるabsolute URLである。
- Authorityとhostを持つ。
- Queryとfragmentを持たない。
- Pathが`/`で終わるcanonical formである。
利用者から末尾`/`のないURLを受け付ける実装は、routeを解決する前に`/`を追加してcanonical formへ変換する。URL schemeと通信securityの選択はHTTP実装とdeploymentの責務であり、このbindingは制約しない。
利用者から末尾`/`のないURLを受け付ける実装は、routeを解決する前に`/`を追加し、canonical formへ変換する。URL schemeと通信securityはHTTP実装とdeploymentが選択し、このbindingは制約しない。
各routeはendpoint URLをbase URLとして、次のrelative referenceをRFC 3986に従って解決する。すべてのinteractionは`POST`を使用する。
各routeは、endpoint URLをbase URLとして、次のrelative referenceをRFC 3986に従って解決する。すべてのinteractionで`POST`を使用する。
| Interaction | Method | Relative reference |
| --- | --- | --- |
@@ -35,27 +35,27 @@ Endpoint URLは次を満たす。
| `fetch_interface` | `POST` | `v1/fetch_interface` |
| `call_operation` | `POST` | `v1/call_operation` |
`v1`はWIP over HTTP Bindingのmajor versionである。Interactionごとに独立したrouteを設定したり、固定suffixを別名へ置き換えたりしない。
`v1`は、WIP over HTTP Bindingのmajor versionを表す。Interactionごとに独立したrouteを設定したり、固定suffixを別名へ置き換えたりしない。
例えば、次のendpointを指定した場合、
例えば、endpointが次のURLである場合、
```text
http://gateway.example/tenants/acme/filesystem/wip/
```
`observe` routeは次になる。
`observe` routeは次のURLになる。
```text
http://gateway.example/tenants/acme/filesystem/wip/v1/observe
```
Endpointのpath prefixはHTTP deployment上のroutingであり、Worldspace内のpathではない。Worldspace pathはrequest bodyのlogical fieldとして渡す。標準route URLはqueryを持たず、query付きURLまたは追加path segmentを同じrouteとして扱わない。
このpath prefixはHTTP deployment上のroutingであり、Worldspace内のpathではない。Worldspace pathは、request bodyのlogical fieldとして渡す。標準route URLはqueryを持たず、query付きURLや追加path segmentを同じrouteとして扱わない。
Clientは異なるcanonical endpoint間でKnown Space、Object observation、Interface observation、validatorを混在させない。同じendpointでも認証主体、tenant、capability、その他のsecurity contextによって異なるWorldspaceが見える場合、それらを異なるeffective Worldspace viewとして分離する。
Clientは、異なるcanonical endpoint間でKnown Space、Object observation、Interface observation、validatorを混在させない。同じendpointでも、認証主体、tenant、capability、その他のsecurity contextによって異なるWorldspaceが見える場合は、異なるeffective Worldspace viewとして分離する。
## HTTP request metadata
標準routeへのrequestは次を満たす。
標準routeへのrequestには、次の条件を適用する。
- Methodは`POST`。
- `Content-Type`は`application/json`または`application/json; charset=utf-8`。
@@ -63,15 +63,15 @@ Clientは異なるcanonical endpoint間でKnown Space、Object observation、Int
- 標準Clientは`Accept: application/json`を送る。
- Request URLは標準routeと完全に一致し、queryを持たない。
Media typeとparameter名の比較はHTTPの規則に従ってcase-insensitiveに行う。`charset`を指定する場合は`utf-8`だけを許可する。同じparameterの重複、UTF-8以外のcharset、その他のmedia type parameterを標準bindingでは使用しない。
Media typeとparameter名は、HTTPの規則に従ってcase-insensitiveに比較する。`charset`を指定する場合に許可するのは`utf-8`だけである。同じparameterの重複、UTF-8以外のcharset、その他のmedia type parameterは、標準bindingでは使用しない。
`Accept`がないrequestをHostは受理してよい。`Accept`がある場合はHTTP content negotiationの規則を適用し、`application/json`に対するeffective quality valueが正である場合だけJSON responseを返す。
Hostは、`Accept`がないrequestを受理してよい。`Accept`がある場合はHTTP content negotiationの規則を適用し、`application/json`に対するeffective quality valueが正である場合だけ、JSON responseを返す。
すべての実装はHTTP identity content codingを扱える。Requestまたはresponseのcontent codingはoptionalなHTTP機能であり、本bindingは特定の圧縮方式を必須にしない。Hostが対応しないrequest content codingはTransport-levelの`415 Unsupported Media Type`として拒否する。Clientが対応しないresponse content codingはTransport failureとして扱う。
すべての実装はHTTP identity content codingを扱える。Requestとresponseのcontent codingはoptionalなHTTP機能であり、このbindingは特定の圧縮方式を必須にしない。Hostが対応しないrequest content codingは、Transport-levelの`415 Unsupported Media Type`として拒否する。Clientが対応しないresponse content codingは、Transport failureとして扱う。
## Routeとmetadataのfailure
Route、method、content negotiation、Transport authenticationはlogical WIP requestの外側にある。次のresponseはProtocol error envelopeを要求しない。
Route、method、content negotiation、Transport authenticationは、logical WIP requestの外側で扱う。次のresponseには、Protocol error envelopeを要求しない。
| 条件 | HTTP response |
| --- | --- |
@@ -82,25 +82,25 @@ Route、method、content negotiation、Transport authenticationはlogical WIP re
| Transport authenticationが必要 | `401 Unauthorized`、必要なら`WWW-Authenticate` |
| Endpoint access surface全体へのaccess拒否 | `403 Forbidden` |
Clientはこれらを`InvalidRequest`、`NotFound`、`PermissionDenied`等へ変換しない。
Clientは、これらを`InvalidRequest`、`NotFound`、`PermissionDenied`等へ変換しない。
標準route、method、media type、authenticationが受理された後、bodyがmalformed JSONである、logical requestへdecodeできない、required fieldがない、未知fieldがある、またはfield semanticsに違反する場合、Hostは`400 Bad Request`と`invalid_request`のProtocol error envelopeを返す。
一方、標準route、method、media type、authenticationを受理した後に、bodyがmalformed JSONである、logical requestへdecodeできない、required fieldがない、未知fieldがある、またはfield semanticsに違反する場合は、Protocol failureとなる。Hostは`400 Bad Request`と、`invalid_request`のProtocol error envelopeを返す。
HTTP server、proxy、gateway、またはClientの運用設定によってmessage size、timeout、rate等の上限に達した場合はTransport failureである。HTTP statusが後述するProtocol error mappingと同じでも、validなProtocol error envelopeを持たないresponseをProtocol failureへ変換しない。
HTTP server、proxy、gateway、Clientの運用設定によってmessage size、timeout、rate等の上限に達した場合は、Transport failureである。HTTP statusがProtocol error mappingと同じでも、validなProtocol error envelopeを持たないresponseをProtocol failureへ変換しない。
## HTTP response
各interactionが成功した場合、Hostは`200 OK`を返し、response bodyへ対応するProtocol responseを直接encodeする。Success bodyを`result`等の共通envelopeで包まない。
各interactionが成功した場合、Hostは`200 OK`を返す。Response bodyには、対応するProtocol responseを直接encodeし、`result`等の共通envelopeで包まない。
Protocol failureの場合、Hostは非2xx statusを返し、bodyへ本章のProtocol error envelopeをencodeする。
Protocol failureの場合は非2xx statusを返し、bodyにProtocol error envelopeをencodeする。
WIP Hostが生成するbody付きresponseは`Content-Type: application/json`または`application/json; charset=utf-8`を持つ。Protocol successまたはProtocol failureのbodyはUTF-8 JSON textである。
WIP Hostが生成するbody付きresponseは、`Content-Type: application/json`または`application/json; charset=utf-8`を持つ。Protocol successとProtocol failureのbodyは、いずれもUTF-8 JSON textである。
HTTP statusは大分類とHTTP infrastructureのための補助情報であり、Protocol failureの意味を決定しない。Clientはstatus、reason phrase、人間向けmessageから`ProtocolErrorCode`を推測しない。
HTTP statusは、大分類とHTTP infrastructureのための補助情報である。Protocol failureの意味を決定するものではなく、Clientはstatus、reason phrase、人間向けmessageから`ProtocolErrorCode`を推測しない。
非2xx responseが、正しいContent-TypeとvalidなProtocol error envelopeを持たない場合、ClientはTransport failureとして扱う。これにより、proxyやgatewayが生成したresponseをHost由来のProtocol failureと誤認しない。
非2xx responseが、正しいContent-TypeとvalidなProtocol error envelopeを持たない場合、ClientはTransport failureとして扱う。Proxyやgatewayが生成したresponseを、Host由来のProtocol failureと誤認しないためである。
次は`InvalidResponse`である。
これに対し、次のresponseは`InvalidResponse`となる。
- `200 OK`以外の2xx statusにvalidなsuccess bodyがある。
- 2xx statusにProtocol error envelopeがある。
@@ -109,7 +109,7 @@ HTTP statusは大分類とHTTP infrastructureのための補助情報であり
## JSON共通規則
JSON encodingには次の規則を適用する。
JSON encodingには、次の規則を適用する。
- JSON textはUTF-8でencodeする。
- RecordはJSON object、listはJSON arrayで表す。
@@ -123,11 +123,11 @@ JSON encodingには次の規則を適用する。
- StringへUnicode normalizationを適用しない。
- JSON syntaxが表現できないNaNと正負Infinityを使用しない。
本章のschema表で`optional`と記していないfieldはrequiredである。
Schema表で`optional`と記していないfieldは、requiredとして扱う。
`Vec<u8>`はRFC 4648 Section 4のstandard base64 alphabetを使用し、必要な`=` paddingを含むcanonical base64 stringとしてencodeする。Whitespace、URL-safe alphabet、padding省略、同じoctet列に対する別表現を受理しない。
`Vec<u8>`はcanonical base64 stringとしてencodeする。RFC 4648 Section 4のstandard base64 alphabetを使用し、必要な`=` paddingを含める。Whitespace、URL-safe alphabet、padding省略、同じoctet列に対する別表現は受理しない。
Path、Interface参照、Object identity、名前、validatorの意味はfieldの位置とProtocolの型によって決まる。
Path、Interface参照、Object identity、名前、validatorの意味は、fieldの位置とProtocolの型によって決まる。JSON上の表現は次のとおりである。
| Logical field | JSON encoding |
| --- | --- |
@@ -138,11 +138,11 @@ Path、Interface参照、Object identity、名前、validatorの意味はfield
| `format` | string |
| Object / Interface validator | canonical base64 string |
JSON serializationのwhitespace、escapeの選択、object member順をcanonical化しない。同じlogical valueがbyte-for-byte同一のJSONになることを要求しない。
ただし、JSON serialization全体をcanonical化するわけではない。Whitespace、escapeの選択、object member順はcanonical化せず、同じlogical valueがbyte-for-byte同一のJSONになることも要求しない。
## Interface Reference
`InterfaceReference`は次のexactなJSON objectとしてencodeする。
`InterfaceReference`は、次のfieldだけを持つexactなJSON objectとしてencodeする。
| Field | JSON type | Presence |
| --- | --- | --- |
@@ -156,13 +156,15 @@ JSON serializationのwhitespace、escapeの選択、object member順をcanonical
}
```
`Object.interfaces`の各要素、`FetchInterfaceRequest.interface`、`FetchInterfaceResponse.interface`、`InterfaceTarget.reference`のすべてでこの形を使用する。Scopeの省略、relative scope、`null`、空name、追加member、旧形式のopaque string、`"/github::issue.read"`等の短縮表記stringは認めない。Requestでの違反は`400 Bad Request`と`invalid_request`、responseでの違反はClient-localな`InvalidResponse`とする。
`Object.interfaces`の各要素、`FetchInterfaceRequest.interface`、`FetchInterfaceResponse.interface`、`InterfaceTarget.reference`で、この形を共通して使用する。Scopeの省略、relative scope、`null`、空name、追加member、旧形式のopaque string、`"/github::issue.read"`等の短縮表記stringは認めない。Requestで違反した場合は`400 Bad Request`と`invalid_request`を返し、responseで違反した場合はClient-localな`InvalidResponse`とする。
参照の比較はJSON decode後の`scope`と`name`の完全一致であり、object member順やJSON escapeの違いは同一性に影響しない。ScopeへURL encoding / decodingを追加せず、name内の`::`や`#`も通常の文字として保持する。ScopeはWorldspace上のpathであり、HTTP endpointのprefixを加えたりscope用のHTTP routeを生成したりしない。合成によるscope変換は[ProtocolのWorldspace composition](3-protocol.md#worldspace-composition)に従う。
参照は、JSON decode後の`scope`と`name`の完全一致で比較する。Object member順やJSON escapeの違いは、同一性に影響しない。ScopeへURL encoding / decodingを追加せず、name内の`::`や`#`も通常の文字として保持する。
ScopeはWorldspace上のpathである。HTTP endpointのprefixを加えたり、scope用のHTTP routeを生成したりしない。合成によるscope変換は、[ProtocolのWorldspace composition](3-protocol.md#worldspace-composition)に従う。
## ObjectとObjectObservation
`Object`は次のJSON objectとしてencodeする。
`Object`は、次のfieldを持つJSON objectとしてencodeする。
| Field | JSON type | Presence |
| --- | --- | --- |
@@ -172,7 +174,7 @@ JSON serializationのwhitespace、escapeの選択、object member順をcanonical
| `ref` | string | optional |
| `validator` | canonical base64 string | optional |
例:
ObjectのJSON表現の例:
```json
{
@@ -187,28 +189,32 @@ JSON serializationのwhitespace、escapeの選択、object member順をcanonical
}
```
`interfaces`のarray順はHostの立項順を保持し、`(scope, name)`の完全一致による重複を含まない。各参照のscopeは観測pathに対してProtocolの祖先制約を満たす。
`interfaces`のarray順にはHostの立項順を保持し、`(scope, name)`の完全一致による重複を含めない。各参照のscopeは、観測pathに対してProtocolの祖先制約を満たす。
`ObjectObservation`は次のJSON objectとしてencodeする。
`ObjectObservation`は、Objectとchildrenの観測を次のJSON objectで表す。
| Field | JSON type | Presence |
| --- | --- | --- |
| `object` | `Object` | required |
| `children` | `ObjectObservation`のarray | optional |
`children`の省略は未観測を、空arrayは観測済みで直接のindexable childが存在しないことを表す。Requested depthより浅いnodeでは`children`を必ず含め、depth境界のnodeでは省略する。Success responseはrequested depthまで完全であり、truncated markerやpartial successを返さない。
`children`の省略は未観測を表す。空arrayは、観測済みで直接のindexable childが存在しないことを表す。Requested depthより浅いnodeでは`children`を必ず含め、depth境界のnodeでは省略する。
Success responseはrequested depthまで完全であり、truncated markerやpartial successを返さない。
## Interface Descriptor
### Format discriminator
標準v1のInterface Descriptor formatは`wip-interface/1`である。このformatでは以下のJSON grammarを使用する。
標準v1のInterface Descriptor formatは、`wip-interface/1`である。このformatのJSON grammarは、以下の定義に従う。
ClientはDescriptor objectのstring `format`を先に読み、対応しないformatを`UnsupportedDescriptorFormat`として扱える。未知formatでもDescriptorはJSON objectであり、string `format`を必ず持つ。それ以外のmemberはそのformat固有であるため、Clientは`wip-interface/1`のschemaで存在、欠落、型を判定せず、内容をOperationへ使用しない。標準v1 Hostは`wip-interface/1`を返す。
Clientは、Descriptor objectのstring `format`を先に読み、対応しないformatを`UnsupportedDescriptorFormat`として扱える。未知formatでも、DescriptorはJSON objectであり、string `format`を必ず持つ。
それ以外のmemberはformat固有であるため、未知formatを`wip-interface/1`のschemaで検証しない。Memberの存在、欠落、型をこのschemaで判定せず、内容をOperationへ使用しない。標準v1 Hostは`wip-interface/1`を返す。
### Documentation
`Documentation`は次のJSON objectである。
`Documentation`は、説明を次のJSON objectで表す。
| Field | JSON type | Presence |
| --- | --- | --- |
@@ -217,7 +223,7 @@ ClientはDescriptor objectのstring `format`を先に読み、対応しないfor
### Descriptor root
`InterfaceDescriptor`は次のJSON objectである。
`InterfaceDescriptor`のrootは、次のJSON objectである。
| Field | JSON type | Presence |
| --- | --- | --- |
@@ -226,7 +232,7 @@ ClientはDescriptor objectのstring `format`を先に読み、対応しないfor
| `types` | `TypeDeclaration`のarray | required |
| `operations` | `OperationDeclaration`のarray | required |
`types`と`operations`のarray順はdeclaration順を保持する。
`types`と`operations`のarrayには、declaration順を保持する。
### TypeDeclaration
@@ -238,7 +244,7 @@ ClientはDescriptor objectのstring `format`を先に読み、対応しないfor
### TypeExpr
すべての`TypeExpr`はstring `kind`を持つJSON objectとしてencodeする。`kind`ごとの正確なmemberは次のとおりである。
すべての`TypeExpr`を、string `kind`を持つJSON objectとしてencodeする。`kind`ごとに持つmemberは、次のものに限定する。
| TypeExpr | `kind` | その他のmember |
| --- | --- | --- |
@@ -256,7 +262,7 @@ ClientはDescriptor objectのstring `format`を先に読み、対応しないfor
| Enum | `enum` | required `EnumCase` array `cases` |
| Union | `union` | required `UnionCase` array `cases` |
例:
ListのitemsがNamedであるTypeExprの例:
```json
{
@@ -268,7 +274,7 @@ ClientはDescriptor objectのstring `format`を先に読み、対応しないfor
}
```
Primitive kindのobjectへ別memberを追加してはならない。例えばUnitは`{"kind":"unit"}`だけで表す。
Primitive kindのobjectに、別memberを追加してはならない。例えばUnitの表現は、`{"kind":"unit"}`だけである。
### FieldDeclaration
@@ -294,7 +300,7 @@ Primitive kindのobjectへ別memberを追加してはならない。例えばUni
| `documentation` | `Documentation` | optional |
| `payload` | `TypeExpr` | optional |
`payload`の省略はpayloadを持たないcaseを表す。
`payload`を省略したcaseは、payloadを持たない。
### OperationDeclaration
@@ -321,9 +327,9 @@ Primitive kindのobjectへ別memberを追加してはならない。例えばUni
| `documentation` | `Documentation` | optional |
| `type` | `TypeExpr` | required |
Descriptorの名前一意性、Named参照、cycle、型整合性等は[3. Protocol](3-protocol.md)に従って検証する。JSON shapeが正しいことだけではvalidなDescriptorにならない。
JSON shapeの検証だけでは、Descriptorのvalidityは確認できない。名前一意性、Named参照、cycle、型整合性等も、[3. Protocol](3-protocol.md)に従って検証する。
完全なDescriptorの例:
Typesとoperationsを含む、完全なDescriptorの例:
```json
{
@@ -400,15 +406,17 @@ Operationのargumentsとresultは、選択したInterface Descriptorの`TypeExpr
| Enum | 宣言されたcase名のstring |
| Union | `$case`と、必要なら`value`を持つobject |
`Json`内部でもnumberは相互運用可能なsafe integerまたはfinite binary64として扱い、Bytesの特別なencodingは適用しない。小数部と指数部を持たずsafe integer範囲にあるJSON numberはlogical `Integer`、それ以外のfiniteなJSON numberはlogical `Number`としてdecodeする。`Json`内のbase64らしいstringをBytesと推測しない。
`Json`内部のnumberにも、相互運用可能なsafe integerまたはfinite binary64という制約を適用する。小数部と指数部を持たずsafe integer範囲にあるJSON numberはlogical `Integer`として、それ以外のfiniteなJSON numberはlogical `Number`としてdecodeする。
RecordとOperation argumentsでは、`required = false`のfieldまたはparameterを省略できる。省略と`null`は異なる。TypeExprがUnit、Json、またはそれらへ解決されるNamedである場合、存在するmemberの`null`はその型のvalueであり、省略を表さない。それ以外の型で`null`を使用してはならない。
`Json`内部にはBytesの特別なencodingを適用しない。Base64らしいstringがあっても、Bytesと推測しない。
Record valueはdeclarationされていないmemberを持たない。Operation argumentsはparameter名をmember名とするJSON objectであり、位置引数を使用しない。引数のないOperationは空objectを使用する。
RecordとOperation argumentsでは、`required = false`のfieldやparameterを省略できる。ただし、省略と`null`は異なる。TypeExprがUnit、Json、またはそれらへ解決されるNamedである場合、存在するmemberの`null`はその型のvalueであり、省略を表さない。それ以外の型では`null`を使用してはならない。
Enumはcase名だけをstringで表し、object envelopeを使用しない。
Record valueには、declarationされていないmemberを含めない。Operation argumentsは、parameter名をmember名とするJSON objectであり、位置引数を使用しない。引数のないOperationには空objectを使用する。
Payloadを持つUnionは次の形である。
Enumはcase名だけをstringで表し、object envelopeは使用しない。
Payloadを持つUnionは、`$case`と`value`を持つ次の形で表す。
```json
{
@@ -417,7 +425,7 @@ Payloadを持つUnionは次の形である。
}
```
Payloadを持たないUnionは`value`を省略する。
Payloadを持たないUnionでは、`value`を省略する。
```json
{
@@ -425,15 +433,15 @@ Payloadを持たないUnionは`value`を省略する。
}
```
Union objectは`$case`と必要な`value`以外のmemberを持たない。Payloadありcaseでは`value`がrequired、payloadなしcaseでは`value`は禁止される。
Union objectに含めるmemberは、`$case`と必要な`value`だけである。Payloadありcaseでは`value`がrequiredとなり、payloadなしcaseでは`value`を禁止する。
ClientはDescriptorに従ってvalueをdecodeし、`entry`と宣言された位置のstringだけをWorldspace entryとして認識する。通常のStringやopaqueなJsonに含まれるpathらしいstringをentryとして推測しない。
Clientは、Descriptorに従ってvalueをdecodeする。Worldspace entryとして認識するのは、`entry`と宣言された位置のstringだけである。通常のStringやopaqueなJsonに含まれるpathらしいstringから、entryを推測しない。
## `observe`
### Request
`POST v1/observe`のbodyは次のJSON objectである。
`POST v1/observe`のbodyには、次のJSON objectを使用する。
| Field | JSON type | Presence |
| --- | --- | --- |
@@ -449,7 +457,7 @@ ClientはDescriptorに従ってvalueをdecodeし、`entry`と宣言された位
### Success response
Success bodyはrootの`ObjectObservation`を直接encodeする。
Success bodyには、rootの`ObjectObservation`を直接encodeする。
```json
{
@@ -473,13 +481,13 @@ Success bodyはrootの`ObjectObservation`を直接encodeする。
}
```
Responseのpath、name、depth、children completenessはrequestと[3. Protocol](3-protocol.md)に従って検証する。完全なresponseをresource budget内で構築できない場合、Hostはpartial successではなく`resource_limit_exceeded`を返す。
Responseのpath、name、depth、children completenessは、requestと[3. Protocol](3-protocol.md)に従って検証する。Hostがresource budget内で完全なresponseを構築できない場合は、partial successにせず、`resource_limit_exceeded`を返す。
## `fetch_interface`
### Request
`POST v1/fetch_interface`のbodyは次のJSON objectである。
`POST v1/fetch_interface`のbodyには、次のJSON objectを使用する。
| Field | JSON type | Presence |
| --- | --- | --- |
@@ -513,9 +521,11 @@ Responseのpath、name、depth、children completenessはrequestと[3. Protocol]
}
```
Responseの`interface`はrequestと完全一致しなければならない。`scope_ref`、Descriptor、validatorは一つのInterface observationとして扱う。`scope_ref`はscope Objectの`ref`と同じopaque stringであり、base64化しない。Scope Objectが`ref`を持つ場合は含め、持たない場合は省略する。`null`は使用しない。
Responseの`interface`は、requestと完全一致しなければならない。`scope_ref`、Descriptor、validatorは、一つのInterface observationとして扱う。
Scope Objectに`ref`がない場合のvalidなresponse例:
`scope_ref`はscope Objectの`ref`と同じopaque stringであり、base64化しない。Scope Objectが`ref`を持つ場合は含め、持たない場合は省略する。`null`は使用しない。
Scope Objectに`ref`がない場合も、次のresponseはvalidである。
```json
{
@@ -528,13 +538,13 @@ Scope Objectに`ref`がない場合のvalidなresponse例:
}
```
`scope_ref`もvalidatorもない観測は許可される。Scopeのidentity追跡はできず、Descriptorはその参照の有効期間中immutableとして扱う。
`scope_ref`もvalidatorもない観測は許可される。この場合、scopeのidentityは追跡できず、Descriptorは参照の有効期間中immutableとして扱う。
## `call_operation`
### Request
`POST v1/call_operation`のbodyは次のJSON objectである。
`POST v1/call_operation`のbodyには、次のJSON objectを使用する。
| Field | JSON type | Presence |
| --- | --- | --- |
@@ -543,14 +553,14 @@ Scope Objectに`ref`がない場合のvalidなresponse例:
| `operation` | Operation名のstring | required |
| `arguments` | 選択したOperation declarationに従うobject | required |
`Target`は次のfieldを持つ。
`Target`は、pathとoptionalなvalidatorを次のfieldで表す。
| Field | JSON type | Presence |
| --- | --- | --- |
| `path` | canonical absolute Worldspace pathのstring | required |
| `validator` | canonical base64 string | optional |
`InterfaceTarget`は次のfieldを持つ。
`InterfaceTarget`は、参照とその観測metadataを次のfieldで表す。
| Field | JSON type | Presence |
| --- | --- | --- |
@@ -576,11 +586,13 @@ Scope Objectに`ref`がない場合のvalidなresponse例:
}
```
`interface.reference`と`operation`は別fieldである。表示用の`/::item-interface-v1#get_related_item`を一つのfieldへencodeしない。`scope_ref`も`InterfaceReference`のmemberや短縮表記の一部にはせず、`InterfaceTarget`の独立したoptional fieldとして送る。
`interface.reference`と`operation`は、別fieldである。表示用の`/::item-interface-v1#get_related_item`を、一つのfieldへencodeしない。`scope_ref`も`InterfaceReference`のmemberや短縮表記の一部にはせず、`InterfaceTarget`の独立したoptional fieldとして送る。
Clientは`fetch_interface`の観測に`scope_ref`があればコピーし、なければ省略する。`scope_ref`に`null`や非stringを指定したrequestは`invalid_request`である。Validなstringを指定したが現在のscope Objectの`ref`と一致しない場合(現在の`ref`の欠落を含む)は、Protocolの検証順に従って`interface_mismatch`とする。省略時はscope identity preconditionを適用せず、それだけを理由に拒否しない。
Clientは、`fetch_interface`の観測に`scope_ref`があればコピーし、なければ省略する。`null`や非stringを`scope_ref`に指定したrequestは、`invalid_request`となる。
HostはDescriptorに依存しない`target`、`interface`、`operation`のshapeを検証し、Protocolのerror precedenceに従って現在のObjectとInterface observationを固定した後、そのDescriptorに従って`arguments`をdecodeする。
Validなstringを指定していても、現在のscope Objectの`ref`と一致しない場合は、Protocolの検証順に従って`interface_mismatch`とする。現在の`ref`が欠落している場合も含む。`scope_ref`を省略した場合はscope identity preconditionを適用せず、省略だけを理由に拒否しない。
Hostはまず、Descriptorに依存しない`target`、`interface`、`operation`のshapeを検証する。次に、Protocolのerror precedenceに従って現在のObjectとInterface observationを固定し、そのDescriptorに従って`arguments`をdecodeする。
### Success response
@@ -599,11 +611,11 @@ HostはDescriptorに依存しない`target`、`interface`、`operation`のshape
}
```
`result`はrequestで指定し、Hostがprecondition確認時に固定したOperation declarationのreturn TypeExprに従ってencodeする。
`result`のencodingには、requestで指定し、Hostがprecondition確認時に固定したOperation declarationのreturn TypeExprを使用する。
## Validator
Object validatorとInterface validatorは対応するJSON body fieldへcanonical base64としてencodeする。
Object validatorとInterface validatorは、対応する次のJSON body fieldにcanonical base64としてencodeする。
- `Object.validator`
- `Target.validator`
@@ -611,7 +623,9 @@ Object validatorとInterface validatorは対応するJSON body fieldへcanonical
- `InterfaceTarget.validator`
- `CallOperationResponse.validator`
WIP validatorを`ETag`、`If-Match`、その他のHTTP headerだけへ移してbody fieldを省略してはならない。Host、gateway、HTTP cacheは通常のHTTP representation metadataとして`ETag`等を追加してよいが、その値はWIP validatorと独立している。ClientはHTTP metadataをObject identity、Interface observation、Operation preconditionとして解釈しない。
WIP validatorを`ETag`、`If-Match`、その他のHTTP headerだけへ移し、body fieldを省略してはならない。
Host、gateway、HTTP cacheは、通常のHTTP representation metadataとして`ETag`等を追加してよい。ただし、その値はWIP validatorとは独立している。ClientはHTTP metadataを、Object identity、Interface observation、Operation preconditionとして解釈しない。
## Protocol error envelope
@@ -626,16 +640,16 @@ WIP validatorを`ETag`、`If-Match`、その他のHTTP headerだけへ移してb
}
```
Top-level objectは`error`だけを持つ。`error` objectは次のfieldだけを持つ。
Top-level objectに含めるのは`error`だけである。`error` objectも、次のfieldだけを持つ。
| Field | JSON type | Presence |
| --- | --- | --- |
| `code` | 下表のstableなsnake_case string | required |
| `message` | boundedな人間向け診断string | required |
Clientは`message`で分岐しない。Hostは秘密情報、credential、非公開Object、backend path、内部stack traceをmessageへ含めない。
Clientは`message`を分岐に使用しない。Hostは秘密情報、credential、非公開Object、backend path、内部stack traceをmessageへ含めない。
`ProtocolErrorCode`のwire spellingとcanonical HTTP statusは次のとおりである。
`ProtocolErrorCode`には、次のwire spellingとcanonical HTTP statusを対応付ける。
| Protocol error code | Wire spelling | HTTP status |
| --- | --- | --- |
@@ -654,35 +668,35 @@ Clientは`message`で分岐しない。Hostは秘密情報、credential、非公
| `Internal` | `internal` | `500 Internal Server Error` |
| `OperationOutcomeUnknown` | `operation_outcome_unknown` | `500 Internal Server Error` |
`resource_limit_exceeded`は、observation completeness、logical nesting、collection件数等、WIP Protocolが扱うlogical requestまたはresponseの上限超過を表し、`422 Unprocessable Content`を使用する。HTTP implementationやdeploymentのmessage-size上限超過をこのcodeへ変換しない。
`resource_limit_exceeded`は、WIP Protocolが扱うlogical requestまたはresponseの上限超過を表す。Observation completeness、logical nesting、collection件数等が対象であり、HTTP statusには`422 Unprocessable Content`を使用する。HTTP implementationやdeploymentのmessage-size上限超過を、このcodeへ変換しない。
Rate limitまたはdeployment concurrency limitによる`429 Too Many Requests`はTransport / deployment concernである。ValidなProtocol error envelopeがない限り`ResourceLimitExceeded`へ変換しない。
Rate limitやdeployment concurrency limitによる`429 Too Many Requests`は、Transport / deployment concernである。ValidなProtocol error envelopeがない限り、`ResourceLimitExceeded`へ変換しない。
Hostはinteractionごとに[3. Protocol](3-protocol.md)で許可されたcodeだけを返す。ClientがvalidなProtocol error envelopeを取得した場合、HTTP statusがcanonical mappingと一致しなくても回復actionは`code`に従い、statusから別codeを推測しない。Status mismatchはBinding違反として診断してよい。
Hostは、interactionごとに[3. Protocol](3-protocol.md)で許可されたcodeだけを返す。ClientがvalidなProtocol error envelopeを取得した場合、回復actionは`code`に従う。HTTP statusがcanonical mappingと一致しなくても、statusから別codeを推測しない。Status mismatchは、Binding違反として診断してよい。
`InvalidResponse`と`UnsupportedDescriptorFormat`はClient-local classificationであり、Hostがerror envelopeで返してはならない。Domain failureもProtocol errorへ変換せず、Operation return typeに従うApplication dataとしてencodeする。
## HTTP authentication boundary
Authentication方式、credential、mTLS、proxy、gateway等はHTTP implementationとdeploymentの関心であり、本bindingは規定しない。
Authentication方式、credential、mTLS、proxy、gateway等は、HTTP implementationとdeploymentが設定・運用する。このbindingは規定しない。
HTTP layerがWIP interactionを開始せずに返す`401 Unauthorized`または`403 Forbidden`は、validなProtocol error envelopeを持たないTransport failureである。Clientはそれらを`PermissionDenied`へ変換しない。
HTTP layerがWIP interactionを開始せずに返す`401 Unauthorized`や`403 Forbidden`は、validなProtocol error envelopeを持たないTransport failureである。Clientはこれらを`PermissionDenied`へ変換しない。
WIP interactionを開始した後のObject、Interface、Operation visibilityとauthorizationはProtocol semanticsに従う。Protocolの`PermissionDenied`はvalidなWIP error envelopeを持つ`403 Forbidden`であり、HTTP layerのaccess rejectionと区別する。
WIP interactionを開始した後のObject、Interface、Operation visibilityとauthorizationは、Protocol semanticsに従う。Protocolの`PermissionDenied`は、validなWIP error envelopeを持つ`403 Forbidden`であり、HTTP layerのaccess rejectionとは区別する。
## HTTP replay
`3xx` response自体はWIP successまたはProtocol failureではなく、Transport failureである。Endpoint discovery、redirect、proxy routingをどう扱うかはHTTP implementationとdeploymentの責務である。
`3xx` response自体は、WIP successやProtocol failureではなく、Transport failureである。Endpoint discovery、redirect、proxy routingの扱いは、HTTP implementationとdeploymentが決定する。
ただし、それらの機構によって一つのlogical `call_operation` requestを複数回dispatchしてはならない。Dispatch後にredirect responseを受け取った場合も、methodとbodyを維持して別endpointへ自動再送しない。
ただし、これらの機構によって、一つのlogical `call_operation` requestを複数回dispatchしてはならない。Dispatch後にredirect responseを受け取った場合も、methodとbodyを維持して別endpointへ自動再送しない。
## Dispatchとretry
RequestがHostへ送信されていないとTransport実装が証明できるfailureはnot dispatchedである。送信開始後にresponseを取得できない場合、ClientはHostがrequestを受理した可能性を否定しない。
Failureをnot dispatchedとして扱えるのは、requestがHostへ送信されていないとTransport実装が証明できる場合である。送信開始後にresponseを取得できない場合、ClientはHostがrequestを受理した可能性を否定しない。
`observe`と`fetch_interface`を再送するか、どのtimeout、retry、cancellation policyを使用するかはClientとHTTP実装の責務である。Response ownershipとProtocol上のcache semanticsは[4. Client](4-client.md)に従う。
`observe`と`fetch_interface`の再送とtimeout・retry・cancellation policyは、ClientとHTTP実装が決定する。Response ownershipとProtocol上のcache semanticsは、[4. Client](4-client.md)に従う。
`call_operation`には次を適用する。
`call_operation`には、次の規則を適用する。
- Redirect、connection retry、HTTP stackのautomatic replay、proxy retryによって再送しない。
- `Retry-After`またはHTTP statusだけを理由に再送しない。
@@ -694,15 +708,15 @@ HTTP implementationとdeploymentは、失敗した`POST v1/call_operation`を透
## HTTP facilitiesとの境界
HTTP cache、proxy、gateway、compression、connection管理、TLS、message size、timeout、concurrency、rate limit等の設定と運用は、本bindingの規定対象外である。
HTTP cache、proxy、gateway、compression、connection管理、TLS、message size、timeout、concurrency、rate limit等の設定と運用は、このbindingの規定対象外である。
HTTP cache metadataはWIP ClientのKnown Space、Interface cache、Object validator、Interface validatorとは別の機構である。`ETag`、`If-Match`、Age、Last-Modified等をWIP observationまたはvalidatorとして解釈しない。それ以外のHTTP cache policyはHTTP implementationとdeploymentが決定する。
HTTP cache metadataは、WIP ClientのKnown Space、Interface cache、Object validator、Interface validatorとは別の機構である。`ETag`、`If-Match`、Age、Last-Modified等を、WIP observationやvalidatorとして解釈しない。それ以外のHTTP cache policyは、HTTP implementationとdeploymentが決定する。
HTTP implementationまたはdeploymentの都合でrequestまたはresponseを交換できない場合、ClientはTransport failureとして扱う。WIPはそれらの運用設定を規定せず、そのfailureを`resource_limit_exceeded`その他のProtocol errorへ包み直さない。
HTTP implementationやdeploymentの都合でrequestやresponseを交換できない場合、ClientはTransport failureとして扱う。WIPはこれらの運用設定を規定せず、そのfailureを`resource_limit_exceeded`その他のProtocol errorへ包み直さない。
## 非目標
本bindingは次を定義しない。
このbindingの定義には、次のものを含めない。
- Host内部のAPI、database、filesystem、queueとの接続方法。
- Endpoint discovery service。
+49 -43
View File
@@ -2,35 +2,35 @@
## Status
この文書は、Rust / TypeScript Host APIを設計する前に、動的なWorldspaceを運用するための責務、処理モデル、要件を整理するdraftである。
動的なWorldspaceを運用するには、Hostが何を解決し、どの範囲のObjectを投影し、どうOperationを実行するかを整理する必要がある。このdraftは、Rust / TypeScript Host APIの設計に先立って、その責務、処理モデル、要件をまとめたものである。
具体的なtrait、class、function、decorator、macro、builderのsyntaxは定義しない。この文書で使用する`Projection Provider`、`Projection Resolution`、`Projected Object`等の名称もworking terminologyであり、canonicalなProtocol typeではない。
具体的なtrait、class、function、decorator、macro、builderのsyntaxは、ここでは定義しない。`Projection Provider`、`Projection Resolution`、`Projected Object`等もHost内部の設計を検討するためのworking terminologyであり、canonicalなProtocol typeではない。
Protocol上の確定事項は[Core Model](../2-core-model.md)、[Object tree / Schema](../2.1-object-tree-schema.md)、[Operation and Interface](../2.2-operation-and-interface.md)、[Protocol](../3-protocol.md)を参照する。言語別のconceptual API modelは[Rust API Model](rust-api-model.md)と[TypeScript API Model](typescript-api-model.md)で扱う。
Protocol上の確定事項は[Core Model](../2-core-model.md)、[Object tree / Schema](../2.1-object-tree-schema.md)、[Operation and Interface](../2.2-operation-and-interface.md)、[Protocol](../3-protocol.md)に従う。言語別のconceptual API modelは[Rust API Model](rust-api-model.md)と[TypeScript API Model](typescript-api-model.md)で扱う。
## 目的
WIP Hostの中心的な実装対象は、事前に列挙された静的endpointだけではない。Filesystem、database row、repository内容、検索結果、外部service上のentityなど、実行時に存在と状態が決まる空間をWorldspaceへ投影できなければならない。
WIP Hostは、事前に列挙した静的endpointだけでなく、実行時に存在と状態が決まる空間をWorldspaceへ投影できなければならない。Filesystem、database row、repository内容、検索結果、外部service上のentityなどが、その実装対象になる。
HostがWorldspace内のすべてのObjectを常駐instanceとして保持することは要求しない。Backend dataをrequest時に解決し、必要な範囲だけObjectとして投影できることを基本とする。
そのために、すべてのObjectを常駐instanceとして保持する必要はない。Backend dataをrequest時に解決し、必要な範囲だけObjectとして投影できることを基本とする。
固定pathへ登録されたObjectやservice endpointは、同じ動的projection modelにおいてrouting / resolution structureが固定された特殊ケースとして扱えるべきである。現在の主体やbackend stateに応じて、そこで返すObject representationやvalidatorが変化することは妨げない。静的登録だけを基本形とし、動的空間を大量のObject登録によって模倣する設計にはしない。
固定pathに登録するObjectやservice endpointも、同じ動的projection modelで表現できるべきである。この場合はrouting / resolution structureが固定されているが、返すObject representationやvalidatorは、現在の主体やbackend stateに応じて変化してよい。静的登録を基本形にして大量のObject登録で動的空間を模倣するのではなく、動的な解決の特殊ケースとして静的登録を扱う。
## 基本的な分離
Host実装APIでは、少なくとも次の責務を区別する必要がある。この区別を一対一のpublic type、trait、objectへ分割することまでは決定しない。
Host実装APIでは、少なくとも次の責務を区別する必要がある。ただし、責務ごとに一つのpublic type、trait、objectを設けるかどうかは未決定である。
### Interface Declaration
Operation名、parameter、return type、documentation等を宣言し、Interface Descriptor、Value codec、boundary validationを生成する。
Interface Declarationは、Operation名、parameter、return type、documentation等の宣言である。その宣言からInterface Descriptor、Value codec、boundary validationを生成する。
Interface Declarationは、多数のObjectが共有できる比較的静的なcapability schemaである。Objectの列挙やbackend dataのlifecycleは担当しない。
多数のObjectが共有できる、比較的静的なcapability schemaとして扱う。Objectの列挙とbackend dataのlifecycleは、Interface Declarationの責務には含めない。
### Worldspace Projection
Clientから受け取ったpathを、現在の主体とbackend stateに基づいて解決し、Protocol上のObject projectionを生成する。一つのProjected Objectは、Host固有のentityを持たないvirtual nodeでも、一つのbackend entityに対応するものでも、複数のbackend entityを集約したものでもよい。
Worldspace Projectionは、Clientから受け取ったpathを現在の主体とbackend stateに基づいて解決し、Protocol上のObject projectionを生成する処理である。投影するObjectは、Host固有のentityを持たないvirtual nodeでも、一つのbackend entityに対応するものでも、複数のbackend entityを集約したものでもよい。
Projectionは、少なくとも次を決定する。
Projectionで決定する内容には、少なくとも次が含まれる。
- そのpathのObjectを現在の主体へ公開するか。
- 公開する`name`、optionalな`description`、`ref`、`validator`。
@@ -40,26 +40,28 @@ Projectionは、少なくとも次を決定する。
### Host Runtime
Protocol requestを受け取り、ProjectionとInterface registryを協調させる。Operation callでは、現在のProjected Objectが公開するInterface集合からClientが指定した一つのDescriptorを固定し、そこに宣言されたOperationをObjectのHost内implementationへ適用する。
Host RuntimeはProtocol requestを受け取り、ProjectionとInterface registryを協調させる。Operation callでは、現在のProjected Objectが公開するInterface集合からClient指定のDescriptorを一つ固定し、そのDescriptorに宣言されたOperationをObjectのHost内implementationへ適用する。
Host RuntimeはProtocol validation、Interface Descriptorの公開、Value validation、error mapping、resource limit等を担う。Backend固有のprojection resolutionやdomain operation implementationそのものはProvider等のHost componentへ委譲できる。Object implementationとOperation実装を接続する具体的なAPIは各言語のSDK側で決定し、Protocol conceptとして追加しない。
また、Protocol validation、Interface Descriptorの公開、Value validation、error mapping、resource limit等も担う。一方、backend固有のprojection resolutionやdomain operation implementationそのものは、Provider等のHost componentへ委譲できる。
Object implementationとOperation実装を接続する具体的なAPIは、各言語のSDK側で決める。これはHost内の実装を接続するためのAPIであり、新たなProtocol conceptとしては追加しない。
## Working terminology
このdraftでは、Host内部の議論のために次の語を使う。
Host内部の投影処理を検討するため、次の語を使う。
- **Backend Entity** — File、database row、issue、repository、remote entity等、projectionの入力になり得るHost固有の実体。一つのProjected Objectと一対一に対応するとは限らない。
- **Projection Resolution** — 現在の主体とpathについて、公開するObject representationと、後続処理に必要なHost-private情報を得るrequest-timeの解決結果。
- **Projection Provider** — Pathと主体からProjection Resolutionを生成し、indexable childrenの発見を支援するHost component。
- **Projected Object** — その時点でClientへ返すProtocol `Object`。Backend Entityを持たないvirtual Object、一つのentityのprojection、複数entityのaggregateのいずれでもよく、Host内の常駐instanceを意味しない。
HostがOperationを実装するために使用するRust struct、TypeScript object、backend handle、transaction context等はHost-privateであり、共通するHost abstractionを必須にしない。これらをProtocolの`Target { path, validator }`、canonical path、Objectの`ref`として公開または流用しない。
Operationの実装に使うRust struct、TypeScript object、backend handle、transaction context等はHost-privateである。これらに共通するHost abstractionは必須としない。また、Protocolの`Target { path, validator }`、canonical path、Objectの`ref`として公開したり、それらへ流用したりしない。
## 運用モデル
### `observe`
`observe(path, depth)`では、Hostは概念的に次を行う。
`observe(path, depth)`では、要求された範囲のObjectを現在の状態から投影する。Hostが概念的に行う処理は次のとおりである。
1. Requestの主体とpathをProjection Providerへ渡す。
2. Providerが現在のbackend stateから、そのpathで公開するProjected ObjectのProjection Resolutionを生成する。
@@ -69,23 +71,25 @@ HostがOperationを実装するために使用するRust struct、TypeScript obj
6. Nodeがrequested depthに達した場合はchildrenを観測せず、responseの`children` fieldを省略する。
7. Requested depthまで完全な`ObjectObservation`を返す。
ProviderはWorldspace全体をmaterializeせず、現在処理しているparentのdirect childrenを遅延して発見できる必要がある。Childrenをstream、iterator、cursor等のHost内部表現で生成してよいが、一つのparentについて成功するには公開されたindexable childrenをすべて調べ終えなければならない。
Providerには、Worldspace全体をmaterializeせず、処理中のparentのdirect childrenを遅延して発見できることが必要になる。Host内部ではstream、iterator、cursor等でchildrenを生成してよい。ただし、一つのparentの観測を成功とするには、その主体へ公開するindexable childrenをすべて調べ終える必要がある。
Backend failure、cancellation、またはresource budget超過をclean exhaustionとして扱わない。Requested depthまでの完全なresponseを構築できない場合、Host Runtimeは部分的なsuccess responseを返さず、対応するfailureを返す。
Backend failure、cancellation、resource budget超過は、列挙が正常に完了したclean exhaustionとは区別する。Requested depthまで完全なresponseを構築できなければ、Host Runtimeは部分的なsuccess responseではなく、対応するfailureを返す。
各childについて現在のObject projectionを構築し、そのcanonical pathを後の`observe`または`call_operation`で現在のProjected Objectとして再解決できなければならない。以前観測したbackend entityやHost内部instanceを再現することは要求しない。
列挙した各childについては、現在のObject projectionを構築し、そのcanonical pathを後の`observe`や`call_operation`で再解決できなければならない。再解決の対象は、その時点のProjected Objectである。以前観測したbackend entityやHost内部instanceの再現は要求しない。
この処理のために、Hostが以前の`observe`で生成したObject instanceを保持している必要はない。内部cacheを利用してもよいが、cacheの有無によってProtocol semanticsを変えてはならない。
したがって、Hostが以前の`observe`で作ったObject instanceを保持する必要もない。内部cacheは利用してよいが、その有無でProtocol semanticsを変えてはならない。
### `fetch_interface`
ProjectionがObjectへ割り当てた各Interface参照は、同じ主体から取得可能なDescriptorへ解決されなければならない。
ProjectionがObjectへ割り当てた各Interface参照は、その主体から取得可能なDescriptorへ解決されなければならない。複数のObjectで同じ参照を共有でき、一つのObjectに複数のInterfaceを組み合わせることもできる。
複数のObjectは同じInterface参照を共有でき、一つのObjectも複数のInterfaceを組み合わせられる。Validatorを返すInterface参照ではDescriptorを変更でき、同じ参照とvalidatorの組が一つのDescriptor observationを表す。Validatorを返さない参照のDescriptorは、その参照が有効な間immutableである。Interface参照のscopeは[2.2. Operation and Interface](../2.2-operation-and-interface.md#interfaceの識別とscope)に従う。登録API、生成時期、deduplication、cacheの具体実装は別途決定する。
Descriptorの変更可否は、Interface参照がvalidatorを返すかどうかで分かれる。Validatorを返す参照ではDescriptorを変更でき、同じ参照とvalidatorの組が一つのDescriptor observationを表す。Validatorを返さない参照では、その参照が有効な間、Descriptorはimmutableである。
Interface参照のscopeは[2.2. Operation and Interface](../2.2-operation-and-interface.md#interfaceの識別とscope)に従う。登録API、生成時期、deduplication、cacheの具体実装は別途決める。
### `call_operation`
`call_operation`では、HostはProviderまたはbackend固有のexecution boundaryへ入り、その同じboundary内で概念的に次を行う。
`call_operation`では、現在のObjectを解決する処理と、そのObjectへの実行を同じexecution boundary内で行う。HostはProviderまたはbackend固有のboundaryに入り、概念的に次を行う。
1. 現在の主体と`target.path`からProjection Resolutionを生成し、同じbackend対象を保持するstable handleまたはtransaction contextを取得する。
2. そのpathのProjected Objectを現在も公開するか確認する。
@@ -97,15 +101,15 @@ ProjectionがObjectへ割り当てた各Interface参照は、同じ主体から
8. 固定したObject implementation、Interface Descriptor、Operation implementationを、step 1で固定した同じbackend対象へ適用する。
9. Resultを同じOperation Declarationで検証し、nestedしたすべての`Entry`へ現在の主体のvisibility checkを適用してから、実行後Object validatorとともに返す。
Step 3から8までの間にObject、Interface、Descriptor、Operation implementation、backend対象の対応が変化し得る実装は、この手順を満たさない。Projectionは、Host RuntimeとProviderがこのatomicityを実現するために必要なstable handle、transaction、conditional operation、lock等を使用できるようにしなければならない。
Step 3から8までの間に、Object、Interface、Descriptor、Operation implementation、backend対象の対応が変わり得る実装では、この手順を満たせない。Host RuntimeとProviderがatomicityを実現できるよう、Projectionは必要なstable handle、transaction、conditional operation、lock等を使用できる必要がある。
過去の`observe`で作成したHost内部Object instanceの存在を前提にしてはならない。Clientから届くprotocol-level Targetはpathとoptionalなvalidatorであり、Hostはcall時の現在状態からObject implementationを解決する。Validatorを省略したcallを現在のOperationが許可する場合は、過去に観測したObjectではなく、実行時にpathが指す現在のObjectへ無条件に実行する。
解決には、過去の`observe`で作ったHost内部Object instanceを前提としない。Clientから届くprotocol-level Targetはpathとoptionalなvalidatorであり、Hostはcall時の現在状態からObject implementationを解決する。現在のOperationがvalidatorの省略を許可する場合、callは過去に観測したObjectではなく、実行時にpathが指す現在のObjectへ無条件に実行する。
Validatorを指定した場合は、Clientが観測したObject identityおよび保護対象状態と実行対象を照合する。Path、`ref`、以前のProjection Resolution、cacheされたHost内部instanceのいずれも、単独ではProtocol上の永続的なObject identityとして扱わない。
一方、validatorが指定されたcallでは、Clientが観測したObject identityと保護対象状態を実行対象へ照合する。Path、`ref`、以前のProjection Resolution、cacheされたHost内部instanceは、いずれも単独ではProtocol上の永続的なObject identityとして扱わない。
## Filesystem projectionの評価例
Filesystemを`/files`以下へ投影する場合、Hostが全file / directoryに対応するObject instanceを作成する必要はない。
Filesystemを`/files`以下へ投影する場合も、全file / directory分のObject instanceを作成する必要はない。Request時の解決と投影を、次のように行える。
- `observe("/files/a.txt", depth = 0)`では、pathをfilesystem entryへ解決し、stat等からObject projectionを構築する。
- `observe("/files", depth = 1)`では、directory listingから直接のindexable childrenをすべて列挙する。
@@ -113,7 +117,7 @@ Filesystemを`/files`以下へ投影する場合、Hostが全file / directoryに
- 主体の権限に応じてObjectを非公開にしたり、read-only、writable等のcapability Interfaceを集合へ追加または除外できる。
- File Operationでは、call時にpathを現在のfilesystem entryへ解決し、Rust struct、TypeScript object、file descriptor等を使ってOperationを実装できる。
この例で、Objectはfileそのものでも、file内容を複製したrecordでもない。FileをWorldspace上で発見および操作するためのprotocol-level projectionである。
この場合のObjectは、fileをWorldspace上で発見・操作するためのprotocol-level projectionである。Fileそのものを渡すわけでも、file内容を複製したrecordを渡すわけでもない。
## 要件
@@ -167,13 +171,13 @@ Filesystemを`/files`以下へ投影する場合、Hostが全file / directoryに
- Operation call時には、その時点でpathが指す現在のProjected ObjectとInterface集合を再解決し、Clientが指定した参照のmembershipとvalidatorを確認する。
- 非公開Object、非公開Operation、公開済みだが実行拒否されたOperationをProtocolで定めたerrorへ一貫して対応付ける。
Backendが並行して変化する場合、複数request間で同じsnapshotを保証することまでは要求しない。観測したObject identityおよび状態と条件付き実行の対応はvalidatorで保護する。Validatorを省略したcallをOperationが許可する場合は実行時の現在Objectへ無条件に実行し、Operationがvalidatorを要求する場合は`ValidatorRequired`として実行しない。
Backendが並行して変化する場合、複数request間で同じsnapshotを保証することまでは要求しない。観測したObject identityと状態を条件付き実行の対象へ対応付けるため、validatorを使う。Operationがvalidatorの省略を許可すれば、callは実行時の現在Objectへ無条件に実行する。Validatorを要求するOperationでは、省略されたcallを`ValidatorRequired`として拒否し、実行しない。
### Operation解決と実行対象のatomicity
Operation callでは、visibility、Object identityとvalidator、Interface membershipとvalidator、Interface Descriptor、Operation implementation、backend対象を一つのlinearization pointで固定しなければならない。ValidatorなしのObject実行をOperationが許可する場合でも、解決後にpathの指すProjected Objectが変化し、以前のDescriptorに基づくOperation implementationが現在の別Objectへ適用されることを許してはならない。
Operation callでは、visibility、Object identityとvalidator、Interface membershipとvalidator、Interface Descriptor、Operation implementation、backend対象を、一つのlinearization pointで固定しなければならない。Object validatorなしの実行をOperationが許可する場合も、この固定は必要である。解決後にpathの指すProjected Objectが変わり、以前のDescriptorに基づくOperation implementationが現在の別Objectへ適用されることは許さない。
少なくとも次を一つのatomicなexecution boundaryとして扱えなければならない。
少なくとも次の処理を、一つのatomicなexecution boundaryとして扱える必要がある。
- Pathが現在指すObject identityと保護対象状態の確認。
- Object validatorの必須判定と比較。
@@ -183,9 +187,9 @@ Operation callでは、visibility、Object identityとvalidator、Interface memb
- Authorizationの確認。
- 同じbackend対象へのOperation実行。
単にpathを一度解決し、validatorを比較した後に、同じpathを別途開き直してOperationを実行する実装では、比較と実行の間に対象が差し替わる可能性がある。
Pathを一度解決してvalidatorを比較しても、その後に同じpathを別途開き直して実行すると、比較と実行の間に対象が差し替わる可能性がある。
Host APIは、backend transaction、lock、revision付きconditional update、file descriptor、identity再確認等、Providerがbackendに適した方法でatomicityを実現できる境界を提供する必要がある。すべてのbackendに共通する特定のlocking方式は要求しない。
そのためHost APIには、Providerがbackendに適した方法でatomicityを実現できる境界が必要になる。Backend transaction、lock、revision付きconditional update、file descriptor、identity再確認等を利用できるようにするが、すべてのbackendに共通する特定のlocking方式は要求しない。
### Host内部Object stateのlifecycleを限定できること
@@ -229,7 +233,7 @@ Host APIは、backend transaction、lock、revision付きconditional update、fi
### RustとTypeScriptで同じsemanticsを表現できること
言語ごとのAPI syntaxは異なってよいが、少なくとも次を両方で実現できなければならない。
RustとTypeScriptでAPI syntaxが異なっても、次の処理や制約は両方で実現できなければならない。
- Asyncなpath resolutionとchild enumeration。
- Data-drivenなObject projection。
@@ -240,11 +244,11 @@ Host APIは、backend transaction、lock、revision付きconditional update、fi
- Request context、主体、cancellation、resource limitの伝播。
- Protocol errorとbackend / implementation errorの分離。
Rust固有のtrait、generic、associated type、type erasureや、TypeScript固有のobject definition、generic inference、runtime schema libraryの選択は、この要件を満たすためのAPI設計段階で決める。
Rustのtrait、generic、associated type、type erasureや、TypeScriptのobject definition、generic inference、runtime schema libraryの選択は、これらの要件を満たすAPIを設計する段階で決める。
## Host内部cache
Hostは性能最適化として、path resolution、backend metadata、Object projection、Interface Descriptor、Host内部Object state等をcacheしてよい。ただし、cacheはProtocol contractではない。
Host内部のcacheは性能最適化であり、Protocol contractではない。Path resolution、backend metadata、Object projection、Interface Descriptor、Host内部Object state等をcacheしてよいが、次の条件を守る必要がある。
- Cacheがなくても正しく動作しなければならない。
- Visibilityとauthorizationを異なる主体間で誤って共有してはならない。
@@ -254,21 +258,23 @@ Hostは性能最適化として、path resolution、backend metadata、Object pr
## Composition
一つのHostは、Filesystem、database、remote API等の複数Providerを一つのWorldspaceへ合成できることが望ましい。
一つのHostで、Filesystem、database、remote API等の複数Providerを一つのWorldspaceへ合成できることが望ましい。
Composition後も、同じ主体へ公開されたWorldspace全体で`ref`とInterface参照のProtocol semanticsを保たなければならない。Provider-local identityやInterface keyをそのまま公開すると衝突し得るため、Hostはnamespace、変換、中央発行等の方法で次を保証する。
合成する場合も、同じ主体へ公開するWorldspace全体で`ref`とInterface参照のProtocol semanticsを保たなければならない。Provider-local identityやInterface keyをそのまま公開すると衝突し得るため、Hostはnamespace、変換、中央発行等によって次を保証する。
- 異なるObjectへ同じ有効な`ref`を割り当てない。
- 同じ有効なInterface参照とvalidatorの組を異なるDescriptorへ対応付けない。
- Validator比較がProvider routingの変更によって別Objectへ適用されない。
Interface参照は[2.2. Operation and Interface](../2.2-operation-and-interface.md#interfaceの識別とscope)の構造化参照を使用する。Objectの祖先制約と、合成後のscope・path・typed `entry`の変換は[ProtocolのWorldspace composition](../3-protocol.md#worldspace-composition)に従う。Objectの`ref`の具体的な発行方式は引き続き未決定とする。ScopeはそのpathのObjectに紐づき、self-scopeを許可する。RuntimeはDescriptorとscope Objectのoptionalな`ref`を一つのInterface observationとして公開し、callで指定された`scope_ref`をrouting・implementationの固定と一貫して確認する。`ref`のないscopeも許可し、そのidentityの追跡を要求しない。
Interface参照には、[2.2. Operation and Interface](../2.2-operation-and-interface.md#interfaceの識別とscope)の構造化参照を使う。Objectの祖先制約と、合成後のscope・path・typed `entry`の変換は、[ProtocolのWorldspace composition](../3-protocol.md#worldspace-composition)に従う。Objectの`ref`を具体的にどう発行するかは、引き続き未決定である。
ただし、mount API、path routing、Provider間のparent / child関係、同名entry conflict、cross-provider Operation、transaction boundaryは未決定である。ProtocolはHost内部のcomposition方式を公開しないため、Host APIでこれらをどこまで標準化するかを別途検討する。
ScopeはそのpathのObjectに紐づき、self-scopeも許可する。RuntimeはDescriptorとscope Objectのoptionalな`ref`を一つのInterface observationとして公開する。Callで指定された`scope_ref`は、routing・implementationの固定と一貫して確認する。`ref`のないscopeも許可し、そのidentityの追跡は要求しない。
Host内部の合成方法については、mount API、path routing、Provider間のparent / child関係、同名entry conflict、cross-provider Operation、transaction boundaryが未決定である。ProtocolではHost内部のcomposition方式を公開しないため、これらをHost APIでどこまで標準化するかは別途検討する。
## 非目標
このdraftは次を要求しない。
動的projectionの要件には、次を含めない。
- Worldspace全体の事前materialization。
- Objectごとの常駐class instanceまたはactor。
@@ -281,7 +287,7 @@ Interface参照は[2.2. Operation and Interface](../2.2-operation-and-interface.
## API設計前に評価するシナリオ
具体API案は、少なくとも次のシナリオで不自然な大量登録や永続Object instanceを要求しないことを確認する。
具体API案は、少なくとも次のシナリオで評価する。不自然な大量登録や、永続Object instanceの保持を要求しないことを確認する必要がある。
1. 数百万entryを持つFilesystemを、directory listingに応じて遅延投影する。
2. Database tableのrowをObjectとして投影し、row keyからcall時に再解決する。
@@ -318,4 +324,4 @@ Interface参照は[2.2. Operation and Interface](../2.2-operation-and-interface.
- Provider composition時のconflict、ownership、lifecycle、shutdown順序。
- Observability、tracing、auditで非公開Objectやsecretを漏らさないための標準hook。
これらを決定する前に、Rust / TypeScript双方で複数のAPI sketchを作り、上記の評価シナリオと要件に照らして比較する。
これらの決定に先立ち、Rust / TypeScript双方で複数のAPI sketchを作る。各案をここに挙げた評価シナリオと要件に照らして比較し、具体的なAPIを検討する。
+33 -31
View File
@@ -2,30 +2,32 @@
## 位置付け
この文書は、YoiのFS投影に対して決めた探索仕様を、WIP Hostの投影方針として記録するdraftである。**Treeで発見するのはfilesystemの入口までとし、その内容はdirectoryのlist / glob / grep Operationで発見する。**
YoiのFS投影では、Treeで発見する範囲をfilesystemの入口までとし、その内容をdirectoryのlist / glob / grep Operationで発見する方針を決めた。このdraftは、その探索仕様をWIP Hostの投影方針として記録するものである。
Indexableな範囲の全量取得をClientで縮めるのではなく、Hostが何をindexableとして公開するかを修正する。個々のファイル・フォルダは非indexableなObjectとして要求時に直接解決できる。
変更するのは、Hostがindexableとして公開する範囲である。Indexableな範囲の全量取得をClient側で縮めるのではなく、Hostで入口と内容を分ける。個々のファイル・フォルダは非indexableなObjectとして、要求時に直接解決できる。
[Object tree / SchemaのIndexable children](../2.1-object-tree-schema.md#indexable-children)、[Client](../4-client.md)、[4.1. AI Tools](../4.1-ai-tools.md)を前提とする。Yoi側の実装追跡はT-714、既存投影はT-699である。本稿は仕様決定の記録であり、実装済みであることを示さない。
前提となる仕様は、[Object tree / SchemaのIndexable children](../2.1-object-tree-schema.md#indexable-children)、[Client](../4-client.md)、[4.1. AI Tools](../4.1-ai-tools.md)に従う。Yoi側の実装追跡はT-714、既存投影はT-699である。このdraftは仕様決定の記録であり、実装済みであることを示すものではない。
## なぜFS全体をindexableにしないか
Indexable childrenには、件数がboundedまたは現実的な範囲で列挙でき、比較的安価で、自然な所有・内包関係であることが求められる。全件列挙が高コストまたは不自然な集合は、対象の集合を扱うObjectのOperationで検索・filter・paginationし、`entry` を返すのが既存の方針である。
任意のfilesystem directoryには、浅い位置でも大量のfileやdirectoryが存在し得る。Depthを小さくしてもAIが把握できない件数になるため、depth制限だけで適切な探索空間を作ることはできない。
任意のfilesystem directoryは、浅い位置に大量のfileやdirectoryを持ち得る。Depthが小さくてもAIが把握できない件数になるため、depth制限だけでは適切な探索空間を作れない。
Indexable childrenには、件数がboundedまたは現実的な範囲で列挙でき、比較的安価で、自然な所有・内包関係であることが求められる。全件列挙が高コストまたは不自然な集合については、その集合を扱うObjectのOperationで検索・filter・paginationし、`entry` を返すのが既存の方針である。
次の対策だけでFS内容をindexableにしてよいとはしない。
FS内容の公開でも、このindexabilityの判断は必要になる。次の対策だけを理由に、内容をindexableにしてよいとはしない。
- Clientが小さいdepthを選ぶこと。
- Hostが件数上限で `ResourceLimitExceeded` を返すこと。
- Directoryをlazyに列挙し、常駐Objectや事前indexを作らないこと。
- Clientが応答を切り捨てて表示すること。
前二者は必要な安全弁、lazy解決は実装上の性質であり、indexabilityの判断とは別である。部分的な応答を完全なtreeとして見せることもできない。本投影では、内容の件数が少ない場合だけchildrenへ展開する方式にはせず、入口と内容の境界を一貫させる。
Depth制限と件数上限は必要な安全弁であり、lazy解決は実装上の性質である。いずれも、内容をindexableにするかどうかとは別の判断になる。また、部分的な応答を、完全なtreeとして見せることもできない。
この投影では、内容の件数が少ない場合だけchildrenへ展開する方式も採らない。件数によって探索方式が変わらないよう、入口と内容の境界を一貫させる。
## Indexableな公開境界
Yoiでは、rootからtreeで発見できる範囲を次とする。
Yoiでrootからtreeを通じて発見できるのは、現在利用できるfilesystemの入口までである。配置は次の範囲とする。
```text
/
@@ -34,9 +36,9 @@ Yoiでは、rootからtreeで発見できる範囲を次とする。
└── docs
```
`/checkouts/<checkout-name>` は、現在利用できるfilesystemの入口であり、directoryとして操作できるObjectでもある。その直下から先のfile / directoryは、入口や内容directoryのindexable childrenには含めない。
`/checkouts/<checkout-name>` はfilesystemの入口であり、directoryとして操作できるObjectでもある。ただし、その直下から先のfile / directoryは、入口にも内容directoryにもindexable childrenとして含めない。
例えば次のpathは有効な操作対象として存在し得るが、上のtreeには展開しない。
例えば、次のpathは有効な操作対象として存在し得るが、上のtreeには展開しない。
```text
/checkouts/main/README.md
@@ -44,24 +46,24 @@ Yoiでは、rootからtreeで発見できる範囲を次とする。
/checkouts/main/src/lib.rs
```
`/checkouts` はYoi側の配置例であり、WIP Protocol全体へ固定namespaceを追加するものではない。単一FSをWorldspace `/` に直接投影する場合は `/` 自体が入口に相当し、その内容をindexable childrenへ展開しない。
`/checkouts` はYoi側の配置例であり、WIP Protocol全体の固定namespaceにはしない。単一FSをWorldspace `/` に直接投影する場合は、`/` 自体を入口として扱い、その内容をindexable childrenへ展開しない。
入口の一覧自体についてもindexableの一般条件は維持する。この境界は、入口の数まで無制限に増やしてよいという意味ではない。
入口の一覧にも、indexableの一般条件を適用する。内容をtreeに含めないからといって、入口の数まで無制限に増やしてよいわけではない。
## 非indexableと非公開は別
File / directoryをindexableにしないことは、Objectとして非公開にすることでも、pathで解決不能にすることでもない。
File / directoryを非indexableにしても、Objectとしての公開やpathによる直接解決は可能である。Treeから発見できる範囲と、既知のpathから解決できる範囲は分けて扱う。
- `observe("/checkouts/main/src/lib.rs", depth = 0)` は、現在の主体に公開できるfileなら、そのObjectを返せる。
- AI向け `inspect(path)` は、ClientがまだObjectを観測していないpathにも使える。
- Directoryの探索やfileの読み書きは、そのObjectが公開するInterfaceのOperationとして実行する。
- 直接解決にも現在の可視性・権限を適用する。Pathを知っていることは権限ではない。
非公開・存在しないpathの扱いは従来のProtocolに従う。非indexableという理由だけで `NotFound` を返してはならない。
非公開・存在しないpathの扱いは、従来のProtocolに従う。非indexableという理由だけで `NotFound` を返してはならない。
## observeのchildren契約
FS入口およびその内容のdirectory/fileは、この投影では内容のindexable childrenを持たない。
この投影では、FS入口にも、その配下のdirectory/fileにも、内容を表すindexable childrenはない。そのため、depthを深くしても入口から先の内容は列挙しない。
| 観測 | 応答の意味 |
| --- | --- |
@@ -71,13 +73,13 @@ FS入口およびその内容のdirectory/fileは、この投影では内容のi
| `observe("/checkouts/main", 1)` | 入口Objectと `children: []` |
| `observe("/checkouts/main/src", 1)` | 直接解決したdirectory Objectと `children: []` |
`children: []` は「indexable childがない」という意味であり、filesystem directoryが空であるとは限らない。内容が空かどうかを知るにはdirectoryの `list` を使う。
`children: []` が示すのは、indexable childがないことである。Filesystem directoryが空であることまでは示さない。内容が空かどうかは、directoryの `list` で確認する。
File数が増えても、入口の正のdepth観測でbackendの全内容を列挙する必要はない。Client側だけで非表示にするのではなく、Hostのchildren列挙境界で内容への走査を行わないようにする。Depth境界でのfield省略と、観測済みの空のchildrenは従来どおり区別する。
File数が増えても、入口を正のdepthで観測するためにbackendの全内容を列挙する必要はない。Client側で内容を非表示にするだけではなく、Hostのchildren列挙境界で内容への走査を行わないようにする。Depth境界でfieldを省略する場合と、観測した結果が空のchildrenである場合は、従来どおり区別する。
## 内容を発見するOperation
FS入口と配下directoryには、次の探索Operationを提供する。これらはInterface上のOperationであり、新しいProtocol interactionや `list` という子Objectではない。
FS入口と配下directoryの内容は、次の探索Operationで発見する。これらはInterface上のOperationであり、新しいProtocol interactionを追加したり、`list` という子Objectを設けたりするものではない。
| Operation | 役割 |
| --- | --- |
@@ -93,32 +95,32 @@ FS入口と配下directoryには、次の探索Operationを提供する。これ
- 大量件数はOperation結果として上限と継続を明示して扱う。部分的な一覧を全件であるかのように返さない。
- Cursor等の継続方式、並び順、parameter名、result recordの具体形は、このdraftでは未決とする。
Yoiの `/checkouts` 自体にある `list` は入口一覧であり、`/checkouts/<checkout-name>` や配下directoryの `list` は内容一覧である。Operation名が同じでも対象とInterfaceが異なる。
Yoiの `/checkouts` にある `list` は入口一覧を返す。一方、`/checkouts/<checkout-name>` や配下directoryの `list` は内容一覧を返す。同じOperation名でも、対象とInterfaceは異なる。
### glob / grep
対象directoryを基準にpatternや検索範囲を解釈する。Resultsからfile / directoryへ移動する参照は `entry` 型として宣言し、表示済みのfilenameや行番号付きtextを再parseして作らない。
Patternや検索範囲は、対象directoryを基準に解釈する。Resultsからfile / directoryへ移動する参照は、`entry` 型として宣言する。表示済みのfilenameや行番号付きtextを再parseして参照を作る方式は採らない。
Globは条件に一致する対象を探す操作であり、directory直下の全内容を表すとは限らない。特にYoiの通常ToolsのGlobはfileのみを返し、directoryは返さず、配下を再帰的に走査し得る。`glob("*")` を `list` と同じ契約として扱わない。
Globで得るのは条件に一致する対象であり、directory直下の全内容とは限らない。特にYoiの通常ToolsのGlobはfileのみを返し、directoryは返さず、配下を再帰的に走査し得る。このため、`glob("*")` を `list` と同じ契約として扱わない。
Grepは内容検索であり、treeの名前・構造の探索ではない。Ignore、検索範囲、結果上限、context、継続等は各Operationの明示された契約に従う。
Grepはfileの内容検索であり、treeの名前や構造を探索する操作ではない。Ignore、検索範囲、結果上限、context、継続等は、各Operationに明示された契約に従う。
## Clientとの接続
典型的な利用は次の流れになる。これは操作の順序の例であり、Tool responseやInterface参照の具体構文を定義するものではない。
Clientでは、treeで入口を知り、directoryのOperationで内容のpathを得て、必要なObjectだけをinspectする流れになる。典型的な操作順序は次のとおりである。これは利用例であり、Tool responseやInterface参照の具体構文を定義するものではない。
1. `tree("/", depth)` で `/checkouts/main` の入口を知る。
2. `inspect("/checkouts/main")` でdirectoryの `list` / `glob` / `grep` を知る。
3. 選んだOperationを `invoke` し、結果から `/checkouts/main/src` やfileのpathを得る。
4. 必要なpathだけを `inspect` し、さらに探索するかfileのOperationを実行する。
結果のすべてのentryを即時にObjectへ展開する必要はない。AIはまずpathだけを受け取り、説明や操作が必要になったときにClientへinspectを依頼できる。
Operation結果のすべてのentryを、直ちにObjectへ展開する必要はない。AIはまずpathだけを受け取り、説明や操作が必要になった時点でClientへinspectを依頼できる。
Clientがそれらを観測してKnown Spaceへ保持しても、rootからのtreeには混ぜない。Pathの階層関係だけからindexable edgeを生成しない。既知の内容directoryをtreeの起点として直接指定した場合も、そのObjectは表示できるが、内容をindexableな子として復活させない。
観測した内容をClientがKnown Spaceへ保持しても、rootからのtreeには混ぜない。Pathの階層関係だけではindexable edgeを生成しない。既知の内容directoryをtreeの起点として直接指定した場合も、そのObjectは表示できるが、内容をindexableな子として再び表示することはしない。
## 解決・権限・整合性
探索方式の変更で、既存の権限やファイル操作の意味を変えない。
内容の探索をOperationへ分けても、既存の権限やファイル操作の意味は変えない。一覧・検索・直接解決・操作には、次の境界を適用する。
- 現在の主体、root/attachment、scope、provider capabilityに基づき、一覧・検索・直接path解決・操作を実行する。
- Hostの一覧結果には、主体へ公開できる対象だけを含める。直接path指定でも同じ境界を守る。
@@ -126,15 +128,15 @@ Clientがそれらを観測してKnown Spaceへ保持しても、rootからのtr
- Object identityとvalidatorは既存Protocolとproviderの実行境界で管理する。
- Fileのread/edit/write等の具体的契約は、各投影のInterfaceに従う。本稿はbyte操作やtext操作の統一を要求しない。
Yoiの実装では、既存Workdir providerのList/Glob/Grep処理と権限・transport境界を共有する。Worker側でremote filesystemのホストパスを直接開く方法や、Bashの `ls` を必須にする方法へ置き換えない。
Yoiの実装では、既存Workdir providerのList/Glob/Grep処理と権限・transport境界を共有する。Workerがremote filesystemのホストパスを直接開く方法や、Bashの `ls` を必須にする方法には置き換えない。
## 現行文書・実装との差
[Dynamic Worldspace Projection](dynamic-worldspace-projection.md)のFilesystem評価例と、現行 `wip-fs-server` は、directoryの内容をchildrenとして列挙する経路を持つ。Yoiの既存 `/checkouts` 投影も、内部List処理をchildren列挙に使い、directoryの独立した `list` Operationは提供していなかった。
[Dynamic Worldspace Projection](dynamic-worldspace-projection.md)のFilesystem評価例と現行 `wip-fs-server` には、directoryの内容をchildrenとして列挙する経路がある。Yoiの既存 `/checkouts` 投影でも、内部List処理をchildren列挙に使い、directoryの独立した `list` Operationは提供していなかった。
本draftは、それらの現状を承認する文書ではなく、FS内容の探索をOperationへ分離する修正方針である。Lazyなrequest-time解決と、既知pathからの直接解決は維持するが、directory listingをindexable childrenの列挙として使う部分は見直す。
それに対し、このdraftはFS内容の探索をOperationへ分離する修正方針である。Lazyなrequest-time解決と、既知pathからの直接解決は維持する。ただし、directory listingをindexable childrenの列挙に使う部分は見直すため、現状の実装を承認するものではない。
既存ProtocolがあらゆるFS Objectのindexabilityを一律に禁止する明文を持つという意味ではない。既存のindexable条件を、任意件数の内容を持つFSへ適用する具体的方針として、このdraftでは入口で境界を固定する。
この方針は、既存Protocolに「あらゆるFS Objectを一律に非indexableとする」明文があることを意味しない。任意件数の内容を持つFSに既存のindexable条件を適用する具体的方針として、入口で境界を固定する。
## 検証するシナリオ
@@ -152,4 +154,4 @@ Yoiの実装では、既存Workdir providerのList/Glob/Grep処理と権限・tr
- Symlinkや特殊entryのlist上の種別表現、各providerのignore方針との整合。
- 本稿を既存の動的投影例、FS実装、AI用Toolsの正本文書へどう反映するか。
通常Tools modeへ独立したList Toolを追加するかどうかは、directory Operationの公開とは別の適用事項であり、本稿で追加済みとは扱わない。
通常Tools modeへ独立したList Toolを追加するかどうかは、directory Operationの公開とは別の適用事項である。このdraftで追加済みとは扱わない。
+67 -69
View File
@@ -2,15 +2,15 @@
## Status
この文書は、WIP HostをRustで実装するための概念的なAPI modelを整理するdraftである。
WIP HostをRustで実装する際、Interfaceの宣言とObjectの実装をどう組み合わせて公開するか。このdraftは、そのための概念的なAPI modelを提案する。
このdraftで示すtrait名、attribute、derive、generated type名、method signatureは説明用であり、具体的なRust API syntaxとして確定しない。Ownership、lifetime、async runtime、error type、macro crate構成も未決定である。
Trait名、attribute、derive、generated type名、method signatureは説明用であり、具体的なRust API syntaxは確定していない。Ownership、lifetime、async runtime、error type、macro crate構成も未決定である。
Protocol上の確定事項は[Core Model](../2-core-model.md)、[Object tree / Schema](../2.1-object-tree-schema.md)、[Operation and Interface](../2.2-operation-and-interface.md)、[Protocol](../3-protocol.md)を参照する。動的なObject projectionの運用要件は[Dynamic Worldspace Projection](dynamic-worldspace-projection.md)、対応するTypeScript modelは[TypeScript API Model](typescript-api-model.md)を参照する。
Protocol上の確定事項は[Core Model](../2-core-model.md)、[Object tree / Schema](../2.1-object-tree-schema.md)、[Operation and Interface](../2.2-operation-and-interface.md)、[Protocol](../3-protocol.md)に従う。動的なObject projectionの運用要件は[Dynamic Worldspace Projection](dynamic-worldspace-projection.md)、対応するTypeScript modelは[TypeScript API Model](typescript-api-model.md)を参照する。
## 目的
Rust APIでは、次のmodelを自然に表現できるようにする。
Rust APIでは、Interfaceをtraitで宣言し、structで実装するmodelを自然に表現できるようにする。ただし、structが実装しているInterfaceと、ある時点で公開するInterfaceは分けて選べるようにする。
1. Rust traitでWIP Interfaceを宣言する。
2. Rust structが、Protocol Objectとして公開するmetadataを提供する。
@@ -19,13 +19,13 @@ Rust APIでは、次のmodelを自然に表現できるようにする。
5. Trait declarationからInterface Descriptor、Value codec、validation、Operation dispatchに必要なcodeを生成する。
6. Struct instanceをWorldspace全体について常駐させず、`observe`と`call_operation`の解決時にdata-drivenに生成できる。
このmodelでは、Protocol上のObjectとInterfaceの関連付けは`Object.interfaces`だけで表す。Operation implementationへ到達するためのRust内部codeはSDK / Host Runtimeの実装詳細であり、新しいProtocol conceptを導入しない。
Protocol上でObjectとInterfaceを関連付けるのは`Object.interfaces`だけである。Operation implementationを呼び出すためのRust内部codeはSDK / Host Runtimeの実装詳細として扱い、新しいProtocol conceptは導入しない。
## Conceptual model
### Interface trait
WIP InterfaceはRust traitとして宣言する。
WIP Interfaceは、Rust traitとして宣言する。
```rust
#[wip::interface]
@@ -47,9 +47,9 @@ trait FileInterface {
}
```
このcodeはconceptual syntaxである。`Option<i64>`の対応範囲、`Bytes` wrapper、documentationの取得方法、async methodとerrorの具体形は別途決定する。
このcodeはconceptual syntaxであり、具体的なAPIとして確定したものではない。`Option<i64>`の対応範囲、`Bytes` wrapper、documentationの取得方法、async methodとerrorの具体形は別途決定する。
Trait declarationは、次のlogical declarationに対応する。
Trait declarationとProtocol上の宣言は、次のように対応付ける。
- 一つのtrait declarationを、一つのInterface Descriptorを生成するRust側definitionとして扱う。
- Trait名はgenerated Rust itemやlocal registrationを識別するために使用できるが、Protocol `InterfaceDescriptor`のfieldや構造化されたInterface参照としてそのまま公開しない。
@@ -60,11 +60,11 @@ Trait declarationは、次のlogical declarationに対応する。
- Rust typeをDescriptorの`TypeExpr`とProtocol `Value`へ対応付ける。
- Documentationをtrait、method、parameter、return、関連typeから取得できるようにする。
Descriptorのshapeはtrait declarationによって決まり、各structのtrait implementationによって変化しない。
したがって、Descriptorのshapeを決めるのはtrait declarationである。各structがそのtraitをどう実装するかによって、Descriptorは変化しない。
### Object implementation
Rust structは、その時点でWorldspaceへ投影するObjectをHost内部で表現できる。
その時点でWorldspaceへ投影するObjectは、Host内部ではRust structとして表現できる。
```rust
struct File {
@@ -75,7 +75,7 @@ struct File {
}
```
Structは概念上の`WipObject` traitを実装する。
公開metadataを提供するために、structが概念上の`WipObject` traitを実装する形を想定する。
```rust
impl WipObject for File {
@@ -97,20 +97,20 @@ impl WipObject for File {
}
```
`WipObject`が返す値のownershipやborrow形式は未決定である。概念的にはProtocol Objectのうち、publication時に選択するInterface集合以外の公開metadataを提供する。
`WipObject`は、Protocol Objectの公開metadataのうち、publication時に選ぶInterface集合以外を提供する。返す値のownershipやborrow形式は未決定である。
`WipObject`がProtocol metadataとして返す値へ次を含めない。これらをimplementing structのprivate fieldとして保持することは禁止しない。
Structが保持する情報のすべてを公開metadataにするわけではない。次の情報は`WipObject`がProtocol metadataとして返す値に含めないが、implementing structのprivate fieldとして保持してよい。
- Absolute path。PathはObjectのfieldではなく、Worldspace resolutionのcontextである。
- Children。ChildrenはTree上の配置contextである。
- 固定されたInterface集合。InterfaceはObjectを公開する時点で追加する。
- Backend connection、file descriptor、credential等のHost-private state。
Structが保持する`path`やbackend handle等はHost内部のOperation implementationに使用できるが、`WipObject`のmetadataまたはProtocol Objectへ自動的にserializeしない。
たとえば、structの`path`やbackend handleはHost内部のOperation implementationで使用できる。ただし、`WipObject`のmetadataやProtocol Objectへ自動的にserializeする対象にはしない。
### Interface implementation
Object implementationとして使用するstructは、公開したいInterface traitを実装する。
Object implementationに使うstructは、公開したいInterface traitを実装する。
```rust
impl FileInterface for File {
@@ -131,15 +131,15 @@ impl FileInterface for File {
}
```
Trait implementationはOperationのbehaviorを提供する。Interface Descriptorはtrait implementationから生成せず、Interface trait declarationから生成する。
Trait implementationが提供するのはOperationのbehaviorである。Interface Descriptorの生成元は、このimplementationではなくInterface trait declarationとする。
Rustには、あるtypeが実装しているtraitを列挙する一般的なreflectionがない。また、一つのstructが複数のInterface traitを実装し得る。そのため、trait implementationが存在するだけでInterfaceを暗黙に公開しない。
また、traitを実装しただけでInterfaceを公開することにはしない。Rustには、あるtypeが実装しているtraitを列挙する一般的なreflectionがなく、一つのstructが複数のInterface traitを実装することもあるためである。
### Object publication
ObjectをWorldspaceへ返す時点で、struct instanceと公開する0個以上のInterface Declarationを明示的に組み合わせる。Interfaceは追加順を保持するordered setであり、同じDefinitionを重複して追加しない。
ObjectをWorldspaceへ返す時点で、struct instanceと、公開する0個以上のInterface Declarationを明示的に組み合わせる。Interfaceは追加順を保持するordered setとし、同じDefinitionの重複追加は認めない。
Conceptual syntaxは次のようになる。
次のconceptual syntaxでは、解決した`File`に公開するInterfaceを追加している。
```rust
let file = File::resolve(path).await?;
@@ -147,9 +147,9 @@ let object = PublishedObject::new(file)
.expose(FileInterfaceDefinition);
```
ここで各`InterfaceDefinition`は、`#[wip::interface]`が生成するconceptualなcompanion definitionである。実際の名前や、associated item、module、valueのどの形で生成するかは未決定である。
各`InterfaceDefinition`は、`#[wip::interface]`が生成するconceptualなcompanion definitionを表す。実際の名前も、associated item、module、valueのどの形で生成するかも未決定である。
Publication APIは、追加する各Definitionについて概念的に次のboundを要求する。
Publication APIが各Definitionの追加に要求するboundは、概念的には次の形になる。
```rust
impl<T: WipObject> PublishedObject<T> {
@@ -165,9 +165,9 @@ impl<T: FileInterface> InterfaceDefinition<T>
}
```
このboundにより、Objectへ追加する各Interfaceについて、公開する値がObject metadataとOperation implementationの両方を提供することをcompile timeに確認できる。どのInterfaceも追加しないObjectも表現できる。
このboundで、公開する値がObject metadataを提供し、追加する各InterfaceのOperation implementationも提供することをcompile timeに確認できる。Interfaceを一つも追加しないObjectも表現できる。
`PublishedObject`はHost SDK内のconceptual typeであり、Protocol typeとして追加しない。Host Runtimeはこれを使用して次を構築する。
`PublishedObject`はHost SDK内のconceptual typeであり、Protocol typeには追加しない。Host Runtimeはこの値からProtocol Objectを構築する。
```rust
Object {
@@ -179,13 +179,15 @@ Object {
}
```
`selected_interface_references`は、Hostが各generated Interface Definitionを登録または公開するときに割り当てる構造化参照`{ scope, name }`を、publication APIへの追加順で並べたものである。同じ`(scope, name)`の重複は拒否し、Objectの配置pathに対する祖先制約も検証する。Macroが参照をcompile timeに固定することは要求しない。
`selected_interface_references`には、Hostが各generated Interface Definitionの登録または公開時に割り当てる構造化参照`{ scope, name }`を、publication APIへの追加順で並べる。同じ`(scope, name)`の重複は拒否し、Objectの配置pathに対する祖先制約も検証する。Macroが参照をcompile timeに固定することは要求しない。
`observe`はDescriptor自体をObjectへ埋め込まず、このInterface参照のordered setだけを返す。Clientが各参照を`fetch_interface`したとき、Host Runtimeはtrait declarationから生成されたDescriptorと、存在する場合はInterface validatorを返す。同じ参照とvalidatorの組のDescriptorはHost上で共有およびcacheできるため、Object instanceごとにDescriptorを再生成または再送する必要はない。
`observe`でObjectに含めるのは、Descriptor自体ではなく、このInterface参照のordered setだけである。Clientが各参照を`fetch_interface`すると、Host Runtimeはtrait declarationから生成したDescriptorと、存在する場合はInterface validatorを返す。
同じ参照とvalidatorの組に対応するDescriptorは、Host上で共有およびcacheできる。このため、Object instanceごとにDescriptorを再生成したり再送したりする必要はない。
## Macroが生成する責務
`#[wip::interface]`は、conceptualには次を生成または提供する。
`#[wip::interface]`には、宣言からDescriptorを生成するだけでなく、Valueの変換・検証とdispatchに必要なcodeを提供する役割を想定する。
- Interface Descriptorを構築するdefinition。
- Trait methodとOperation Declarationの対応情報。
@@ -196,15 +198,13 @@ Object {
- 任意の`T: WipObject + InterfaceTrait`について、そのInterfaceを`PublishedObject<T>`へ追加するための型付きentry point。
- HostがInterface参照、optional validator、Descriptorを登録、取得、cacheするためのidentity。
MacroがRust codebase内のtrait implementationを探索または列挙することは要求しない。Publication時のgeneric boundによって、対象structがInterface traitを実装していることを確認する。
対象structがInterface traitを実装しているかは、publication時のgeneric boundで確認する。MacroがRust codebase内のtrait implementationを探索したり列挙したりすることは要求しない。
Generated dispatch codeはRust SDK内部の実装詳細である。Host内部のdispatch mechanismやRust type名等をProtocolへ公開しない。
Generated dispatch codeはRust SDK内部の実装詳細である。Host内部のdispatch mechanismやRust type名等はProtocolへ公開しない。
## Rust typeとProtocol type
Interface traitで使用できるRust typeは、Descriptorの`TypeExpr`とProtocol `Value`へ対応付けられなければならない。
Conceptualにはderiveまたは明示的なcodec implementationを使用する。
Interface traitで使うRust typeには、Descriptorの`TypeExpr`とProtocol `Value`への対応付けが必要となる。概念的には、deriveまたは明示的なcodec implementationを使うことを想定する。
```rust
#[derive(WipType)]
@@ -221,7 +221,7 @@ enum ReadResult {
}
```
このsyntaxも未決定である。少なくとも次を表現できる必要がある。
このsyntaxも未決定である。Typeの対応付けでは、少なくとも次を表現できる必要がある。
- Unit、Boolean、Integer、Number、String、Bytes、Json、Entry。
- Record、List、Enum、Union。
@@ -229,15 +229,15 @@ enum ReadResult {
- Requiredとoptionalなfieldおよびparameter。
- Documentation。
Rustの`Option<T>`をoptional field / parameter以外で許可するか、enumをProtocol EnumまたはUnionへどう対応付けるか、newtypeをどのように扱うかは未決定である。
Rustの`Option<T>`をoptional field / parameter以外でも許可するかは、まだ決めていない。EnumをProtocol EnumまたはUnionへどう対応付けるか、newtypeをどう扱うかも未決定である。
Rust SDKは、integerのProtocol相互運用範囲、finite number、unknown field、Union shape、Entry path等をProtocol boundaryで検証しなければならない。
型の対応付けとは別に、Protocol boundaryでの検証も必要となる。Rust SDKは、integerのProtocol相互運用範囲、finite number、unknown field、Union shape、Entry path等をそこで検証しなければならない。
## Dynamic Worldspaceでのlifecycle
### `observe`
Projection implementationはrequest時にbackend dataを解決し、struct instanceを生成する。
Projection implementationはrequest時にbackend dataを解決し、その時点のstruct instanceを生成する。
```rust
async fn resolve_file(path: &WipPath) -> Result<PublishedObject> {
@@ -255,9 +255,9 @@ async fn resolve_file(path: &WipPath) -> Result<PublishedObject> {
}
```
Host Runtimeは`PublishedObject`からProtocol Objectを返す。Response生成後にこの`File` instanceを破棄してよく、Worldspace内の全fileに対応するinstanceを保持しない。
Host Runtimeは`PublishedObject`からProtocol Objectを返す。Responseを生成した後は、この`File` instanceを破棄してよい。Worldspace内の全fileに対応するinstanceを保持する必要はない。
Requested depthが正の場合、Directory listingで発見した各entryについて、その時点のstruct instanceを生成して公開できる。Providerがdirectory全体を先に収集してから`Vec`として返すことは要求しないが、一つのparentのobservationを成功させるには公開されたindexable childrenをclean exhaustionまで列挙しなければならない。
Requested depthが正の場合は、Directory listingで発見した各entryについて、その時点のstruct instanceを生成して公開できる。Providerがdirectory全体を先に収集し、`Vec`として返すことは要求しない。ただし、一つのparentのobservationを成功させるには、公開されたindexable childrenをclean exhaustionまで列挙する必要がある。
```rust
let mut entries = filesystem.discover_children(path, budget).await?;
@@ -274,7 +274,7 @@ while let Some(entry) = entries.next().await? {
}
```
`discover_children`、`budget`、`observation`はconceptualであり、具体APIではない。必要なsemanticsは次である。
`discover_children`、`budget`、`observation`は具体APIではなく、conceptualな表記である。Childの発見と公開には、次のsemanticsを要求する。
- 各childを現在の主体についてprojectし、非公開Objectとそのsubtreeを返さない。
- 公開されたindexable childrenをすべて列挙し、clean exhaustionで終了する。
@@ -286,7 +286,7 @@ while let Some(entry) = entries.next().await? {
### `call_operation`
Hostはcall時に、requestのTargetと`InterfaceTarget`をHost Runtimeへ渡す。Runtimeは一つのatomic execution boundaryへ入ってから`target.path`を現在のObject implementationとstableなbackend対象へ解決する。
Call時には現在のObjectを解決し直す。HostはrequestのTargetと`InterfaceTarget`をHost Runtimeへ渡し、Runtimeは一つのatomic execution boundaryに入ってから、`target.path`を現在のObject implementationとstableなbackend対象へ解決する。
```rust
runtime.call_current(
@@ -299,7 +299,7 @@ runtime.call_current(
).await
```
`resolve_current_projection`と`runtime.call_current`というAPIを採用することは決定しない。ResolverはRuntimeが開始したexecution boundary内で呼ばれ、返す値はそのboundary中にObject identityとbackend対象を安定して保持するhandleまたはtransaction contextを含む必要がある。このexampleが示す要件は次である。
`resolve_current_projection`と`runtime.call_current`を実際のAPIとして採用するかは決めていない。ResolverはRuntimeが開始したexecution boundary内で呼ばれ、そのboundary中にObject identityとbackend対象を安定して保持するhandleまたはtransaction contextを含む値を返す必要がある。上のexampleは、次の要件を表す。
- 過去の`observe`で作成したstruct instanceを保持していなくてもOperationを実行できる。
- Call時の現在の主体、Object visibility、Object metadata、Interface集合を同じProjection pathで再解決し、Objectが非公開なら`NotFound`を返す。
@@ -315,15 +315,15 @@ runtime.call_current(
- Macro-generated dispatchが、選択されたInterface traitのmethodを現在のstruct instanceに対して呼び出す。異なるInterfaceの同名Operationをmergeまたは曖昧に解決しない。
- Operation実行後の現在状態に対応するvalidatorを、必要に応じて`CallOperationResponse`へ返せる。
Object validatorをObject identityへ結び付けるためにClient-facingな`ref`を要求しない。ProviderまたはHostはHost-privateなidentityを使用できるが、そのidentity confirmation、Object validator比較、Interface membershipとvalidator比較、DescriptorとOperation implementationの固定、authorization、Operation実行を一つのatomic boundaryで行う。
Object validatorとObject identityの関連付けに、Client-facingな`ref`は必須ではない。ProviderまたはHostはHost-privateなidentityを使用できる。ただし、identity confirmation、Object validator比較、Interface membershipとvalidator比較、DescriptorとOperation implementationの固定、authorization、Operation実行は、一つのatomic boundaryで行う。
Operation実行後validatorを、同じstruct instanceから再計算するか、Operation resultとともに返すか、backendを再観測するかは未決定である。どの方式でも、resultを生成した実行後状態とvalidatorを対応させなければならない。
実行後のvalidatorをどこから取得するかも未決定である。同じstruct instanceから再計算する方式、Operation resultとともに返す方式、backendを再観測する方式が考えられるが、いずれもresultを生成した実行後状態とvalidatorを対応させる必要がある。
Structが`PathBuf`だけを保持し、validator比較後にpathを無条件で開き直す実装は、対象差し替えに対するatomicityを保証できない場合がある。Rust APIは、file descriptor、transaction、conditional update、lock等を利用してbackend固有のatomicityを実現できる必要があるが、その抽象化は未決定である。
Structが`PathBuf`だけを保持している場合、validator比較後にpathを無条件で開き直すと、対象差し替えに対するatomicityを保証できないことがある。Rust APIには、file descriptor、transaction、conditional update、lock等でbackend固有のatomicityを実現できることを求める。そのための抽象化は未決定である。
## 複数Interfaceの実装
一つのstructは複数のInterface traitを実装できる。
一つのstructは、複数のInterface traitを実装できる。
```rust
impl ReadOnlyFileInterface for File {
@@ -335,7 +335,7 @@ impl WritableFileInterface for File {
}
```
Publication時に、現在の主体へ公開する0個以上のInterfaceを選択し、表示したい順で追加する。
そのうち、現在の主体へ公開する0個以上のInterfaceをpublication時に選び、表示したい順に追加する。
```rust
let mut object = PublishedObject::new(file)
@@ -348,15 +348,15 @@ if authorization.can_write() {
object
```
Protocol Objectの`interfaces`は追加順を保持するordered setである。同じInterface参照の重複は拒否する。各Interface Descriptorは独立したOperation集合を宣言し、複数trait implementationを一つのDescriptorへ暗黙にmergeしない。
Protocol Objectの`interfaces`は追加順を保持するordered setであり、同じInterface参照の重複は拒否する。各Interface Descriptorは独立したOperation集合を宣言するため、複数のtrait implementationを一つのDescriptorへ暗黙にmergeしない。
異なるInterfaceは同じOperation名を宣言できる。Dispatchはrequestの`InterfaceTarget.reference`とOperation名の組で一意に決まり、表示上のqualified表記は[Text Viewの参照表記](../4.2-text-view.md#参照表記)に従う。Signature全体をProtocol request fieldへparseし直さない。
異なるInterfaceが同じOperation名を宣言しても、dispatchはrequestの`InterfaceTarget.reference`とOperation名の組で一意に決まる。表示上のqualified表記は[Text Viewの参照表記](../4.2-text-view.md#参照表記)に従い、signature全体をProtocol request fieldへparseし直さない。
Rust traitのsupertrait、trait alias、複数traitの組み合わせをDescriptor生成へどう対応付けるかは未決定であり、Protocol上のInterface inheritanceを暗黙に導入しない。
Rust traitのsupertrait、trait alias、複数traitの組み合わせをDescriptor生成にどう対応付けるかは未決定である。これらによって、Protocol上のInterface inheritanceを暗黙に導入することはしない。
## 固定Interface向けのsugar
一つのRust typeを常に同じInterface集合で公開する場合、次のようなsugarを追加してよい。
一つのRust typeを常に同じInterface集合で公開する場合は、次のようなsugarを追加してよい。
```rust
#[wip::object(interfaces = [ReadOnlyFileInterface, WritableFileInterface])]
@@ -365,19 +365,19 @@ struct File {
}
```
または、conceptualには`WipObject`のassociated itemとしてdefault Interface集合を指定できる。
別のconceptualな形として、`WipObject`のassociated itemにdefault Interface集合を指定することも考えられる。
ただし、固定Interface集合をcore modelにはしない。主体、policy、resource kind等に基づいて同じstructへ異なるInterface subsetを追加できるexplicit publication modelを基礎とする。
ただし、core modelの基礎はexplicit publicationとする。主体、policy、resource kind等によって、同じstructへ異なるInterface subsetを追加できる必要があるため、固定Interface集合をcore modelにはしない。
Sugarを使用する場合も、対象typeが指定されたすべてのInterface traitを実装していることと、同じInterfaceを重複していないことを確認しなければならない。
Sugarを使う場合も、対象typeが指定したすべてのInterface traitを実装していることと、同じInterfaceを重複していないことを確認する必要がある。
## HostへのInterface登録
Generated Interface DefinitionをHostへ登録し、構造化されたInterface参照を割り当てる必要がある。
Generated Interface Definitionには、Hostへの登録を通じて構造化されたInterface参照を割り当てる必要がある。参照の絶対scopeとlocal name、および配置pathへの祖先制約は[2.2. Operation and Interface](../2.2-operation-and-interface.md#interfaceの識別とscope)に従う。
参照の絶対scopeとlocal name、および配置pathへの祖先制約は[2.2. Operation and Interface](../2.2-operation-and-interface.md#interfaceの識別とscope)に従う。以下のconceptual API例はscope / nameを渡す具体構文を省略しており、暗黙のroot scopeを定めるものではない。登録時のcontextと引数の具体APIは引き続き未決定である。Self-scopeは許可され、scopeはそのpathのObjectに紐づく。Scope Objectのoptionalな`ref`はProtocolの`scope_ref`として観測・検証し、`ref`がない場合のidentity追跡不能も許容する。Scopeの移動追跡や独立したscope validatorを導入しない。
Self-scopeは許可され、scopeはそのpathのObjectに紐づく。Scope Objectのoptionalな`ref`はProtocolの`scope_ref`として観測・検証する。`ref`がなければidentityを追跡できないことも許容し、scopeの移動追跡や独立したscope validatorは導入しない。
Conceptualには、eager registrationとlazy registrationの両方が考えられる。
登録方法としては、conceptualにはeager registrationとlazy registrationの両方が考えられる。次の例はscope / nameを渡す具体構文を省略しており、暗黙のroot scopeを定めてはいない。登録時のcontextと引数の具体APIも引き続き未決定である。
```rust
let file_read_interface = host.register_interface(ReadOnlyFileInterfaceDefinition)?;
@@ -387,9 +387,7 @@ let object = PublishedObject::new(file)
.expose(file_write_interface);
```
または、Hostが最初のpublication時に各definitionをinternしてよい。
どちらの場合も次を守る。
また、Hostが最初のpublication時に各definitionをinternする方式でもよい。どちらの登録方法でも、次の条件を満たす必要がある。
- MutableなInterface参照では`fetch_interface`がvalidatorを返し、同じ参照とvalidatorの組から異なるDescriptorを返さない。
- Validatorを返さないInterface参照は、その参照の有効期間中Descriptorをimmutableにする。
@@ -401,7 +399,7 @@ let object = PublishedObject::new(file)
## Request contextとauthorization
Operation implementationは、Object instance以外にrequest contextを必要とし得る。
Operation implementationが必要とする情報は、Object instanceだけとは限らない。Request contextとして、次の情報も必要になり得る。
- 現在の主体。
- Cancellationとdeadline。
@@ -409,30 +407,30 @@ Operation implementationは、Object instance以外にrequest contextを必要
- Host serviceやbackend connectionへのaccess。
- Resource limit。
これらをmethod parameter、receiver wrapper、generated context、task-local stateのどれで渡すかは未決定である。Protocol parameterとして宣言された値と、Hostが注入するcontextを明確に区別しなければならない。
このcontextをmethod parameter、receiver wrapper、generated context、task-local stateのどれで渡すかは未決定である。どの形でも、Protocol parameterとして宣言された値とHostが注入するcontextは明確に区別する必要がある。
Object publication時のInterface集合の選択と、Operation call時のmembership、Interface validator、authorizationの再評価を実装できる必要がある。以前の`observe`で公開されたInterface集合だけを根拠に、現在のOperation実行を許可してはならない。
Interface集合はObject publication時に選択するだけでなく、Operation call時にもmembership、Interface validator、authorizationを再評価できなければならない。以前の`observe`で公開したInterface集合だけを根拠に、現在のOperation実行を許可することはできない。
Operation resultのRecord、List、Union等へnestedしたすべての`Entry`位置について、Hostは現在の主体にそのpathを認識させてよいことを再帰的に確認できなければならない。通常のstructural Value validationだけではこのvisibility checkを満たさない。Macro-generated code、Projection、Host Runtimeのどこで確認するかは未決定である。
Resultのvisibility checkも、通常のstructural Value validationとは別に必要となる。Hostは、Operation resultのRecord、List、Union等にnestedしたすべての`Entry`について、現在の主体にそのpathを認識させてよいかを再帰的に確認できなければならない。この確認をMacro-generated code、Projection、Host Runtimeのどこで行うかは未決定である。
Operation argumentとして`Entry` pathを受け取った場合も、pathの所持をauthorizationの証明として扱わず、参照先へ作用する時点で現在の主体について認可する。
Argumentとして受け取った`Entry` pathについても、pathの所持をauthorizationの証明にはしない。参照先へ作用する時点で、現在の主体について認可する。
## Error model
Rust methodのerror表現は、次の四種類を区別できなければならない。
Rust methodのerror表現には、次の四種類を区別できることを求める。
- Protocol validationまたはdispatch failure。
- Effectがcommitされていないと保証できるHost / backend implementation failure。
- Operationの未実行またはrollbackを保証できない`OperationOutcomeUnknown`。
- Interfaceがreturn typeとして宣言したdomain failure。
現在のProtocolでは、domain failureはOperation resultのUnion caseとして表す。Rustの`Result<T, E>`をdomain Union、Host error、または両方のどれへ対応付けるかは未決定である。
現在のProtocolはdomain failureをOperation resultのUnion caseとして表す。Rustの`Result<T, E>`をdomain Union、Host error、またはその両方のどれに対応付けるかは未決定である。
MacroがRust panic、result encode failure、宣言型に違反するimplementation resultをdomain failureへ自動変換してはならない。Host Runtimeは、effectがcommitされていないと保証できる場合だけ`Internal`へmappingし、保証できない場合は`OperationOutcomeUnknown`へmappingする。Clientへ送信済みか不明なtransport切断も自動retryしない。
Rust panic、result encode failure、宣言型に違反するimplementation resultを、Macroがdomain failureへ自動変換することは認めない。Host Runtimeは、effectがcommitされていないと保証できる場合だけ`Internal`へmappingし、保証できなければ`OperationOutcomeUnknown`へmappingする。Clientへ送信済みかどうか不明なtransport切断についても、自動retryはしない。
## 要件
Rust API modelは少なくとも次を満たす。
このdraftのRust API modelに求める要件は、少なくとも次のとおりである。
- Interface Descriptorをtrait declarationから生成し、trait implementationごとに変化させない。
- Structが`WipObject`と、追加する各Interface traitを実装していることをcompile timeに確認する。
@@ -459,7 +457,7 @@ Rust API modelは少なくとも次を満たす。
## 非目標
このdraftは次を決定しない。
次の事項は、このdraftでは決定しない。
- 最終的なcrate、module、trait、attribute、deriveの名前。
- Proc macroの内部実装。
@@ -495,4 +493,4 @@ Rust API modelは少なくとも次を満たす。
- 主体ごとに異なるInterface combinationを追加したPublished Objectのconcrete return typeをどう統一するか。
- Rust client APIを同じtrait declarationから生成するか。
これらを決定する際は、静的service objectだけでなく、Filesystem、database row、virtual aggregate、主体別Interface compositionを同じAPIで実装できるか評価する。
これらの選択は、静的service objectに使えるだけでは足りない。Filesystem、database row、virtual aggregate、主体別Interface compositionも、同じAPIで実装できるかを評価して決定する。
+91 -91
View File
@@ -2,15 +2,15 @@
## Status
この文書は、WIP HostをTypeScriptで実装するための概念的なAPI modelを整理するdraftである。
TypeScriptの型は、通常のJavaScript outputには残らない。WIP Hostがruntimeに必要とするInterface Descriptorやvalidationをどう定義するか。このdraftは、TypeScriptでHostを実装するための概念的なAPI modelを提案する。
このdraftで示すfunction、object shape、generic type、class、method signatureは説明用であり、具体的なTypeScript API syntaxとして確定しない。Package構成、schema builderの最終名称、ownership、async context、error type、bundler integrationも未決定である。
Function、object shape、generic type、class、method signatureは説明用であり、具体的なTypeScript API syntaxは確定していない。Package構成、schema builderの最終名称、ownership、async context、error type、bundler integrationも未決定である。
Protocol上の確定事項は[Core Model](../2-core-model.md)、[Object tree / Schema](../2.1-object-tree-schema.md)、[Operation and Interface](../2.2-operation-and-interface.md)、[Protocol](../3-protocol.md)を参照する。動的なObject projectionの運用要件は[Dynamic Worldspace Projection](dynamic-worldspace-projection.md)、対応するRust modelは[Rust API Model](rust-api-model.md)を参照する。
Protocol上の確定事項は[Core Model](../2-core-model.md)、[Object tree / Schema](../2.1-object-tree-schema.md)、[Operation and Interface](../2.2-operation-and-interface.md)、[Protocol](../3-protocol.md)に従う。動的なObject projectionの運用要件は[Dynamic Worldspace Projection](dynamic-worldspace-projection.md)、対応するRust modelは[Rust API Model](rust-api-model.md)を参照する。
## 目的
TypeScript APIでは、次のmodelを自然に表現できるようにする。
TypeScript APIでは、runtimeに残るdefinition objectを使い、Protocol上の宣言とTypeScript型の推論を対応付けるmodelを自然に表現できるようにする。Objectの実装と、ある時点で公開するInterfaceの選択は分けて扱う。
1. Runtimeに残るdefinition objectでWIP Interfaceを宣言する。
2. 同じdefinition objectからInterface Descriptor、Value codec、validationを構築する。
@@ -20,11 +20,11 @@ TypeScript APIでは、次のmodelを自然に表現できるようにする。
6. Object instanceをWorldspace全体について常駐させず、`observe`と`call_operation`の解決時にdata-drivenに生成できる。
7. Custom transpiler、TypeScript compiler plugin、decorator metadataをcore APIの前提にしない。
このmodelでは、Protocol上のObjectとInterfaceの関連付けは`Object.interfaces`だけで表す。Operation implementationへ到達するためのTypeScript / JavaScript内部codeはSDK / Host Runtimeの実装詳細であり、新しいProtocol conceptを導入しない。
Protocol上でObjectとInterfaceを関連付けるのは`Object.interfaces`だけである。Operation implementationを呼び出すためのTypeScript / JavaScript内部codeはSDK / Host Runtimeの実装詳細として扱い、新しいProtocol conceptは導入しない。
## TypeScriptの型消去
TypeScriptの`interface`、`type`、generic type argumentは、通常のJavaScript outputには残らない。
TypeScriptの`interface`、`type`、generic type argumentは、通常のJavaScript outputには残らない。たとえば、次のdeclarationだけからruntimeにInterface Descriptorを取得することはできない。
```ts
interface FileOperations {
@@ -32,13 +32,11 @@ interface FileOperations {
}
```
このdeclarationだけから、runtimeにInterface Descriptorを取得することはできない。
```ts
host.registerInterface(FileOperations); // runtime valueではない
```
そのため、TypeScript APIではruntime valueをsource of truthにする。
そこで、TypeScript APIではruntime valueをsource of truthにする。
```ts
const FileInterface = wip.interface({
@@ -46,13 +44,13 @@ const FileInterface = wip.interface({
});
```
このobjectは通常のJavaScript valueとしてtranspile後も残る。TypeScript型は、このruntime definitionから推論する。
このobjectは、通常のJavaScript valueとしてtranspile後も残る。TypeScript型は、このruntime definitionから推論する。
## Conceptual model
### Type definition
Record、Enum、Union等もruntime definition objectとして宣言する。
Record、Enum、Union等の型も、runtime definition objectとして宣言する。
```ts
const WriteResult = wip.union({
@@ -70,17 +68,17 @@ const WriteResult = wip.union({
});
```
TypeScript型はdefinitionから推論する。
このdefinitionから、TypeScript型を推論する。
```ts
type WriteResult = wip.Infer<typeof WriteResult>;
```
`wip.Infer`の具体的な型実装と、Union DTOのTypeScript representationは未決定である。Runtime definitionと推論された型が、同じProtocol `TypeExpr`および`Value` semanticsを表すことが要件である。
`wip.Infer`の具体的な型実装とUnion DTOのTypeScript representationは、まだ決めていない。Runtime definitionと推論した型が、同じProtocol `TypeExpr`および`Value` semanticsを表すことを要件とする。
### Interface definition
WIP Interfaceはruntime definition objectとして宣言する。
WIP Interfaceも、runtime definition objectとして宣言する。
```ts
const FileInterface = wip.interface({
@@ -125,9 +123,9 @@ const FileInterface = wip.interface({
});
```
このsyntaxはconceptualである。Definition objectのproperty名、documentationの指定方法、Named typeの参照方法、`optional`の表現は未決定である。
このsyntaxはconceptualであり、具体的なAPIとして確定したものではない。Definition objectのproperty名、documentationの指定方法、Named typeの参照方法、`optional`の表現は未決定である。
Interface definitionは、次のlogical declarationに対応する。
Interface definitionとProtocol上の宣言は、次のように対応付ける。
- 一つのruntime definition objectを、一つのInterface Descriptorを構築するTypeScript側definitionとして扱う。
- JavaScript variable名`FileInterface`はlocal code上の識別子であり、Protocol `InterfaceDescriptor`のfieldや構造化されたInterface参照としてそのまま公開しない。
@@ -137,22 +135,24 @@ Interface definitionは、次のlogical declarationに対応する。
- Runtime type definitionをDescriptorの`TypeExpr`とProtocol `Value`へ対応付ける。
- DocumentationをInterface、Operation、parameter、return、type、field、caseへ指定できるようにする。
Descriptorのshapeはruntime definition objectによって決まり、各classまたはplain objectのimplementationによって変化しない。
Descriptorのshapeを決めるのはruntime definition objectである。各classまたはplain objectがどう実装するかによって、Descriptorは変化しない。
Operation、parameter、type、field、caseのProtocol名はfinalized definition内のstableなstring dataとして保持する。JavaScript variable名、constructor名、functionの`.name`、prototype上のmethod列挙から推測しない。Hostはincoming Operation名をfinalized dispatch table上のinternal tokenまたはaccessorへ解決し、Clientから受け取った名前をそのままobject property lookupへ使用しない。Object-literal keyをauthoring sugarとして使う場合にproperty manglingからどう保護するかは未決定である。
Operation、parameter、type、field、caseのProtocol名は、finalized definition内にstableなstring dataとして保持する。JavaScript variable名、constructor名、functionの`.name`、prototype上のmethod列挙から推測することはしない。
Definition objectはHostへの登録時に一つのimmutableなartifactとしてfinalizeする。MutableなProtocol Interface参照を提供する場合は、同じ参照へ新しいvalidatorと新しいfinalized artifactを対応付け、同じ参照とvalidatorの組から異なるDescriptorを返してはならない。
Hostはincoming Operation名を、finalized dispatch table上のinternal tokenまたはaccessorへ解決する。Clientから受け取った名前をそのままobject property lookupに使うことはしない。Object-literal keyをauthoring sugarとして使う場合、property manglingからどう保護するかは未決定である。
Definition objectは、Hostへの登録時に一つのimmutableなartifactとしてfinalizeする。MutableなProtocol Interface参照を提供する場合は、同じ参照へ新しいvalidatorと新しいfinalized artifactを対応付ける。同じ参照とvalidatorの組から異なるDescriptorを返すことは認めない。
### Operation implementation type
Interface definitionから、必要なOperation implementationのTypeScript型を推論する。
必要なOperation implementationのTypeScript型は、Interface definitionから推論する。
```ts
type FileOperations =
wip.Implementation<typeof FileInterface>;
```
Conceptualには、次のようなobject typeへ展開される。
概念的には、次のようなobject typeへ展開される。
```ts
type FileOperations = {
@@ -167,9 +167,9 @@ type FileOperations = {
};
```
Function-valued propertyを基本形とし、`strictFunctionTypes`を含むstrictなcompiler settingsの下でparameterをcontravariantに検査できるようにする。通常のclass method parameterはTypeScriptのassignabilityでbivariantに扱われる場合があるため、method-shapedな`implements`だけを「すべてのschema-valid argumentを安全に受け取れる」ことの完全な証明としては扱わない。
Function-valued propertyを基本形とし、`strictFunctionTypes`を含むstrictなcompiler settingsの下でparameterをcontravariantに検査できるようにする。通常のclass method parameterは、TypeScriptのassignabilityでbivariantに扱われる場合がある。そのため、method-shapedな`implements`だけを「すべてのschema-valid argumentを安全に受け取れる」ことの完全な証明にはしない。
Definition-awareなbuilderでimplementationをcontextual typingする形も考えられる。
Definition-awareなbuilderによって、implementationをcontextual typingする形も考えられる。
```ts
const operations = FileInterface.implement({
@@ -183,13 +183,13 @@ const operations = FileInterface.implement({
});
```
`implement`の採用は未決定である。どの形でもruntime validationとcallable checkをauthorityとし、TypeScript型はdeveloper feedbackとして扱う。
`implement`を採用するかは未決定である。どの形でも、実行時の判定はruntime validationとcallable checkをauthorityとし、TypeScript型はdeveloper feedbackとして扱う。
このfunction property shapeは説明用である。Operation parameterを一つのarguments objectとして渡すか、request contextを別parameterにするか、sync returnを許可するかは未決定である。
上のfunction property shapeも説明用である。Operation parameterを一つのarguments objectとして渡すか、request contextを別parameterにするか、sync returnを許可するかは、まだ決めていない。
### Object implementation
Classは、その時点でWorldspaceへ投影するObjectをHost内部で表現できる。
その時点でWorldspaceへ投影するObjectは、Host内部ではclassとして表現できる。
```ts
class File implements WipObject, FileOperations {
@@ -218,7 +218,7 @@ class File implements WipObject, FileOperations {
}
```
`WipObject`と`WipObjectMetadata`の具体的なshapeは未決定である。概念的にはProtocol Objectのうち、publication時に選択するInterface集合以外の公開metadataを提供する。
`WipObject`と`WipObjectMetadata`は、Protocol Objectの公開metadataのうち、publication時に選ぶInterface集合以外を提供するための概念的な型である。具体的なshapeは未決定である。
```ts
interface WipObject {
@@ -233,16 +233,16 @@ interface WipObjectMetadata {
}
```
`WipObjectMetadata`へ次を含めない。これらをimplementing classのprivate fieldとして保持することは禁止しない。
Classが保持する情報のすべてを公開metadataにするわけではない。次の情報は`WipObjectMetadata`に含めないが、implementing classのprivate fieldとして保持してよい。
- Absolute path。PathはObjectのfieldではなく、Worldspace resolutionのcontextである。
- Children。ChildrenはTree上の配置contextである。
- 固定されたInterface集合。InterfaceはObjectを公開する時点で追加する。
- Backend connection、file descriptor、credential等のHost-private state。
Classが保持するpathやbackend handle等をOperation implementationに使用してよいが、Object metadataまたはProtocol Objectへ自動的にserializeしない。
Classのpathやbackend handleはOperation implementationで使用できる。ただし、Object metadataやProtocol Objectへ自動的にserializeする対象にはしない。
Classの使用は必須ではない。Structural typingを利用してplain objectも使用できる。
また、classの使用は必須ではない。Structural typingを利用し、plain objectを使うこともできる。
```ts
const file = {
@@ -262,7 +262,7 @@ const file = {
### Object publication
ObjectをWorldspaceへ返す時点で、object instanceと公開する0個以上のInterface definitionを明示的に組み合わせる。Interfaceは追加順を保持するordered setであり、同じdefinitionまたは同じ登録済み参照を重複して追加しない。
ObjectをWorldspaceへ返す時点で、object instanceと、公開する0個以上のInterface definitionを明示的に組み合わせる。Interfaceは追加順を保持するordered setとし、同じdefinitionまたは同じ登録済み参照の重複追加は認めない。
```ts
const file = new File(path, objectMetadata);
@@ -270,7 +270,7 @@ const object = wip.publish(file)
.expose(FileInterface, file);
```
Publication APIはconceptualに、追加する各definitionと、そのImplementation型を満たすbindingを受け取る。
Publication APIは、概念的には各definitionと、そのImplementation型を満たすbindingを受け取る。
```ts
interface WipInterfaceDefinition<Implementation extends object> {
@@ -285,11 +285,13 @@ interface PublishedObject<T extends WipObject> {
}
```
実際のTypeScript generic表現は未決定である。このconstraintは、strictなcompiler settingsとfunction-valued property shapeを使用する場合に、追加する各Interfaceへbindした値が必要なOperation functionを提供するか検査する。Object instance自身をimplementationとして渡しても、Interface専用のadapter objectを渡してもよく、どのInterfaceも追加しないObjectも表現できる。通常のclass methodやtype assertion等で検査を弱められるため、各Interfaceを追加する時点とdispatch時のruntime callable check、およびValue validationは常に必要である。
実際のTypeScript generic表現は未決定である。このconstraintは、strictなcompiler settingsとfunction-valued property shapeを使用した場合に、各Interfaceへbindする値が必要なOperation functionを提供するかを検査するためのものである。
Host Runtimeは各bindingを登録済みInterface参照と対応付ける。異なるInterfaceが同名Operationを宣言しても、選択されたInterface参照に対応するbindingだけをdispatch対象とし、単一object上の同名propertyへmergeしない。
ImplementationにはObject instance自身を渡しても、Interface専用のadapter objectを渡してもよい。Interfaceを一つも追加しないObjectも表現できる。ただし、通常のclass methodやtype assertion等で型の検査を弱められるため、各Interfaceの追加時とdispatch時にはruntime callable checkを行い、Value validationも常に行う必要がある。
`PublishedObject`はHost SDK内のconceptual typeであり、Protocol typeとして追加しない。Host Runtimeはこれを使用して次を構築する。
Host Runtimeは、各bindingを登録済みInterface参照と対応付ける。異なるInterfaceが同名Operationを宣言していても、dispatch対象は選択されたInterface参照に対応するbindingだけであり、単一object上の同名propertyへmergeしない。
`PublishedObject`はHost SDK内のconceptual typeであり、Protocol typeには追加しない。Host Runtimeはこの値からProtocol Objectを構築する。
```ts
const protocolObject = {
@@ -301,15 +303,17 @@ const protocolObject = {
};
```
Optional propertyの`undefined`はwireへ出力せず、field省略として扱う。`null`へ自動変換しない。
Optional propertyの`undefined`はwireへ出力せず、fieldの省略として扱う。`null`へ自動変換することはしない。
`selectedInterfaceReferences`は、Hostが各runtime Interface definitionを登録または公開するときに割り当てる構造化参照`{ scope, name }`を、publication APIへの追加順で並べたものである。同じ`(scope, name)`の重複は拒否し、Objectの配置pathに対する祖先制約も検証する。Variable名やJavaScript object identityをportableなProtocol参照としてそのまま使用することは要求しない。
`selectedInterfaceReferences`には、Hostが各runtime Interface definitionの登録または公開時に割り当てる構造化参照`{ scope, name }`を、publication APIへの追加順で並べる。同じ`(scope, name)`の重複は拒否し、Objectの配置pathに対する祖先制約も検証する。Variable名やJavaScript object identityを、そのままportableなProtocol参照として使用することは要求しない。
`observe`はDescriptor自体をObjectへ埋め込まず、このInterface参照のordered setだけを返す。Clientが各参照を`fetch_interface`したとき、Host Runtimeはruntime definition objectから構築したDescriptorと、存在する場合はInterface validatorを返す。同じ参照とvalidatorの組のDescriptorはHost上で共有およびcacheできるため、Object instanceごとにDescriptorを再生成または再送する必要はない。
`observe`でObjectに含めるのは、Descriptor自体ではなく、このInterface参照のordered setだけである。Clientが各参照を`fetch_interface`すると、Host Runtimeはruntime definition objectから構築したDescriptorと、存在する場合はInterface validatorを返す。
同じ参照とvalidatorの組に対応するDescriptorは、Host上で共有およびcacheできる。このため、Object instanceごとにDescriptorを再生成したり再送したりする必要はない。
## Runtime definitionの責務
`wip.interface(...)`が返すdefinition objectは、conceptualには次を生成または提供する。
`wip.interface(...)`が返すdefinition objectには、Descriptorの構築に加えて、Valueの変換・検証とInterfaceごとのdispatchに必要な情報を提供する役割を想定する。
- Interface Descriptorを構築するruntime definition。
- Operation propertyとOperation Declarationの対応情報。
@@ -320,7 +324,7 @@ Optional propertyの`undefined`はwireへ出力せず、field省略として扱
- 各Interfaceの推論されたImplementation型を満たす値を、そのInterface参照へbindするtyped entry point。
- HostがInterface参照、optional validator、Descriptorを登録、取得、cacheするためのlocal identity。
TypeScriptのstructural type checkはcompile-timeのdeveloper feedbackである。Runtimeでは少なくとも次を検証する。
TypeScriptのstructural type checkはcompile-timeのdeveloper feedbackである。Runtimeでは、少なくとも次を検証する必要がある。
- Object metadataがProtocol上有効である。
- 追加する各InterfaceへbindしたOperation implementationが呼び出し可能である。
@@ -329,13 +333,11 @@ TypeScriptのstructural type checkはcompile-timeのdeveloper feedbackである
- ResultがDescriptorに従っている。
- Integer、Number、Entry、Record、Union等の追加制約を満たす。
Generatedまたはgenericなdispatch codeはTypeScript SDK内部の実装詳細である。Host内部のdispatch mechanism、class名、prototype、constructor等をProtocolへ公開しない。
Generatedまたはgenericなdispatch codeは、TypeScript SDK内部の実装詳細である。Host内部のdispatch mechanism、class名、prototype、constructor等はProtocolへ公開しない。
## TypeScript typeとProtocol type
Runtime definitionは、Descriptorの`TypeExpr`、Protocol `Value`、TypeScript static typeの三つを対応付ける。
Conceptualな対応例は次のとおりである。
Runtime definitionは、Descriptorの`TypeExpr`、Protocol `Value`、TypeScript static typeの三つを対応付ける。次の表はconceptualな対応例であり、具体的なpublic typeは未決定である。
| WIP definition | TypeScript representation | Runtime validation |
| --- | --- | --- |
@@ -352,21 +354,19 @@ Conceptualな対応例は次のとおりである。
| `wip.enum(...)` | String literal union | 宣言caseのみ |
| `wip.union(...)` | Discriminated union | Case、payload、shape |
この表の具体的なpublic typeは未決定である。
`wip.json()`が受け付けるのは、null、boolean、finite number、string、Array、およびstring-keyedなplain objectから再帰的に構成されるJSON-compatible valueだけである。`undefined`、`bigint`、`symbol`、function、`Uint8Array`、`Date`、`Map`、`Set`、class instance、cyclic object graph、NaN、正負Infinity、sparse array等は、暗黙にJsonへ変換せずvalidation failureとする。Integerとして表現する値にも、Protocolの相互運用範囲を適用する。
`wip.json()`が受け付けるのは、null、boolean、finite number、string、Array、およびstring-keyedなplain objectから再帰的に構成されるJSON-compatible valueだけである。`undefined`、`bigint`、`symbol`、function、`Uint8Array`、`Date`、`Map`、`Set`、class instance、cyclic object graph、NaN、正負Infinity、sparse array等を暗黙にJsonへ変換せず、validation failureとする。Integerとして表現する値にもProtocolの相互運用範囲を適用する。
TypeScriptの`number`はIntegerにもNumberにも使えるため、runtime schemaの位置に基づいて検証する。`wip.integer()`ではProtocolの相互運用範囲を超える値を拒否し、`bigint`を暗黙にIntegerへ変換しない。
TypeScriptの`number`はIntegerとNumberの両方に使用できるため、runtime schemaの位置に基づいて検証する。`wip.integer()`はProtocolの相互運用範囲を超える値を拒否する。`bigint`を暗黙にIntegerへ変換しない。
Protocol `Unit`には、たとえば`wip.unitValue`のような専用singleton / sentinelを使い、`undefined`は使わない。RequiredなUnit fieldではsentinelを明示する。OptionalなUnit fieldでは、sentinelがpresent Unitを表し、property欠落またはoptional positionの`undefined`が省略を表す。
Protocol `Unit`は、例えば`wip.unitValue`のような専用singleton / sentinelで表す。`undefined`をUnitとして使用しない。RequiredなUnit fieldはsentinelを明示し、optionalなUnit fieldではsentinelがpresent Unit、property欠落またはoptional positionの`undefined`が省略を表す。
`wip.optional(T)`はfieldまたはparameterの省略を表し、`null`を許可する意味ではない。Implementationへ渡すarguments objectではproperty欠落を省略とし、optional positionへ明示された`undefined`をSDK convenienceとして省略へnormalizeしてよい。`undefined`自体をProtocol Valueとしてencodeせず、required positionの`undefined`はvalidation failureとする。
同様に、`wip.optional(T)`はfieldまたはparameterの省略を表すものであり、`null`を許可する意味ではない。Implementationへ渡すarguments objectではproperty欠落を省略として扱う。Optional positionに明示した`undefined`は、SDK convenienceとして省略へnormalizeしてよいが、`undefined`自体をProtocol Valueとしてencodeすることはしない。Required positionの`undefined`はvalidation failureとする。
## Dynamic Worldspaceでのlifecycle
### `observe`
Projection implementationはrequest時にbackend dataを解決し、classまたはplain object instanceを生成する。
Projection implementationはrequest時にbackend dataを解決し、その時点のclassまたはplain object instanceを生成する。
```ts
async function resolveFile(
@@ -399,9 +399,9 @@ async function resolveFile(
}
```
Host Runtimeは`PublishedObject`からProtocol Objectを返す。Response生成後にこの`File` instanceを破棄してよく、Worldspace内の全fileに対応するinstanceを保持しない。
Host Runtimeは`PublishedObject`からProtocol Objectを返す。Responseを生成した後は、この`File` instanceを破棄してよい。Worldspace内の全fileに対応するinstanceを保持する必要はない。
Requested depthが正の場合、Providerはdirect childrenをlazyに発見できる。Directory全体を先に収集してArrayとして返すことは要求しないが、一つのparentのobservationを成功させるには公開されたindexable childrenをclean exhaustionまで列挙しなければならない。ConceptualにはAsync Iterable等を利用できる。
Requested depthが正の場合、Providerはdirect childrenをlazyに発見できる。Directory全体を先に収集し、Arrayとして返すことは要求しない。ただし、一つのparentのobservationを成功させるには、公開されたindexable childrenをclean exhaustionまで列挙する必要がある。概念的には、Async Iterable等を利用できる。
```ts
const entries = filesystem.discoverChildren(path, budget);
@@ -420,7 +420,7 @@ for await (const entry of entries) {
}
```
`discoverChildren`、`budget`、`observation`はconceptualであり、具体APIではない。必要なsemanticsは次である。
`discoverChildren`、`budget`、`observation`は具体APIではなく、conceptualな表記である。Childの発見と公開には、次のsemanticsを要求する。
- 各childを現在の主体についてprojectし、非公開Objectとそのsubtreeを返さない。
- 公開されたindexable childrenをすべて列挙し、clean exhaustionで終了する。
@@ -432,7 +432,7 @@ for await (const entry of entries) {
### `call_operation`
Hostはcall時に、requestのTargetと`InterfaceTarget`をHost Runtimeへ渡す。Runtimeは一つのatomic execution boundaryへ入ってから`target.path`を現在のObject implementationとstableなbackend対象へ解決する。
Call時には現在のObjectを解決し直す。HostはrequestのTargetと`InterfaceTarget`をHost Runtimeへ渡し、Runtimeは一つのatomic execution boundaryに入ってから、`target.path`を現在のObject implementationとstableなbackend対象へ解決する。
```ts
await runtime.callCurrent(
@@ -445,7 +445,7 @@ await runtime.callCurrent(
);
```
`resolveCurrentProjection`と`runtime.callCurrent`というAPIを採用することは決定しない。ResolverはRuntimeが開始したexecution boundary内で呼ばれ、返す値はそのboundary中にObject identityとbackend対象を安定して保持するhandleまたはtransaction contextを含む必要がある。このexampleが示す要件は次である。
`resolveCurrentProjection`と`runtime.callCurrent`を実際のAPIとして採用するかは決めていない。ResolverはRuntimeが開始したexecution boundary内で呼ばれ、そのboundary中にObject identityとbackend対象を安定して保持するhandleまたはtransaction contextを含む値を返す必要がある。上のexampleは、次の要件を表す。
- 過去の`observe`で作成したobject instanceを保持していなくてもOperationを実行できる。
- Call時の現在の主体、Object visibility、Object metadata、Interface集合を同じProjection pathで再解決し、Objectが非公開なら`NotFound`を返す。
@@ -461,15 +461,15 @@ await runtime.callCurrent(
- Runtime dispatchが、選択されたInterface definitionへbindしたOperation implementationを現在のObject contextへ適用する。異なるInterfaceの同名Operationをmergeまたは曖昧に解決しない。
- Operation実行後の現在状態に対応するvalidatorを、必要に応じて`CallOperationResponse`へ返せる。
Object validatorをObject identityへ結び付けるためにClient-facingな`ref`を要求しない。ProviderまたはHostはHost-privateなidentityを使用できるが、そのidentity confirmation、Object validator比較、Interface membershipとvalidator比較、DescriptorとInterface-specific implementation bindingの固定、authorization、Operation実行を一つのatomic boundaryで行う。
Object validatorとObject identityの関連付けに、Client-facingな`ref`は必須ではない。ProviderまたはHostはHost-privateなidentityを使用できる。ただし、identity confirmation、Object validator比較、Interface membershipとvalidator比較、DescriptorとInterface-specific implementation bindingの固定、authorization、Operation実行は、一つのatomic boundaryで行う。
Operation実行後validatorを、同じobject instanceから再計算するか、Operation resultとともに返すか、backendを再観測するかは未決定である。どの方式でも、resultを生成した実行後状態とvalidatorを対応させなければならない。
実行後のvalidatorをどこから取得するかも未決定である。同じobject instanceから再計算する方式、Operation resultとともに返す方式、backendを再観測する方式が考えられるが、いずれもresultを生成した実行後状態とvalidatorを対応させる必要がある。
Object instanceがpath文字列だけを保持し、validator比較後にpathを無条件で開き直す実装は、対象差し替えに対するatomicityを保証できない場合がある。TypeScript APIは、transaction、conditional update、backend handle、lock等を利用してbackend固有のatomicityを実現できる必要があるが、その抽象化は未決定である。
Object instanceがpath文字列だけを保持している場合、validator比較後にpathを無条件で開き直すと、対象差し替えに対するatomicityを保証できないことがある。TypeScript APIには、transaction、conditional update、backend handle、lock等でbackend固有のatomicityを実現できることを求める。そのための抽象化は未決定である。
## 複数Interfaceの実装
一つのclassまたはplain objectは複数のInterface implementation typeを満たせる。Property名が衝突する場合やInterfaceごとに異なるbehaviorを提供する場合は、Interfaceごとのadapter objectをbindできる。
一つのclassまたはplain objectは、複数のInterface implementation typeを満たせる。Property名が衝突する場合や、Interfaceごとに異なるbehaviorを提供する場合は、Interfaceごとのadapter objectをbindできる。
```ts
type ReadOnlyFileOperations =
@@ -488,7 +488,7 @@ class File
}
```
Publication時に、現在の主体へ公開する0個以上のInterfaceを選択し、表示したい順で追加する。
現在の主体へ公開する0個以上のInterfaceはpublication時に選び、表示したい順に追加する。
```ts
let object = wip.publish(file)
@@ -505,9 +505,9 @@ if (authorization.canWrite) {
return object;
```
Protocol Objectの`interfaces`は追加順を保持するordered setである。同じInterface参照の重複は拒否する。複数のImplementation bindingを一つのDescriptorやdispatch tableへ暗黙にmergeせず、各Interface Descriptorとbindingは独立したOperation集合およびbehaviorを提供する。
Protocol Objectの`interfaces`は追加順を保持するordered setであり、同じInterface参照の重複は拒否する。各Interface Descriptorとbindingは、それぞれ独立したOperation集合およびbehaviorを提供する。複数のImplementation bindingを一つのDescriptorやdispatch tableへ暗黙にmergeすることはしない。
異なるInterfaceは同じOperation名を宣言できる。Dispatchはrequestの`InterfaceTarget.reference`とOperation名の組で一意に決まり、そのInterfaceへbindしたimplementationを使用するため、同じObjectに意味の異なる同名Operationを実装できる。
異なるInterfaceが同じOperation名を宣言しても、dispatchはrequestの`InterfaceTarget.reference`とOperation名の組で一意に決まる。そのInterfaceへbindしたimplementationを使うため、同じObjectに意味の異なる同名Operationを実装できる。
```ts
const object = wip.publish(file)
@@ -519,17 +519,17 @@ const object = wip.publish(file)
});
```
表示上のqualified表記は[Text Viewの参照表記](../4.2-text-view.md#参照表記)に従う。Signature全体をProtocol request fieldへparseし直さない。
表示上のqualified表記は[Text Viewの参照表記](../4.2-text-view.md#参照表記)に従い、signature全体をProtocol request fieldへparseし直さない。
Intersection type、interface extension、mixin等をDescriptorのcompositionへ自動変換しない。Protocol上のInterface inheritanceを暗黙に導入しない。
Intersection type、interface extension、mixin等をDescriptorのcompositionへ自動変換することはしない。これらによって、Protocol上のInterface inheritanceを暗黙に導入することもない。
## HostへのInterface登録
Runtime Interface definitionをHostへ登録し、構造化されたInterface参照を割り当てる必要がある。
Runtime Interface definitionには、Hostへの登録を通じて構造化されたInterface参照を割り当てる必要がある。参照の絶対scopeとlocal name、および配置pathへの祖先制約は[2.2. Operation and Interface](../2.2-operation-and-interface.md#interfaceの識別とscope)に従う。
参照の絶対scopeとlocal name、および配置pathへの祖先制約は[2.2. Operation and Interface](../2.2-operation-and-interface.md#interfaceの識別とscope)に従う。以下のconceptual API例はscope / nameを渡す具体構文を省略しており、暗黙のroot scopeを定めるものではない。登録時のcontextと引数の具体APIは引き続き未決定である。Self-scopeは許可され、scopeはそのpathのObjectに紐づく。Scope Objectのoptionalな`ref`はProtocolの`scope_ref`として観測・検証し、`ref`がない場合のidentity追跡不能も許容する。Scopeの移動追跡や独立したscope validatorを導入しない。
Self-scopeは許可され、scopeはそのpathのObjectに紐づく。Scope Objectのoptionalな`ref`はProtocolの`scope_ref`として観測・検証する。`ref`がなければidentityを追跡できないことも許容し、scopeの移動追跡や独立したscope validatorは導入しない。
Conceptualには、eager registrationとlazy registrationの両方が考えられる。
登録方法としては、conceptualにはeager registrationとlazy registrationの両方が考えられる。次の例はscope / nameを渡す具体構文を省略しており、暗黙のroot scopeを定めてはいない。登録時のcontextと引数の具体APIも引き続き未決定である。
```ts
const readInterface = host.registerInterface(ReadOnlyFileInterface);
@@ -543,9 +543,7 @@ const object = wip.publish(file)
});
```
または、Hostが最初のpublication時に各definitionをinternしてよい。
どちらの場合も次を守る。
また、Hostが最初のpublication時に各definitionをinternする方式でもよい。どちらの登録方法でも、次の条件を満たす必要がある。
- MutableなInterface参照では`fetch_interface`がvalidatorを返し、同じ参照とvalidatorの組から異なるDescriptorを返さない。
- Validatorを返さないInterface参照は、その参照の有効期間中Descriptorをimmutableにする。
@@ -556,11 +554,13 @@ const object = wip.publish(file)
- Variable名、module path、JavaScript object address等を、そのままportableなProtocol semanticsとして扱わない。
- 一つのfinalized artifactを後からmutationしてDescriptorを変化させない。Hostはdefinitionをfreezeするか、検証済みのimmutable snapshotを保持できなければならない。
Registrationまたは最初のpublicationで、Descriptor、type codec、validator、Operation dispatch tableを一つのfinalized artifactとして再帰的に検証および固定する。`fetch_interface`、arguments / result validation、Operation dispatchはすべて同じartifactを使用する。Descriptorだけをsnapshotし、dispatch時にはmutation可能な元definitionを読み直す実装にはしない。Finalization後のmutationは拒否するか、既存artifactへ影響しないものとして扱う。
Registrationまたは最初のpublicationでは、Descriptor、type codec、validator、Operation dispatch tableを一つのfinalized artifactとして再帰的に検証し、固定する。`fetch_interface`、arguments / result validation、Operation dispatchは、すべて同じartifactを使う。
Descriptorだけをsnapshotし、dispatch時にmutation可能な元definitionを読み直す方式では、この固定を満たせない。Finalization後のmutationは拒否するか、既存artifactに影響しないものとして扱う。
## Request contextとauthorization
Operation implementationは、Object instance以外にrequest contextを必要とし得る。
Operation implementationが必要とする情報は、Object instanceだけとは限らない。Request contextとして、次の情報も必要になり得る。
- 現在の主体。
- `AbortSignal`等のcancellation。
@@ -569,34 +569,34 @@ Operation implementationは、Object instance以外にrequest contextを必要
- Host serviceやbackend connectionへのaccess。
- Resource limit。
これらをmethod parameter、wrapper object、AsyncLocalStorage、closure等のどれで渡すかは未決定である。Protocol parameterとして宣言された値と、Hostが注入するcontextを明確に区別しなければならない。
このcontextをmethod parameter、wrapper object、AsyncLocalStorage、closure等のどれで渡すかは未決定である。どの形でも、Protocol parameterとして宣言された値とHostが注入するcontextは明確に区別する必要がある。
Object publication時のInterface集合の選択と、Operation call時のmembership、Interface validator、authorizationの再評価を実装できる必要がある。以前の`observe`で公開されたInterface集合だけを根拠に、現在のOperation実行を許可してはならない。
Interface集合はObject publication時に選択するだけでなく、Operation call時にもmembership、Interface validator、authorizationを再評価できなければならない。以前の`observe`で公開したInterface集合だけを根拠に、現在のOperation実行を許可することはできない。
Operation resultのRecord、List、Union等へnestedしたすべての`Entry`位置について、Hostは現在の主体にそのpathを認識させてよいことを再帰的に確認できなければならない。通常のstructural Value validationだけではこのvisibility checkを満たさない。Runtime definition、Projection、Host Runtimeのどこで確認するかは未決定である。
Resultのvisibility checkも、通常のstructural Value validationとは別に必要となる。Hostは、Operation resultのRecord、List、Union等にnestedしたすべての`Entry`について、現在の主体にそのpathを認識させてよいかを再帰的に確認できなければならない。この確認をRuntime definition、Projection、Host Runtimeのどこで行うかは未決定である。
Operation argumentとして`Entry` pathを受け取った場合も、pathの所持をauthorizationの証明として扱わず、参照先へ作用する時点で現在の主体について認可する。
Argumentとして受け取った`Entry` pathについても、pathの所持をauthorizationの証明にはしない。参照先へ作用する時点で、現在の主体について認可する。
## Error model
TypeScript methodのerror表現は、次の四種類を区別できなければならない。
TypeScript methodのerror表現には、次の四種類を区別できることを求める。
- Protocol validationまたはdispatch failure。
- Effectがcommitされていないと保証できるHost / backend implementation failure。
- Operationの未実行またはrollbackを保証できない`OperationOutcomeUnknown`。
- Interfaceがreturn typeとして宣言したdomain failure。
現在のProtocolでは、domain failureはOperation resultのUnion caseとして表す。Thrown value、rejected Promise、explicit result objectをdomain resultまたはHost errorへどう対応付けるかは、Interface authoring APIで明示しなければならない。
現在のProtocolはdomain failureをOperation resultのUnion caseとして表す。Thrown value、rejected Promise、explicit result objectをdomain resultまたはHost errorへどう対応付けるかは、Interface authoring APIで明示する必要がある。
Arbitrary thrown value、Promise rejection、result encode failure、宣言型に違反するimplementation resultをdomain failureへ自動変換してはならない。Host Runtimeは、effectがcommitされていないと保証できる場合だけ`Internal`へmappingし、保証できない場合は`OperationOutcomeUnknown`へmappingする。Abortやtransport切断を未実行の証明として扱わず、自動retryしない。
Arbitrary thrown value、Promise rejection、result encode failure、宣言型に違反するimplementation resultを、domain failureへ自動変換することは認めない。Host Runtimeは、effectがcommitされていないと保証できる場合だけ`Internal`へmappingし、保証できなければ`OperationOutcomeUnknown`へmappingする。Abortやtransport切断は未実行の証明とはならず、自動retryはしない。
## Custom transpilerを必須にしない
通常のTypeScript `interface`または`type`をsource of truthにしてInterface Descriptorを生成するには、TypeScript Compiler API、custom transformer、code generator等が必要になる。
通常のTypeScript `interface`または`type`をsource of truthとしてInterface Descriptorを生成するには、TypeScript Compiler API、custom transformer、code generator等が必要になる。
Core APIはこれを要求しない。Runtime definition objectをsource of truthにすることで、通常の`tsc`、bundler、JavaScript runtimeで動作できるようにする。
Core APIでは、これらを必須にしない。Runtime definition objectをsource of truthとすることで、通常の`tsc`、bundler、JavaScript runtimeで動作できるようにする。
Build-time toolingはoptionalなauthoring layerとして追加してよい。
Build-time toolingは、optionalなauthoring layerとして追加してよい。
```ts
/** @wip-interface */
@@ -605,9 +605,9 @@ interface FileOperations {
}
```
Toolingがこのdeclarationからruntime definition moduleを生成することはできるが、生成物はcore APIと同じruntime definition semanticsを満たさなければならない。
Toolingによってこのdeclarationからruntime definition moduleを生成することはできる。ただし、その生成物もcore APIと同じruntime definition semanticsを満たす必要がある。
Build-time toolingには少なくとも次の課題がある。
Build-time toolingには、少なくとも次の課題がある。
- TypeScript compiler versionとCompiler APIへの依存。
- Bundler、incremental build、package boundaryとの統合。
@@ -618,15 +618,15 @@ Build-time toolingには少なくとも次の課題がある。
## Decoratorをcoreにしない
Decoratorだけでは、通常はUnion case、Record field、optional、Entry、Integer、nested type、generic、documentation等を完全なruntime schemaとして取得できない。
Decoratorだけでは通常、Union case、Record field、optional、Entry、Integer、nested type、generic、documentation等を、完全なruntime schemaとして取得できない。
`emitDecoratorMetadata`等が提供するconstructor-level metadataだけでは、WIP Interface DescriptorとValue validationを再構築するには不足する。Decoratorをoptional sugarとして提供する場合も、明示的なruntime definitionまたはbuild-time generationへ接続する。
`emitDecoratorMetadata`等が提供するconstructor-level metadataも、WIP Interface DescriptorとValue validationを再構築するには不足する。Decoratorをoptional sugarとして提供する場合には、明示的なruntime definitionまたはbuild-time generationへ接続する。
Class inheritanceをInterface declarationの基本形にすると、複数Interface implementation、plain object、data-drivenなpublicationが不必要に制限されるため、runtime definition objectをcore modelとする。
また、class inheritanceをInterface declarationの基本形にすると、複数Interface implementation、plain object、data-drivenなpublicationを不必要に制限することになる。このため、runtime definition objectをcore modelとする。
## 要件
TypeScript API modelは少なくとも次を満たす。
このdraftのTypeScript API modelに求める要件は、少なくとも次のとおりである。
- Runtime definition objectをInterface Descriptorとruntime validationのsource of truthにする。
- 同じdefinitionからTypeScript implementation typeを推論できる。
@@ -656,7 +656,7 @@ TypeScript API modelは少なくとも次を満たす。
## 非目標
このdraftは次を決定しない。
次の事項は、このdraftでは決定しない。
- 最終的なpackage、module、function、generic type、class、methodの名前。
- 特定のschema libraryまたはvalidation libraryの採用。
@@ -698,4 +698,4 @@ TypeScript API modelは少なくとも次を満たす。
- TypeScript client APIを同じruntime definitionから生成するか。
- Build-time code generationをoptional packageとして提供するか。
これらを決定する際は、静的service objectだけでなく、Filesystem、database row、virtual aggregate、主体別Interface compositionを同じAPIで実装できるか評価する。
これらの選択は、静的service objectに使えるだけでは足りない。Filesystem、database row、virtual aggregate、主体別Interface compositionも、同じAPIで実装できるかを評価して決定する。
+7 -5
View File
@@ -1,6 +1,6 @@
# 未解決事項
主要な未解決事項を、canonicalなCore文書へのindexとしてまとめる。
主要な未解決事項と、対応するcanonicalなCore文書への参照をまとめる。
## 2.2. Operation and Interface
@@ -19,16 +19,18 @@
### Interface scopeとcomposition
構造化参照と絶対scopeは[2.2. Operation and Interface](../2.2-operation-and-interface.md#interfaceの識別とscope)、fieldとHost変換は[3. Protocol](../3-protocol.md#worldspace-composition)、短縮表記は[4.2. Text View](../4.2-text-view.md#参照表記)、JSON encodingは[5.1. WIP over HTTP](../5.1-wip-over-http.md#interface-reference)へ統合済み。
Interface scopeとcompositionの基本仕様は、すでに各文書へ統合されている。構造化参照と絶対scopeは[2.2. Operation and Interface](../2.2-operation-and-interface.md#interfaceの識別とscope)、fieldとHost変換は[3. Protocol](../3-protocol.md#worldspace-composition)、短縮表記は[4.2. Text View](../4.2-text-view.md#参照表記)、JSON encodingは[5.1. WIP over HTTP](../5.1-wip-over-http.md#interface-reference)に従う。
Self-scopeとroot scope `/`の利用は許可する。ScopeはそのpathのObjectに紐づき、optionalな`ref`で紐付きを確認する。`ref`なしの差し替えをidentityで追跡できないことは仕様上許容する。Scopeが消えれば旧参照の有効期間は終了し、Clientは不要なcacheを破棄できる。移動先は別参照であり、Clientの移動追跡は要求しない。詳細は[Scope Objectと有効期間](../2.2-operation-and-interface.md#scope-objectと有効期間)および[Protocolの紐付き確認](../3-protocol.md#scope-objectの紐付き)に従う。
Self-scopeとroot scope `/` の利用は許可する。ScopeはそのpathのObjectに紐づき、optionalな`ref`で紐付きを確認する。`ref`がない場合、Objectの差し替えをidentityで追跡できないことは仕様上許容する。
残る論点:
Scopeが消えると旧参照の有効期間は終了し、Clientは不要なcacheを破棄できる。移動先は別参照となるため、Clientに移動追跡は要求しない。詳細は[Scope Objectと有効期間](../2.2-operation-and-interface.md#scope-objectと有効期間)および[Protocolの紐付き確認](../3-protocol.md#scope-objectの紐付き)に従う。
これらの仕様を前提として、次の論点が残る。
- **複数配置とidentity**:同じUpstream Objectを複数scopeへ投影する場合の共通祖先scopeでの共有やprojectionごとの`ref`・validator。同じ`ref`とvalidatorで異なるrepresentationを返せるようにはしない。
- **部分合成と拒否条件**:公開subtree外のscope・typed `entry`への対応付け、対応不能時の公開・実行拒否とerror mapping。非公開情報の秘匿と既存のerror precedenceを維持し、effectがcommit済みか不明なcallを未実行保証のerrorへ置き換えない。
Host内部のmount API、Provider登録API、合成設定の共通data structureは引き続きHost API draftで検討する。
Host内部のmount API、Provider登録API、合成設定の共通data structureも引き続き検討対象であり、Host API draftで扱う。
### Type / Value